1 // Copyright (C) 2014-2020 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 email : webmaster.salome@opencascade.com
20 #include <SketchSolver_Storage.h>
21 #include <PlaneGCSSolver_UpdateCoincidence.h>
22 #include <PlaneGCSSolver_UpdateFeature.h>
24 #include <ModelAPI_AttributeRefAttr.h>
25 #include <ModelAPI_AttributeRefList.h>
26 #include <SketchPlugin_Arc.h>
27 #include <SketchPlugin_Circle.h>
28 #include <SketchPlugin_Line.h>
29 #include <SketchPlugin_Point.h>
30 #include <SketchPlugin_IntersectionPoint.h>
31 #include <SketchPlugin_ConstraintCoincidence.h>
32 #include <SketchPlugin_ConstraintMirror.h>
33 #include <SketchPlugin_ConstraintRigid.h>
36 SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
37 : mySketchSolver(theSolver),
38 myNeedToResolve(false),
39 myEventsBlocked(false)
41 // create updaters (constraints processed at first)
42 UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
43 myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
46 void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint,
47 ConstraintWrapperPtr theSolverConstraint)
49 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
50 aFound = myConstraintMap.find(theConstraint);
51 if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
52 setNeedToResolve(true);
54 //// if (theSolverConstraints.empty()) {
55 //// // constraint links to the empty list, add its attributes linked to the empty entities
56 //// std::list<AttributePtr> aRefAttrs =
57 //// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
58 //// std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
59 //// for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
60 //// AttributeRefAttrPtr aRef =
61 //// std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
62 //// if (aRef->isObject()) {
63 //// FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
64 //// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
66 //// addEntity(aRef->attr(), EntityWrapperPtr());
68 //// std::list<AttributePtr> aRefLists =
69 //// theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
70 //// for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
71 //// AttributeRefListPtr aRef =
72 //// std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
73 //// std::list<ObjectPtr> anObj = aRef->list();
74 //// std::list<ObjectPtr>::iterator anIt = anObj.begin();
75 //// for (; anIt != anObj.end(); ++anIt) {
76 //// FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
77 //// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
81 //// else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
82 //// // Do not add point-point coincidence, because it is already made by setting
83 //// // the same parameters for both points
84 //// std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
85 //// for (; aCIt != theSolverConstraints.end(); ++aCIt)
89 if (!theSolverConstraint || aFound == myConstraintMap.end())
90 myConstraintMap[theConstraint] = theSolverConstraint;
91 // block events if necessary
92 if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
93 theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
96 void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
97 EntityWrapperPtr theSolverEntity)
99 if (theSolverEntity) {
100 myFeatureMap[theFeature] = theSolverEntity;
101 setNeedToResolve(true);
104 // block events if necessary
105 if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
106 theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
109 void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
110 EntityWrapperPtr theSolverEntity)
112 if (theSolverEntity) {
113 myAttributeMap[theAttribute] = theSolverEntity;
114 setNeedToResolve(true);
117 // block events if necessary
118 if (myEventsBlocked && theAttribute->owner() &&
119 theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
120 theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
125 const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
126 const ConstraintPtr& theConstraint) const
128 static ConstraintWrapperPtr aDummy;
130 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
131 aFound = myConstraintMap.find(theConstraint);
132 if (aFound != myConstraintMap.end())
133 return aFound->second;
137 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
139 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
140 if (aFound != myFeatureMap.end())
141 return aFound->second;
143 static EntityWrapperPtr aDummy;
147 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
149 std::map<AttributePtr, EntityWrapperPtr>::const_iterator
150 aFound = myAttributeMap.find(theAttribute);
151 if (aFound != myAttributeMap.end())
152 return aFound->second;
154 AttributeRefAttrPtr aRefAttr =
155 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
157 AttributePtr anAttribute;
159 if (aRefAttr->isObject()) {
160 /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
162 resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
164 return entity(aFeature);
166 anAttribute = aRefAttr->attr();
168 return entity(anAttribute);
171 static EntityWrapperPtr aDummy;
176 void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
178 myFeatureMap.erase(theFeature);
179 myNeedToResolve = true;
182 void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
184 myAttributeMap.erase(theAttribute);
185 myNeedToResolve = true;
189 bool SketchSolver_Storage::areFeaturesValid() const
191 // Check the features are valid
192 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
193 for (; aFIter != myFeatureMap.end(); aFIter++)
194 if (!aFIter->first->data() || !aFIter->first->data()->isValid())
199 void SketchSolver_Storage::blockEvents(bool isBlocked)
201 std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
202 for (; aFIter != myFeatureMap.end(); aFIter++)
203 if (aFIter->first->data() && aFIter->first->data()->isValid())
204 aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
206 std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
207 for (; anAtIter != myAttributeMap.end(); anAtIter++)
208 if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
209 anAtIter->first->owner()->data()->isValid())
210 anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
212 myEventsBlocked = isBlocked;
215 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
217 std::set<ObjectPtr> aConflicting;
218 std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
219 aConstrIt = myConstraintMap.begin();
220 for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
221 if (theSolver->isConflicting(aConstrIt->second->id()))
222 aConflicting.insert(aConstrIt->first);
227 void SketchSolver_Storage::subscribeUpdates(
228 SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
230 myUpdaters->attach(theSubscriber, theGroup);
233 void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
235 myUpdaters->detach(theSubscriber);
238 void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
240 myUpdaters->update(theFeature);
243 void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
244 FeaturePtr& theFeature, AttributePtr& theAttribute)
246 FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
250 // if the feature has several results, we choose which one is referred
251 const std::list<ResultPtr>& aResults = aFeature->results();
252 if (aResults.size() > 1 && theResult != aFeature->lastResult()) {
253 // actually, the attribute refers to center of arc or circle,
254 // but not the edge, get correct attributes
255 std::string anAttrName;
256 if (aFeature->getKind() == SketchPlugin_Arc::ID())
257 anAttrName = SketchPlugin_Arc::CENTER_ID();
258 else if (aFeature->getKind() == SketchPlugin_Circle::ID())
259 anAttrName = SketchPlugin_Circle::CENTER_ID();
260 if (!anAttrName.empty()) {
261 theAttribute = aFeature->attribute(anAttrName);
262 aFeature = FeaturePtr();
265 theFeature = aFeature;