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 <PlaneGCSSolver_UpdateCoincidence.h>
9 #include <PlaneGCSSolver_UpdateFeature.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>
23 SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
24 : mySketchSolver(theSolver),
25 myNeedToResolve(false),
26 myEventsBlocked(false)
28 // create updaters (constraints processed at first)
29 UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
30 myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
33 void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint,
34 ConstraintWrapperPtr theSolverConstraint)
36 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
37 aFound = myConstraintMap.find(theConstraint);
38 if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
39 setNeedToResolve(true);
41 //// if (theSolverConstraints.empty()) {
42 //// // constraint links to the empty list, add its attributes linked to the empty entities
43 //// std::list<AttributePtr> aRefAttrs =
44 //// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
45 //// std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
46 //// for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
47 //// AttributeRefAttrPtr aRef =
48 //// 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());
53 //// addEntity(aRef->attr(), EntityWrapperPtr());
55 //// std::list<AttributePtr> aRefLists =
56 //// theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
57 //// for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
58 //// AttributeRefListPtr aRef =
59 //// std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
60 //// std::list<ObjectPtr> anObj = aRef->list();
61 //// std::list<ObjectPtr>::iterator anIt = anObj.begin();
62 //// for (; anIt != anObj.end(); ++anIt) {
63 //// FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
64 //// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
68 //// else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
69 //// // Do not add point-point coincidence, because it is already made by setting
70 //// // the same parameters for both points
71 //// std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
72 //// for (; aCIt != theSolverConstraints.end(); ++aCIt)
76 if (!theSolverConstraint || aFound == myConstraintMap.end())
77 myConstraintMap[theConstraint] = theSolverConstraint;
78 // block events if necessary
79 if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
80 theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
83 static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
85 std::list<AttributePtr> aPoints;
86 if (!theFeature->data() || !theFeature->data()->isValid())
88 if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
89 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
90 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::START_ID()));
91 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::END_ID()));
93 else if (theFeature->getKind() == SketchPlugin_Circle::ID())
94 aPoints.push_back(theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
95 else if (theFeature->getKind() == SketchPlugin_Line::ID()) {
96 aPoints.push_back(theFeature->attribute(SketchPlugin_Line::START_ID()));
97 aPoints.push_back(theFeature->attribute(SketchPlugin_Line::END_ID()));
99 else if (theFeature->getKind() == SketchPlugin_Point::ID() ||
100 theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
101 aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID()));
105 void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
106 EntityWrapperPtr theSolverEntity)
108 if (theSolverEntity) {
109 myFeatureMap[theFeature] = theSolverEntity;
110 setNeedToResolve(true);
112 // feature links to the empty entity, add its attributes
113 std::list<AttributePtr> aPntAttrs = pointAttributes(theFeature);
114 std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
115 for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
116 addEntity(*anAttrIt, EntityWrapperPtr());
117 myFeatureMap[theFeature] = theSolverEntity;
120 // block events if necessary
121 if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
122 theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
125 void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
126 EntityWrapperPtr theSolverEntity)
128 if (theSolverEntity) {
129 myAttributeMap[theAttribute] = theSolverEntity;
130 setNeedToResolve(true);
133 // block events if necessary
134 if (myEventsBlocked && theAttribute->owner() &&
135 theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
136 theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
141 const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
142 const ConstraintPtr& theConstraint) const
144 static ConstraintWrapperPtr aDummy;
146 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
147 aFound = myConstraintMap.find(theConstraint);
148 if (aFound != myConstraintMap.end())
149 return aFound->second;
153 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
155 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
156 if (aFound != myFeatureMap.end())
157 return aFound->second;
159 static EntityWrapperPtr aDummy;
163 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
165 std::map<AttributePtr, EntityWrapperPtr>::const_iterator
166 aFound = myAttributeMap.find(theAttribute);
167 if (aFound != myAttributeMap.end())
168 return aFound->second;
170 AttributeRefAttrPtr aRefAttr =
171 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
173 AttributePtr anAttribute;
175 if (aRefAttr->isObject()) {
176 /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
178 resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
180 return entity(aFeature);
182 anAttribute = aRefAttr->attr();
184 return entity(anAttribute);
187 static EntityWrapperPtr aDummy;
192 void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
194 myFeatureMap.erase(theFeature);
197 void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
199 myAttributeMap.erase(theAttribute);
203 bool SketchSolver_Storage::isConsistent() const
205 // Check the constraints are valid
206 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
207 aCIter = myConstraintMap.begin();
208 for (; aCIter != myConstraintMap.end(); ++aCIter)
209 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
211 // Check the features are valid
212 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
213 for (; aFIter != myFeatureMap.end(); aFIter++)
214 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
219 void SketchSolver_Storage::blockEvents(bool isBlocked)
221 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
222 for (; aFIter != myFeatureMap.end(); aFIter++)
223 if (aFIter->first->data() && aFIter->first->data()->isValid())
224 aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
226 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
227 for (; anAtIter != myAttributeMap.end(); anAtIter++)
228 if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
229 anAtIter->first->owner()->data()->isValid())
230 anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
232 myEventsBlocked = isBlocked;
235 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
237 std::set<ObjectPtr> aConflicting;
238 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
239 aConstrIt = myConstraintMap.begin();
240 for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
241 if (theSolver->isConflicting(aConstrIt->second->id()))
242 aConflicting.insert(aConstrIt->first);
247 void SketchSolver_Storage::subscribeUpdates(
248 SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
250 myUpdaters->attach(theSubscriber, theGroup);
253 void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
255 myUpdaters->detach(theSubscriber);
258 void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
260 myUpdaters->update(theFeature);
263 void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
264 FeaturePtr& theFeature, AttributePtr& theAttribute)
266 FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
270 // if the feature has several results, we choose which one is referred
271 const std::list<ResultPtr>& aResults = aFeature->results();
272 if (aResults.size() > 1 && theResult != aFeature->lastResult()) {
273 // actually, the attribute refers to center of arc or circle,
274 // but not the edge, get correct attributes
275 std::string anAttrName;
276 if (aFeature->getKind() == SketchPlugin_Arc::ID())
277 anAttrName = SketchPlugin_Arc::CENTER_ID();
278 else if (aFeature->getKind() == SketchPlugin_Circle::ID())
279 anAttrName = SketchPlugin_Circle::CENTER_ID();
280 if (!anAttrName.empty()) {
281 theAttribute = aFeature->attribute(anAttrName);
282 aFeature = FeaturePtr();
285 theFeature = aFeature;