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