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