Salome HOME
Issue #2171: Avoid error message appears for tangency constraint
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintFixed.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 #include <SketchSolver_ConstraintFixed.h>
4 #include <SketchSolver_Error.h>
5
6 #include <PlaneGCSSolver_ConstraintWrapper.h>
7 #include <PlaneGCSSolver_EdgeWrapper.h>
8 #include <PlaneGCSSolver_EntityDestroyer.h>
9 #include <PlaneGCSSolver_FeatureBuilder.h>
10 #include <PlaneGCSSolver_PointWrapper.h>
11
12 #include <GeomDataAPI_Point2D.h>
13 #include <SketchPlugin_Feature.h>
14
15 #include <cmath>
16
17 // Verify the entities are equal
18 static bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
19 // Convert entity to the list of parameters
20 static GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity);
21
22
23 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
24   : SketchSolver_Constraint(theConstraint)
25 {
26   myType = CONSTRAINT_FIXED;
27 }
28
29 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
30   : SketchSolver_Constraint(),
31     myBaseFeature(theFeature)
32 {
33   myType = CONSTRAINT_FIXED;
34 }
35
36 void SketchSolver_ConstraintFixed::blockEvents(bool isBlocked)
37 {
38   if (myBaseFeature)
39     myBaseFeature->data()->blockSendAttributeUpdated(isBlocked);
40   if (myBaseConstraint)
41     SketchSolver_Constraint::blockEvents(isBlocked);
42 }
43
44 void SketchSolver_ConstraintFixed::process()
45 {
46   cleanErrorMsg();
47   if ((!myBaseConstraint && !myBaseFeature) || !myStorage) {
48     // Not enough parameters are assigned
49     return;
50   }
51
52   EntityWrapperPtr aBaseEntity;
53   getAttributes(aBaseEntity, myFixedEntity);
54   if (!aBaseEntity) {
55     moveFeature(); // remove myFixed entity
56     myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
57   }
58   if (!myErrorMsg.empty())
59     return;
60
61   fixFeature(aBaseEntity);
62 }
63
64 void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
65 {
66   GCS::VEC_pD aParameters = toParameters(theFeature);
67
68   // Fix given list of parameters
69   std::list<GCSConstraintPtr> aConstraints;
70   myFixedValues.reserve(aParameters.size());
71   GCS::VEC_pD::const_iterator anIt = aParameters.begin();
72   for (int i = 0; anIt != aParameters.end(); ++anIt, ++i) {
73     myFixedValues.push_back(**anIt);
74     aConstraints.push_back(
75         GCSConstraintPtr(new GCS::ConstraintEqual(&myFixedValues[i], *anIt)));
76   }
77
78   myConstraint = ConstraintWrapperPtr(
79       new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
80
81   if (myBaseConstraint)
82     myStorage->addConstraint(myBaseConstraint, myConstraint);
83   else
84     myStorage->addTemporaryConstraint(myConstraint);
85 }
86
87 void SketchSolver_ConstraintFixed::getAttributes(EntityWrapperPtr& theBaseEntity,
88                                                  EntityWrapperPtr& theFixedEntity)
89 {
90   if (myBaseFeature) {
91     // if the feature is copy, do not move it
92     std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
93         std::dynamic_pointer_cast<SketchPlugin_Feature>(myBaseFeature);
94     if (aSketchFeature && aSketchFeature->isCopy()) {
95       myStorage->setNeedToResolve(true);
96       return;
97     }
98
99     // The feature is fixed.
100     PlaneGCSSolver_FeatureBuilder aBuilder;
101     std::list<AttributePtr> aBaseAttr = myBaseFeature->data()->attributes(std::string());
102     std::list<AttributePtr>::const_iterator anIt = aBaseAttr.begin();
103     for (; anIt != aBaseAttr.end(); ++anIt)
104       aBuilder.createAttribute(*anIt);
105     theFixedEntity = aBuilder.createFeature(myBaseFeature);
106
107     theBaseEntity = myStorage->entity(myBaseFeature);
108     if (isEqual(theBaseEntity, theFixedEntity))
109       theBaseEntity = EntityWrapperPtr(); // do not want to fix already fixed entity
110
111   } else if (myBaseConstraint) {
112     // Constraint Fixed is added by user.
113     // Get the attribute of constraint (it should be alone in the list of constraints).
114     EntityWrapperPtr aValue;
115     std::vector<EntityWrapperPtr> anAttributes;
116     SketchSolver_Constraint::getAttributes(aValue, anAttributes);
117     std::vector<EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
118     for (; anIt != anAttributes.end(); ++anIt)
119       if (*anIt)
120         theBaseEntity = *anIt;
121   } else
122     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
123 }
124
125 void SketchSolver_ConstraintFixed::moveFeature()
126 {
127   if (!myFixedEntity)
128     return;
129
130   GCS::VEC_pD aFixedParams = toParameters(myFixedEntity);
131   for (int i = 0; i < aFixedParams.size() && i < myFixedValues.size(); ++i)
132     myFixedValues[i] = *(aFixedParams[i]);
133
134   // Remove fixed entity due to its parameters already copied into the constraint
135   PlaneGCSSolver_EntityDestroyer aDestroyer;
136   aDestroyer.remove(myFixedEntity);
137   std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage)->removeParameters(
138       aDestroyer.parametersToRemove());
139
140   myFixedEntity = EntityWrapperPtr();
141 }
142
143
144
145
146 // ====================   Auxiliary functions   ===============================
147 GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity)
148 {
149   GCS::VEC_pD aParameters;
150   if (!theEntity)
151     return aParameters;
152
153   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
154       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
155
156   // Collect parameters for each type of entity
157   switch (theEntity->type()) {
158   case ENTITY_POINT: {
159     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
160         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
161     aParameters.push_back(aPoint->point()->x);
162     aParameters.push_back(aPoint->point()->y);
163     break;
164     }
165   case ENTITY_LINE: {
166     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
167     aParameters.push_back(aLine->p1.x);
168     aParameters.push_back(aLine->p1.y);
169     aParameters.push_back(aLine->p2.x);
170     aParameters.push_back(aLine->p2.y);
171     break;
172     }
173   case ENTITY_CIRCLE: {
174     std::shared_ptr<GCS::Circle> aCircle =
175         std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
176     aParameters.push_back(aCircle->center.x);
177     aParameters.push_back(aCircle->center.y);
178     aParameters.push_back(aCircle->rad);
179     break;
180     }
181   case ENTITY_ARC: {
182     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
183     aParameters.push_back(anArc->center.x);
184     aParameters.push_back(anArc->center.y);
185     aParameters.push_back(anArc->rad);
186     aParameters.push_back(anArc->startAngle);
187     aParameters.push_back(anArc->endAngle);
188     break;
189     }
190   default:
191     break;
192   }
193
194   return aParameters;
195 }
196
197 bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2)
198 {
199   GCS::VEC_pD aParamList1 = toParameters(theEntity1);
200   GCS::VEC_pD aParamList2 = toParameters(theEntity2);
201
202   GCS::VEC_pD::const_iterator anIt1 = aParamList1.begin();
203   GCS::VEC_pD::const_iterator anIt2 = aParamList2.begin();
204   for (; anIt1 != aParamList1.end() && anIt2 != aParamList2.end(); ++anIt1, ++anIt2)
205     if (fabs((**anIt1) - (**anIt2)) > tolerance)
206       return false;
207
208   return anIt1 == aParamList1.end() && anIt2 == aParamList2.end();
209 }