Salome HOME
Fix for the issue #2753 : error when dump/load script
[modules/shaper.git] / src / SketchSolver / SketchSolver_Storage.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <SketchSolver_Storage.h>
22 #include <PlaneGCSSolver_UpdateCoincidence.h>
23 #include <PlaneGCSSolver_UpdateFeature.h>
24
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>
35
36
37 SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
38   : mySketchSolver(theSolver),
39     myNeedToResolve(false),
40     myEventsBlocked(false)
41 {
42   // create updaters (constraints processed at first)
43   UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
44   myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
45 }
46
47 void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
48                                          ConstraintWrapperPtr theSolverConstraint)
49 {
50   std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
51       aFound = myConstraintMap.find(theConstraint);
52   if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
53     setNeedToResolve(true);
54
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());
66 ////      } else
67 ////        addEntity(aRef->attr(), EntityWrapperPtr());
68 ////    }
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());
79 ////      }
80 ////    }
81 ////  }
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)
87 ////      update(*aCIt);
88 ////  }
89
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);
95 }
96
97 static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
98 {
99   std::list<AttributePtr> aPoints;
100   if (!theFeature->data() || !theFeature->data()->isValid())
101     return aPoints;
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()));
106   }
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()));
112   }
113   else if (theFeature->getKind() == SketchPlugin_Point::ID() ||
114            theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
115     aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID()));
116   return aPoints;
117 }
118
119 void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
120                                      EntityWrapperPtr theSolverEntity)
121 {
122   if (theSolverEntity) {
123     myFeatureMap[theFeature] = theSolverEntity;
124     setNeedToResolve(true);
125   } else {
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;
132   }
133
134   // block events if necessary
135   if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
136     theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
137 }
138
139 void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
140                                      EntityWrapperPtr theSolverEntity)
141 {
142   if (theSolverEntity) {
143     myAttributeMap[theAttribute] = theSolverEntity;
144     setNeedToResolve(true);
145   }
146
147   // block events if necessary
148   if (myEventsBlocked && theAttribute->owner() &&
149       theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
150     theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
151 }
152
153
154
155 const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
156     const ConstraintPtr& theConstraint) const
157 {
158   static ConstraintWrapperPtr aDummy;
159
160   std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
161       aFound = myConstraintMap.find(theConstraint);
162   if (aFound != myConstraintMap.end())
163     return aFound->second;
164   return aDummy;
165 }
166
167 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
168 {
169   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
170   if (aFound != myFeatureMap.end())
171     return aFound->second;
172
173   static EntityWrapperPtr aDummy;
174   return aDummy;
175 }
176
177 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
178 {
179   std::map<AttributePtr, EntityWrapperPtr>::const_iterator
180       aFound = myAttributeMap.find(theAttribute);
181   if (aFound != myAttributeMap.end())
182     return aFound->second;
183
184   AttributeRefAttrPtr aRefAttr =
185       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
186   if (aRefAttr) {
187     AttributePtr anAttribute;
188
189     if (aRefAttr->isObject()) {
190       /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
191       FeaturePtr aFeature;
192       resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
193       if (aFeature)
194         return entity(aFeature);
195     } else
196       anAttribute = aRefAttr->attr();
197
198     return entity(anAttribute);
199   }
200
201   static EntityWrapperPtr aDummy;
202   return aDummy;
203 }
204
205
206 void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
207 {
208   myFeatureMap.erase(theFeature);
209   myNeedToResolve = true;
210 }
211
212 void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
213 {
214   myAttributeMap.erase(theAttribute);
215   myNeedToResolve = true;
216 }
217
218
219 bool SketchSolver_Storage::areFeaturesValid() const
220 {
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())
225       return false;
226   return true;
227 }
228
229 void SketchSolver_Storage::blockEvents(bool isBlocked)
230 {
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);
235
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);
241
242   myEventsBlocked = isBlocked;
243 }
244
245 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
246 {
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);
253   }
254   return aConflicting;
255 }
256
257 void SketchSolver_Storage::subscribeUpdates(
258     SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
259 {
260   myUpdaters->attach(theSubscriber, theGroup);
261 }
262
263 void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
264 {
265   myUpdaters->detach(theSubscriber);
266 }
267
268 void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
269 {
270   myUpdaters->update(theFeature);
271 }
272
273 void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
274     FeaturePtr& theFeature, AttributePtr& theAttribute)
275 {
276   FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
277   if (!aFeature)
278     return;
279
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();
293     }
294   }
295   theFeature = aFeature;
296 }