1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: SketchSolver_Storage.cpp
4 // Created: 30 Nov 2015
5 // Author: Artem ZHIDKOV
7 #include <SketchSolver_Storage.h>
8 #include <SketchSolver_Manager.h>
10 #include <GeomDataAPI_Point2D.h>
11 #include <ModelAPI_AttributeRefAttr.h>
12 #include <SketchPlugin_Arc.h>
13 #include <SketchPlugin_Circle.h>
16 /// \brief Verify two vectors of constraints are equal.
17 /// Vectors differ by the order of elements are equal.
18 static bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
19 const std::list<ConstraintWrapperPtr>& theCVec2);
22 void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint,
23 ConstraintWrapperPtr theSolverConstraint)
25 std::list<ConstraintWrapperPtr> aConstrList(1, theSolverConstraint);
26 addConstraint(theConstraint, aConstrList);
29 void SketchSolver_Storage::addConstraint(
30 ConstraintPtr theConstraint,
31 std::list<ConstraintWrapperPtr> theSolverConstraints)
33 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
34 aFound = myConstraintMap.find(theConstraint);
35 if (aFound == myConstraintMap.end() || !isEqual(aFound->second, theSolverConstraints))
36 setNeedToResolve(true);
38 // Do not add point-point coincidence, because it is already made by setting
39 // the same parameters for both points
40 if (!theSolverConstraints.empty() &&
41 theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
42 std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
43 for (; aCIt != theSolverConstraints.end(); ++aCIt)
46 myConstraintMap[theConstraint] = theSolverConstraints;
49 void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
50 EntityWrapperPtr theSolverEntity)
52 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
53 if (aFound == myFeatureMap.end() || !aFound->second || !aFound->second->isEqual(theSolverEntity))
54 setNeedToResolve(true); // the entity is new or modified
56 myFeatureMap[theFeature] = theSolverEntity;
59 void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
60 EntityWrapperPtr theSolverEntity)
62 std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound = myAttributeMap.find(theAttribute);
63 if (aFound == myAttributeMap.end() || !aFound->second || !aFound->second->isEqual(theSolverEntity))
64 setNeedToResolve(true); // the entity is new or modified
66 myAttributeMap[theAttribute] = theSolverEntity;
70 bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup)
72 bool isUpdated = false;
73 EntityWrapperPtr aRelated = entity(theFeature);
74 if (!aRelated) { // Feature is not exist, create it
75 std::list<EntityWrapperPtr> aSubs;
76 // Firstly, create/update its attributes
77 std::list<AttributePtr> anAttrs =
78 theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
79 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
80 for (; anIt != anAttrs.end(); ++anIt) {
81 isUpdated = update(*anIt, theGroup) || isUpdated;
82 aSubs.push_back(entity(*anIt));
84 // If the feature is a circle, add its radius as a sub
85 if (theFeature->getKind() == SketchPlugin_Circle::ID()) {
86 AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
87 isUpdated = update(aRadius, theGroup) || isUpdated;
88 aSubs.push_back(entity(aRadius));
90 // If the feature if circle or arc, we need to add normal of the sketch to the list of subs
91 if (theFeature->getKind() == SketchPlugin_Arc::ID() ||
92 theFeature->getKind() == SketchPlugin_Circle::ID()) {
93 EntityWrapperPtr aNormal = getNormal();
94 if (aNormal) aSubs.push_back(aNormal);
96 // Secondly, convert feature
97 BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
98 aRelated = aBuilder->createFeature(theFeature, aSubs, theGroup);
101 addEntity(theFeature, aRelated);
102 } else if (theGroup != GID_UNKNOWN)
103 changeGroup(aRelated, theGroup);
104 return update(aRelated) || isUpdated;
107 bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup)
109 AttributePtr anAttribute = theAttribute;
110 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
112 if (aRefAttr->isObject()) {
113 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
114 return update(aFeature, theGroup);
116 anAttribute = aRefAttr->attr();
119 EntityWrapperPtr aRelated = entity(anAttribute);
120 if (!aRelated) { // Attribute is not exist, create it
121 BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
122 aRelated = aBuilder->createAttribute(anAttribute, theGroup);
125 addEntity(anAttribute, aRelated);
126 } else if (theGroup != GID_UNKNOWN)
127 changeGroup(aRelated, theGroup);
128 return update(aRelated);
133 const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
134 const ConstraintPtr& theConstraint) const
136 static std::list<ConstraintWrapperPtr> aDummy;
138 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr>>::const_iterator
139 aFound = myConstraintMap.find(theConstraint);
140 if (aFound != myConstraintMap.end())
141 return aFound->second;
145 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
147 static EntityWrapperPtr aDummy;
149 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
150 if (aFound != myFeatureMap.end())
151 return aFound->second;
155 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
157 static EntityWrapperPtr aDummy;
159 std::map<AttributePtr, EntityWrapperPtr>::const_iterator
160 aFound = myAttributeMap.find(theAttribute);
161 if (aFound != myAttributeMap.end())
162 return aFound->second;
164 AttributeRefAttrPtr aRefAttr =
165 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
167 if (aRefAttr->isObject()) {
168 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
169 return entity(aFeature);
171 return entity(aRefAttr->attr());
176 bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
180 if (myConstraintMap.empty())
181 return true; // empty storage interacts with each feature
183 ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
185 if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
187 } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
190 std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
191 std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
192 for (; anIt != anAttrList.end(); ++anIt)
193 if (isInteract(*anIt))
199 bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
204 AttributeRefAttrPtr aRefAttr =
205 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
207 return myAttributeMap.find(theAttribute) != myAttributeMap.end();
208 if (!aRefAttr->isObject())
209 return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
211 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
212 return isInteract(aFeature);
215 bool SketchSolver_Storage::isConsistent() const
217 // Check the constraints are valid
218 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
219 aCIter = myConstraintMap.begin();
220 for (; aCIter != myConstraintMap.end(); ++aCIter)
221 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
223 // Check the features are valid
224 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
225 for (; aFIter != myFeatureMap.end(); aFIter++)
226 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
231 bool SketchSolver_Storage::isFixed(EntityWrapperPtr theEntity) const
233 if (theEntity->group() != myGroupID)
235 // no need additional checking for entities differ than point
236 if (theEntity->type() != ENTITY_POINT)
239 CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin();
240 for (; anIt != myCoincidentPoints.end(); ++anIt)
241 if (anIt->first == theEntity || anIt->second.find(theEntity) != anIt->second.end()) {
242 if (anIt->first->group() != myGroupID)
244 std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
245 for (; anEntIt != anIt->second.end(); ++anEntIt)
246 if ((*anEntIt)->group() != myGroupID)
252 void SketchSolver_Storage::removeInvalidEntities()
254 // Remove invalid constraints
255 std::list<ConstraintPtr> anInvalidConstraints;
256 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
257 aCIter = myConstraintMap.begin();
258 for (; aCIter != myConstraintMap.end(); ++aCIter)
259 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
260 anInvalidConstraints.push_back(aCIter->first);
261 std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
262 for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
263 removeConstraint(*anInvCIt);
264 // Remove invalid features
265 std::list<FeaturePtr> anInvalidFeatures;
266 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
267 for (; aFIter != myFeatureMap.end(); aFIter++)
268 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
269 anInvalidFeatures.push_back(aFIter->first);
270 std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
271 for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
272 removeEntity(*anInvFIt);
275 EntityWrapperPtr SketchSolver_Storage::getNormal() const
277 EntityWrapperPtr aSketch = sketch();
281 // Find normal entity
282 const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
283 std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
284 for (; aSIt != aSketchSubs.end(); ++aSIt)
285 if ((*aSIt)->type() == ENTITY_NORMAL)
287 return EntityWrapperPtr();
290 const EntityWrapperPtr& SketchSolver_Storage::sketch() const
292 static EntityWrapperPtr aDummySketch;
294 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
295 for (; aFIt != myFeatureMap.end(); ++aFIt)
296 if (aFIt->second->type() == ENTITY_SKETCH)
298 if (aFIt == myFeatureMap.end())
303 void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
307 addEntity(FeaturePtr(), theSketch);
310 void SketchSolver_Storage::blockEvents(bool isBlocked) const
312 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
313 aCIter = myConstraintMap.begin();
314 for (; aCIter != myConstraintMap.end(); aCIter++)
315 if (aCIter->first->data() && aCIter->first->data()->isValid())
316 aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
318 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
319 for (; aFIter != myFeatureMap.end(); aFIter++)
320 if (aFIter->first->data() && aFIter->first->data()->isValid())
321 aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
323 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
324 for (; anAtIter != myAttributeMap.end(); anAtIter++)
325 if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
326 anAtIter->first->owner()->data()->isValid())
327 anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
335 // ============== Auxiliary functions ====================================
336 bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
337 const std::list<ConstraintWrapperPtr>& theCVec2)
339 if (theCVec1.size() != theCVec2.size())
342 std::list<bool> aChecked(theCVec2.size(), false);
343 std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
344 for (; anIt1 != theCVec1.end(); ++anIt1) {
345 std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
346 std::list<bool>::iterator aCheckIt = aChecked.begin();
347 while (aCheckIt != aChecked.end() && *aCheckIt) {
351 for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
352 if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
356 // the same constraint is not found
357 if (anIt2 == theCVec2.end())