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 = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
48 //// if (aRef->isObject()) {
49 //// FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
50 //// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
52 //// addEntity(aRef->attr(), EntityWrapperPtr());
54 //// std::list<AttributePtr> aRefLists =
55 //// theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
56 //// for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
57 //// AttributeRefListPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
58 //// std::list<ObjectPtr> anObj = aRef->list();
59 //// std::list<ObjectPtr>::iterator anIt = anObj.begin();
60 //// for (; anIt != anObj.end(); ++anIt) {
61 //// FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
62 //// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
66 //// else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
67 //// // Do not add point-point coincidence, because it is already made by setting
68 //// // the same parameters for both points
69 //// std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
70 //// for (; aCIt != theSolverConstraints.end(); ++aCIt)
74 if (!theSolverConstraint || aFound == myConstraintMap.end())
75 myConstraintMap[theConstraint] = theSolverConstraint;
76 // block events if necessary
77 if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
78 theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
81 static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
83 std::list<AttributePtr> aPoints;
84 if (!theFeature->data() || !theFeature->data()->isValid())
86 if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
87 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
88 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::START_ID()));
89 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::END_ID()));
91 else if (theFeature->getKind() == SketchPlugin_Circle::ID())
92 aPoints.push_back(theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
93 else if (theFeature->getKind() == SketchPlugin_Line::ID()) {
94 aPoints.push_back(theFeature->attribute(SketchPlugin_Line::START_ID()));
95 aPoints.push_back(theFeature->attribute(SketchPlugin_Line::END_ID()));
97 else if (theFeature->getKind() == SketchPlugin_Point::ID() ||
98 theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
99 aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID()));
103 void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
104 EntityWrapperPtr theSolverEntity)
106 if (theSolverEntity) {
107 myFeatureMap[theFeature] = theSolverEntity;
108 setNeedToResolve(true);
110 // feature links to the empty entity, add its attributes
111 std::list<AttributePtr> aPntAttrs = pointAttributes(theFeature);
112 std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
113 for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
114 addEntity(*anAttrIt, EntityWrapperPtr());
115 myFeatureMap[theFeature] = theSolverEntity;
118 // block events if necessary
119 if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
120 theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
123 void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
124 EntityWrapperPtr theSolverEntity)
126 if (theSolverEntity) {
127 myAttributeMap[theAttribute] = theSolverEntity;
128 setNeedToResolve(true);
131 // block events if necessary
132 if (myEventsBlocked && theAttribute->owner() &&
133 theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
134 theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
139 const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
140 const ConstraintPtr& theConstraint) const
142 static ConstraintWrapperPtr aDummy;
144 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
145 aFound = myConstraintMap.find(theConstraint);
146 if (aFound != myConstraintMap.end())
147 return aFound->second;
151 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
153 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
154 if (aFound != myFeatureMap.end())
155 return aFound->second;
157 static EntityWrapperPtr aDummy;
161 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
163 std::map<AttributePtr, EntityWrapperPtr>::const_iterator
164 aFound = myAttributeMap.find(theAttribute);
165 if (aFound != myAttributeMap.end())
166 return aFound->second;
168 AttributeRefAttrPtr aRefAttr =
169 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
171 AttributePtr anAttribute;
173 if (aRefAttr->isObject()) {
174 /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
176 resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
178 return entity(aFeature);
180 anAttribute = aRefAttr->attr();
182 return entity(anAttribute);
185 static EntityWrapperPtr aDummy;
190 void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
192 myFeatureMap.erase(theFeature);
195 void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
197 myAttributeMap.erase(theAttribute);
201 bool SketchSolver_Storage::isConsistent() const
203 // Check the constraints are valid
204 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
205 aCIter = myConstraintMap.begin();
206 for (; aCIter != myConstraintMap.end(); ++aCIter)
207 if (!aCIter->first->data() || !aCIter->first->data()->isValid())
209 // Check the features are valid
210 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
211 for (; aFIter != myFeatureMap.end(); aFIter++)
212 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
217 void SketchSolver_Storage::blockEvents(bool isBlocked)
219 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
220 for (; aFIter != myFeatureMap.end(); aFIter++)
221 if (aFIter->first->data() && aFIter->first->data()->isValid())
222 aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
224 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
225 for (; anAtIter != myAttributeMap.end(); anAtIter++)
226 if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
227 anAtIter->first->owner()->data()->isValid())
228 anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
230 myEventsBlocked = isBlocked;
233 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
235 std::set<ObjectPtr> aConflicting;
236 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
237 aConstrIt = myConstraintMap.begin();
238 for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
239 if (theSolver->isConflicting(aConstrIt->second->id())) {
240 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;