]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Storage.cpp
Salome HOME
81714314f264bd8c0b95dbc3d286a9c61752c4c7
[modules/shaper.git] / src / SketchSolver / SketchSolver_Storage.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    SketchSolver_Storage.cpp
4 // Created: 30 Nov 2015
5 // Author:  Artem ZHIDKOV
6
7 #include <SketchSolver_Storage.h>
8 #include <PlaneGCSSolver_UpdateCoincidence.h>
9 #include <PlaneGCSSolver_UpdateFeature.h>
10
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>
21
22
23 SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
24   : mySketchSolver(theSolver),
25     myNeedToResolve(false),
26     myEventsBlocked(false)
27 {
28   // create updaters (constraints processed at first)
29   UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
30   myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
31 }
32
33 void SketchSolver_Storage::addConstraint(ConstraintPtr        theConstraint,
34                                          ConstraintWrapperPtr theSolverConstraint)
35 {
36   std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
37       aFound = myConstraintMap.find(theConstraint);
38   if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
39     setNeedToResolve(true);
40
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());
51 ////      } else
52 ////        addEntity(aRef->attr(), EntityWrapperPtr());
53 ////    }
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());
63 ////      }
64 ////    }
65 ////  }
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)
71 ////      update(*aCIt);
72 ////  }
73
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);
79 }
80
81 static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
82 {
83   std::list<AttributePtr> aPoints;
84   if (!theFeature->data() || !theFeature->data()->isValid())
85     return aPoints;
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()));
90   }
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()));
96   }
97   else if (theFeature->getKind() == SketchPlugin_Point::ID() ||
98            theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
99     aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID()));
100   return aPoints;
101 }
102
103 void SketchSolver_Storage::addEntity(FeaturePtr       theFeature,
104                                      EntityWrapperPtr theSolverEntity)
105 {
106   if (theSolverEntity) {
107     myFeatureMap[theFeature] = theSolverEntity;
108     setNeedToResolve(true);
109   } else {
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;
116   }
117
118   // block events if necessary
119   if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
120     theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
121 }
122
123 void SketchSolver_Storage::addEntity(AttributePtr     theAttribute,
124                                      EntityWrapperPtr theSolverEntity)
125 {
126   if (theSolverEntity) {
127     myAttributeMap[theAttribute] = theSolverEntity;
128     setNeedToResolve(true);
129   }
130
131   // block events if necessary
132   if (myEventsBlocked && theAttribute->owner() &&
133       theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
134     theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
135 }
136
137
138
139 const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
140     const ConstraintPtr& theConstraint) const
141 {
142   static ConstraintWrapperPtr aDummy;
143
144   std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
145       aFound = myConstraintMap.find(theConstraint);
146   if (aFound != myConstraintMap.end())
147     return aFound->second;
148   return aDummy;
149 }
150
151 const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
152 {
153   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
154   if (aFound != myFeatureMap.end())
155     return aFound->second;
156
157   static EntityWrapperPtr aDummy;
158   return aDummy;
159 }
160
161 const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
162 {
163   std::map<AttributePtr, EntityWrapperPtr>::const_iterator
164       aFound = myAttributeMap.find(theAttribute);
165   if (aFound != myAttributeMap.end())
166     return aFound->second;
167
168   AttributeRefAttrPtr aRefAttr =
169       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
170   if (aRefAttr) {
171     AttributePtr anAttribute;
172
173     if (aRefAttr->isObject()) {
174       /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
175       FeaturePtr aFeature;
176       resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
177       if (aFeature)
178         return entity(aFeature);
179     } else
180       anAttribute = aRefAttr->attr();
181
182     return entity(anAttribute);
183   }
184
185   static EntityWrapperPtr aDummy;
186   return aDummy;
187 }
188
189
190 void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
191 {
192   myFeatureMap.erase(theFeature);
193 }
194
195 void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
196 {
197   myAttributeMap.erase(theAttribute);
198 }
199
200
201 bool SketchSolver_Storage::isConsistent() const
202 {
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())
208       return false;
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())
213       return false;
214   return true;
215 }
216
217 void SketchSolver_Storage::blockEvents(bool isBlocked)
218 {
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);
223
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);
229
230   myEventsBlocked = isBlocked;
231 }
232
233 std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
234 {
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);
241       break;
242     }
243   }
244   return aConflicting;
245 }
246
247 void SketchSolver_Storage::subscribeUpdates(
248     SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
249 {
250   myUpdaters->attach(theSubscriber, theGroup);
251 }
252
253 void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
254 {
255   myUpdaters->detach(theSubscriber);
256 }
257
258 void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
259 {
260   myUpdaters->update(theFeature);
261 }
262
263 void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
264     FeaturePtr& theFeature, AttributePtr& theAttribute)
265 {
266   FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
267   if (!aFeature)
268     return;
269
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();
283     }
284   }
285   theFeature = aFeature;
286 }