Salome HOME
Merge remote-tracking branch 'remotes/origin/master'
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintFixed.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <SketchSolver_ConstraintFixed.h>
22 #include <SketchSolver_Error.h>
23
24 #include <PlaneGCSSolver_ConstraintWrapper.h>
25 #include <PlaneGCSSolver_EdgeWrapper.h>
26 #include <PlaneGCSSolver_EntityDestroyer.h>
27 #include <PlaneGCSSolver_FeatureBuilder.h>
28 #include <PlaneGCSSolver_PointWrapper.h>
29
30 #include <GeomDataAPI_Point2D.h>
31 #include <SketchPlugin_Feature.h>
32
33 #include <cmath>
34
35 // Verify the points are equal
36 static bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2);
37 // Verify the entities are equal
38 static bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
39 // Convert entity to the list of parameters
40 static GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity);
41
42
43 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
44   : SketchSolver_Constraint(theConstraint)
45 {
46   myType = CONSTRAINT_FIXED;
47 }
48
49 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
50   : SketchSolver_Constraint(),
51     myBaseFeature(theFeature)
52 {
53   myType = CONSTRAINT_FIXED;
54 }
55
56 void SketchSolver_ConstraintFixed::blockEvents(bool isBlocked)
57 {
58   if (myBaseFeature)
59     myBaseFeature->data()->blockSendAttributeUpdated(isBlocked);
60   if (myBaseConstraint)
61     SketchSolver_Constraint::blockEvents(isBlocked);
62 }
63
64 void SketchSolver_ConstraintFixed::process()
65 {
66   cleanErrorMsg();
67   if ((!myBaseConstraint && !myBaseFeature) || !myStorage) {
68     // Not enough parameters are assigned
69     return;
70   }
71
72   EntityWrapperPtr aBaseEntity;
73   getAttributes(aBaseEntity, myFixedEntity);
74   if (!aBaseEntity) {
75     moveFeature(); // remove myFixed entity
76     myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
77   }
78   if (!myErrorMsg.empty())
79     return;
80
81   fixFeature(aBaseEntity);
82 }
83
84 void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
85 {
86   GCS::VEC_pD aParameters = toParameters(theFeature);
87
88   // Fix given list of parameters
89   std::list<GCSConstraintPtr> aConstraints;
90   myFixedValues.reserve(aParameters.size());
91   GCS::VEC_pD::const_iterator anIt = aParameters.begin();
92   for (int i = 0; anIt != aParameters.end(); ++anIt, ++i) {
93     myFixedValues.push_back(**anIt);
94     aConstraints.push_back(
95         GCSConstraintPtr(new GCS::ConstraintEqual(&myFixedValues[i], *anIt)));
96   }
97
98   myConstraint = ConstraintWrapperPtr(
99       new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
100
101   if (myBaseConstraint)
102     myStorage->addConstraint(myBaseConstraint, myConstraint);
103   else
104     myStorage->addTemporaryConstraint(myConstraint);
105 }
106
107 void SketchSolver_ConstraintFixed::getAttributes(EntityWrapperPtr& theBaseEntity,
108                                                  EntityWrapperPtr& theFixedEntity)
109 {
110   if (myBaseFeature) {
111     // if the feature is copy, do not move it
112     std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
113         std::dynamic_pointer_cast<SketchPlugin_Feature>(myBaseFeature);
114     if (aSketchFeature && aSketchFeature->isCopy()) {
115       myStorage->setNeedToResolve(true);
116       return;
117     }
118
119     bool fixFullFeature = false;
120     theBaseEntity = EntityWrapperPtr();
121     theFixedEntity = EntityWrapperPtr();
122
123     // The feature is fixed.
124     PlaneGCSSolver_FeatureBuilder aBuilder;
125     std::list<AttributePtr> aBaseAttr = myBaseFeature->data()->attributes(std::string());
126     std::list<AttributePtr>::const_iterator anIt = aBaseAttr.begin();
127     for (; anIt != aBaseAttr.end(); ++anIt) {
128       EntityWrapperPtr anEntity = aBuilder.createAttribute(*anIt);
129       EntityWrapperPtr aBaseEntity = myStorage->entity(*anIt);
130       if (!anEntity || !aBaseEntity)
131         continue;
132
133       if (!fixFullFeature && anEntity->type() == ENTITY_POINT &&
134           !isEqual(anEntity, aBaseEntity)) {
135         if (theFixedEntity)
136           fixFullFeature = true;
137         theFixedEntity = anEntity;
138         theBaseEntity = aBaseEntity;
139       }
140     }
141
142     if (fixFullFeature) {
143       theFixedEntity = aBuilder.createFeature(myBaseFeature);
144       theBaseEntity = myStorage->entity(myBaseFeature);
145       if (isEqual(theBaseEntity, theFixedEntity))
146         theBaseEntity = EntityWrapperPtr(); // do not want to fix already fixed entity
147     }
148
149   } else if (myBaseConstraint) {
150     // Constraint Fixed is added by user.
151     // Get the attribute of constraint (it should be alone in the list of constraints).
152     EntityWrapperPtr aValue;
153     std::vector<EntityWrapperPtr> anAttributes;
154     SketchSolver_Constraint::getAttributes(aValue, anAttributes);
155     std::vector<EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
156     for (; anIt != anAttributes.end(); ++anIt)
157       if (*anIt)
158         theBaseEntity = *anIt;
159   } else
160     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
161 }
162
163 void SketchSolver_ConstraintFixed::moveFeature()
164 {
165   if (!myFixedEntity)
166     return;
167
168   GCS::VEC_pD aFixedParams = toParameters(myFixedEntity);
169   for (int i = 0; i < aFixedParams.size() && i < myFixedValues.size(); ++i)
170     myFixedValues[i] = *(aFixedParams[i]);
171
172   // Remove fixed entity due to its parameters already copied into the constraint
173   PlaneGCSSolver_EntityDestroyer aDestroyer;
174   aDestroyer.remove(myFixedEntity);
175   std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage)->removeParameters(
176       aDestroyer.parametersToRemove());
177
178   myFixedEntity = EntityWrapperPtr();
179 }
180
181
182
183
184 // ====================   Auxiliary functions   ===============================
185 GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity)
186 {
187   GCS::VEC_pD aParameters;
188   if (!theEntity)
189     return aParameters;
190
191   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
192       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
193
194   // Collect parameters for each type of entity
195   switch (theEntity->type()) {
196   case ENTITY_POINT: {
197     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
198         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
199     aParameters.push_back(aPoint->point()->x);
200     aParameters.push_back(aPoint->point()->y);
201     break;
202     }
203   case ENTITY_LINE: {
204     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
205     aParameters.push_back(aLine->p1.x);
206     aParameters.push_back(aLine->p1.y);
207     aParameters.push_back(aLine->p2.x);
208     aParameters.push_back(aLine->p2.y);
209     break;
210     }
211   case ENTITY_CIRCLE: {
212     std::shared_ptr<GCS::Circle> aCircle =
213         std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
214     aParameters.push_back(aCircle->center.x);
215     aParameters.push_back(aCircle->center.y);
216     aParameters.push_back(aCircle->rad);
217     break;
218     }
219   case ENTITY_ARC: {
220     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
221     aParameters.push_back(anArc->center.x);
222     aParameters.push_back(anArc->center.y);
223     aParameters.push_back(anArc->rad);
224     aParameters.push_back(anArc->startAngle);
225     aParameters.push_back(anArc->endAngle);
226     break;
227     }
228   default:
229     break;
230   }
231
232   return aParameters;
233 }
234
235 bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
236 {
237   return fabs((*thePoint1.x) - (*thePoint2.x)) <= tolerance &&
238          fabs((*thePoint1.y) - (*thePoint2.y)) <= tolerance;
239 }
240
241 bool isEqual(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2)
242 {
243   GCS::VEC_pD aParamList1 = toParameters(theEntity1);
244   GCS::VEC_pD aParamList2 = toParameters(theEntity2);
245
246   GCS::VEC_pD::const_iterator anIt1 = aParamList1.begin();
247   GCS::VEC_pD::const_iterator anIt2 = aParamList2.begin();
248   for (; anIt1 != aParamList1.end() && anIt2 != aParamList2.end(); ++anIt1, ++anIt2)
249     if (fabs((**anIt1) - (**anIt2)) > tolerance)
250       return false;
251
252   return anIt1 == aParamList1.end() && anIt2 == aParamList2.end();
253 }