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