1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: SketchSolver_Manager.cpp
4 // Created: 08 May 2014
5 // Author: Artem ZHIDKOV
7 #include "SketchSolver_Manager.h"
8 #include "SketchSolver_Error.h"
10 #include <Events_Loop.h>
11 #include <ModelAPI_Events.h>
12 #include <ModelAPI_ResultConstruction.h>
13 #include <ModelAPI_Session.h>
14 #include <ModelAPI_Validator.h>
15 #include <SketchPlugin_Sketch.h>
17 /// Global constraint manager object
18 static SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
20 /// \brief Verifies is the feature valid
21 static bool isFeatureValid(FeaturePtr theFeature)
23 if (!theFeature || !theFeature->data() || !theFeature->data()->isValid())
26 SessionPtr aMgr = ModelAPI_Session::get();
27 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
28 return aFactory->validate(theFeature);
33 // ========================================================
34 // ========= SketchSolver_Manager ===============
35 // ========================================================
36 SketchSolver_Manager* SketchSolver_Manager::instance()
38 static SketchSolver_Manager* mySelf = 0; // Self pointer to implement singleton functionality
40 mySelf = new SketchSolver_Manager();
44 SketchSolver_Manager::SketchSolver_Manager()
49 // Register in event loop
50 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
51 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
52 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
53 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED));
55 ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
56 ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
57 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_PREPARED));
60 SketchSolver_Manager::~SketchSolver_Manager()
65 bool SketchSolver_Manager::groupMessages()
70 // ============================================================================
71 // Function: processEvent
72 // Purpose: listen the event loop and process the message
73 // ============================================================================
74 void SketchSolver_Manager::processEvent(
75 const std::shared_ptr<Events_Message>& theMessage)
77 bool needToResolve = false;
78 bool isUpdateFlushed = false;
79 bool isMovedEvt = false;
81 static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
82 static const Events_ID aSketchPreparedEvent = Events_Loop::eventByName(EVENT_SKETCH_PREPARED);
83 // sketch is prepared for resolve: all the needed events
84 // are collected and must be processed by the solver
85 if (theMessage->eventID() == aSketchPreparedEvent) {
86 flushGrouped(anUpdateEvent);
94 if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
95 || theMessage->eventID() == anUpdateEvent
96 || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
97 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
98 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
99 std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
101 isUpdateFlushed = stopSendUpdate();
103 isMovedEvt = theMessage->eventID()
104 == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
106 // Shows that the message has at least one feature applicable for solver
107 bool hasProperFeature = false;
109 // update sketch features only
110 std::set<ObjectPtr>::iterator aFeatIter;
111 for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
112 std::shared_ptr<SketchPlugin_Feature> aFeature =
113 std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
114 if (!aFeature || aFeature->isMacro())
117 hasProperFeature = updateFeature(aFeature, isMovedEvt) || hasProperFeature;
120 if (isMovedEvt && hasProperFeature)
121 needToResolve = true;
123 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
124 std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
125 std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
126 const std::set<std::string>& aFeatureGroups = aDeleteMsg->groups();
128 // Find SketchPlugin_Sketch::ID() in groups.
129 // The constraint groups should be updated when an object removed from Sketch
130 std::set<std::string>::const_iterator aFGrIter;
131 for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
132 if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 ||
133 aFGrIter->compare(ModelAPI_Feature::group()) == 0)
136 if (aFGrIter != aFeatureGroups.end()) {
137 std::list<SketchGroupPtr>::iterator aGroupIter = myGroups.begin();
138 while (aGroupIter != myGroups.end()) {
139 if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed
140 std::list<SketchGroupPtr>::iterator aRemoveIt = aGroupIter++;
141 myGroups.erase(aRemoveIt);
145 (*aGroupIter)->repairConsistency();
149 myIsComputed = false;
152 // resolve constraints if needed
153 bool needToUpdate = needToResolve && resolveConstraints();
154 releaseFeaturesIfEventsBlocked();
156 // Features may be updated => now send events, but for all changed at once
160 myIsComputed = false;
162 // send update for movement in any case
163 if (needToUpdate || isMovedEvt)
164 Events_Loop::loop()->flush(anUpdateEvent);
167 // ============================================================================
168 // Function: changeConstraintOrEntity
169 // Purpose: create/update the constraint or the feature and place it into appropriate group
170 // ============================================================================
171 bool SketchSolver_Manager::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature,
174 // Check feature validity and find a group to place it.
175 // If the feature is not valid, the returned group will be empty.
176 // This will protect to deal with wrong (not fully initialized) features.
177 SketchGroupPtr aGroup = findGroup(theFeature);
180 aGroup->blockEvents(true);
182 std::shared_ptr<SketchPlugin_Constraint> aConstraint =
183 std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
187 isOk = aGroup->changeConstraint(aConstraint);
189 isOk = aGroup->moveFeature(theFeature);
191 isOk = aGroup->updateFeature(theFeature);
195 // ============================================================================
196 // Function: findGroup
197 // Purpose: search groups of entities interacting with given feature
198 // ============================================================================
199 SketchGroupPtr SketchSolver_Manager::findGroup(
200 std::shared_ptr<SketchPlugin_Feature> theFeature)
202 if (!isFeatureValid(theFeature))
203 return SketchGroupPtr(); // do not process wrong features
205 // Obtain sketch, containing the feature
206 CompositeFeaturePtr aSketch;
207 const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
208 std::set<AttributePtr>::const_iterator aRefIt = aRefsList.begin();
209 for (; aRefIt != aRefsList.end(); ++aRefIt) {
210 FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
211 if (anOwner && anOwner->getKind() == SketchPlugin_Sketch::ID()) {
212 aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(anOwner);
218 return SketchGroupPtr(); // not a sketch's feature
220 std::list<SketchGroupPtr>::const_iterator aGroupIt;
221 for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); ++aGroupIt)
222 if ((*aGroupIt)->getWorkplane() == aSketch)
225 // group for the sketch does not created yet
226 SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(aSketch));
227 myGroups.push_back(aNewGroup);
231 // ============================================================================
232 // Function: resolveConstraints
233 // Purpose: change entities according to available constraints
234 // ============================================================================
235 bool SketchSolver_Manager::resolveConstraints()
237 bool needToUpdate = false;
238 std::list<SketchGroupPtr>::const_iterator aGroupIter = myGroups.begin();
239 for (; aGroupIter != myGroups.end(); ++aGroupIter) {
240 if ((*aGroupIter)->resolveConstraints())
246 void SketchSolver_Manager::releaseFeaturesIfEventsBlocked() const
248 std::list<SketchGroupPtr>::const_iterator aGroupIter = myGroups.begin();
249 for (; aGroupIter != myGroups.end(); ++aGroupIter)
250 (*aGroupIter)->blockEvents(false);
253 bool SketchSolver_Manager::stopSendUpdate() const
255 static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
256 // to avoid redisplay of each segment on update by solver one by one in the viewer
257 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
258 if (isUpdateFlushed) {
259 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
261 return isUpdateFlushed;
264 void SketchSolver_Manager::allowSendUpdate() const
266 Events_Loop::loop()->setFlushed(Events_Loop::eventByName(EVENT_OBJECT_UPDATED), true);