1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 #include <SketchSolver_ConstraintTangent.h>
4 #include <SketchSolver_Error.h>
5 #include <SketchSolver_Manager.h>
7 #include <GeomAPI_Pnt2d.h>
8 #include <SketchPlugin_Circle.h>
9 #include <SketchPlugin_ConstraintCoincidence.h>
14 /// \brief Check whether the entities has only one shared point or less
15 static bool hasSingleCoincidence(FeaturePtr theFeature1, FeaturePtr theFeature2)
17 const std::set<AttributePtr>& aRefs1 = theFeature1->data()->refsToMe();
18 const std::set<AttributePtr>& aRefs2 = theFeature2->data()->refsToMe();
20 // collect all shared coincidendes
21 std::set<FeaturePtr> aCoincidences;
22 std::set<AttributePtr>::const_iterator anIt;
23 for (anIt = aRefs1.begin(); anIt != aRefs1.end(); ++anIt) {
24 FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
25 if (aRef && aRef->getKind() == SketchPlugin_ConstraintCoincidence::ID())
26 aCoincidences.insert(aRef);
28 for (anIt = aRefs2.begin(); anIt != aRefs2.end(); ++anIt) {
29 FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
31 aCoincidences.erase(aRef);
34 return aCoincidences.size() <= 1;
37 /// \brief Check if two connected arcs have centers
38 /// in same direction relatively to connection point
39 static bool isInternalTangency(EntityWrapperPtr theEntity1, EntityWrapperPtr theEntity2)
41 BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
42 return aBuilder->isArcArcTangencyInternal(theEntity1, theEntity2);
46 void SketchSolver_ConstraintTangent::getAttributes(
47 EntityWrapperPtr& theValue,
48 std::vector<EntityWrapperPtr>& theAttributes)
50 SketchSolver_Constraint::getAttributes(theValue, theAttributes);
51 if (!myErrorMsg.empty() || !theAttributes[2] || !theAttributes[3]) {
52 theAttributes.clear();
56 // Check the quantity of entities of each type and their order (arcs first)
60 bool isSwap = false; // whether need to swap arguments (arc goes before line)
61 std::vector<EntityWrapperPtr>::iterator anEntIt = theAttributes.begin() + 2;
62 for (; anEntIt != theAttributes.end(); ++anEntIt) {
63 if ((*anEntIt)->type() == ENTITY_LINE)
65 else if ((*anEntIt)->type() == ENTITY_ARC) {
67 isSwap = aNbLines > 0;
69 else if ((*anEntIt)->type() == ENTITY_CIRCLE) {
71 isSwap = aNbLines > 0;
75 if (aNbArcs < 1 && aNbCircles < 1) {
76 myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
81 myType = CONSTRAINT_TANGENT_ARC_LINE;
82 else if (aNbCircles == 1)
83 myType = CONSTRAINT_TANGENT_CIRCLE_LINE;
85 else if (aNbArcs == 2) {
86 myType = CONSTRAINT_TANGENT_ARC_ARC;
87 isArcArcInternal = isInternalTangency(theAttributes[2], theAttributes[3]);
90 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
94 if (myType == CONSTRAINT_TANGENT_ARC_LINE) {
95 AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
96 FeaturePtr aFeature1 = ModelAPI_Feature::feature(aRefAttr->object());
97 aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
98 FeaturePtr aFeature2 = ModelAPI_Feature::feature(aRefAttr->object());
100 if (!hasSingleCoincidence(aFeature1, aFeature2))
101 myErrorMsg = SketchSolver_Error::TANGENCY_FAILED();
105 EntityWrapperPtr aTemp = theAttributes[2];
106 theAttributes[2] = theAttributes[3];
107 theAttributes[3] = aTemp;
111 void SketchSolver_ConstraintTangent::adjustConstraint()
113 if (myType == CONSTRAINT_TANGENT_ARC_ARC) {
114 EntityWrapperPtr anEntity1 =
115 myStorage->entity(myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
116 EntityWrapperPtr anEntity2 =
117 myStorage->entity(myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
119 if (isArcArcInternal != isInternalTangency(anEntity1, anEntity2)) {
120 // fully rebuld constraint, because it is unable to access attributes of PlaneGCS constraint