]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Storage.cpp
Salome HOME
e440a795b1f888227abdde6877564dc67aa5f024
[modules/shaper.git] / src / SketchSolver / SketchSolver_Storage.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    SketchSolver_Storage.cpp
4 // Created: 30 Nov 2015
5 // Author:  Artem ZHIDKOV
6
7 #include <SketchSolver_Storage.h>
8 #include <SketchSolver_Manager.h>
9
10 #include <GeomDataAPI_Point2D.h>
11 #include <ModelAPI_AttributeRefAttr.h>
12 #include <ModelAPI_AttributeRefList.h>
13 #include <SketchPlugin_Arc.h>
14 #include <SketchPlugin_Circle.h>
15
16
17 /// \brief Verify two vectors of constraints are equal.
18 ///        Vectors differ by the order of elements are equal.
19 static bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
20                     const std::list<ConstraintWrapperPtr>& theCVec2);
21
22
23 void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
24                                          ConstraintWrapperPtr theSolverConstraint)
25 {
26   std::list<ConstraintWrapperPtr> aConstrList(1, theSolverConstraint);
27   addConstraint(theConstraint, aConstrList);
28 }
29
30 void SketchSolver_Storage::addConstraint(
31     ConstraintPtr                   theConstraint,
32     std::list<ConstraintWrapperPtr> theSolverConstraints)
33 {
34   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
35       aFound = myConstraintMap.find(theConstraint);
36   if (aFound == myConstraintMap.end() || !isEqual(aFound->second, theSolverConstraints))
37     setNeedToResolve(true);
38
39   // Do not add point-point coincidence, because it is already made by setting
40   // the same parameters for both points
41   if (!theSolverConstraints.empty() &&
42       theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
43     std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
44     for (; aCIt != theSolverConstraints.end(); ++aCIt)
45       update(*aCIt);
46   }
47   myConstraintMap[theConstraint] = theSolverConstraints;
48   // block events if necessary
49   if (myEventsBlocked && theConstraint->data() && theConstraint->data()->isValid())
50     theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
51 }
52
53 void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
54                                      EntityWrapperPtr theSolverEntity)
55 {
56   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
57   if (aFound == myFeatureMap.end() || !aFound->second || !aFound->second->isEqual(theSolverEntity))
58     setNeedToResolve(true); // the entity is new or modified
59
60   myFeatureMap[theFeature] = theSolverEntity;
61   // block events if necessary
62   if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
63     theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
64 }
65
66 void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
67                                      EntityWrapperPtr theSolverEntity)
68 {
69   std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound = myAttributeMap.find(theAttribute);
70   if (aFound == myAttributeMap.end() || !aFound->second || !aFound->second->isEqual(theSolverEntity))
71     setNeedToResolve(true); // the entity is new or modified
72
73   myAttributeMap[theAttribute] = theSolverEntity;
74   // block events if necessary
75   if (myEventsBlocked && theAttribute->owner() &&
76       theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
77     theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
78 }
79
80
81 bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup)
82 {
83   bool isUpdated = false;
84   EntityWrapperPtr aRelated = entity(theFeature);
85   if (!aRelated) { // Feature is not exist, create it
86     std::list<EntityWrapperPtr> aSubs;
87     // Reserve the feature in the map of features (do not want to add several copies of it)
88     myFeatureMap[theFeature] = aRelated;
89     // Firstly, create/update its attributes
90     std::list<AttributePtr> anAttrs =
91         theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
92     std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
93     for (; anIt != anAttrs.end(); ++anIt) {
94       isUpdated = update(*anIt, theGroup) || isUpdated;
95       aSubs.push_back(entity(*anIt));
96     }
97     // If the feature is a circle, add its radius as a sub
98     if (theFeature->getKind() == SketchPlugin_Circle::ID()) {
99       AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
100       isUpdated = update(aRadius, theGroup) || isUpdated;
101       aSubs.push_back(entity(aRadius));
102     }
103     // If the feature if circle or arc, we need to add normal of the sketch to the list of subs
104     if (theFeature->getKind() == SketchPlugin_Arc::ID() ||
105         theFeature->getKind() == SketchPlugin_Circle::ID()) {
106       EntityWrapperPtr aNormal = getNormal();
107       if (aNormal) aSubs.push_back(aNormal);
108     }
109     // Secondly, convert feature
110     BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
111     GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
112     aRelated = aBuilder->createFeature(theFeature, aSubs, aGroup);
113     if (!aRelated)
114       return false;
115     addEntity(theFeature, aRelated);
116   } else if (theGroup != GID_UNKNOWN)
117     changeGroup(aRelated, theGroup);
118   return update(aRelated) || isUpdated;
119 }
120
121 bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup)
122 {
123   AttributePtr anAttribute = theAttribute;
124   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
125   if (aRefAttr) {
126     if (aRefAttr->isObject()) {
127       FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
128       return update(aFeature, theGroup);
129     } else
130       anAttribute = aRefAttr->attr();
131   }
132
133   EntityWrapperPtr aRelated = entity(anAttribute);
134   if (!aRelated) { // Attribute is not exist, create it
135     // verify the attribute is a point of arc and add whole arc
136     if (anAttribute->owner()) {
137       FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
138       if (aFeature->getKind() == SketchPlugin_Arc::ID() &&
139           myFeatureMap.find(aFeature) == myFeatureMap.end()) {
140         // Additional checking that all attributes are initialized
141         if (aFeature->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() && 
142             aFeature->attribute(SketchPlugin_Arc::START_ID())->isInitialized() && 
143             aFeature->attribute(SketchPlugin_Arc::END_ID())->isInitialized()) {
144 ////          myFeatureMap[aFeature] = EntityWrapperPtr();
145           return SketchSolver_Storage::update(aFeature);
146         }
147       }
148     }
149     BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
150     GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
151     aRelated = aBuilder->createAttribute(anAttribute, aGroup);
152     if (!aRelated)
153       return false;
154     addEntity(anAttribute, aRelated);
155   } else if (theGroup != GID_UNKNOWN)
156     changeGroup(aRelated, theGroup);
157   return update(aRelated);
158 }
159
160
161
162 const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
163     const ConstraintPtr& theConstraint) const
164 {
165   static std::list<ConstraintWrapperPtr> aDummy;
166
167   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr>>::const_iterator
168       aFound = myConstraintMap.find(theConstraint);
169   if (aFound != myConstraintMap.end())
170     return aFound->second;
171   return aDummy;
172 }
173
174 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
175 {
176   static EntityWrapperPtr aDummy;
177
178   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
179   if (aFound != myFeatureMap.end())
180     return aFound->second;
181   return aDummy;
182 }
183
184 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
185 {
186   static EntityWrapperPtr aDummy;
187
188   std::map<AttributePtr, EntityWrapperPtr>::const_iterator
189       aFound = myAttributeMap.find(theAttribute);
190   if (aFound != myAttributeMap.end())
191     return aFound->second;
192
193   AttributeRefAttrPtr aRefAttr =
194       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
195   if (aRefAttr) {
196     if (aRefAttr->isObject()) {
197       FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
198       return entity(aFeature);
199     } else
200       return entity(aRefAttr->attr());
201   }
202   return aDummy;
203 }
204
205 bool SketchSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
206 {
207   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
208       aFound = myConstraintMap.find(theConstraint);
209   if (aFound == myConstraintMap.end())
210     return true; // no constraint, already deleted
211
212   // Remove constraint
213   std::list<ConstraintWrapperPtr> aConstrList = aFound->second;
214   myConstraintMap.erase(aFound);
215   // Remove SolveSpace constraints
216   bool isFullyRemoved = true;
217   std::list<ConstraintWrapperPtr>::iterator anIt = aConstrList.begin();
218   while (anIt != aConstrList.end()) {
219     if (remove(*anIt)) {
220       std::list<ConstraintWrapperPtr>::iterator aRemoveIt = anIt++;
221       aConstrList.erase(aRemoveIt);
222     } else {
223       isFullyRemoved = false;
224       ++anIt;
225     }
226   }
227   if (!isFullyRemoved) {
228     // revert removed constraint
229     addConstraint(theConstraint, aConstrList);
230   }
231   return isFullyRemoved;
232 }
233
234 template <class ENT_TYPE>
235 static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
236 {
237   std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
238   for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
239     if ((*anEntIt)->isBase(theEntity))
240       return true;
241   return false;
242 }
243
244 static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
245 {
246   std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
247   for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
248     if ((*aSubIt)->isBase(theSubEntity))
249       return true;
250   return false;
251 }
252
253 bool SketchSolver_Storage::isUsed(FeaturePtr theFeature) const
254 {
255   if (myFeatureMap.find(theFeature) != myFeatureMap.end())
256     return true;
257   // check constraints
258   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
259       aCIt = myConstraintMap.begin();
260   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
261   for (; aCIt != myConstraintMap.end(); ++aCIt)
262     for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
263       if (::isUsed(*aCWIt, theFeature))
264         return true;
265   // check attributes
266   std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
267   std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
268   for (; anIt != anAttrList.end(); ++anIt)
269     if (isUsed(*anIt))
270       return true;
271   return false;
272 }
273
274 bool SketchSolver_Storage::isUsed(AttributePtr theAttribute) const
275 {
276   AttributePtr anAttribute = theAttribute;
277   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
278   if (aRefAttr) {
279     if (aRefAttr->isObject())
280       return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
281     else
282       anAttribute = aRefAttr->attr();
283   }
284
285   if (myAttributeMap.find(theAttribute) != myAttributeMap.end())
286     return true;
287   // check in constraints
288   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
289       aCIt = myConstraintMap.begin();
290   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
291   for (; aCIt != myConstraintMap.end(); ++aCIt)
292     for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
293       if (::isUsed(*aCWIt, anAttribute))
294         return true;
295   // check in features
296   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
297   for (; aFIt != myFeatureMap.end(); ++aFIt)
298     if (::isUsed(aFIt->second, anAttribute))
299       return true;
300   return false;
301 }
302
303
304 bool SketchSolver_Storage::removeEntity(FeaturePtr theFeature)
305 {
306   std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
307   if (aFound == myFeatureMap.end())
308     return false; // feature not found, nothing to delete
309
310   // Check the feature is not used by constraints
311   if (isUsed(theFeature))
312     return false; // the feature is used, don't remove it
313
314   // Remove feature
315   EntityWrapperPtr anEntity = aFound->second;
316   myFeatureMap.erase(aFound);
317   if (remove(anEntity))
318     return true;
319   // feature is not removed, revert operation
320   myFeatureMap[theFeature] = anEntity;
321   update(anEntity);
322   return false;
323 }
324
325 bool SketchSolver_Storage::removeEntity(AttributePtr theAttribute)
326 {
327   std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
328   if (aFound == myAttributeMap.end())
329     return false; // attribute not found, nothing to delete
330
331   // Check the attribute is not used by constraints
332   if (isUsed(theAttribute))
333     return false; // the attribute is used, don't remove it
334   // Check the attribute is not used by other features
335   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
336   for (; aFIt != myFeatureMap.end(); ++aFIt)
337     if (::isUsed(aFIt->second, theAttribute)) // the attribute is used, don't remove it
338       return false;
339
340   // Remove attribute
341   EntityWrapperPtr anEntity = aFound->second;
342   myAttributeMap.erase(aFound);
343   if (remove(anEntity))
344     return true;
345   // attribute is not removed, revert operation
346   myAttributeMap[theAttribute] = anEntity;
347   update(anEntity);
348   return false;
349 }
350
351
352 bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
353 {
354   bool isFullyRemoved = true;
355   std::list<EntityWrapperPtr>::const_iterator anIt = theConstraint->entities().begin();
356   for (; anIt != theConstraint->entities().end(); ++anIt) {
357     FeaturePtr aBaseFeature = (*anIt)->baseFeature();
358     if (aBaseFeature)
359       isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
360     else
361       isFullyRemoved = SketchSolver_Storage::removeEntity((*anIt)->baseAttribute()) && isFullyRemoved;
362   }
363   return isFullyRemoved;
364 }
365
366 bool SketchSolver_Storage::remove(EntityWrapperPtr theEntity)
367 {
368   bool isFullyRemoved = true;
369   std::list<EntityWrapperPtr>::const_iterator anEntIt = theEntity->subEntities().begin();
370   for (; anEntIt != theEntity->subEntities().end(); ++anEntIt) {
371     FeaturePtr aBaseFeature = (*anEntIt)->baseFeature();
372     if (aBaseFeature)
373       isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
374     else
375       isFullyRemoved = SketchSolver_Storage::removeEntity((*anEntIt)->baseAttribute()) && isFullyRemoved;
376   }
377
378   std::list<ParameterWrapperPtr>::const_iterator aParIt = theEntity->parameters().begin();
379   for (; aParIt != theEntity->parameters().end(); ++aParIt)
380     isFullyRemoved = remove(*aParIt) && isFullyRemoved;
381   return isFullyRemoved;
382 }
383
384
385 bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
386 {
387   if (!theFeature)
388     return false;
389   if (myConstraintMap.empty())
390     return true; // empty storage interacts with each feature
391
392   ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
393   if (aConstraint) {
394     if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
395       return true;
396   } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
397     return true;
398
399   std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
400   std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
401   for (; anIt != anAttrList.end(); ++anIt)
402     if (isInteract(*anIt))
403       return true;
404
405   return false;
406 }
407
408 bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
409 {
410   if (!theAttribute)
411     return false;
412
413   AttributeRefListPtr aRefList = 
414       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
415   if (aRefList) {
416     std::list<ObjectPtr> anObjects = aRefList->list();
417     std::list<ObjectPtr>::iterator anObjIt = anObjects.begin();
418     for (; anObjIt != anObjects.end(); ++anObjIt) {
419       FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
420       if (isInteract(aFeature))
421         return true;
422     }
423     return false;
424   }
425
426   AttributeRefAttrPtr aRefAttr =
427       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
428   if (!aRefAttr)
429     return myAttributeMap.find(theAttribute) != myAttributeMap.end();
430   if (!aRefAttr->isObject())
431     return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
432
433   FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
434   return isInteract(aFeature);
435 }
436
437 bool SketchSolver_Storage::isConsistent() const
438 {
439   // Check the constraints are valid
440   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
441       aCIter = myConstraintMap.begin();
442   for (; aCIter != myConstraintMap.end(); ++aCIter)
443     if (!aCIter->first->data() || !aCIter->first->data()->isValid())
444       return false;
445   // Check the features are valid
446   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
447   for (; aFIter != myFeatureMap.end(); aFIter++)
448     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
449       return false;
450   return true;
451 }
452
453 bool SketchSolver_Storage::isFixed(EntityWrapperPtr theEntity) const
454 {
455   if (theEntity->group() != myGroupID)
456     return true;
457   // no need additional checking for entities differ than point
458   if (theEntity->type() != ENTITY_POINT)
459     return false;
460
461   CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin();
462   for (; anIt != myCoincidentPoints.end(); ++anIt)
463     if (anIt->first == theEntity || anIt->second.find(theEntity) != anIt->second.end()) {
464       if (anIt->first->group() != myGroupID)
465         return true;
466       std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
467       for (; anEntIt != anIt->second.end(); ++anEntIt)
468         if ((*anEntIt)->group() != myGroupID)
469           return true;
470     }
471   return false;
472 }
473
474 void SketchSolver_Storage::removeInvalidEntities()
475 {
476   // Remove invalid constraints
477   std::list<ConstraintPtr> anInvalidConstraints;
478   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
479       aCIter = myConstraintMap.begin();
480   for (; aCIter != myConstraintMap.end(); ++aCIter)
481     if (!aCIter->first->data() || !aCIter->first->data()->isValid())
482       anInvalidConstraints.push_back(aCIter->first);
483   std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
484   for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
485     removeConstraint(*anInvCIt);
486   // Remove invalid features
487   std::list<FeaturePtr> anInvalidFeatures;
488   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
489   for (; aFIter != myFeatureMap.end(); aFIter++)
490     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
491       anInvalidFeatures.push_back(aFIter->first);
492   std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
493   for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
494     removeEntity(*anInvFIt);
495 }
496
497 EntityWrapperPtr SketchSolver_Storage::getNormal() const
498 {
499   EntityWrapperPtr aSketch = sketch();
500   if (!aSketch)
501     return aSketch;
502
503   // Find normal entity
504   const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
505   std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
506   for (; aSIt != aSketchSubs.end(); ++aSIt)
507     if ((*aSIt)->type() == ENTITY_NORMAL)
508       return *aSIt;
509   return EntityWrapperPtr();
510 }
511
512 const EntityWrapperPtr& SketchSolver_Storage::sketch() const
513 {
514   static EntityWrapperPtr aDummySketch;
515
516   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
517   for (; aFIt != myFeatureMap.end(); ++aFIt)
518     if (aFIt->second && aFIt->second->type() == ENTITY_SKETCH)
519       break;
520   if (aFIt == myFeatureMap.end())
521     return aDummySketch;
522   return aFIt->second;
523 }
524
525 void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
526 {
527   if (sketch())
528     return;
529   addEntity(FeaturePtr(), theSketch);
530 }
531
532 void SketchSolver_Storage::blockEvents(bool isBlocked)
533 {
534   if (isBlocked == myEventsBlocked)
535     return;
536
537   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
538       aCIter = myConstraintMap.begin();
539   for (; aCIter != myConstraintMap.end(); aCIter++)
540     if (aCIter->first->data() && aCIter->first->data()->isValid())
541       aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
542
543   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
544   for (; aFIter != myFeatureMap.end(); aFIter++)
545     if (aFIter->first->data() && aFIter->first->data()->isValid())
546       aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
547
548   std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
549   for (; anAtIter != myAttributeMap.end(); anAtIter++)
550     if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
551         anAtIter->first->owner()->data()->isValid())
552       anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
553   myEventsBlocked = isBlocked;
554 }
555
556
557
558
559
560
561 // ==============   Auxiliary functions   ====================================
562 bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
563              const std::list<ConstraintWrapperPtr>& theCVec2)
564 {
565   if (theCVec1.size() != theCVec2.size())
566     return false;
567
568   std::list<bool> aChecked(theCVec2.size(), false);
569   std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
570   for (; anIt1 != theCVec1.end(); ++anIt1) {
571     std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
572     std::list<bool>::iterator aCheckIt = aChecked.begin();
573     while (aCheckIt != aChecked.end() && *aCheckIt) {
574       ++aCheckIt;
575       ++anIt2;
576     }
577     for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
578       if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
579         *aCheckIt = true;
580         break;
581       }
582     // the same constraint is not found
583     if (anIt2 == theCVec2.end())
584       return false;
585   }
586   return true;
587 }