Forbid by validators the selection of tangent entities if at least on is a B-spline curve and they have no coincident boundary point.
std::set<AttributePtr>::const_iterator aIt;
for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
- if (aConstrFeature && aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
+ if (aConstrFeature && (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
+ aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()))
aCoincident.insert(aConstrFeature);
}
return aCoincident;
#include "SketchPlugin_BSplinePeriodic.h"
#include "SketchPlugin_Circle.h"
#include "SketchPlugin_ConstraintCoincidence.h"
+#include "SketchPlugin_ConstraintCoincidenceInternal.h"
#include "SketchPlugin_ConstraintDistance.h"
#include "SketchPlugin_ConstraintRigid.h"
#include "SketchPlugin_ConstraintTangent.h"
bool isObject = aRefAttr->isObject();
ObjectPtr anObject = aRefAttr->object();
- if (isObject && anObject.get()) {
- FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
+ if (!isObject || !anObject.get()) {
+ theError = "It uses an empty object";
+ return false;
+ }
- AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA);
- ObjectPtr aOtherObject = aOtherAttr->object();
- FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
- if (!aOtherFea)
- return true;
+ FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
- if (aRefFea->getKind() == SketchPlugin_Line::ID() &&
- aOtherFea->getKind() == SketchPlugin_Line::ID()) {
- theError = "Two segments cannot be tangent";
- return false;
- }
- else if (isSpline(aRefFea) && isSpline(aOtherFea)) {
- theError = "Two B-splines cannot be tangent";
- return false;
- }
+ AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA);
+ ObjectPtr aOtherObject = aOtherAttr->object();
+ FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
+ if (!aOtherFea)
return true;
+
+ if (aRefFea->getKind() == SketchPlugin_Line::ID() &&
+ aOtherFea->getKind() == SketchPlugin_Line::ID()) {
+ theError = "Two segments cannot be tangent";
+ return false;
}
- else {
- theError = "It uses an empty object";
+ else if (isSpline(aRefFea) && isSpline(aOtherFea)) {
+ theError = "Two B-splines cannot be tangent";
return false;
}
- return true;
+ bool isValid = true;
+ bool hasSpline = isSpline(aRefFea);
+ if (!hasSpline && isSpline(aOtherFea)) {
+ hasSpline = true;
+ std::swap(aRefFea, aOtherFea);
+ }
+ if (hasSpline) {
+ auto isApplicableCoincidence = [](FeaturePtr theFeature, const std::string& theAttrName) {
+ AttributeRefAttrPtr aRefAttr = theFeature->refattr(theAttrName);
+ if (aRefAttr->isObject())
+ return false;
+ AttributePtr anAttr = aRefAttr->attr();
+ FeaturePtr anOwner = ModelAPI_Feature::feature(anAttr->owner());
+ AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+ if (aPointAttr) {
+ return anOwner->getKind() == SketchPlugin_BSpline::ID() &&
+ (aPointAttr->id() == SketchPlugin_BSpline::START_ID() ||
+ aPointAttr->id() == SketchPlugin_BSpline::END_ID());
+ }
+
+ AttributePoint2DArrayPtr aPntArray =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(anAttr);
+ if (aPntArray) {
+ // check index of the pole
+ AttributeIntegerPtr anIndex = theAttrName == SketchPlugin_Constraint::ENTITY_A() ?
+ theFeature->integer(SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A()) :
+ theFeature->integer(SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B());
+ return anIndex && (anIndex->value() == 0 || anIndex->value() == aPntArray->size() - 1);
+ }
+ return false;
+ };
+
+ isValid = false;
+ AttributePoint2DArrayPtr aBSplinePoles = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
+ aRefFea->attribute(SketchPlugin_BSplineBase::POLES_ID()));
+ // additional check the B-spline edge and the other edge have a coincident boundary point
+ std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(aRefFea);
+ for (std::set<FeaturePtr>::iterator anIt = aCoincidences.begin();
+ anIt != aCoincidences.end() && !isValid; ++anIt) {
+ std::set<FeaturePtr> aCoinc;
+ if (isApplicableCoincidence(*anIt, SketchPlugin_Constraint::ENTITY_A()))
+ SketchPlugin_Tools::findCoincidences(*anIt, SketchPlugin_Constraint::ENTITY_B(),
+ aCoinc, true);
+ else if (isApplicableCoincidence(*anIt, SketchPlugin_Constraint::ENTITY_B()))
+ SketchPlugin_Tools::findCoincidences(*anIt, SketchPlugin_Constraint::ENTITY_A(),
+ aCoinc, true);
+
+ isValid = aCoinc.find(aOtherFea) != aCoinc.end();
+ }
+ }
+
+ return isValid;
}
bool SketchPlugin_PerpendicularAttrValidator::isValid(const AttributePtr& theAttribute,
self.myDOF += 4
model.do()
- self.mySketch.setTangent(self.mySpline.result(), aLine.result())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), aLine.result())
+ model.end()
- self.assertTangentFeatures(aLine, self.mySpline)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_circle_tangent(self):
""" Test 2. Set tangency between B-spline and a circle
self.myDOF += 3
model.do()
- self.mySketch.setTangent(self.mySpline.result(), aCircle.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), aCircle.defaultResult())
+ model.end()
- self.assertTangentFeatures(aCircle, self.mySpline)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_arc_tangent(self):
""" Test 3. Set tangency between B-spline and an arc
self.myDOF += 5
model.do()
- self.mySketch.setTangent(self.mySpline.result(), anArc.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), anArc.defaultResult())
+ model.end()
- self.assertTangentFeatures(anArc, self.mySpline)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_ellipse_tangent(self):
""" Test 4. Set tangency between B-spline and an ellipse
self.myDOF += 5
model.do()
- self.mySketch.setTangent(self.mySpline.result(), anEllipse.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), anEllipse.defaultResult())
+ model.end()
- self.assertTangentFeatures(anEllipse, self.mySpline)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_elliptic_arc_tangent(self):
""" Test 5. Set tangency between B-spline and an elliptic arc
self.myDOF += 7
model.do()
- self.mySketch.setTangent(self.mySpline.result(), anEllipticArc.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), anEllipticArc.defaultResult())
+ model.end()
- self.assertTangentFeatures(anEllipticArc, self.mySpline)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_spline_tangent(self):
""" Test 6. Set tangency between two B-spline curves
self.myDOF += aSpline.poles().size() * 2
model.do()
- self.mySketch.setTangent(self.mySpline.result(), aSpline.result())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), aSpline.result())
+ model.end()
- #self.assertTangentFeatures(aSpline, self.mySpline)
- self.myExpectedFailure = True
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_line_tangent_coincident_by_pole(self):
self.myDOF -= 1
model.do()
- self.mySketch.setTangent(self.mySpline.result(), aLine.result())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), aLine.result())
+ model.end()
- self.assertPointLineDistance(self.mySpline.startPoint(), aLine)
- self.assertTangentFeatures(aLine, self.mySpline)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_circle_tangent_coincident_by_pole(self):
""" Test 8. Set tangency between B-spline and a circle coincident with B-spline end point
self.myDOF -= 1
model.do()
- self.mySketch.setTangent(self.mySpline.result(), aCircle.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), aCircle.defaultResult())
+ model.end()
- self.assertTangentFeatures(aCircle, self.mySpline)
- dist = model.distancePointPoint(self.mySpline.startPoint(), aCircle.center())
- self.assertAlmostEqual(dist, aCircle.radius().value())
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_arc_tangent_coincident_by_pole(self):
""" Test 9. Set tangency between B-spline and an arc coincident with B-spline end point
self.myDOF -= 1
model.do()
- self.mySketch.setTangent(self.mySpline.result(), anArc.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), anArc.defaultResult())
+ model.end()
- self.assertTangentFeatures(anArc, self.mySpline)
- dist = model.distancePointPoint(self.mySpline.endPoint(), anArc.center())
- self.assertAlmostEqual(dist, anArc.radius().value())
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_ellipse_tangent_coincident_by_pole(self):
""" Test 10. Set tangency between B-spline and an ellipse coincident with B-spline start point
self.myDOF -= 1
model.do()
- self.mySketch.setTangent(self.mySpline.result(), anEllipse.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), anEllipse.defaultResult())
+ model.end()
- self.assertTangentLineEllipse(SketchAPI_Line(self.myControlLines[0]), anEllipse)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_elliptic_arc_tangent_coincident_by_pole(self):
""" Test 11. Set tangency between B-spline and an elliptic arc coincident with B-spline start point
self.myDOF -= 1
model.do()
- self.mySketch.setTangent(self.mySpline.result(), anEllipticArc.defaultResult())
- self.myNbTangency += 1
- self.myDOF -= 1
- model.do()
+ aTangency = self.mySketch.setTangent(self.mySpline.result(), anEllipticArc.defaultResult())
+ model.end()
- self.assertTangentLineEllipse(SketchAPI_Line(self.myControlLines[0]), anEllipticArc)
+ self.assertNotEqual(aTangency.feature().error(), "")
+ model.undo()
+ model.begin()
def test_line_tangent_coincident_by_boundaries(self):
#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_Ellipse2d.h>
+#include <GeomDataAPI_Point2DArray.h>
+
#include <ModelAPI_AttributeInteger.h>
#include <SketchPlugin_Arc.h>
{
std::set<FeaturePtr> aCoincidences = collectCoincidences(theFeature1, theFeature2);
// collect points only
- std::set<AttributePtr> aCoincidentPoints;
+ std::map<FeaturePtr, std::set<AttributePtr> > aCoincidentPoints;
std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
for (; aCIt != aCoincidences.end(); ++ aCIt) {
for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
FeaturePtr anOwner = ModelAPI_Feature::feature(anAttr->owner());
if (anOwner == theFeature1 || anOwner == theFeature2) {
if (anAttr->id() == SketchPlugin_BSplineBase::POLES_ID()) {
- AttributeIntegerPtr anIndex = (*aCIt)->integer(i == 0 ?
- SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() :
- SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B());
+ AttributePoint2DArrayPtr aPoles =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(anAttr);
+
+ AttributeIntegerPtr anIndex;
+ if (anOwner->getKind() == SketchPlugin_BSpline::ID()) {
+ anIndex = (*aCIt)->integer(i == 0 ?
+ SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() :
+ SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B());
+ }
if (anIndex) {
if (anIndex->value() == 0)
anAttr = anOwner->attribute(SketchPlugin_BSpline::START_ID());
- else
+ else if (anIndex->value() + 1 == aPoles->size())
anAttr = anOwner->attribute(SketchPlugin_BSpline::END_ID());
if (anAttr)
- aCoincidentPoints.insert(anAttr);
+ aCoincidentPoints[anOwner].insert(anAttr);
}
}
else if (anAttr->id() != SketchPlugin_Arc::CENTER_ID() &&
anAttr->id() != SketchPlugin_Circle::CENTER_ID())
- aCoincidentPoints.insert(anAttr);
+ aCoincidentPoints[anOwner].insert(anAttr);
}
}
}
- return aCoincidentPoints;
+
+ std::set<AttributePtr> aBoundaryPoints;
+ if (aCoincidentPoints.size() == 2) {
+ for (std::map<FeaturePtr, std::set<AttributePtr> >::iterator anIt = aCoincidentPoints.begin();
+ anIt != aCoincidentPoints.end(); ++anIt)
+ aBoundaryPoints.insert(anIt->second.begin(), anIt->second.end());
+ }
+ return aBoundaryPoints;
}
static std::set<AttributePtr> refsToFeatureAndResults(FeaturePtr theFeature)