X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintManager.cpp;h=682bbf23a48fdb89cbf4602e7e62115e9c5b045d;hb=506a83727ca8f8297fc1dcdf4ea40d7865c35450;hp=4a2cf08eee22be617261246917b57b5b0daf55fc;hpb=8dc74f82810d5f597b78633b457efb0ef4f89f9f;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index 4a2cf08ee..682bbf23a 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -1,3 +1,5 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + // File: SketchSolver_ConstraintManager.cpp // Created: 08 May 2014 // Author: Artem ZHIDKOV @@ -11,6 +13,7 @@ #include #include #include +#include #include @@ -19,8 +22,11 @@ #include #include #include +#include #include +#include +#include // Initialization of constraint manager self pointer SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0; @@ -28,6 +34,7 @@ SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0; /// Global constraint manager object SketchSolver_ConstraintManager* myManager = SketchSolver_ConstraintManager::Instance(); + // ======================================================== // ========= SketchSolver_ConstraintManager =============== // ======================================================== @@ -41,6 +48,7 @@ SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::Instance() SketchSolver_ConstraintManager::SketchSolver_ConstraintManager() { myGroups.clear(); + myIsComputed = false; // Register in event loop Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); @@ -56,65 +64,72 @@ SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager() // ============================================================================ // Function: processEvent -// Class: SketchSolver_PluginManager +// Class: SketchSolver_Session // Purpose: listen the event loop and process the message // ============================================================================ -void SketchSolver_ConstraintManager::processEvent(const Events_Message* theMessage) +void SketchSolver_ConstraintManager::processEvent( + const std::shared_ptr& theMessage) { + if (myIsComputed) + return; if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED) || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED) || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) { - const ModelAPI_ObjectUpdatedMessage* anUpdateMsg = - dynamic_cast(theMessage); + std::shared_ptr anUpdateMsg = + std::dynamic_pointer_cast(theMessage); std::set aFeatures = anUpdateMsg->objects(); - bool isModifiedEvt = theMessage->eventID() - == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED); - if (!isModifiedEvt) { + // Shows the message has at least one feature applicable for solver + bool hasProperFeature = false; + + bool isMovedEvt = theMessage->eventID() + == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED); + if (isMovedEvt) { std::set::iterator aFeatIter; for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - FeaturePtr aFeature = boost::dynamic_pointer_cast(*aFeatIter); - if (!aFeature) - continue; - // Only sketches and constraints can be added by Create event - const std::string& aFeatureKind = aFeature->getKind(); - if (aFeatureKind.compare(SketchPlugin_Sketch::ID()) == 0) { - boost::shared_ptr aSketch = boost::dynamic_pointer_cast< - SketchPlugin_Feature>(aFeature); - if (aSketch) - changeWorkplane(aSketch); - continue; + std::shared_ptr aSFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (aSFeature) { + moveEntity(aSFeature); + hasProperFeature = true; } - boost::shared_ptr aConstraint = boost::dynamic_pointer_cast< - SketchPlugin_Constraint>(aFeature); - if (aConstraint) - changeConstraint(aConstraint); - else { - // Sketch plugin features can be only updated - boost::shared_ptr aSFeature = boost::dynamic_pointer_cast< - SketchPlugin_Feature>(aFeature); - if (aSFeature) - updateEntity(aSFeature); + } + } else { + std::list aSketchFeatures = SketchSolver_Group::selectApplicableFeatures(aFeatures); + std::list::iterator aFeatIter = aSketchFeatures.begin(); + for (; aFeatIter != aSketchFeatures.end(); ++aFeatIter) { + if ((*aFeatIter)->getKind() == SketchPlugin_Sketch::ID()) { + std::shared_ptr aSketch = + std::dynamic_pointer_cast(*aFeatIter); + hasProperFeature = changeWorkplane(aSketch) || hasProperFeature; + continue; } + std::shared_ptr aFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (!aFeature) + continue; + hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature; } } // Solve the set of constraints - resolveConstraints(); + if (hasProperFeature) + resolveConstraints(isMovedEvt); // send update for movement in any case } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) { - const ModelAPI_ObjectDeletedMessage* aDeleteMsg = - dynamic_cast(theMessage); + std::shared_ptr aDeleteMsg = + std::dynamic_pointer_cast(theMessage); const std::set& aFeatureGroups = aDeleteMsg->groups(); // Find SketchPlugin_Sketch::ID() in groups. The constraint groups should be updated when an object removed from Sketch std::set::const_iterator aFGrIter; for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++) - if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0) + if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 || + aFGrIter->compare(ModelAPI_Feature::group()) == 0) break; if (aFGrIter != aFeatureGroups.end()) { - std::vector::iterator aGroupIter = myGroups.begin(); - std::vector aSeparatedGroups; + std::vector::iterator aGroupIter = myGroups.begin(); + std::vector aSeparatedGroups; while (aGroupIter != myGroups.end()) { if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed delete *aGroupIter; @@ -123,7 +138,7 @@ void SketchSolver_ConstraintManager::processEvent(const Events_Message* theMessa aGroupIter = myGroups.begin() + aShift; continue; } - if ((*aGroupIter)->updateGroup()) { // some constraints were removed, try to split the group + if (!(*aGroupIter)->isConsistent()) { // some constraints were removed, try to split the group (*aGroupIter)->splitGroup(aSeparatedGroups); } aGroupIter++; @@ -136,16 +151,15 @@ void SketchSolver_ConstraintManager::processEvent(const Events_Message* theMessa // ============================================================================ // Function: changeWorkplane -// Class: SketchSolver_PluginManager +// Class: SketchSolver_Session // Purpose: update workplane by given parameters of the sketch // ============================================================================ -bool SketchSolver_ConstraintManager::changeWorkplane( - boost::shared_ptr theSketch) +bool SketchSolver_ConstraintManager::changeWorkplane(CompositeFeaturePtr theSketch) { bool aResult = true; // changed when a workplane wrongly updated bool isUpdated = false; // Try to update specified workplane in all groups - std::vector::iterator aGroupIter; + std::vector::iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) if ((*aGroupIter)->isBaseWorkplane(theSketch)) { isUpdated = true; @@ -154,9 +168,9 @@ bool SketchSolver_ConstraintManager::changeWorkplane( } // If the workplane is not updated, so this is a new workplane if (!isUpdated) { - SketchSolver_ConstraintGroup* aNewGroup = new SketchSolver_ConstraintGroup(theSketch); + SketchSolver_Group* aNewGroup = new SketchSolver_Group(theSketch); // Verify that the group is created successfully - if (!aNewGroup->isBaseWorkplane(theSketch)) { + if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) { delete aNewGroup; return false; } @@ -166,40 +180,50 @@ bool SketchSolver_ConstraintManager::changeWorkplane( } // ============================================================================ -// Function: changeConstraint -// Class: SketchSolver_PluginManager -// Purpose: create/update the constraint and place it into appropriate group +// Function: changeConstraintOrEntity +// Class: SketchSolver_Session +// Purpose: create/update the constraint or the feature and place it into appropriate group // ============================================================================ -bool SketchSolver_ConstraintManager::changeConstraint( - boost::shared_ptr theConstraint) +bool SketchSolver_ConstraintManager::changeConstraintOrEntity( + std::shared_ptr theFeature) { - // Search the groups which this constraint touches + // Search the groups which this feature touches std::set aGroups; - findGroups(theConstraint, aGroups); + findGroups(theFeature, aGroups); + + std::shared_ptr aConstraint = + std::dynamic_pointer_cast(theFeature); // Process the groups list - if (aGroups.size() == 0) { // There are no groups applicable for this constraint => create new one - boost::shared_ptr aWP = findWorkplaneForConstraint(theConstraint); + if (aGroups.size() == 0) { + // There are no groups applicable for this constraint => create new one + // The group will be created only for constraints, not for features + if (!aConstraint) return false; + std::shared_ptr aWP = findWorkplane(aConstraint); if (!aWP) return false; - SketchSolver_ConstraintGroup* aGroup = new SketchSolver_ConstraintGroup(aWP); - if (!aGroup->changeConstraint(theConstraint)) { + SketchSolver_Group* aGroup = new SketchSolver_Group(aWP); + if (!aGroup->changeConstraint(aConstraint)) { delete aGroup; return false; } myGroups.push_back(aGroup); return true; - } else if (aGroups.size() == 1) { // Only one group => add constraint into it + } else if (aGroups.size() == 1) { // Only one group => add feature into it Slvs_hGroup aGroupId = *(aGroups.begin()); - std::vector::iterator aGroupIter; + std::vector::iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) - if ((*aGroupIter)->getId() == aGroupId) - return (*aGroupIter)->changeConstraint(theConstraint); - } else if (aGroups.size() > 1) { // Several groups applicable for this constraint => need to merge them + if ((*aGroupIter)->getId() == aGroupId) { + // If the group is empty, the feature is not added (the constraint only) + if (!aConstraint && !(*aGroupIter)->isEmpty()) + return (*aGroupIter)->updateFeature(theFeature); + return (*aGroupIter)->changeConstraint(aConstraint); + } + } else if (aGroups.size() > 1) { // Several groups applicable for this feature => need to merge them std::set::const_iterator aGroupsIter = aGroups.begin(); // Search first group - std::vector::iterator aFirstGroupIter; + std::vector::iterator aFirstGroupIter; for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++) if ((*aFirstGroupIter)->getId() == *aGroupsIter) break; @@ -207,7 +231,7 @@ bool SketchSolver_ConstraintManager::changeConstraint( return false; // Append other groups to the first one - std::vector::iterator anOtherGroupIter = aFirstGroupIter + 1; + std::vector::iterator anOtherGroupIter = aFirstGroupIter + 1; for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) { for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++) if ((*anOtherGroupIter)->getId() == *aGroupsIter) @@ -226,7 +250,9 @@ bool SketchSolver_ConstraintManager::changeConstraint( anOtherGroupIter = myGroups.begin() + aShiftOther; } - return (*aFirstGroupIter)->changeConstraint(theConstraint); + if (aConstraint) + return (*aFirstGroupIter)->changeConstraint(aConstraint); + return (*aFirstGroupIter)->updateFeature(theFeature); } // Something goes wrong @@ -234,71 +260,34 @@ bool SketchSolver_ConstraintManager::changeConstraint( } // ============================================================================ -// Function: updateEntity -// Class: SketchSolver_PluginManager -// Purpose: update any element on the sketch, which is used by constraints +// Function: moveEntity +// Class: SketchSolver_Session +// Purpose: update element moved on the sketch, which is used by constraints // ============================================================================ -void SketchSolver_ConstraintManager::updateEntity( - boost::shared_ptr theFeature) +void SketchSolver_ConstraintManager::moveEntity( + std::shared_ptr theFeature) { - // Create list of attributes depending on type of the feature - std::vector anAttrList; - const std::string& aFeatureKind = theFeature->getKind(); - // Point - if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) - anAttrList.push_back(SketchPlugin_Point::COORD_ID()); - // Line - else if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) { - anAttrList.push_back(SketchPlugin_Line::START_ID()); - anAttrList.push_back(SketchPlugin_Line::END_ID()); - } - // Circle - else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) { - anAttrList.push_back(SketchPlugin_Circle::CENTER_ID()); - anAttrList.push_back(SketchPlugin_Circle::RADIUS_ID()); - } - // Arc - else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) { - anAttrList.push_back(SketchPlugin_Arc::CENTER_ID()); - anAttrList.push_back(SketchPlugin_Arc::START_ID()); - anAttrList.push_back(SketchPlugin_Arc::END_ID()); - } - /// \todo Other types of features should be implemented - - // Check changing of feature's attributes (go through the groups and search usage of the attributes) - std::vector::const_iterator anAttrIter; - for (anAttrIter = anAttrList.begin(); anAttrIter != anAttrList.end(); anAttrIter++) { - std::vector::iterator aGroupIter; - for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) { - if ((*aGroupIter)->isEmpty()) - continue; - boost::shared_ptr anAttribute = boost::dynamic_pointer_cast< - ModelAPI_Attribute>(theFeature->data()->attribute(*anAttrIter)); - (*aGroupIter)->updateEntityIfPossible(anAttribute); - } - } - - std::vector::iterator aGroupIter; - for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) - if (!(*aGroupIter)->isEmpty()) - (*aGroupIter)->updateRelatedConstraints(theFeature); + std::vector::iterator aGroupIt = myGroups.begin(); + for (; aGroupIt != myGroups.end(); aGroupIt++) + if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature)) + (*aGroupIt)->moveFeature(theFeature); } // ============================================================================ // Function: findGroups -// Class: SketchSolver_PluginManager -// Purpose: search groups of entities interacting with given constraint +// Class: SketchSolver_Session +// Purpose: search groups of entities interacting with given feature // ============================================================================ void SketchSolver_ConstraintManager::findGroups( - boost::shared_ptr theConstraint, + std::shared_ptr theFeature, std::set& theGroupIDs) const { - boost::shared_ptr aWP = findWorkplaneForConstraint(theConstraint); + std::shared_ptr aWP = findWorkplane(theFeature); - SketchSolver_ConstraintGroup* anEmptyGroup = 0; // appropriate empty group for specified constraint - std::vector::const_iterator aGroupIter; + SketchSolver_Group* anEmptyGroup = 0; // appropriate empty group for specified constraint + std::vector::const_iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) - if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theConstraint)) { + if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) { if (!(*aGroupIter)->isEmpty()) theGroupIDs.insert((*aGroupIter)->getId()); else if (!anEmptyGroup) @@ -311,47 +300,68 @@ void SketchSolver_ConstraintManager::findGroups( } // ============================================================================ -// Function: findWorkplaneForConstraint -// Class: SketchSolver_PluginManager -// Purpose: search workplane containing given constraint +// Function: findWorkplane +// Class: SketchSolver_Session +// Purpose: search workplane containing given feature // ============================================================================ -boost::shared_ptr SketchSolver_ConstraintManager::findWorkplaneForConstraint( - boost::shared_ptr theConstraint) const +std::shared_ptr SketchSolver_ConstraintManager +::findWorkplane(std::shared_ptr theFeature) const { // Already verified workplanes - std::set > aVerified; + std::set > aVerified; - std::vector::const_iterator aGroupIter; + std::vector::const_iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) { - boost::shared_ptr aWP = (*aGroupIter)->getWorkplane(); + std::shared_ptr aWP = (*aGroupIter)->getWorkplane(); if (aVerified.find(aWP) != aVerified.end()) continue; - boost::shared_ptr aWPFeatures = boost::dynamic_pointer_cast< - ModelAPI_AttributeRefList>(aWP->data()->attribute(SketchPlugin_Sketch::FEATURES_ID())); - std::list aFeaturesList = aWPFeatures->list(); - std::list::const_iterator anIter; - for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++) - if (*anIter == theConstraint) - return aWP; // workplane is found + DataPtr aData = aWP->data(); + if (aData->isValid()) { + std::shared_ptr aWPFeatures = std::dynamic_pointer_cast< + ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID())); + std::list aFeaturesList = aWPFeatures->list(); + std::list::const_iterator anIter; + for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++) + if (*anIter == theFeature) + return aWP; // workplane is found + } aVerified.insert(aWP); } - return boost::shared_ptr(); + return std::shared_ptr(); } // ============================================================================ // Function: resolveConstraints -// Class: SketchSolver_PluginManager +// Class: SketchSolver_Session // Purpose: change entities according to available constraints // ============================================================================ -void SketchSolver_ConstraintManager::resolveConstraints() +void SketchSolver_ConstraintManager::resolveConstraints(const bool theForceUpdate) { - std::vector::iterator aGroupIter; + myIsComputed = true; + bool needToUpdate = false; + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + // to avoid redisplay of each segment on update by solver one by one in the viewer + bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); + if (isUpdateFlushed) { + Events_Loop::loop()->setFlushed(anUpdateEvent, false); + } + + std::vector::iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) - (*aGroupIter)->resolveConstraints(); + if ((*aGroupIter)->resolveConstraints()) + needToUpdate = true; - // Features may be updated => send events - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + // Features may be updated => now send events, but for all changed at once + if (isUpdateFlushed) { + Events_Loop::loop()->setFlushed(anUpdateEvent, true); + } + // Must be before flush because on "Updated" flush the results may be produced + // and the creation event is appeared with many new objects. If myIsComputed these + // events are missed in processEvents and some elements are not added. + myIsComputed = false; + if (needToUpdate || theForceUpdate) + Events_Loop::loop()->flush(anUpdateEvent); }