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