1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <SketchSolver_Storage.h>
22 #include <PlaneGCSSolver_UpdateCoincidence.h>
23 #include <PlaneGCSSolver_UpdateFeature.h>
25 #include <ModelAPI_AttributeRefAttr.h>
26 #include <ModelAPI_AttributeRefList.h>
27 #include <SketchPlugin_Arc.h>
28 #include <SketchPlugin_Circle.h>
29 #include <SketchPlugin_Line.h>
30 #include <SketchPlugin_Point.h>
31 #include <SketchPlugin_IntersectionPoint.h>
32 #include <SketchPlugin_ConstraintCoincidence.h>
33 #include <SketchPlugin_ConstraintMirror.h>
34 #include <SketchPlugin_ConstraintRigid.h>
37 SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
38 : mySketchSolver(theSolver),
39 myNeedToResolve(false),
40 myEventsBlocked(false)
42 // create updaters (constraints processed at first)
43 UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
44 myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
47 void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint,
48 ConstraintWrapperPtr theSolverConstraint)
50 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
51 aFound = myConstraintMap.find(theConstraint);
52 if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
53 setNeedToResolve(true);
55 //// if (theSolverConstraints.empty()) {
56 //// // constraint links to the empty list, add its attributes linked to the empty entities
57 //// std::list<AttributePtr> aRefAttrs =
58 //// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
59 //// std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
60 //// for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
61 //// AttributeRefAttrPtr aRef =
62 //// std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
63 //// if (aRef->isObject()) {
64 //// FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
65 //// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
67 //// addEntity(aRef->attr(), EntityWrapperPtr());
69 //// std::list<AttributePtr> aRefLists =
70 //// theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
71 //// for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
72 //// AttributeRefListPtr aRef =
73 //// std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
74 //// std::list<ObjectPtr> anObj = aRef->list();
75 //// std::list<ObjectPtr>::iterator anIt = anObj.begin();
76 //// for (; anIt != anObj.end(); ++anIt) {
77 //// FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
78 //// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
82 //// else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
83 //// // Do not add point-point coincidence, because it is already made by setting
84 //// // the same parameters for both points
85 //// std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
86 //// for (; aCIt != theSolverConstraints.end(); ++aCIt)
90 if (!theSolverConstraint || aFound == myConstraintMap.end())
91 myConstraintMap[theConstraint] = theSolverConstraint;
92 // block events if necessary
93 if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
94 theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
97 static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
99 std::list<AttributePtr> aPoints;
100 if (!theFeature->data() || !theFeature->data()->isValid())
102 if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
103 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
104 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::START_ID()));
105 aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::END_ID()));
107 else if (theFeature->getKind() == SketchPlugin_Circle::ID())
108 aPoints.push_back(theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
109 else if (theFeature->getKind() == SketchPlugin_Line::ID()) {
110 aPoints.push_back(theFeature->attribute(SketchPlugin_Line::START_ID()));
111 aPoints.push_back(theFeature->attribute(SketchPlugin_Line::END_ID()));
113 else if (theFeature->getKind() == SketchPlugin_Point::ID() ||
114 theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
115 aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID()));
119 void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
120 EntityWrapperPtr theSolverEntity)
122 if (theSolverEntity) {
123 myFeatureMap[theFeature] = theSolverEntity;
124 setNeedToResolve(true);
126 // feature links to the empty entity, add its attributes
127 std::list<AttributePtr> aPntAttrs = pointAttributes(theFeature);
128 std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
129 for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
130 addEntity(*anAttrIt, EntityWrapperPtr());
131 myFeatureMap[theFeature] = theSolverEntity;
134 // block events if necessary
135 if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
136 theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
139 void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
140 EntityWrapperPtr theSolverEntity)
142 if (theSolverEntity) {
143 myAttributeMap[theAttribute] = theSolverEntity;
144 setNeedToResolve(true);
147 // block events if necessary
148 if (myEventsBlocked && theAttribute->owner() &&
149 theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
150 theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
155 const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
156 const ConstraintPtr& theConstraint) const
158 static ConstraintWrapperPtr aDummy;
160 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
161 aFound = myConstraintMap.find(theConstraint);
162 if (aFound != myConstraintMap.end())
163 return aFound->second;
167 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
169 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
170 if (aFound != myFeatureMap.end())
171 return aFound->second;
173 static EntityWrapperPtr aDummy;
177 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
179 std::map<AttributePtr, EntityWrapperPtr>::const_iterator
180 aFound = myAttributeMap.find(theAttribute);
181 if (aFound != myAttributeMap.end())
182 return aFound->second;
184 AttributeRefAttrPtr aRefAttr =
185 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
187 AttributePtr anAttribute;
189 if (aRefAttr->isObject()) {
190 /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
192 resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
194 return entity(aFeature);
196 anAttribute = aRefAttr->attr();
198 return entity(anAttribute);
201 static EntityWrapperPtr aDummy;
206 void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
208 myFeatureMap.erase(theFeature);
209 myNeedToResolve = true;
212 void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
214 myAttributeMap.erase(theAttribute);
215 myNeedToResolve = true;
219 bool SketchSolver_Storage::areFeaturesValid() const
221 // Check the features are valid
222 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
223 for (; aFIter != myFeatureMap.end(); aFIter++)
224 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
229 void SketchSolver_Storage::blockEvents(bool isBlocked)
231 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
232 for (; aFIter != myFeatureMap.end(); aFIter++)
233 if (aFIter->first->data() && aFIter->first->data()->isValid())
234 aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
236 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
237 for (; anAtIter != myAttributeMap.end(); anAtIter++)
238 if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
239 anAtIter->first->owner()->data()->isValid())
240 anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
242 myEventsBlocked = isBlocked;
245 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
247 std::set<ObjectPtr> aConflicting;
248 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
249 aConstrIt = myConstraintMap.begin();
250 for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
251 if (theSolver->isConflicting(aConstrIt->second->id()))
252 aConflicting.insert(aConstrIt->first);
257 void SketchSolver_Storage::subscribeUpdates(
258 SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
260 myUpdaters->attach(theSubscriber, theGroup);
263 void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
265 myUpdaters->detach(theSubscriber);
268 void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
270 myUpdaters->update(theFeature);
273 void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
274 FeaturePtr& theFeature, AttributePtr& theAttribute)
276 FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
280 // if the feature has several results, we choose which one is referred
281 const std::list<ResultPtr>& aResults = aFeature->results();
282 if (aResults.size() > 1 && theResult != aFeature->lastResult()) {
283 // actually, the attribute refers to center of arc or circle,
284 // but not the edge, get correct attributes
285 std::string anAttrName;
286 if (aFeature->getKind() == SketchPlugin_Arc::ID())
287 anAttrName = SketchPlugin_Arc::CENTER_ID();
288 else if (aFeature->getKind() == SketchPlugin_Circle::ID())
289 anAttrName = SketchPlugin_Circle::CENTER_ID();
290 if (!anAttrName.empty()) {
291 theAttribute = aFeature->attribute(anAttrName);
292 aFeature = FeaturePtr();
295 theFeature = aFeature;