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