]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Storage.cpp
Salome HOME
PlaneGCS: Fix the problem regarding update of a distance during moving of a line...
[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 #include <SketchPlugin_Line.h>
16 #include <SketchPlugin_Point.h>
17 #include <SketchPlugin_IntersectionPoint.h>
18 #include <SketchPlugin_ConstraintCoincidence.h>
19 #include <SketchPlugin_ConstraintMirror.h>
20 #include <SketchPlugin_ConstraintRigid.h>
21
22
23 /// \brief Verify two vectors of constraints are equal.
24 ///        Vectors differ by the order of elements are equal.
25 static bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
26                     const std::list<ConstraintWrapperPtr>& theCVec2);
27
28
29 void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
30                                          ConstraintWrapperPtr theSolverConstraint)
31 {
32   if (theSolverConstraint) {
33     std::list<ConstraintWrapperPtr> aConstrList(1, theSolverConstraint);
34     addConstraint(theConstraint, aConstrList);
35   } else
36     addConstraint(theConstraint, std::list<ConstraintWrapperPtr>());
37 }
38
39 void SketchSolver_Storage::addConstraint(
40     ConstraintPtr                   theConstraint,
41     std::list<ConstraintWrapperPtr> theSolverConstraints)
42 {
43   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
44       aFound = myConstraintMap.find(theConstraint);
45   if (aFound == myConstraintMap.end() || !isEqual(aFound->second, theSolverConstraints))
46     setNeedToResolve(true);
47
48   if (theSolverConstraints.empty()) {
49     // constraint links to the empty list, add its attributes linked to the empty entities
50     std::list<AttributePtr> aRefAttrs =
51         theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
52     std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
53     for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
54       AttributeRefAttrPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
55       if (aRef->isObject()) {
56         FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
57         if (aFeature) addEntity(aFeature, EntityWrapperPtr());
58       } else
59         addEntity(aRef->attr(), EntityWrapperPtr());
60     }
61     std::list<AttributePtr> aRefLists =
62         theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
63     for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
64       AttributeRefListPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
65       std::list<ObjectPtr> anObj = aRef->list();
66       std::list<ObjectPtr>::iterator anIt = anObj.begin();
67       for (; anIt != anObj.end(); ++anIt) {
68         FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
69         if (aFeature) addEntity(aFeature, EntityWrapperPtr());
70       }
71     }
72   }
73   else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
74     // Do not add point-point coincidence, because it is already made by setting
75     // the same parameters for both points
76     std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
77     for (; aCIt != theSolverConstraints.end(); ++aCIt)
78       update(*aCIt);
79   }
80
81   if (!theSolverConstraints.empty() || aFound == myConstraintMap.end())
82     myConstraintMap[theConstraint] = theSolverConstraints;
83   // block events if necessary
84   if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
85     theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
86 }
87
88 static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
89 {
90   std::list<AttributePtr> aPoints;
91   if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
92     aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
93     aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::START_ID()));
94     aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::END_ID()));
95   }
96   else if (theFeature->getKind() == SketchPlugin_Circle::ID())
97     aPoints.push_back(theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
98   else if (theFeature->getKind() == SketchPlugin_Line::ID()) {
99     aPoints.push_back(theFeature->attribute(SketchPlugin_Line::START_ID()));
100     aPoints.push_back(theFeature->attribute(SketchPlugin_Line::END_ID()));
101   }
102   else if (theFeature->getKind() == SketchPlugin_Point::ID() ||
103            theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
104     aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID()));
105   return aPoints;
106 }
107
108 void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
109                                      EntityWrapperPtr theSolverEntity)
110 {
111   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
112   if (aFound == myFeatureMap.end() || !aFound->second ||
113      (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
114     setNeedToResolve(true); // the entity is new or modified
115
116   if (!theSolverEntity) {
117     // feature links to the empty entity, add its attributes
118     std::list<AttributePtr> aPntAttrs = pointAttributes(theFeature);
119     std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
120     for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
121       addEntity(*anAttrIt, EntityWrapperPtr());
122     if (aFound == myFeatureMap.end())
123       myFeatureMap[theFeature] = theSolverEntity;
124   } else
125     myFeatureMap[theFeature] = theSolverEntity;
126
127   // block events if necessary
128   if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
129     theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
130 }
131
132 void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
133                                      EntityWrapperPtr theSolverEntity)
134 {
135   std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound = myAttributeMap.find(theAttribute);
136   if (aFound == myAttributeMap.end() || !aFound->second ||
137      (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
138     setNeedToResolve(true); // the entity is new or modified
139
140   if (theSolverEntity || aFound == myAttributeMap.end())
141     myAttributeMap[theAttribute] = theSolverEntity;
142   // block events if necessary
143   if (myEventsBlocked && theAttribute->owner() &&
144       theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
145     theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
146 }
147
148
149 static bool isCopyInMulti(std::shared_ptr<SketchPlugin_Feature> theFeature,
150     const std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >& theConstraints)
151 {
152   bool aResult = theFeature->isCopy();
153   if (aResult) {
154     std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
155         anIt = theConstraints.begin();
156     for (; anIt != theConstraints.end() && aResult; ++anIt) {
157       if (anIt->first->getKind() != SketchPlugin_ConstraintMirror::ID())
158         continue;
159       AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
160           anIt->first->attribute(SketchPlugin_Constraint::ENTITY_C()));
161       std::list<ObjectPtr> aMirroredList =  aRefList->list();
162       std::list<ObjectPtr>::const_iterator aMIt = aMirroredList.begin();
163       for (; aMIt != aMirroredList.end() && aResult; ++aMIt) {
164         FeaturePtr aFeat = ModelAPI_Feature::feature(*aMIt);
165         if (aFeat == theFeature)
166           aResult = false;
167       }
168     }
169   }
170   return aResult;
171 }
172
173 bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup)
174 {
175   bool isUpdated = false;
176   EntityWrapperPtr aRelated = entity(theFeature);
177   if (!aRelated) { // Feature is not exist, create it
178     std::list<EntityWrapperPtr> aSubs;
179     // Reserve the feature in the map of features (do not want to add several copies of it)
180     myFeatureMap[theFeature] = aRelated;
181     // Firstly, create/update its attributes
182     std::list<AttributePtr> anAttrs = pointAttributes(theFeature);
183     std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
184     for (; anIt != anAttrs.end(); ++anIt) {
185       isUpdated = update(*anIt, theGroup) || isUpdated;
186       aSubs.push_back(entity(*anIt));
187     }
188     // If the feature is a circle, add its radius as a sub
189     if (theFeature->getKind() == SketchPlugin_Circle::ID()) {
190       AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
191       isUpdated = update(aRadius, theGroup) || isUpdated;
192       aSubs.push_back(entity(aRadius));
193     }
194     // If the feature if circle or arc, we need to add normal of the sketch to the list of subs
195     if (theFeature->getKind() == SketchPlugin_Arc::ID() ||
196         theFeature->getKind() == SketchPlugin_Circle::ID()) {
197       EntityWrapperPtr aNormal = getNormal();
198       if (aNormal) aSubs.push_back(aNormal);
199     }
200     // Secondly, convert feature
201     BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
202     GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
203     // Check external feature
204     std::shared_ptr<SketchPlugin_Feature> aSketchFeature = 
205         std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
206     if (aSketchFeature && (aSketchFeature->isExternal() || isCopyInMulti(aSketchFeature, myConstraintMap)))
207       aGroup = GID_OUTOFGROUP;
208     aRelated = aBuilder->createFeature(theFeature, aSubs, aGroup);
209     if (!aRelated)
210       return false;
211     addEntity(theFeature, aRelated);
212   } else if (theGroup != GID_UNKNOWN)
213     changeGroup(aRelated, theGroup);
214   return update(aRelated) || isUpdated;
215 }
216
217 bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup)
218 {
219   AttributePtr anAttribute = theAttribute;
220   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
221   if (aRefAttr) {
222     if (aRefAttr->isObject()) {
223       FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
224       return update(aFeature, theGroup);
225     } else
226       anAttribute = aRefAttr->attr();
227   }
228
229   EntityWrapperPtr aRelated = entity(anAttribute);
230   if (!aRelated) { // Attribute is not exist, create it
231     // verify the attribute is a point of arc and add whole arc
232     if (anAttribute->owner()) {
233       FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
234       if (aFeature->getKind() == SketchPlugin_Arc::ID() &&
235           myFeatureMap.find(aFeature) == myFeatureMap.end()) {
236         // Additional checking that all attributes are initialized
237         if (aFeature->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() && 
238             aFeature->attribute(SketchPlugin_Arc::START_ID())->isInitialized() && 
239             aFeature->attribute(SketchPlugin_Arc::END_ID())->isInitialized()) {
240           return SketchSolver_Storage::update(aFeature);
241         } else {
242           myFeatureMap[aFeature] = EntityWrapperPtr();
243           myExistArc = true;
244         }
245       }
246     }
247     BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
248     GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
249     // Check attribute of external features
250     std::shared_ptr<SketchPlugin_Feature> aSketchFeature = 
251         std::dynamic_pointer_cast<SketchPlugin_Feature>(theAttribute->owner());
252     if (aSketchFeature && (aSketchFeature->isExternal() || isCopyInMulti(aSketchFeature, myConstraintMap)))
253       aGroup = GID_OUTOFGROUP;
254     aRelated = aBuilder->createAttribute(anAttribute, aGroup);
255     if (!aRelated)
256       return false;
257     addEntity(anAttribute, aRelated);
258   } else if (theGroup != GID_UNKNOWN)
259     changeGroup(aRelated, theGroup);
260   return update(aRelated);
261 }
262
263
264
265 const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
266     const ConstraintPtr& theConstraint) const
267 {
268   static std::list<ConstraintWrapperPtr> aDummy;
269
270   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr>>::const_iterator
271       aFound = myConstraintMap.find(theConstraint);
272   if (aFound != myConstraintMap.end())
273     return aFound->second;
274   return aDummy;
275 }
276
277 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
278 {
279   static EntityWrapperPtr aDummy;
280
281   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
282   if (aFound != myFeatureMap.end())
283     return aFound->second;
284   return aDummy;
285 }
286
287 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
288 {
289   static EntityWrapperPtr aDummy;
290
291   std::map<AttributePtr, EntityWrapperPtr>::const_iterator
292       aFound = myAttributeMap.find(theAttribute);
293   if (aFound != myAttributeMap.end())
294     return aFound->second;
295
296   AttributeRefAttrPtr aRefAttr =
297       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
298   if (aRefAttr) {
299     if (aRefAttr->isObject()) {
300       FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
301       return entity(aFeature);
302     } else
303       return entity(aRefAttr->attr());
304   }
305   return aDummy;
306 }
307
308 bool SketchSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
309 {
310   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
311       aFound = myConstraintMap.find(theConstraint);
312   if (aFound == myConstraintMap.end())
313     return true; // no constraint, already deleted
314
315   // Remove constraint
316   std::list<ConstraintWrapperPtr> aConstrList = aFound->second;
317   myConstraintMap.erase(aFound);
318   // Remove SolveSpace constraints
319   bool isFullyRemoved = true;
320   std::list<ConstraintWrapperPtr>::iterator anIt = aConstrList.begin();
321   while (anIt != aConstrList.end()) {
322     if (remove(*anIt)) {
323       std::list<ConstraintWrapperPtr>::iterator aRemoveIt = anIt++;
324       aConstrList.erase(aRemoveIt);
325     } else {
326       isFullyRemoved = false;
327       ++anIt;
328     }
329   }
330   return isFullyRemoved;
331 }
332
333 template <class ENT_TYPE>
334 static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
335 {
336   if (!theConstraint || !theEntity)
337     return false;
338   std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
339   for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
340     if ((*anEntIt)->isBase(theEntity))
341       return true;
342   return false;
343 }
344
345 static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
346 {
347   if (!theFeature || !theSubEntity)
348     return false;
349   std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
350   for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
351     if ((*aSubIt)->isBase(theSubEntity))
352       return true;
353   return false;
354 }
355
356 static bool isUsed(ConstraintPtr theConstraint, AttributePtr theAttribute)
357 {
358   if (!theConstraint || !theAttribute)
359     return false;
360   std::list<AttributePtr> anAttrList = theConstraint->data()->attributes(std::string());
361   std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
362   for (; anIt != anAttrList.end(); ++anIt) {
363     if (*anIt == theAttribute)
364       return true;
365     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
366     if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theAttribute)
367       return true;
368   }
369   return false;
370 }
371
372 bool SketchSolver_Storage::isUsed(FeaturePtr theFeature) const
373 {
374   if (myFeatureMap.find(theFeature) != myFeatureMap.end())
375     return true;
376   // check constraints
377   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
378       aCIt = myConstraintMap.begin();
379   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
380   for (; aCIt != myConstraintMap.end(); ++aCIt)
381     for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
382       if (::isUsed(*aCWIt, theFeature))
383         return true;
384   // check attributes
385   std::list<AttributePtr> anAttrList = pointAttributes(theFeature);
386   std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
387   for (; anIt != anAttrList.end(); ++anIt)
388     if (isUsed(*anIt))
389       return true;
390   return false;
391 }
392
393 bool SketchSolver_Storage::isUsed(AttributePtr theAttribute) const
394 {
395   AttributePtr anAttribute = theAttribute;
396   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
397   if (aRefAttr) {
398     if (aRefAttr->isObject())
399       return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
400     else
401       anAttribute = aRefAttr->attr();
402   }
403
404   if (myAttributeMap.find(theAttribute) != myAttributeMap.end())
405     return true;
406   // check in constraints
407   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
408       aCIt = myConstraintMap.begin();
409   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
410   for (; aCIt != myConstraintMap.end(); ++aCIt) {
411     for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
412       if (::isUsed(*aCWIt, anAttribute))
413         return true;
414     // Additional check for the Fixed constraints, which have no wrapper associated.
415     if (aCIt->first->getKind() == SketchPlugin_ConstraintRigid::ID() &&
416         ::isUsed(aCIt->first, anAttribute))
417       return true;
418   }
419   // check in features
420   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
421   for (; aFIt != myFeatureMap.end(); ++aFIt)
422     if (::isUsed(aFIt->second, anAttribute))
423       return true;
424   return false;
425 }
426
427
428 bool SketchSolver_Storage::removeEntity(FeaturePtr theFeature)
429 {
430   std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
431   if (aFound == myFeatureMap.end())
432     return true; // feature not found, nothing to delete
433
434   EntityWrapperPtr anEntity = aFound->second;
435   myFeatureMap.erase(aFound);
436
437   // Check if the feature is not used by constraints, remove it
438   if (!anEntity || (!isUsed(theFeature) && remove(anEntity)))
439     return true;
440
441   // feature is not removed, revert operation
442   myFeatureMap[theFeature] = anEntity;
443   update(anEntity);
444   return false;
445 }
446
447 bool SketchSolver_Storage::removeEntity(AttributePtr theAttribute)
448 {
449   std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
450   if (aFound == myAttributeMap.end())
451     return true; // attribute not found, nothing to delete
452
453   EntityWrapperPtr anEntity = aFound->second;
454   myAttributeMap.erase(aFound);
455
456   // Check if the attribute is not used by constraints and features, remove it
457   if (!anEntity || (!isUsed(theAttribute) && remove(anEntity)))
458     return true;
459
460   // attribute is not removed, revert operation
461   myAttributeMap[theAttribute] = anEntity;
462   update(anEntity);
463   return false;
464 }
465
466
467 bool SketchSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
468 {
469   std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
470   std::list<EntityWrapperPtr>::const_iterator aPIt;
471
472   CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
473   for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
474     for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
475       if (aPtPtIt->first == *aPIt ||
476           aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
477         break;
478     if (aPIt != aPoints.end())
479       break;
480   }
481
482   if (aPtPtIt == myCoincidentPoints.end())
483     return true; // already removed
484
485   // Create new copies of coincident points
486   BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
487   std::list<EntityWrapperPtr> aNewPoints;
488   for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
489     aNewPoints.push_back(aBuilder->createAttribute(
490         (*aPIt)->baseAttribute(), myGroupID, mySketchID));
491
492   // Find all points fallen out of group of coincident points
493   std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
494   aNotCoinc[aPtPtIt->first] = EntityWrapperPtr();
495   std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
496   for (; aTempIt != aPtPtIt->second.end(); ++aTempIt)
497     aNotCoinc[*aTempIt] = EntityWrapperPtr();
498   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
499       aConstrIt = myConstraintMap.begin();
500   for (; aConstrIt != myConstraintMap.end(); ++aConstrIt)
501     if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
502       AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
503           aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A()));
504       AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
505           aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B()));
506       AttributePtr anAttrA, anAttrB;
507       if (aConstrIt->first->data()->isValid()) {
508         if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject())
509           continue;
510         anAttrA = aRefAttrA->attr();
511         anAttrB = aRefAttrB->attr();
512       } else {
513         // obtain attributes from the constraint wrapper
514         ConstraintWrapperPtr aWrapper = aConstrIt->second.front();
515         anAttrA = aWrapper->entities().front()->baseAttribute();
516         anAttrB = aWrapper->entities().back()->baseAttribute();
517       }
518       std::map<AttributePtr, EntityWrapperPtr>::iterator
519           aFound = myAttributeMap.find(anAttrA);
520       if (aFound != myAttributeMap.end())
521         aNotCoinc.erase(aFound->second);
522       aFound = myAttributeMap.find(anAttrB);
523       if (aFound != myAttributeMap.end())
524         aNotCoinc.erase(aFound->second);
525     }
526   if (aNotCoinc.empty())
527     return false;
528   std::list<EntityWrapperPtr>::const_iterator aNewPIt;
529   for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin();
530        aPIt != aPoints.end(); ++aPIt, ++aNewPIt) {
531     if (aNotCoinc.find(*aPIt) != aNotCoinc.end())
532       aNotCoinc[*aPIt] = *aNewPIt;
533   }
534
535   // Find all features and constraints uses coincident points
536   std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNotCIt;
537   std::set<EntityWrapperPtr> anUpdFeatures;
538   std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
539   for (; aFIt != myFeatureMap.end(); ++aFIt) {
540     if (!aFIt->second)
541       continue; // avoid not completed arcs
542     for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
543       if (!aNotCIt->second || !aFIt->second->isUsed(aNotCIt->first->baseAttribute()))
544         continue;
545       std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
546       std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
547       bool isUpd = false;
548       for (; aSIt != aSubs.end(); ++aSIt)
549         if (*aSIt == aNotCIt->first) {
550           *aSIt = aNotCIt->second;
551           isUpd = true;
552         }
553       if (isUpd) {
554         aFIt->second->setSubEntities(aSubs);
555         anUpdFeatures.insert(aFIt->second);
556       }
557     }
558   }
559   // update features
560   std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
561   for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
562     update(EntityWrapperPtr(*anUpdIt));
563
564   // remove not coincident points
565   for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
566     if (aPtPtIt->second.size() <= 1) {
567       myCoincidentPoints.erase(aPtPtIt);
568       break;
569     }
570     if (aPtPtIt->first == aNotCIt->first) {
571       std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
572       EntityWrapperPtr aNewMaster = *aSlaves.begin();
573       aSlaves.erase(aSlaves.begin());
574       myCoincidentPoints.erase(aPtPtIt);
575       myCoincidentPoints[aNewMaster] = aSlaves;
576       aPtPtIt = myCoincidentPoints.find(aNewMaster);
577     } else
578       aPtPtIt->second.erase(aNotCIt->first);
579   }
580   return true;
581 }
582
583 bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
584 {
585   bool isFullyRemoved = true;
586   std::list<EntityWrapperPtr>::const_iterator anIt = theConstraint->entities().begin();
587   for (; anIt != theConstraint->entities().end(); ++anIt) {
588     FeaturePtr aBaseFeature = (*anIt)->baseFeature();
589     if (aBaseFeature)
590       isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
591     else
592       isFullyRemoved = SketchSolver_Storage::removeEntity((*anIt)->baseAttribute()) && isFullyRemoved;
593   }
594   return isFullyRemoved;
595 }
596
597 bool SketchSolver_Storage::remove(EntityWrapperPtr theEntity)
598 {
599   bool isFullyRemoved = true;
600   std::list<EntityWrapperPtr>::const_iterator anEntIt = theEntity->subEntities().begin();
601   for (; anEntIt != theEntity->subEntities().end(); ++anEntIt) {
602     FeaturePtr aBaseFeature = (*anEntIt)->baseFeature();
603     if (aBaseFeature)
604       isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
605     else
606       isFullyRemoved = SketchSolver_Storage::removeEntity((*anEntIt)->baseAttribute()) && isFullyRemoved;
607   }
608
609   std::list<ParameterWrapperPtr>::const_iterator aParIt = theEntity->parameters().begin();
610   for (; aParIt != theEntity->parameters().end(); ++aParIt)
611     isFullyRemoved = remove(*aParIt) && isFullyRemoved;
612   return isFullyRemoved;
613 }
614
615
616 bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
617 {
618   if (!theFeature)
619     return false;
620   if (myConstraintMap.empty())
621     return true; // empty storage interacts with each feature
622
623   ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
624   if (aConstraint) {
625     if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
626       return true;
627   } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
628     return true;
629
630   std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
631   std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
632   for (; anIt != anAttrList.end(); ++anIt)
633     if (isInteract(*anIt))
634       return true;
635
636   return false;
637 }
638
639 bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
640 {
641   if (!theAttribute)
642     return false;
643
644   AttributeRefListPtr aRefList = 
645       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
646   if (aRefList) {
647     std::list<ObjectPtr> anObjects = aRefList->list();
648     std::list<ObjectPtr>::iterator anObjIt = anObjects.begin();
649     for (; anObjIt != anObjects.end(); ++anObjIt) {
650       FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
651       if (isInteract(aFeature))
652         return true;
653     }
654     return false;
655   }
656
657   AttributeRefAttrPtr aRefAttr =
658       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
659   if (!aRefAttr)
660     return myAttributeMap.find(theAttribute) != myAttributeMap.end();
661   if (!aRefAttr->isObject())
662     return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
663
664   FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
665   return isInteract(aFeature);
666 }
667
668 bool SketchSolver_Storage::isConsistent() const
669 {
670   // Check the constraints are valid
671   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
672       aCIter = myConstraintMap.begin();
673   for (; aCIter != myConstraintMap.end(); ++aCIter)
674     if (!aCIter->first->data() || !aCIter->first->data()->isValid())
675       return false;
676   // Check the features are valid
677   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
678   for (; aFIter != myFeatureMap.end(); aFIter++)
679     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
680       return false;
681   return true;
682 }
683
684 bool SketchSolver_Storage::isFixed(EntityWrapperPtr theEntity) const
685 {
686   if (theEntity->group() != myGroupID)
687     return true;
688   // no need additional checking for entities differ than point
689   if (theEntity->type() != ENTITY_POINT)
690     return false;
691
692   CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin();
693   for (; anIt != myCoincidentPoints.end(); ++anIt)
694     if (anIt->first == theEntity || anIt->second.find(theEntity) != anIt->second.end()) {
695       if (anIt->first->group() != myGroupID)
696         return true;
697       std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
698       for (; anEntIt != anIt->second.end(); ++anEntIt)
699         if ((*anEntIt)->group() != myGroupID)
700           return true;
701     }
702
703   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator aCIt = myConstraintMap.begin();
704   std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
705   for (; aCIt != myConstraintMap.end(); ++aCIt) {
706     if (aCIt->second.empty())
707       continue;
708     aCWIt = aCIt->second.begin();
709     if ((*aCWIt)->type() != CONSTRAINT_FIXED)
710       continue;
711     for (; aCWIt != aCIt->second.end(); ++aCIt)
712       if ((theEntity->baseAttribute() && (*aCWIt)->isUsed(theEntity->baseAttribute())) ||
713           (theEntity->baseFeature() && (*aCWIt)->isUsed(theEntity->baseFeature())))
714         return true;
715   }
716
717   return false;
718 }
719
720 void SketchSolver_Storage::removeInvalidEntities()
721 {
722   // Remove invalid constraints
723   std::list<ConstraintPtr> anInvalidConstraints;
724   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
725       aCIter = myConstraintMap.begin();
726   for (; aCIter != myConstraintMap.end(); ++aCIter)
727     if (!aCIter->first->data() || !aCIter->first->data()->isValid())
728       anInvalidConstraints.push_back(aCIter->first);
729   std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
730   for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
731     removeConstraint(*anInvCIt);
732   // Remove invalid features
733   std::list<FeaturePtr> anInvalidFeatures;
734   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
735   for (; aFIter != myFeatureMap.end(); aFIter++)
736     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
737       anInvalidFeatures.push_back(aFIter->first);
738   std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
739   for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
740     removeEntity(*anInvFIt);
741 }
742
743 EntityWrapperPtr SketchSolver_Storage::getNormal() const
744 {
745   EntityWrapperPtr aSketch = sketch();
746   if (!aSketch)
747     return aSketch;
748
749   // Find normal entity
750   const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
751   std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
752   for (; aSIt != aSketchSubs.end(); ++aSIt)
753     if ((*aSIt)->type() == ENTITY_NORMAL)
754       return *aSIt;
755   return EntityWrapperPtr();
756 }
757
758 const EntityWrapperPtr& SketchSolver_Storage::sketch() const
759 {
760   static EntityWrapperPtr aDummySketch;
761
762   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
763   for (; aFIt != myFeatureMap.end(); ++aFIt)
764     if (aFIt->second && aFIt->second->type() == ENTITY_SKETCH)
765       break;
766   if (aFIt == myFeatureMap.end())
767     return aDummySketch;
768   return aFIt->second;
769 }
770
771 void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
772 {
773   if (sketch())
774     return;
775   addEntity(FeaturePtr(), theSketch);
776 }
777
778 void SketchSolver_Storage::processArcs()
779 {
780   myExistArc = false;
781   std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
782   for (; aFIt != myFeatureMap.end(); ++aFIt)
783     if (!aFIt->second && aFIt->first->getKind() == SketchPlugin_Arc::ID()) {
784       // Additional checking the attributes are initialized
785       if (aFIt->first->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() && 
786           aFIt->first->attribute(SketchPlugin_Arc::START_ID())->isInitialized() && 
787           aFIt->first->attribute(SketchPlugin_Arc::END_ID())->isInitialized())
788         update(aFIt->first);
789       else
790         myExistArc = true;
791     }
792 }
793
794 void SketchSolver_Storage::blockEvents(bool isBlocked)
795 {
796   if (isBlocked == myEventsBlocked)
797     return;
798
799   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
800       aCIter = myConstraintMap.begin();
801   for (; aCIter != myConstraintMap.end(); aCIter++)
802     if (aCIter->first->data() && aCIter->first->data()->isValid())
803       aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
804
805   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
806   for (; aFIter != myFeatureMap.end(); aFIter++)
807     if (aFIter->first->data() && aFIter->first->data()->isValid())
808       aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
809
810   std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
811   for (; anAtIter != myAttributeMap.end(); anAtIter++)
812     if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
813         anAtIter->first->owner()->data()->isValid())
814       anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
815   myEventsBlocked = isBlocked;
816 }
817
818 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
819 {
820   std::set<ObjectPtr> aConflicting;
821   std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
822       aConstrIt = myConstraintMap.begin();
823   for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
824     std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstrIt->second.begin();
825     for (; anIt != aConstrIt->second.end(); ++anIt)
826       if (theSolver->isConflicting((*anIt)->id())) {
827         aConflicting.insert(aConstrIt->first);
828         break;
829       }
830   }
831   return aConflicting;
832 }
833
834
835
836
837
838 // ==============   Auxiliary functions   ====================================
839 bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
840              const std::list<ConstraintWrapperPtr>& theCVec2)
841 {
842   if (theCVec1.size() != theCVec2.size())
843     return false;
844
845   std::list<bool> aChecked(theCVec2.size(), false);
846   std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
847   for (; anIt1 != theCVec1.end(); ++anIt1) {
848     std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
849     std::list<bool>::iterator aCheckIt = aChecked.begin();
850     while (aCheckIt != aChecked.end() && *aCheckIt) {
851       ++aCheckIt;
852       ++anIt2;
853     }
854     for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
855       if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
856         *aCheckIt = true;
857         break;
858       }
859     // the same constraint is not found
860     if (anIt2 == theCVec2.end())
861       return false;
862   }
863   return true;
864 }