]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_ConstraintMulti.cpp
Salome HOME
Protect "Multi" constraint if it already removed (issue #1790)
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMulti.cpp
1 #include <SketchSolver_ConstraintMulti.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Manager.h>
4
5 #include <GeomDataAPI_Point2D.h>
6 #include <ModelAPI_AttributeInteger.h>
7 #include <ModelAPI_AttributeRefAttr.h>
8 #include <ModelAPI_AttributeRefList.h>
9 #include <SketchPlugin_Arc.h>
10 #include <SketchPlugin_Circle.h>
11 #include <SketchPlugin_Line.h>
12 #include <SketchPlugin_Point.h>
13 #include <SketchPlugin_IntersectionPoint.h>
14
15 void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
16 {
17   myAdjusted = false;
18   DataPtr aData = myBaseConstraint->data();
19
20   // Lists of objects and number of copies
21   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
22       aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
23   myNumberOfObjects = anInitialRefList->size();
24   myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
25   if (myNumberOfCopies <= 0)
26     return;
27
28   AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
29       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
30   if (!aRefList || aRefList->size() == 0) {
31     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
32     return;
33   }
34
35   FeaturePtr aFeature;
36   std::list<ObjectPtr> anObjectList = aRefList->list();
37   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
38   if ((myNumberOfCopies + 1) * myNumberOfObjects != aRefList->size()) // execute for the feature is not called yet
39     myNumberOfCopies = aRefList->size() / myNumberOfObjects - 1;
40
41   while (anObjIt != anObjectList.end()) {
42     aFeature = ModelAPI_Feature::feature(*anObjIt++);
43     if (!aFeature)
44       continue;
45
46     if (!myStorage->update(aFeature)) // the entity is not created, so it is a copy in "multi" constraint, force its creation
47       myStorage->update(aFeature, myGroupID, true);
48     theEntities.push_back(myStorage->entity(aFeature));
49     myFeatures.insert(aFeature);
50     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
51       // just add copied features into the list of objects
52       aFeature = ModelAPI_Feature::feature(*anObjIt);
53       if (aFeature)
54         myFeatures.insert(aFeature);
55     }
56   }
57 }
58
59 bool SketchSolver_ConstraintMulti::remove()
60 {
61   myFeatures.clear();
62   return SketchSolver_Constraint::remove();
63 }
64
65 void SketchSolver_ConstraintMulti::update()
66 {
67   update(false);
68 }
69
70 void SketchSolver_ConstraintMulti::update(bool isForce)
71 {
72   cleanErrorMsg();
73   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
74       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
75   AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
76   if (!anInitialRefList || !aNbObjects)
77     return; // the "Multi" constraint is in queue to remove
78   bool isUpdated= anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
79   if (!isUpdated) {
80     // additional check that the features and their copies are changed
81     AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
82         myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
83     if (aRefList && aRefList->size() != 0) {
84       FeaturePtr aFeature;
85       std::list<ObjectPtr> anObjectList = aRefList->list();
86       std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
87       for (; anObjIt != anObjectList.end(); ++anObjIt) {
88         aFeature = ModelAPI_Feature::feature(*anObjIt);
89         if (aFeature && myFeatures.find(aFeature) == myFeatures.end()) {
90           isUpdated = true;
91           break;
92         }
93       }
94     } else
95       isUpdated = true;
96   }
97   if (isUpdated) {
98     remove();
99     process();
100     return;
101   }
102
103   // update derivative object
104   updateLocal();
105   if (isForce)
106     myAdjusted = false;
107   adjustConstraint();
108 }
109
110 void SketchSolver_ConstraintMulti::adjustConstraint()
111 {
112   AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
113       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
114   if (!aRefList || aRefList->size() == 0) {
115     myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
116     return;
117   }
118
119   FeaturePtr anOriginal, aFeature;
120   std::list<ObjectPtr> anObjectList = aRefList->list();
121   std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
122   while (anObjIt != anObjectList.end()) {
123     anOriginal = ModelAPI_Feature::feature(*anObjIt++);
124     if (!anOriginal)
125       continue;
126
127     // Fill lists of coordinates of points composing a feature
128     std::list<double> aX, aY;
129     std::list<double>::iterator aXIt, aYIt;
130     double aXCoord, aYCoord;
131     EntityWrapperPtr anEntity = myStorage->entity(anOriginal);
132     std::list<EntityWrapperPtr> aSubs = anEntity->subEntities();
133     std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
134     for (; aSIt != aSubs.end(); ++aSIt) {
135       if ((*aSIt)->type() != ENTITY_POINT)
136         continue;
137       AttributePoint2DPtr aPoint =
138           std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSIt)->baseAttribute());
139       if (aPoint) {
140         aXCoord = aPoint->x();
141         aYCoord = aPoint->y();
142       } else {
143         std::list<ParameterWrapperPtr> aParameters = (*aSIt)->parameters();
144         aXCoord = aParameters.front()->value();
145         aYCoord = aParameters.back()->value();
146       }
147       getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
148       aX.push_back(aXCoord);
149       aY.push_back(aYCoord);
150     }
151
152     // Calculate positions of copied features
153     for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
154       aFeature = ModelAPI_Feature::feature(*anObjIt);
155       if (!aFeature)
156         continue;
157       anEntity = myStorage->entity(aFeature);
158
159       if (!anEntity || !myStorage->isEventsBlocked())
160         aFeature->data()->blockSendAttributeUpdated(true);
161
162       std::list<AttributePtr> aPoints;
163       if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
164         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
165         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::START_ID()));
166         aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::END_ID()));
167       } else if (aFeature->getKind() == SketchPlugin_Line::ID()) {
168         aPoints.push_back(aFeature->attribute(SketchPlugin_Line::START_ID()));
169         aPoints.push_back(aFeature->attribute(SketchPlugin_Line::END_ID()));
170       } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
171         aPoints.push_back(aFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
172         // update circle's radius
173         aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
174             anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
175       } else if (aFeature->getKind() == SketchPlugin_Point::ID() ||
176                aFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
177         aPoints.push_back(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
178
179       std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
180       for (aXIt = aX.begin(), aYIt = aY.begin(); aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
181         transformRelative(*aXIt, *aYIt);
182         getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
183
184         std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
185             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
186         aPoint2D->setValue(aXCoord, aYCoord);
187       }
188
189       // update feature in the storage if it is used by another constraints
190       if (anEntity)
191         myStorage->update(aFeature);
192       else { // update attributes, if they exist in the storage
193         for (aPtIt = aPoints.begin(); aPtIt != aPoints.end(); ++aPtIt) {
194           EntityWrapperPtr aPntEnt = myStorage->entity(*aPtIt);
195           if (aPntEnt)
196             myStorage->update(*aPtIt);
197         }
198       }
199
200       if (!anEntity || !myStorage->isEventsBlocked())
201         aFeature->data()->blockSendAttributeUpdated(false);
202     }
203   }
204
205   myAdjusted = true;
206 }
207
208 bool SketchSolver_ConstraintMulti::isUsed(FeaturePtr theFeature) const
209 {
210   return theFeature && (myFeatures.find(theFeature) != myFeatures.end() ||
211          SketchSolver_Constraint::isUsed(theFeature));
212 }
213
214 bool SketchSolver_ConstraintMulti::isUsed(AttributePtr theAttribute) const
215 {
216   AttributePtr anAttribute = theAttribute;
217   AttributeRefAttrPtr aRefAttr =
218       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
219   if (aRefAttr) {
220     if (aRefAttr->isObject())
221       return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
222     else
223       anAttribute = aRefAttr->attr();
224   }
225   if (!anAttribute)
226     return false;
227
228   FeaturePtr anOwner = ModelAPI_Feature::feature(anAttribute->owner());
229   return myFeatures.find(anOwner) != myFeatures.end();
230 }