Salome HOME
Update test cases according to new Fillet API.
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintTangent.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 #include <SketchSolver_ConstraintTangent.h>
4 #include <SketchSolver_Error.h>
5
6 #include <PlaneGCSSolver_Tools.h>
7
8 #include <GeomAPI_Pnt2d.h>
9 #include <SketchPlugin_Circle.h>
10 #include <SketchPlugin_ConstraintCoincidence.h>
11
12 #include <cmath>
13
14
15 /// \brief Check whether the entities has only one shared point or less
16 static bool hasSingleCoincidence(FeaturePtr theFeature1, FeaturePtr theFeature2)
17 {
18   const std::set<AttributePtr>& aRefs1 = theFeature1->data()->refsToMe();
19   const std::set<AttributePtr>& aRefs2 = theFeature2->data()->refsToMe();
20
21   // collect all shared coincidendes
22   std::set<FeaturePtr> aCoincidences;
23   std::set<AttributePtr>::const_iterator anIt;
24   for (anIt = aRefs1.begin(); anIt != aRefs1.end(); ++anIt) {
25     FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
26     if (aRef && aRef->getKind() == SketchPlugin_ConstraintCoincidence::ID())
27       aCoincidences.insert(aRef);
28   }
29   int aNbCoinCidentPoints = 0;
30   for (anIt = aRefs2.begin(); anIt != aRefs2.end(); ++anIt) {
31     FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
32     if (aCoincidences.find(aRef) != aCoincidences.end())
33       ++aNbCoinCidentPoints;
34   }
35
36   return aNbCoinCidentPoints <= 1;
37 }
38
39 void SketchSolver_ConstraintTangent::getAttributes(
40     EntityWrapperPtr& theValue,
41     std::vector<EntityWrapperPtr>& theAttributes)
42 {
43   SketchSolver_Constraint::getAttributes(theValue, theAttributes);
44   if (!myErrorMsg.empty() || !theAttributes[2] || !theAttributes[3]) {
45     theAttributes.clear();
46     return;
47   }
48
49   // Check the quantity of entities of each type and their order (arcs first)
50   int aNbLines = 0;
51   int aNbCircles = 0;
52   std::vector<EntityWrapperPtr>::iterator anEntIt = theAttributes.begin() + 2;
53   for (; anEntIt != theAttributes.end(); ++anEntIt) {
54     if ((*anEntIt)->type() == ENTITY_LINE)
55       ++aNbLines;
56     else if ((*anEntIt)->type() == ENTITY_ARC || (*anEntIt)->type() == ENTITY_CIRCLE)
57       ++aNbCircles;
58   }
59
60   if (aNbCircles < 1) {
61     myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
62     return;
63   }
64   if (aNbLines == 1 && aNbCircles == 1) {
65     myType = CONSTRAINT_TANGENT_CIRCLE_LINE;
66   }
67   else if (aNbCircles == 2) {
68     myType = CONSTRAINT_TANGENT_CIRCLE_CIRCLE;
69     isArcArcInternal =
70         PlaneGCSSolver_Tools::isArcArcTangencyInternal(theAttributes[2], theAttributes[3]);
71   }
72   else {
73     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
74     return;
75   }
76
77   if (myType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
78     AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
79     FeaturePtr aFeature1 = ModelAPI_Feature::feature(aRefAttr->object());
80     aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
81     FeaturePtr aFeature2 = ModelAPI_Feature::feature(aRefAttr->object());
82
83     if (!hasSingleCoincidence(aFeature1, aFeature2))
84       myErrorMsg = SketchSolver_Error::TANGENCY_FAILED();
85   }
86 }
87
88 void SketchSolver_ConstraintTangent::adjustConstraint()
89 {
90   if (myType == CONSTRAINT_TANGENT_CIRCLE_CIRCLE) {
91     EntityWrapperPtr anEntity1 =
92         myStorage->entity(myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
93     EntityWrapperPtr anEntity2 =
94         myStorage->entity(myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
95
96     if (isArcArcInternal != PlaneGCSSolver_Tools::isArcArcTangencyInternal(anEntity1, anEntity2)) {
97       // fully rebuld constraint, because it is unable to access attributes of PlaneGCS constraint
98       remove();
99       process();
100     }
101   }
102 }