X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Manager.cpp;h=5761c09b4ebef3f312f98739b5a6b4f72f63fd6e;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=c4a9969a523d6db83c5c412f6bc47d7839c2bdcd;hpb=2532fb2df83ee1ddd9ff3e8b381d3788eaa15b69;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Manager.cpp b/src/SketchSolver/SketchSolver_Manager.cpp index c4a9969a5..5761c09b4 100644 --- a/src/SketchSolver/SketchSolver_Manager.cpp +++ b/src/SketchSolver/SketchSolver_Manager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2023 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,15 +12,17 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "SketchSolver_Manager.h" #include "SketchSolver_Error.h" #include +#include +#include #include #include #include @@ -41,6 +43,64 @@ static bool isFeatureValid(FeaturePtr theFeature) return aFactory->validate(theFeature); } +typedef std::map> IndexedFeatureMap; + +static void featuresOrderedByCreation(const std::set& theOriginalFeatures, + IndexedFeatureMap& theOrderedFeatures) +{ + std::set::iterator aFeatIter = theOriginalFeatures.begin(); + for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) { + std::shared_ptr aFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) { + theOrderedFeatures[aFeature->data()->featureId()] = aFeature; + } + } +} + +static void featuresOrderedByType(const std::set& theOriginalFeatures, + IndexedFeatureMap& theOrderedFeatures, + CompositeFeaturePtr& theSketch) +{ + int aFeatureIndex = 0; + int aConstraintIndex = (int)theOriginalFeatures.size(); + + std::set::iterator aFeatIter = theOriginalFeatures.begin(); + for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) { + std::shared_ptr aFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (aFeature) { + if (!aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) { + std::shared_ptr aConstraint = + std::dynamic_pointer_cast(aFeature); + if (aConstraint) + theOrderedFeatures[++aConstraintIndex] = aFeature; + else + theOrderedFeatures[++aFeatureIndex] = aFeature; + } + } + else { + CompositeFeaturePtr aSketch = + std::dynamic_pointer_cast(*aFeatIter); + if (aSketch && aSketch->getKind() == SketchPlugin_Sketch::ID()) + theSketch = aSketch; + } + } +} + +static void setPoint(AttributePtr theAttribute, + const int thePointIndex, + const std::shared_ptr theValue) +{ + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast(theAttribute); + AttributePoint2DArrayPtr aPointArrayAttr = + std::dynamic_pointer_cast(theAttribute); + if (aPointAttr) + aPointAttr->setValue(theValue); + else if (aPointArrayAttr && thePointIndex >= 0) + aPointArrayAttr->setPnt(thePointIndex, theValue); +} + // ======================================================== @@ -68,6 +128,7 @@ SketchSolver_Manager::SketchSolver_Manager() ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED)); ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED)); Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_PREPARED)); + Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_GET_DOF_OBJECTS)); } SketchSolver_Manager::~SketchSolver_Manager() @@ -91,6 +152,7 @@ void SketchSolver_Manager::processEvent( bool isUpdateFlushed = false; bool isMovedEvt = false; + static const Events_ID aCreatedEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); static const Events_ID aSketchPreparedEvent = Events_Loop::eventByName(EVENT_SKETCH_PREPARED); // sketch is prepared for resolve: all the needed events @@ -104,46 +166,61 @@ void SketchSolver_Manager::processEvent( return; myIsComputed = true; - if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED) - || theMessage->eventID() == anUpdateEvent - || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) { + if (theMessage->eventID() == aCreatedEvent || theMessage->eventID() == anUpdateEvent) { std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); - std::set aFeatures = anUpdateMsg->objects(); isUpdateFlushed = stopSendUpdate(); - isMovedEvt = theMessage->eventID() - == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED); - - // Shows that the message has at least one feature applicable for solver - bool hasProperFeature = false; - // update sketch features only - std::set::iterator aFeatIter; - for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - std::shared_ptr aFeature = - std::dynamic_pointer_cast(*aFeatIter); - if (!aFeature || aFeature->isMacro()) - continue; - - hasProperFeature = updateFeature(aFeature, isMovedEvt) || hasProperFeature; + const std::set& aFeatures = anUpdateMsg->objects(); + IndexedFeatureMap anOrderedFeatures; + CompositeFeaturePtr aSketchFeature; + // try to keep order as features were created if there are several created features: #2229 + if (theMessage->eventID() == aCreatedEvent && aFeatures.size() > 1) { + featuresOrderedByCreation(aFeatures, anOrderedFeatures); + } else { // order is not important, just process features before constraints + featuresOrderedByType(aFeatures, anOrderedFeatures, aSketchFeature); + } + + IndexedFeatureMap::iterator aFeat; + for (aFeat = anOrderedFeatures.begin(); aFeat != anOrderedFeatures.end(); aFeat++) { + updateFeature(aFeat->second); } + updateSketch(aSketchFeature); + + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) { + std::shared_ptr aMoveMsg = + std::dynamic_pointer_cast(theMessage); + + ObjectPtr aMovedObject = aMoveMsg->movedObject(); + AttributePtr aMovedAttribute = aMoveMsg->movedAttribute(); + int aMovedPoint = aMoveMsg->movedPointIndex(); - if (isMovedEvt && hasProperFeature) - needToResolve = true; + const std::shared_ptr& aFrom = aMoveMsg->originalPosition(); + const std::shared_ptr& aTo = aMoveMsg->currentPosition(); + + if (aMovedObject) { + FeaturePtr aMovedFeature = ModelAPI_Feature::feature(aMovedObject); + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aMovedFeature); + if (aSketchFeature && !aSketchFeature->isMacro()) + needToResolve = moveFeature(aSketchFeature, aFrom, aTo); + } else if (aMovedAttribute) + needToResolve = moveAttribute(aMovedAttribute, aMovedPoint, aFrom, aTo); } 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(); + const std::list, std::string>>& 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; + std::list, std::string>>::const_iterator aFGrIter; for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++) - if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 || - aFGrIter->compare(ModelAPI_Feature::group()) == 0) + if (aFGrIter->second == ModelAPI_ResultConstruction::group() || + aFGrIter->second == ModelAPI_Feature::group()) break; if (aFGrIter != aFeatureGroups.end()) { @@ -161,6 +238,35 @@ void SketchSolver_Manager::processEvent( } myIsComputed = false; } + else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_GET_DOF_OBJECTS)) { + std::shared_ptr anUpdateMsg = + std::dynamic_pointer_cast(theMessage); + std::set aObjects = anUpdateMsg->objects(); + if (aObjects.size() == 1) { + std::set::const_iterator aIt; + for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) { + CompositeFeaturePtr aFeature = + std::dynamic_pointer_cast(*aIt); + if (aFeature) { + SketchGroupPtr aGroup = findGroup(aFeature); + + std::set aFreeFeatures; + aGroup->underconstrainedFeatures(aFreeFeatures); + + std::list aFeatures; + std::set::const_iterator aIt; + for (aIt = aFreeFeatures.cbegin(); aIt != aFreeFeatures.cend(); ++aIt) { + aFeatures.push_back(*aIt); + } + + // send features to GUI + static const Events_ID anEvent = Events_Loop::eventByName(EVENT_DOF_OBJECTS); + ModelAPI_EventCreator::get()->sendUpdated(aFeatures, anEvent); + Events_Loop::loop()->flush(anEvent); + } + } + } + } // resolve constraints if needed bool needToUpdate = needToResolve && resolveConstraints(); @@ -178,11 +284,29 @@ void SketchSolver_Manager::processEvent( } // ============================================================================ -// Function: changeConstraintOrEntity -// Purpose: create/update the constraint or the feature and place it into appropriate group +// Function: updateSketch +// Purpose: update sketch plane in appropriate group +// ============================================================================ +bool SketchSolver_Manager::updateSketch(const CompositeFeaturePtr& theSketch) +{ + if (!theSketch) + return true; + + bool isOk = true; + std::list::const_iterator aGroupIt; + for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); ++aGroupIt) + if ((*aGroupIt)->getWorkplane() == theSketch) { + (*aGroupIt)->updateSketch(theSketch); + break; + } + return isOk; +} + +// ============================================================================ +// Function: updateFeature +// Purpose: create/update constraint or feature in appropriate group // ============================================================================ -bool SketchSolver_Manager::updateFeature(std::shared_ptr theFeature, - bool theMoved) +bool SketchSolver_Manager::updateFeature(const std::shared_ptr& theFeature) { // Check feature validity and find a group to place it. // If the feature is not valid, the returned group will be empty. @@ -198,19 +322,82 @@ bool SketchSolver_Manager::updateFeature(std::shared_ptr t bool isOk = false; if (aConstraint) isOk = aGroup->changeConstraint(aConstraint); - else if (theMoved) - isOk = aGroup->moveFeature(theFeature); else isOk = aGroup->updateFeature(theFeature); return isOk; } +// ============================================================================ +// Function: moveFeature +// Purpose: move given feature in appropriate group +// ============================================================================ +bool SketchSolver_Manager::moveFeature( + const std::shared_ptr& theMovedFeature, + const std::shared_ptr& theFrom, + const std::shared_ptr& theTo) +{ + SketchGroupPtr aGroup = findGroup(theMovedFeature); + if (!aGroup) + return false; + + std::shared_ptr aConstraint = + std::dynamic_pointer_cast(theMovedFeature); + if (aConstraint) + { + std::shared_ptr aPntAttr = std::dynamic_pointer_cast + (aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + if (aPntAttr) + { + aPntAttr->setValue(theTo); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return true; + } + + aGroup->blockEvents(true); + return aGroup->moveFeature(theMovedFeature, theFrom, theTo); +} + +// ============================================================================ +// Function: moveAttribute +// Purpose: move given attribute in appropriate group +// ============================================================================ +bool SketchSolver_Manager::moveAttribute( + const std::shared_ptr& theMovedAttribute, + const int theMovedPointIndex, + const std::shared_ptr& theFrom, + const std::shared_ptr& theTo) +{ + FeaturePtr anOwner = ModelAPI_Feature::feature(theMovedAttribute->owner()); + std::shared_ptr aConstraint = + std::dynamic_pointer_cast(anOwner); + if (aConstraint) + { + setPoint(theMovedAttribute, theMovedPointIndex, theTo); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + return true; + } + + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(anOwner); + SketchGroupPtr aGroup; + if (aSketchFeature) + aGroup = findGroup(aSketchFeature); + if (!aGroup) { + setPoint(theMovedAttribute, theMovedPointIndex, theTo); + return false; + } + + aGroup->blockEvents(true); + return aGroup->movePoint(theMovedAttribute, theMovedPointIndex, theFrom, theTo); +} + // ============================================================================ // Function: findGroup // Purpose: search groups of entities interacting with given feature // ============================================================================ SketchGroupPtr SketchSolver_Manager::findGroup( - std::shared_ptr theFeature) + std::shared_ptr theFeature) { if (!isFeatureValid(theFeature)) return SketchGroupPtr(); // do not process wrong features @@ -226,17 +413,21 @@ SketchGroupPtr SketchSolver_Manager::findGroup( break; } } + return findGroup(aSketch); +} - if (!aSketch) +SketchGroupPtr SketchSolver_Manager::findGroup(CompositeFeaturePtr theSketch) +{ + if (!theSketch) return SketchGroupPtr(); // not a sketch's feature std::list::const_iterator aGroupIt; for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); ++aGroupIt) - if ((*aGroupIt)->getWorkplane() == aSketch) + if ((*aGroupIt)->getWorkplane() == theSketch) return *aGroupIt; // group for the sketch does not created yet - SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(aSketch)); + SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(theSketch)); myGroups.push_back(aNewGroup); return aNewGroup; }