X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintManager.cpp;h=682bbf23a48fdb89cbf4602e7e62115e9c5b045d;hb=506a83727ca8f8297fc1dcdf4ea40d7865c35450;hp=a3136681381719388cc90fbc4aacaabab7945fd6;hpb=388c833ce58fe2991881c9a66d529d805fa84bd5;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index a31366813..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 @@ -9,6 +11,9 @@ #include #include #include +#include +#include +#include #include @@ -17,7 +22,11 @@ #include #include #include +#include +#include +#include +#include // Initialization of constraint manager self pointer SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0; @@ -39,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)); @@ -54,84 +64,81 @@ 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 (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::set< ObjectPtr > aFeatures = anUpdateMsg->objects(); - - bool isModifiedEvt = - theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED); - if (!isModifiedEvt) - { - std::set< ObjectPtr >::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(SKETCH_KIND) == 0) - { - boost::shared_ptr aSketch = - boost::dynamic_pointer_cast(aFeature); - if (aSketch) - changeWorkplane(aSketch); - continue; + 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)) { + std::shared_ptr anUpdateMsg = + std::dynamic_pointer_cast(theMessage); + std::set aFeatures = anUpdateMsg->objects(); + + // 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++) { + std::shared_ptr aSFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (aSFeature) { + moveEntity(aSFeature); + hasProperFeature = true; } - boost::shared_ptr aConstraint = - boost::dynamic_pointer_cast(aFeature); - if (aConstraint) - changeConstraint(aConstraint); - else - { - // Sketch plugin features can be only updated - boost::shared_ptr aSFeature = - boost::dynamic_pointer_cast(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(); - } - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) - { - const ModelAPI_ObjectDeletedMessage* aDeleteMsg = - dynamic_cast(theMessage); + if (hasProperFeature) + resolveConstraints(isMovedEvt); // send update for movement in any case + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) { + std::shared_ptr aDeleteMsg = + std::dynamic_pointer_cast(theMessage); const std::set& aFeatureGroups = aDeleteMsg->groups(); - // Find SKETCH_KIND in groups. The constraint groups should be updated when an object removed from Sketch + // 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(SKETCH_KIND) == 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; - while (aGroupIter != myGroups.end()) - { - if (!(*aGroupIter)->isWorkplaneValid()) - { // the group should be removed + + if (aFGrIter != aFeatureGroups.end()) { + std::vector::iterator aGroupIter = myGroups.begin(); + std::vector aSeparatedGroups; + while (aGroupIter != myGroups.end()) { + if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed delete *aGroupIter; int aShift = aGroupIter - myGroups.begin(); myGroups.erase(aGroupIter); 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++; @@ -144,29 +151,26 @@ 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 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)) - { + if ((*aGroupIter)->isBaseWorkplane(theSketch)) { isUpdated = true; if (!(*aGroupIter)->updateWorkplane()) aResult = false; } // If the workplane is not updated, so this is a new workplane - if (!isUpdated) - { - SketchSolver_ConstraintGroup* aNewGroup = new SketchSolver_ConstraintGroup(theSketch); + if (!isUpdated) { + 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; } @@ -176,45 +180,50 @@ bool SketchSolver_ConstraintManager::changeWorkplane(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 (!aWP) return false; - SketchSolver_ConstraintGroup* aGroup = new SketchSolver_ConstraintGroup(aWP); - if (!aGroup->changeConstraint(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_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; @@ -222,14 +231,12 @@ bool SketchSolver_ConstraintManager::changeConstraint( return false; // Append other groups to the first one - std::vector::iterator anOtherGroupIter = aFirstGroupIter + 1; - for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) - { - for ( ; anOtherGroupIter != myGroups.end(); anOtherGroupIter++) + std::vector::iterator anOtherGroupIter = aFirstGroupIter + 1; + for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) { + for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++) if ((*anOtherGroupIter)->getId() == *aGroupsIter) break; - if (anOtherGroupIter == myGroups.end()) - { // Group disappears + if (anOtherGroupIter == myGroups.end()) { // Group disappears anOtherGroupIter = aFirstGroupIter + 1; continue; } @@ -239,11 +246,13 @@ bool SketchSolver_ConstraintManager::changeConstraint( int aShiftOther = anOtherGroupIter - myGroups.begin(); delete *anOtherGroupIter; myGroups.erase(anOtherGroupIter); - aFirstGroupIter = myGroups.begin() + aShiftFirst; + aFirstGroupIter = myGroups.begin() + aShiftFirst; anOtherGroupIter = myGroups.begin() + aShiftOther; } - return (*aFirstGroupIter)->changeConstraint(theConstraint); + if (aConstraint) + return (*aFirstGroupIter)->changeConstraint(aConstraint); + return (*aFirstGroupIter)->updateFeature(theFeature); } // Something goes wrong @@ -251,77 +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(SKETCH_POINT_KIND) == 0) - anAttrList.push_back(POINT_ATTR_COORD); - // Line - else if (aFeatureKind.compare(SKETCH_LINE_KIND) == 0) - { - anAttrList.push_back(LINE_ATTR_START); - anAttrList.push_back(LINE_ATTR_END); - } - // Circle - else if (aFeatureKind.compare(SKETCH_CIRCLE_KIND) == 0) - { - anAttrList.push_back(CIRCLE_ATTR_CENTER); - anAttrList.push_back(CIRCLE_ATTR_RADIUS); - } - // Arc - else if (aFeatureKind.compare(SKETCH_ARC_KIND) == 0) - { - anAttrList.push_back(ARC_ATTR_CENTER); - anAttrList.push_back(ARC_ATTR_START); - anAttrList.push_back(ARC_ATTR_END); - } - /// \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(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::set& theGroupIDs) const + 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) @@ -334,48 +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< boost::shared_ptr > aVerified; + std::set > aVerified; - std::vector::const_iterator aGroupIter; - for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) - { - boost::shared_ptr aWP = (*aGroupIter)->getWorkplane(); + std::vector::const_iterator aGroupIter; + for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) { + std::shared_ptr aWP = (*aGroupIter)->getWorkplane(); if (aVerified.find(aWP) != aVerified.end()) continue; - boost::shared_ptr aWPFeatures = - boost::dynamic_pointer_cast(aWP->data()->attribute(SKETCH_ATTR_FEATURES)); - std::list< ObjectPtr >& aFeaturesList = aWPFeatures->list(); - std::list< ObjectPtr >::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); }