Salome HOME
#1123 Cancel constraint after preview: the edge does not go back to its previous...
[modules/shaper.git] / src / SketchSolver / SketchSolver_FeatureStorage.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    SketchSolver_FeatureStorage.cpp
4 // Created: 23 Mar 2015
5 // Author:  Artem ZHIDKOV
6
7 #include <SketchSolver_FeatureStorage.h>
8
9 #include <ModelAPI_AttributeRefAttr.h>
10 #include <ModelAPI_AttributeRefList.h>
11 #include <ModelAPI_ResultConstruction.h>
12 #include <GeomDataAPI_Point2D.h>
13
14 void SketchSolver_FeatureStorage::changeConstraint(ConstraintPtr theConstraint)
15 {
16   std::list<AttributePtr> anAttributes = theConstraint->data()->attributes(std::string());
17   std::list<AttributePtr>::iterator anIter = anAttributes.begin();
18   for (; anIter != anAttributes.end(); anIter++) {
19     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
20     if (aRefAttr) {
21       if (!aRefAttr->isObject()) {
22         changeAttribute(aRefAttr->attr(), theConstraint);
23         continue;
24       }
25       ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
26           aRefAttr->object());
27       FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
28           std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
29       if (aFeature)
30         changeFeature(aFeature, theConstraint);
31       continue;
32     }
33     AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
34     if (aRefList) {
35       std::list<ObjectPtr> aList = aRefList->list();
36       std::list<ObjectPtr>::iterator aListIter = aList.begin();
37       for (; aListIter != aList.end(); aListIter++) {
38         ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
39             *aListIter);
40         FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
41             std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
42         if (aFeature)
43           changeFeature(aFeature, theConstraint);
44       }
45       continue;
46     }
47     changeAttribute(*anIter, theConstraint);
48   }
49   myConstraints.insert(theConstraint);
50 }
51
52 void SketchSolver_FeatureStorage::removeConstraint(ConstraintPtr theConstraint)
53 {
54   DataPtr aData = theConstraint->data();
55   if (aData) { // Constraint has data. Iterate through its attributes and remove them
56     std::list<AttributePtr> anAttributes = aData->attributes(std::string());
57     std::list<AttributePtr>::iterator anIter = anAttributes.begin();
58     for (; anIter != anAttributes.end(); anIter++) {
59       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
60       if (aRefAttr) {
61         if (!aRefAttr->isObject()) {
62           removeAttribute(aRefAttr->attr(), theConstraint);
63           continue;
64         }
65         ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
66             aRefAttr->object());
67         FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
68             std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
69         if (aFeature)
70           removeFeature(aFeature, theConstraint);
71         continue;
72       }
73       AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
74       if (aRefList) {
75         std::list<ObjectPtr> aList = aRefList->list();
76         std::list<ObjectPtr>::iterator aListIter = aList.begin();
77         for (; aListIter != aList.end(); aListIter++) {
78           ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
79               *aListIter);
80           FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
81               std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
82           if (aFeature)
83             removeFeature(aFeature, theConstraint);
84         }
85         continue;
86       }
87       removeAttribute(*anIter, theConstraint);
88     }
89   } else { // Constraint has no data. Search the links on it in the lists of back references for features and attributes
90     std::set<ConstraintPtr>::iterator aCIter;
91     MapFeatureConstraint::iterator aFeatIter = myFeatures.begin();
92     while (aFeatIter != myFeatures.end()) {
93       aCIter = aFeatIter->second.find(theConstraint);
94       if (aCIter != aFeatIter->second.end()) {
95         FeaturePtr aFeature = aFeatIter->first;
96         aFeatIter++;
97         removeFeature(aFeature, theConstraint);
98         continue;
99       }
100       aFeatIter++;
101     }
102     std::set<FeaturePtr>::iterator aFIter;
103     MapAttributeFeature::iterator anAttrIter = myAttributes.begin();
104     while (anAttrIter != myAttributes.end()) {
105       aFIter = anAttrIter->second.find(theConstraint);
106       if (aFIter != anAttrIter->second.end()) {
107         anAttrIter->second.erase(aFIter);
108         if (anAttrIter->second.empty()) {
109           MapAttributeFeature::iterator aTmpIter = anAttrIter; // stores iterator for the next element, while the current is deleting
110           aTmpIter++;
111           myAttributes.erase(anAttrIter);
112           anAttrIter = aTmpIter;
113           continue;
114         }
115       }
116       anAttrIter++;
117     }
118   }
119   myConstraints.erase(theConstraint);
120 }
121
122 bool SketchSolver_FeatureStorage::isInteract(ConstraintPtr theConstraint) const
123 {
124   if (myConstraints.empty() || myConstraints.find(theConstraint) != myConstraints.end())
125     return true;
126
127   DataPtr aData = theConstraint->data();
128   if (!aData)
129     return false;
130
131   std::list<AttributePtr> anAttributes = aData->attributes(std::string());
132   std::list<AttributePtr>::iterator anIter = anAttributes.begin();
133   for (; anIter != anAttributes.end(); anIter++) {
134     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
135     if (aRefAttr) {
136       if (!aRefAttr->isObject()) {
137         if (isInteract(aRefAttr->attr()))
138           return true;
139         continue;
140       }
141       ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
142           aRefAttr->object());
143       FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
144           std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
145       if (aFeature)
146         if (isInteract(aFeature))
147           return true;
148       continue;
149     }
150     AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
151     if (aRefList) {
152       std::list<ObjectPtr> aList = aRefList->list();
153       std::list<ObjectPtr>::iterator aListIter = aList.begin();
154       for (; aListIter != aList.end(); aListIter++) {
155         ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
156             *aListIter);
157         FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
158             std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
159         if (aFeature)
160           if (isInteract(aFeature))
161             return true;
162       }
163       continue;
164     }
165     if (isInteract(*anIter))
166       return true;
167   }
168   return false;
169 }
170
171
172 void SketchSolver_FeatureStorage::changeFeature(FeaturePtr theFeature)
173 {
174   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
175   std::list<AttributePtr>::iterator anIter = anAttributes.begin();
176   for (; anIter != anAttributes.end(); anIter++) {
177     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
178     if (aRefAttr) {
179       if (!aRefAttr->isObject())
180         changeAttribute(aRefAttr->attr(), theFeature);
181       continue;
182     }
183     changeAttribute(*anIter, theFeature);
184   }
185   if (myFeatures.find(theFeature) == myFeatures.end())
186     myFeatures[theFeature] = std::set<ConstraintPtr>();
187 }
188
189 void SketchSolver_FeatureStorage::changeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint)
190 {
191   // Change all attributes of the feature
192   changeFeature(theFeature);
193   // Add back reference feature to constraint
194   myFeatures[theFeature].insert(theConstraint);
195 }
196
197 void SketchSolver_FeatureStorage::removeFeature(FeaturePtr theFeature)
198 {
199   MapFeatureConstraint::iterator aFeatIter = myFeatures.find(theFeature);
200   if (aFeatIter == myFeatures.end())
201     return; // no such feature
202
203   std::set<ConstraintPtr> aConstraints = aFeatIter->second;
204   std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
205   for (; aCIter != aConstraints.end(); aCIter++)
206     removeFeature(theFeature, *aCIter);
207 }
208
209 void SketchSolver_FeatureStorage::removeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint)
210 {
211   MapFeatureConstraint::iterator aFeatIter = myFeatures.find(theFeature);
212   if (aFeatIter == myFeatures.end())
213     return; // no such feature
214
215   if (theFeature->data()) {
216     std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
217     std::list<AttributePtr>::iterator anIter = anAttributes.begin();
218     for (; anIter != anAttributes.end(); anIter++) {
219       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
220       if (aRefAttr) {
221         if (!aRefAttr->isObject())
222           removeAttribute(aRefAttr->attr(), theFeature);
223         continue;
224       }
225       removeAttribute(*anIter, theFeature);
226     }
227   } else {
228     // iterate on attributes to find items refered to theFeature
229     MapAttributeFeature::iterator anIter = myAttributes.begin();
230     while (anIter != myAttributes.end()) {
231       if (anIter->second.find(theFeature) != anIter->second.end()) {
232         anIter->second.erase(theFeature);
233         if (anIter->second.empty()) {
234           MapAttributeFeature::iterator aDeadIter = anIter++;
235           myAttributes.erase(aDeadIter);
236           continue;
237         }
238       }
239       anIter++;
240     }
241   }
242
243   aFeatIter->second.erase(theConstraint);
244   if (aFeatIter->second.empty())
245     myFeatures.erase(aFeatIter);
246 }
247
248 bool SketchSolver_FeatureStorage::isInteract(FeaturePtr theFeature) const
249 {
250   if (myFeatures.find(theFeature) != myFeatures.end())
251     return true;
252   if (!theFeature->data() || !theFeature->data()->isValid())
253     return false;
254
255   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
256   std::list<AttributePtr>::iterator anIter = anAttributes.begin();
257   for (; anIter != anAttributes.end(); anIter++) {
258     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
259     if (aRefAttr) {
260       if (!aRefAttr->isObject())
261         if (isInteract(aRefAttr->attr()))
262           return true;
263       continue;
264     }
265     if (isInteract(*anIter))
266       return true;
267   }
268   return false;
269 }
270
271
272 void SketchSolver_FeatureStorage::changeAttribute(AttributePtr theAttribute)
273 {
274   if (myAttributes.find(theAttribute) == myAttributes.end())
275     myAttributes[theAttribute] = std::set<FeaturePtr>();
276 }
277
278 void SketchSolver_FeatureStorage::changeAttribute(AttributePtr theAttribute, FeaturePtr theFeature)
279 {
280   MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
281   if (anAttrIter == myAttributes.end()) {
282     std::set<FeaturePtr> aFeatures;
283     aFeatures.insert(theFeature);
284     myAttributes[theAttribute] = aFeatures;
285     return;
286   }
287   anAttrIter->second.insert(theFeature);
288 }
289
290 void SketchSolver_FeatureStorage::removeAttribute(AttributePtr theAttribute)
291 {
292   MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
293   if (anAttrIter == myAttributes.end())
294     return;
295
296   std::set<FeaturePtr> aFeatures = anAttrIter->second;
297   std::set<FeaturePtr>::iterator aFeatIter = aFeatures.begin();
298   for (; aFeatIter != aFeatures.end(); aFeatIter++)
299     removeAttribute(theAttribute, *aFeatIter);
300 }
301
302 void SketchSolver_FeatureStorage::removeAttribute(AttributePtr theAttribute, FeaturePtr theFeature)
303 {
304   MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
305   if (anAttrIter == myAttributes.end())
306     return; // no such attribute
307
308   anAttrIter->second.erase(theFeature);
309   if (!anAttrIter->second.empty())
310     return;
311
312   // Check there is no features containing such attribute
313   MapFeatureConstraint::iterator aFeatIter = myFeatures.begin();
314   for (; aFeatIter != myFeatures.end(); aFeatIter++) {
315     DataPtr aData = aFeatIter->first->data();
316     if (!aData || !aData->isValid())
317       continue;
318     std::list<AttributePtr> anAttrList = aData->attributes(GeomDataAPI_Point2D::typeId());
319     std::list<AttributePtr>::iterator anAtIt = anAttrList.begin();
320     for (; anAtIt != anAttrList.end(); anAtIt++) {
321       std::shared_ptr<GeomDataAPI_Point2D> aPoint =
322           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAtIt);
323       if (aPoint == theAttribute)
324         anAttrIter->second.insert(aFeatIter->first);
325     }
326   }
327   if (anAttrIter->second.empty())
328     myAttributes.erase(anAttrIter);
329 }
330
331 bool SketchSolver_FeatureStorage::isInteract(AttributePtr theAttribute) const
332 {
333   return myAttributes.find(theAttribute) != myAttributes.end();
334 }
335
336
337 bool SketchSolver_FeatureStorage::isConsistent() const
338 {
339   // Check the constraints are valid
340   std::set<ConstraintPtr>::const_iterator aCIter = myConstraints.begin();
341   for (; aCIter != myConstraints.end(); aCIter++)
342     if (!(*aCIter)->data() || !(*aCIter)->data()->isValid())
343       return false;
344   // Check the features are valid
345   MapFeatureConstraint::const_iterator aFIter = myFeatures.begin();
346   for (; aFIter != myFeatures.end(); aFIter++)
347     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
348       return false;
349   return true;
350 }
351
352 std::set<ConstraintPtr> SketchSolver_FeatureStorage::getConstraints(FeaturePtr theFeature) const
353 {
354   std::set<ConstraintPtr> aResult;
355   MapFeatureConstraint::const_iterator aFeatIter = myFeatures.find(theFeature);
356   if (aFeatIter != myFeatures.end())
357     aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
358
359   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
360   std::list<AttributePtr>::const_iterator anAttrIter = anAttributes.begin();
361   for (; anAttrIter != anAttributes.end(); anAttrIter++) {
362     MapAttributeFeature::const_iterator anIt = myAttributes.find(*anAttrIter);
363     if (anIt == myAttributes.end())
364       continue;
365     std::set<FeaturePtr>::const_iterator aFIter = anIt->second.begin();
366     for (; aFIter != anIt->second.end(); aFIter++) {
367       aFeatIter = myFeatures.find(*aFIter);
368       if (aFeatIter != myFeatures.end())
369         aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
370       else {
371         ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aFIter);
372         if (aConstraint)
373           aResult.insert(aConstraint);
374       }
375     }
376   }
377   return aResult;
378 }
379
380 std::set<ConstraintPtr> SketchSolver_FeatureStorage::getConstraints(AttributePtr theAttribute) const
381 {
382   std::set<ConstraintPtr> aResult;
383   MapAttributeFeature::const_iterator anIt = myAttributes.find(theAttribute);
384   if (anIt == myAttributes.end())
385     return aResult;
386   std::set<FeaturePtr>::const_iterator aFIter = anIt->second.begin();
387   MapFeatureConstraint::const_iterator aFeatIter;
388   for (; aFIter != anIt->second.end(); aFIter++) {
389     aFeatIter = myFeatures.find(*aFIter);
390     if (aFeatIter != myFeatures.end())
391       aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
392     else {
393       ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aFIter);
394       if (aConstraint)
395         aResult.insert(aConstraint);
396     }
397   }
398   return aResult;
399 }
400
401 void SketchSolver_FeatureStorage::blockEvents(bool isBlocked) const
402 {
403   std::set<ConstraintPtr>::iterator aCIter = myConstraints.begin();
404   for (; aCIter != myConstraints.end(); aCIter++)
405     if ((*aCIter)->data() && (*aCIter)->data()->isValid())
406       (*aCIter)->data()->blockSendAttributeUpdated(isBlocked);
407
408   MapFeatureConstraint::const_iterator aFIter = myFeatures.begin();
409   for (; aFIter != myFeatures.end(); aFIter++)
410     if (aFIter->first->data() && aFIter->first->data()->isValid())
411       aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
412
413   MapAttributeFeature::const_iterator anAtIter = myAttributes.begin();
414   for (; anAtIter != myAttributes.end(); anAtIter++)
415     if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
416         anAtIter->first->owner()->data()->isValid())
417       anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
418 }