]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Storage.cpp
Salome HOME
fed8d3e82d2cb6c5860a2567c4ae73649f434b23
[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   std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
279   for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
280     if ((*anEntIt)->isBase(theEntity))
281       return true;
282   return false;
283 }
284
285 static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
286 {
287   std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
288   for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
289     if ((*aSubIt)->isBase(theSubEntity))
290       return true;
291   return false;
292 }
293
294 bool SketchSolver_Storage::isUsed(FeaturePtr theFeature) const
295 {
296   if (myFeatureMap.find(theFeature) != myFeatureMap.end())
297     return true;
298   // check constraints
299   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
300       aCIt = myConstraintMap.begin();
301   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
302   for (; aCIt != myConstraintMap.end(); ++aCIt)
303     for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
304       if (::isUsed(*aCWIt, theFeature))
305         return true;
306   // check attributes
307   std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
308   std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
309   for (; anIt != anAttrList.end(); ++anIt)
310     if (isUsed(*anIt))
311       return true;
312   return false;
313 }
314
315 bool SketchSolver_Storage::isUsed(AttributePtr theAttribute) const
316 {
317   AttributePtr anAttribute = theAttribute;
318   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
319   if (aRefAttr) {
320     if (aRefAttr->isObject())
321       return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
322     else
323       anAttribute = aRefAttr->attr();
324   }
325
326   if (myAttributeMap.find(theAttribute) != myAttributeMap.end())
327     return true;
328   // check in constraints
329   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
330       aCIt = myConstraintMap.begin();
331   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
332   for (; aCIt != myConstraintMap.end(); ++aCIt)
333     for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
334       if (::isUsed(*aCWIt, anAttribute))
335         return true;
336   // check in features
337   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
338   for (; aFIt != myFeatureMap.end(); ++aFIt)
339     if (::isUsed(aFIt->second, anAttribute))
340       return true;
341   return false;
342 }
343
344
345 bool SketchSolver_Storage::removeEntity(FeaturePtr theFeature)
346 {
347   std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
348   if (aFound == myFeatureMap.end())
349     return false; // feature not found, nothing to delete
350
351   EntityWrapperPtr anEntity = aFound->second;
352   myFeatureMap.erase(aFound);
353
354   // Check if the feature is not used by constraints, remove it
355   if (!isUsed(theFeature) && remove(anEntity))
356     return true;
357
358   // feature is not removed, revert operation
359   myFeatureMap[theFeature] = anEntity;
360   update(anEntity);
361   return false;
362 }
363
364 bool SketchSolver_Storage::removeEntity(AttributePtr theAttribute)
365 {
366   std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
367   if (aFound == myAttributeMap.end())
368     return false; // attribute not found, nothing to delete
369
370   EntityWrapperPtr anEntity = aFound->second;
371   myAttributeMap.erase(aFound);
372
373   // Check if the attribute is not used by constraints and features, remove it
374   if (!isUsed(theAttribute) && remove(anEntity))
375     return true;
376
377   // attribute is not removed, revert operation
378   myAttributeMap[theAttribute] = anEntity;
379   update(anEntity);
380   return false;
381 }
382
383
384 bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
385 {
386   bool isFullyRemoved = true;
387   std::list<EntityWrapperPtr>::const_iterator anIt = theConstraint->entities().begin();
388   for (; anIt != theConstraint->entities().end(); ++anIt) {
389     FeaturePtr aBaseFeature = (*anIt)->baseFeature();
390     if (aBaseFeature)
391       isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
392     else
393       isFullyRemoved = SketchSolver_Storage::removeEntity((*anIt)->baseAttribute()) && isFullyRemoved;
394   }
395   return isFullyRemoved;
396 }
397
398 bool SketchSolver_Storage::remove(EntityWrapperPtr theEntity)
399 {
400   bool isFullyRemoved = true;
401   std::list<EntityWrapperPtr>::const_iterator anEntIt = theEntity->subEntities().begin();
402   for (; anEntIt != theEntity->subEntities().end(); ++anEntIt) {
403     FeaturePtr aBaseFeature = (*anEntIt)->baseFeature();
404     if (aBaseFeature)
405       isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
406     else
407       isFullyRemoved = SketchSolver_Storage::removeEntity((*anEntIt)->baseAttribute()) && isFullyRemoved;
408   }
409
410   std::list<ParameterWrapperPtr>::const_iterator aParIt = theEntity->parameters().begin();
411   for (; aParIt != theEntity->parameters().end(); ++aParIt)
412     isFullyRemoved = remove(*aParIt) && isFullyRemoved;
413   return isFullyRemoved;
414 }
415
416
417 bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
418 {
419   if (!theFeature)
420     return false;
421   if (myConstraintMap.empty())
422     return true; // empty storage interacts with each feature
423
424   ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
425   if (aConstraint) {
426     if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
427       return true;
428   } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
429     return true;
430
431   std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
432   std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
433   for (; anIt != anAttrList.end(); ++anIt)
434     if (isInteract(*anIt))
435       return true;
436
437   return false;
438 }
439
440 bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
441 {
442   if (!theAttribute)
443     return false;
444
445   AttributeRefListPtr aRefList = 
446       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
447   if (aRefList) {
448     std::list<ObjectPtr> anObjects = aRefList->list();
449     std::list<ObjectPtr>::iterator anObjIt = anObjects.begin();
450     for (; anObjIt != anObjects.end(); ++anObjIt) {
451       FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
452       if (isInteract(aFeature))
453         return true;
454     }
455     return false;
456   }
457
458   AttributeRefAttrPtr aRefAttr =
459       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
460   if (!aRefAttr)
461     return myAttributeMap.find(theAttribute) != myAttributeMap.end();
462   if (!aRefAttr->isObject())
463     return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
464
465   FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
466   return isInteract(aFeature);
467 }
468
469 bool SketchSolver_Storage::isConsistent() const
470 {
471   // Check the constraints are valid
472   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
473       aCIter = myConstraintMap.begin();
474   for (; aCIter != myConstraintMap.end(); ++aCIter)
475     if (!aCIter->first->data() || !aCIter->first->data()->isValid())
476       return false;
477   // Check the features are valid
478   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
479   for (; aFIter != myFeatureMap.end(); aFIter++)
480     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
481       return false;
482   return true;
483 }
484
485 bool SketchSolver_Storage::isFixed(EntityWrapperPtr theEntity) const
486 {
487   if (theEntity->group() != myGroupID)
488     return true;
489   // no need additional checking for entities differ than point
490   if (theEntity->type() != ENTITY_POINT)
491     return false;
492
493   CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin();
494   for (; anIt != myCoincidentPoints.end(); ++anIt)
495     if (anIt->first == theEntity || anIt->second.find(theEntity) != anIt->second.end()) {
496       if (anIt->first->group() != myGroupID)
497         return true;
498       std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
499       for (; anEntIt != anIt->second.end(); ++anEntIt)
500         if ((*anEntIt)->group() != myGroupID)
501           return true;
502     }
503
504   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator aCIt = myConstraintMap.begin();
505   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
506   for (; aCIt != myConstraintMap.end(); ++aCIt) {
507     if (aCIt->second.empty())
508       continue;
509     aCWIt = aCIt->second.begin();
510     if ((*aCWIt)->type() != CONSTRAINT_FIXED)
511       continue;
512     for (; aCWIt != aCIt->second.end(); ++aCIt)
513       if ((theEntity->baseAttribute() && (*aCWIt)->isUsed(theEntity->baseAttribute())) ||
514           (theEntity->baseFeature() && (*aCWIt)->isUsed(theEntity->baseFeature())))
515         return true;
516   }
517
518   return false;
519 }
520
521 void SketchSolver_Storage::removeInvalidEntities()
522 {
523   // Remove invalid constraints
524   std::list<ConstraintPtr> anInvalidConstraints;
525   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
526       aCIter = myConstraintMap.begin();
527   for (; aCIter != myConstraintMap.end(); ++aCIter)
528     if (!aCIter->first->data() || !aCIter->first->data()->isValid())
529       anInvalidConstraints.push_back(aCIter->first);
530   std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
531   for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
532     removeConstraint(*anInvCIt);
533   // Remove invalid features
534   std::list<FeaturePtr> anInvalidFeatures;
535   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
536   for (; aFIter != myFeatureMap.end(); aFIter++)
537     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
538       anInvalidFeatures.push_back(aFIter->first);
539   std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
540   for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
541     removeEntity(*anInvFIt);
542 }
543
544 EntityWrapperPtr SketchSolver_Storage::getNormal() const
545 {
546   EntityWrapperPtr aSketch = sketch();
547   if (!aSketch)
548     return aSketch;
549
550   // Find normal entity
551   const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
552   std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
553   for (; aSIt != aSketchSubs.end(); ++aSIt)
554     if ((*aSIt)->type() == ENTITY_NORMAL)
555       return *aSIt;
556   return EntityWrapperPtr();
557 }
558
559 const EntityWrapperPtr& SketchSolver_Storage::sketch() const
560 {
561   static EntityWrapperPtr aDummySketch;
562
563   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
564   for (; aFIt != myFeatureMap.end(); ++aFIt)
565     if (aFIt->second && aFIt->second->type() == ENTITY_SKETCH)
566       break;
567   if (aFIt == myFeatureMap.end())
568     return aDummySketch;
569   return aFIt->second;
570 }
571
572 void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
573 {
574   if (sketch())
575     return;
576   addEntity(FeaturePtr(), theSketch);
577 }
578
579 void SketchSolver_Storage::processArcs()
580 {
581   myExistArc = false;
582   std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
583   for (; aFIt != myFeatureMap.end(); ++aFIt)
584     if (!aFIt->second && aFIt->first->getKind() == SketchPlugin_Arc::ID()) {
585       // Additional checking the attributes are initialized
586       if (aFIt->first->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() && 
587           aFIt->first->attribute(SketchPlugin_Arc::START_ID())->isInitialized() && 
588           aFIt->first->attribute(SketchPlugin_Arc::END_ID())->isInitialized())
589         update(aFIt->first);
590       else
591         myExistArc = true;
592     }
593 }
594
595 void SketchSolver_Storage::blockEvents(bool isBlocked)
596 {
597   if (isBlocked == myEventsBlocked)
598     return;
599
600   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
601       aCIter = myConstraintMap.begin();
602   for (; aCIter != myConstraintMap.end(); aCIter++)
603     if (aCIter->first->data() && aCIter->first->data()->isValid())
604       aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
605
606   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
607   for (; aFIter != myFeatureMap.end(); aFIter++)
608     if (aFIter->first->data() && aFIter->first->data()->isValid())
609       aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
610
611   std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
612   for (; anAtIter != myAttributeMap.end(); anAtIter++)
613     if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
614         anAtIter->first->owner()->data()->isValid())
615       anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
616   myEventsBlocked = isBlocked;
617 }
618
619
620
621
622
623
624 // ==============   Auxiliary functions   ====================================
625 bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
626              const std::list<ConstraintWrapperPtr>& theCVec2)
627 {
628   if (theCVec1.size() != theCVec2.size())
629     return false;
630
631   std::list<bool> aChecked(theCVec2.size(), false);
632   std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
633   for (; anIt1 != theCVec1.end(); ++anIt1) {
634     std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
635     std::list<bool>::iterator aCheckIt = aChecked.begin();
636     while (aCheckIt != aChecked.end() && *aCheckIt) {
637       ++aCheckIt;
638       ++anIt2;
639     }
640     for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
641       if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
642         *aCheckIt = true;
643         break;
644       }
645     // the same constraint is not found
646     if (anIt2 == theCVec2.end())
647       return false;
648   }
649   return true;
650 }