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 (!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->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->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 ////const ParameterWrapperPtr& SketchSolver_Storage::parameter(const AttributeDoublePtr& theAttribute) const
178 //// static ParameterWrapperPtr aDummy;
180 //// std::map<AttributeDoublePtr, ParameterWrapperPtr>::const_iterator
181 //// aFound = myParametersMap.find(theAttribute);
182 //// if (aFound != myParametersMap.end())
183 //// return aFound->second;
188 bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
192 if (myConstraintMap.empty())
193 return true; // empty storage interacts with each feature
195 ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
197 if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
199 } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
202 std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
203 std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
204 for (; anIt != anAttrList.end(); ++anIt)
205 if (isInteract(*anIt))
211 bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
216 AttributeRefAttrPtr aRefAttr =
217 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
219 return myAttributeMap.find(theAttribute) != myAttributeMap.end();
220 if (!aRefAttr->isObject())
221 return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
223 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
224 return isInteract(aFeature);
227 bool SketchSolver_Storage::isConsistent() const
229 // Check the constraints are valid
230 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
231 aCIter = myConstraintMap.begin();
232 for (; aCIter != myConstraintMap.end(); ++aCIter)
233 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
235 // Check the features are valid
236 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
237 for (; aFIter != myFeatureMap.end(); aFIter++)
238 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
243 void SketchSolver_Storage::removeInvalidEntities()
245 // Remove invalid constraints
246 std::list<ConstraintPtr> anInvalidConstraints;
247 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
248 aCIter = myConstraintMap.begin();
249 for (; aCIter != myConstraintMap.end(); ++aCIter)
250 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
251 anInvalidConstraints.push_back(aCIter->first);
252 std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
253 for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
254 removeConstraint(*anInvCIt);
255 // Remove invalid features
256 std::list<FeaturePtr> anInvalidFeatures;
257 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
258 for (; aFIter != myFeatureMap.end(); aFIter++)
259 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
260 anInvalidFeatures.push_back(aFIter->first);
261 std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
262 for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
263 removeEntity(*anInvFIt);
266 EntityWrapperPtr SketchSolver_Storage::getNormal() const
268 EntityWrapperPtr aSketch = sketch();
272 // Find normal entity
273 const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
274 std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
275 for (; aSIt != aSketchSubs.end(); ++aSIt)
276 if ((*aSIt)->type() == ENTITY_NORMAL)
278 return EntityWrapperPtr();
281 const EntityWrapperPtr& SketchSolver_Storage::sketch() const
283 static EntityWrapperPtr aDummySketch;
285 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
286 for (; aFIt != myFeatureMap.end(); ++aFIt)
287 if (aFIt->second->type() == ENTITY_SKETCH)
289 if (aFIt == myFeatureMap.end())
294 void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
298 addEntity(FeaturePtr(), theSketch);
301 void SketchSolver_Storage::blockEvents(bool isBlocked) const
303 std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
304 aCIter = myConstraintMap.begin();
305 for (; aCIter != myConstraintMap.end(); aCIter++)
306 if (aCIter->first->data() && aCIter->first->data()->isValid())
307 aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
309 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
310 for (; aFIter != myFeatureMap.end(); aFIter++)
311 if (aFIter->first->data() && aFIter->first->data()->isValid())
312 aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
314 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
315 for (; anAtIter != myAttributeMap.end(); anAtIter++)
316 if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
317 anAtIter->first->owner()->data()->isValid())
318 anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
326 // ============== Auxiliary functions ====================================
327 bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
328 const std::list<ConstraintWrapperPtr>& theCVec2)
330 if (theCVec1.size() != theCVec2.size())
333 std::list<bool> aChecked(theCVec2.size(), false);
334 std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
335 for (; anIt1 != theCVec1.end(); ++anIt1) {
336 std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
337 std::list<bool>::iterator aCheckIt = aChecked.begin();
338 while (aCheckIt != aChecked.end() && *aCheckIt) {
342 for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
343 if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
347 // the same constraint is not found
348 if (anIt2 == theCVec2.end())