X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintManager.cpp;h=ef725b5633fe6ddc5eb464c7313c3b84b018b737;hb=61cd0845b41710ad4e7eae07cc6106904be67b9f;hp=1dec2867f7ee2b098386b0f51ffcf5a82c12353f;hpb=7125268eb399c4bfa4bf5a493b52684c82d2f001;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index 1dec2867f..ef725b563 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,16 +13,24 @@ #include #include #include +#include #include +#include +#include +#include +#include #include #include #include #include #include +#include #include +#include +#include // Initialization of constraint manager self pointer SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0; @@ -61,55 +71,77 @@ SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager() // Purpose: listen the event loop and process the message // ============================================================================ void SketchSolver_ConstraintManager::processEvent( - const boost::shared_ptr& theMessage) + 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)) { - boost::shared_ptr anUpdateMsg = - boost::dynamic_pointer_cast(theMessage); + 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++) { - boost::shared_ptr aSFeature = - boost::dynamic_pointer_cast(*aFeatIter); - if (aSFeature) - updateEntity(aSFeature); + std::shared_ptr aSFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (aSFeature) { + moveEntity(aSFeature); + hasProperFeature = true; + } } } else { std::set::iterator aFeatIter; + // iterate sketchers fisrt to create all sketches before (on load may exist several sketches) for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - FeaturePtr aFeature = boost::dynamic_pointer_cast(*aFeatIter); + FeaturePtr aFeature = std::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< + std::shared_ptr aSketch = std::dynamic_pointer_cast< ModelAPI_CompositeFeature>(aFeature); - if (aSketch) - changeWorkplane(aSketch); + hasProperFeature = changeWorkplane(aSketch) || hasProperFeature; + } + } + // then get anything but not the sketch + std::set aComplexConstraints; + // fillet and mirror an tangency constraints will be processed later + for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { + std::shared_ptr aFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (!aFeature) + continue; + if (SketchSolver_Group::isComplexConstraint(aFeature)) { + aComplexConstraints.insert(aFeature); continue; } - // Sketch plugin features can be only updated - boost::shared_ptr aSFeature = boost::dynamic_pointer_cast< - SketchPlugin_Feature>(aFeature); - if (aSFeature) - changeConstraintOrEntity(aSFeature); + hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature; + } + // processing remain constraints + aFeatIter = aComplexConstraints.begin(); + for (; aFeatIter != aComplexConstraints.end(); aFeatIter++) { + 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)) { - boost::shared_ptr aDeleteMsg = - boost::dynamic_pointer_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 @@ -120,8 +152,8 @@ void SketchSolver_ConstraintManager::processEvent( 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; @@ -130,7 +162,7 @@ void SketchSolver_ConstraintManager::processEvent( 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++; @@ -146,13 +178,12 @@ void SketchSolver_ConstraintManager::processEvent( // 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; @@ -161,9 +192,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; } @@ -178,24 +209,24 @@ bool SketchSolver_ConstraintManager::changeWorkplane( // Purpose: create/update the constraint or the feature and place it into appropriate group // ============================================================================ bool SketchSolver_ConstraintManager::changeConstraintOrEntity( - boost::shared_ptr theFeature) + std::shared_ptr theFeature) { // Search the groups which this feature touches std::set aGroups; findGroups(theFeature, aGroups); - boost::shared_ptr aConstraint = - boost::dynamic_pointer_cast(theFeature); + 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 // The group will be created only for constraints, not for features if (!aConstraint) return false; - boost::shared_ptr aWP = findWorkplane(aConstraint); + std::shared_ptr aWP = findWorkplane(aConstraint); if (!aWP) return false; - SketchSolver_ConstraintGroup* aGroup = new SketchSolver_ConstraintGroup(aWP); + SketchSolver_Group* aGroup = new SketchSolver_Group(aWP); if (!aGroup->changeConstraint(aConstraint)) { delete aGroup; return false; @@ -204,19 +235,19 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity( return true; } 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) { // If the group is empty, the feature is not added (the constraint only) if (!aConstraint && !(*aGroupIter)->isEmpty()) - return (*aGroupIter)->changeEntity(theFeature) != SLVS_E_UNKNOWN; + 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; @@ -224,7 +255,7 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity( 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) @@ -245,7 +276,7 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity( if (aConstraint) return (*aFirstGroupIter)->changeConstraint(aConstraint); - return (*aFirstGroupIter)->changeEntity(theFeature) != SLVS_E_UNKNOWN; + return (*aFirstGroupIter)->updateFeature(theFeature); } // Something goes wrong @@ -253,54 +284,17 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity( } // ============================================================================ -// Function: updateEntity +// Function: moveEntity // Class: SketchSolver_Session -// Purpose: update any element on the sketch, which is used by constraints +// 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); } // ============================================================================ @@ -309,13 +303,13 @@ void SketchSolver_ConstraintManager::updateEntity( // Purpose: search groups of entities interacting with given feature // ============================================================================ void SketchSolver_ConstraintManager::findGroups( - boost::shared_ptr theFeature, + std::shared_ptr theFeature, std::set& theGroupIDs) const { - boost::shared_ptr aWP = findWorkplane(theFeature); + 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(theFeature)) { if (!(*aGroupIter)->isEmpty()) @@ -334,29 +328,32 @@ void SketchSolver_ConstraintManager::findGroups( // Class: SketchSolver_Session // Purpose: search workplane containing given feature // ============================================================================ -boost::shared_ptr SketchSolver_ConstraintManager::findWorkplane( - boost::shared_ptr theFeature) 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 == theFeature) - 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(); } // ============================================================================ @@ -364,18 +361,30 @@ boost::shared_ptr SketchSolver_ConstraintManager::fin // Class: SketchSolver_Session // Purpose: change entities according to available constraints // ============================================================================ -void SketchSolver_ConstraintManager::resolveConstraints() +void SketchSolver_ConstraintManager::resolveConstraints(const bool theForceUpdate) { myIsComputed = true; bool needToUpdate = false; - std::vector::iterator aGroupIter; + 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++) if ((*aGroupIter)->resolveConstraints()) needToUpdate = true; - // Features may be updated => send events - if (needToUpdate) - 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); } -