Salome HOME
6846f9656e2d2888b1000c4f09751ce788be69ea
[modules/shaper.git] / src / SketchSolver / SketchSolver_Storage.cpp
1 // Copyright (C) 2014-2023  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include <SketchSolver_Storage.h>
21 #include <PlaneGCSSolver_UpdateCoincidence.h>
22 #include <PlaneGCSSolver_UpdateFeature.h>
23
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>
34
35
36 SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
37   : mySketchSolver(theSolver),
38     myNeedToResolve(false),
39     myEventsBlocked(false)
40 {
41   // create updaters (constraints processed at first)
42   UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
43   myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
44 }
45
46 void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
47                                          ConstraintWrapperPtr theSolverConstraint)
48 {
49   std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
50       aFound = myConstraintMap.find(theConstraint);
51   if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
52     setNeedToResolve(true);
53
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());
65 ////      } else
66 ////        addEntity(aRef->attr(), EntityWrapperPtr());
67 ////    }
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());
78 ////      }
79 ////    }
80 ////  }
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)
86 ////      update(*aCIt);
87 ////  }
88
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);
94 }
95
96 void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
97                                      EntityWrapperPtr theSolverEntity)
98 {
99   if (theSolverEntity) {
100     myFeatureMap[theFeature] = theSolverEntity;
101     setNeedToResolve(true);
102   }
103
104   // block events if necessary
105   if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
106     theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
107 }
108
109 void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
110                                      EntityWrapperPtr theSolverEntity)
111 {
112   if (theSolverEntity) {
113     myAttributeMap[theAttribute] = theSolverEntity;
114     setNeedToResolve(true);
115   }
116
117   // block events if necessary
118   if (myEventsBlocked && theAttribute->owner() &&
119       theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
120     theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
121 }
122
123
124
125 const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
126     const ConstraintPtr& theConstraint) const
127 {
128   static ConstraintWrapperPtr aDummy;
129
130   std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
131       aFound = myConstraintMap.find(theConstraint);
132   if (aFound != myConstraintMap.end())
133     return aFound->second;
134   return aDummy;
135 }
136
137 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
138 {
139   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
140   if (aFound != myFeatureMap.end())
141     return aFound->second;
142
143   static EntityWrapperPtr aDummy;
144   return aDummy;
145 }
146
147 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
148 {
149   std::map<AttributePtr, EntityWrapperPtr>::const_iterator
150       aFound = myAttributeMap.find(theAttribute);
151   if (aFound != myAttributeMap.end())
152     return aFound->second;
153
154   AttributeRefAttrPtr aRefAttr =
155       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
156   if (aRefAttr) {
157     AttributePtr anAttribute;
158
159     if (aRefAttr->isObject()) {
160       /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
161       FeaturePtr aFeature;
162       resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
163       if (aFeature)
164         return entity(aFeature);
165     } else
166       anAttribute = aRefAttr->attr();
167
168     return entity(anAttribute);
169   }
170
171   static EntityWrapperPtr aDummy;
172   return aDummy;
173 }
174
175
176 void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
177 {
178   myFeatureMap.erase(theFeature);
179   myNeedToResolve = true;
180 }
181
182 void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
183 {
184   myAttributeMap.erase(theAttribute);
185   myNeedToResolve = true;
186 }
187
188
189 bool SketchSolver_Storage::areFeaturesValid() const
190 {
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())
195       return false;
196   return true;
197 }
198
199 void SketchSolver_Storage::blockEvents(bool isBlocked)
200 {
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);
205
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);
211
212   myEventsBlocked = isBlocked;
213 }
214
215 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
216 {
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);
223   }
224   return aConflicting;
225 }
226
227 void SketchSolver_Storage::subscribeUpdates(
228     SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
229 {
230   myUpdaters->attach(theSubscriber, theGroup);
231 }
232
233 void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
234 {
235   myUpdaters->detach(theSubscriber);
236 }
237
238 void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
239 {
240   myUpdaters->update(theFeature);
241 }
242
243 void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
244     FeaturePtr& theFeature, AttributePtr& theAttribute)
245 {
246   FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
247   if (!aFeature)
248     return;
249
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();
263     }
264   }
265   theFeature = aFeature;
266 }