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