Salome HOME
Fix problem with unit tests on CentOS
[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_PointWrapper.h>
9
10 #include <GeomDataAPI_Point2D.h>
11 #include <SketchPlugin_Feature.h>
12
13 #include <cmath>
14
15 // Find parameters of the feature that have been updated during the movement
16 static EntityWrapperPtr getChangedEntity(const FeaturePtr& theFeature,
17                                          const StoragePtr& theStorage);
18
19
20 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
21   : SketchSolver_Constraint(theConstraint)
22 {
23   myType = CONSTRAINT_FIXED;
24 }
25
26 SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
27   : SketchSolver_Constraint(),
28     myBaseFeature(theFeature)
29 {
30   myType = CONSTRAINT_FIXED;
31 }
32
33 void SketchSolver_ConstraintFixed::blockEvents(bool isBlocked)
34 {
35   if (myBaseFeature)
36     myBaseFeature->data()->blockSendAttributeUpdated(isBlocked);
37   if (myBaseConstraint)
38     SketchSolver_Constraint::blockEvents(isBlocked);
39 }
40
41 void SketchSolver_ConstraintFixed::process()
42 {
43   cleanErrorMsg();
44   if ((!myBaseConstraint && !myBaseFeature) || !myStorage) {
45     // Not enough parameters are assigned
46     return;
47   }
48
49   EntityWrapperPtr aValue;
50   std::vector<EntityWrapperPtr> anEntities;
51   getAttributes(aValue, anEntities);
52   if (anEntities.empty())
53     myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
54   if (!myErrorMsg.empty())
55     return;
56   fixFeature(anEntities.front());
57 }
58
59 void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
60 {
61   std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
62       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theFeature);
63
64   GCS::VEC_pD aParameters; // parameters of entity to be fixed
65
66   // Collect parameters for each type of entity
67   switch (theFeature->type()) {
68   case ENTITY_POINT: {
69     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
70         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theFeature);
71     aParameters.push_back(aPoint->point()->x);
72     aParameters.push_back(aPoint->point()->y);
73     break;
74     }
75   case ENTITY_LINE: {
76     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
77     aParameters.push_back(aLine->p1.x);
78     aParameters.push_back(aLine->p1.y);
79     aParameters.push_back(aLine->p2.x);
80     aParameters.push_back(aLine->p2.y);
81     break;
82     }
83   case ENTITY_CIRCLE: {
84     std::shared_ptr<GCS::Circle> aCircle =
85         std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
86     aParameters.push_back(aCircle->center.x);
87     aParameters.push_back(aCircle->center.y);
88     aParameters.push_back(aCircle->rad);
89     break;
90     }
91   case ENTITY_ARC: {
92     myFixedValues.reserve(4);
93     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
94     aParameters.push_back(anArc->center.x);
95     aParameters.push_back(anArc->center.y);
96     aParameters.push_back(anArc->rad);
97     aParameters.push_back(anArc->startAngle);
98     aParameters.push_back(anArc->endAngle);
99     break;
100     }
101   default:
102     break;
103   }
104
105   // Fix given list of parameters
106   std::list<GCSConstraintPtr> aConstraints;
107   myFixedValues.reserve(aParameters.size());
108   GCS::VEC_pD::const_iterator anIt = aParameters.begin();
109   for (int i = 0; anIt != aParameters.end(); ++anIt, ++i) {
110     myFixedValues.push_back(**anIt);
111     aConstraints.push_back(
112         GCSConstraintPtr(new GCS::ConstraintEqual(*anIt, &myFixedValues[i])));
113   }
114
115   myConstraint = ConstraintWrapperPtr(
116       new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
117
118   if (myBaseConstraint)
119     myStorage->addConstraint(myBaseConstraint, myConstraint);
120   else
121     myStorage->addTemporaryConstraint(myConstraint);
122 }
123
124 void SketchSolver_ConstraintFixed::getAttributes(
125     EntityWrapperPtr& theValue,
126     std::vector<EntityWrapperPtr>& theAttributes)
127 {
128   if (myBaseFeature) {
129     // if the feature is copy, do not move it
130     std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
131         std::dynamic_pointer_cast<SketchPlugin_Feature>(myBaseFeature);
132     if (aSketchFeature && aSketchFeature->isCopy()) {
133       myStorage->setNeedToResolve(true);
134       return;
135     }
136
137     // The feature is fixed.
138     EntityWrapperPtr aSolverEntity = getChangedEntity(myBaseFeature, myStorage);
139     myStorage->update(myBaseFeature);
140     if (aSolverEntity)
141       theAttributes.push_back(aSolverEntity);
142   } else if (myBaseConstraint) {
143     // Constraint Fixed is added by user.
144     // Get the attribute of constraint (it should be alone in the list of constraints).
145     std::vector<EntityWrapperPtr> anAttributes;
146     SketchSolver_Constraint::getAttributes(theValue, anAttributes);
147     std::vector<EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
148     for (; anIt != anAttributes.end(); ++anIt)
149       if (*anIt)
150         theAttributes.push_back(*anIt);
151   } else
152     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
153 }
154
155
156
157
158 // ====================   Auxiliary functions   ===============================
159 static bool isSameCoordinates(const AttributePoint2DPtr& thePointAttr,
160                               const PointWrapperPtr& thePointWrapper)
161 {
162   GCSPointPtr aGCSPoint = thePointWrapper->point();
163   return fabs(*aGCSPoint->x - thePointAttr->x()) < tolerance &&
164          fabs(*aGCSPoint->y - thePointAttr->y()) < tolerance;
165 }
166
167 EntityWrapperPtr getChangedEntity(const FeaturePtr& theFeature,
168                                   const StoragePtr& theStorage)
169 {
170   std::list<AttributePtr> aPoints = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
171   std::list<EntityWrapperPtr> aChangedPoints;
172
173   std::list<AttributePtr>::const_iterator aPIt = aPoints.begin();
174   for (; aPIt != aPoints.end(); ++aPIt) {
175     AttributePoint2DPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPIt);
176     EntityWrapperPtr anEnt = theStorage->entity(*aPIt);
177     if (anEnt) {
178       PointWrapperPtr aPW = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anEnt);
179       if (!isSameCoordinates(aPnt, aPW))
180         aChangedPoints.push_back(anEnt);
181     } else {
182       theStorage->update(*aPIt);
183       aChangedPoints.push_back(theStorage->entity(*aPIt));
184     }
185   }
186
187   EntityWrapperPtr aChanged;
188   if (aChangedPoints.size() == 1)
189     aChanged = aChangedPoints.front();
190   else if (!aChangedPoints.empty()) // update whole feature
191     aChanged = theStorage->entity(theFeature);
192   return aChanged;
193 }