X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Manager.cpp;h=849c95b0c9eb6ac72de7010c53c2ec4abbb99b1a;hb=5136b236aed3f5e7422eb60ecf10cf52c32e5b4d;hp=d430a9651675ca523c9aa0d4640414455d45fcc6;hpb=6b074436fd3875330cd67cab7db2424a46a8c654;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Manager.cpp b/src/SketchSolver/SketchSolver_Manager.cpp index d430a9651..849c95b0c 100644 --- a/src/SketchSolver/SketchSolver_Manager.cpp +++ b/src/SketchSolver/SketchSolver_Manager.cpp @@ -8,55 +8,26 @@ #include "SketchSolver_Error.h" #include -#include -#include -#include #include -#include #include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include +/// Global constraint manager object +static SketchSolver_Manager* myManager = SketchSolver_Manager::instance(); -static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); +/// \brief Verifies is the feature valid +static bool isFeatureValid(FeaturePtr theFeature) +{ + if (!theFeature || !theFeature->data() || !theFeature->data()->isValid()) + return false; -// Initialization of constraint manager self pointer -SketchSolver_Manager* SketchSolver_Manager::mySelf = 0; + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + return aFactory->validate(theFeature); +} -/// Global constraint manager object -SketchSolver_Manager* myManager = SketchSolver_Manager::instance(); // ======================================================== @@ -64,6 +35,7 @@ SketchSolver_Manager* myManager = SketchSolver_Manager::instance(); // ======================================================== SketchSolver_Manager* SketchSolver_Manager::instance() { + static SketchSolver_Manager* mySelf = 0; // Self pointer to implement singleton functionality if (!mySelf) mySelf = new SketchSolver_Manager(); return mySelf; @@ -80,8 +52,9 @@ SketchSolver_Manager::SketchSolver_Manager() Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED)); Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED)); - 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_SOLVER_FAILED)); + ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED)); + Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_PREPARED)); } SketchSolver_Manager::~SketchSolver_Manager() @@ -89,14 +62,9 @@ SketchSolver_Manager::~SketchSolver_Manager() myGroups.clear(); } -void SketchSolver_Manager::setBuilder(BuilderPtr theBuilder) -{ - myBuilder = theBuilder; -} - -BuilderPtr SketchSolver_Manager::builder() +bool SketchSolver_Manager::groupMessages() { - return myBuilder; + return true; } // ============================================================================ @@ -106,515 +74,185 @@ BuilderPtr SketchSolver_Manager::builder() void SketchSolver_Manager::processEvent( const std::shared_ptr& theMessage) { - checkConflictingConstraints(theMessage); + bool needToResolve = false; + bool isUpdateFlushed = false; + bool isMovedEvt = false; + + 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 + // are collected and must be processed by the solver + if (theMessage->eventID() == aSketchPreparedEvent) { + flushGrouped(anUpdateEvent); + needToResolve = true; + } + if (myIsComputed) return; myIsComputed = true; - // Shows that the message has at least one feature applicable for solver - bool hasProperFeature = false; - if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED) - || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED) + || theMessage->eventID() == anUpdateEvent || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) { std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); std::set aFeatures = anUpdateMsg->objects(); - bool isUpdateFlushed = stopSendUpdate(); + isUpdateFlushed = stopSendUpdate(); - bool isMovedEvt = theMessage->eventID() + 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)) { - // Want to avoid recalculation of DoF too frequently. - // So, set the flag when the feature is really moved. - hasProperFeature = true; - } - } - if (!hasProperFeature) // in this iteration it will compute nothing, so, no problem with recursion - // it is important that solver flushes signal updated after processing move signal as there is - // optimization that relies on this update, might be found by key "optimization" - myIsComputed = false; - } 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 = changeFeature(aFeature) || hasProperFeature; - } - } - bool needToUpdate = false; - // Solve the set of constraints - if (hasProperFeature) - needToUpdate = resolveConstraints(); + // Shows that the message has at least one feature applicable for solver + bool hasProperFeature = false; - // Features may be updated => now send events, but for all changed at once - if (isUpdateFlushed) - allowSendUpdate(); - // send update for movement in any case - if (needToUpdate || isMovedEvt) - Events_Loop::loop()->flush(anUpdateEvent); + // 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; + } + + if (isMovedEvt && hasProperFeature) + needToResolve = true; } 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 SketchPlugin_Sketch::ID() 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(ModelAPI_ResultConstruction::group()) == 0 || - aFGrIter->compare(ModelAPI_Feature::group()) == 0) + aFGrIter->compare(ModelAPI_Feature::group()) == 0) break; if (aFGrIter != aFeatureGroups.end()) { - hasProperFeature = true; - std::list aGroupsToResolve; - std::list::iterator aGroupIter = myGroups.begin(); - std::list aSeparatedGroups; + std::list::iterator aGroupIter = myGroups.begin(); while (aGroupIter != myGroups.end()) { if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed - delete *aGroupIter; - std::list::iterator aRemoveIt = aGroupIter++; + std::list::iterator aRemoveIt = aGroupIter++; myGroups.erase(aRemoveIt); continue; } - if (!(*aGroupIter)->isConsistent()) { // some constraints were removed, try to split the group - (*aGroupIter)->splitGroup(aSeparatedGroups); - if (!(*aGroupIter)->getWorkplane()->string( - SketchPlugin_Sketch::SOLVER_ERROR())->value().empty() || - (*aGroupIter)->isFailed()) - aGroupsToResolve.push_back(*aGroupIter); - } - aGroupIter++; - } - if (aSeparatedGroups.size() > 0) { - myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end()); - aGroupsToResolve.insert(aGroupsToResolve.end(), - aSeparatedGroups.begin(), aSeparatedGroups.end()); - } - if (!aGroupsToResolve.empty()) - resolveConstraints(aGroupsToResolve); + (*aGroupIter)->repairConsistency(); + ++aGroupIter; + } } + myIsComputed = false; } - if (hasProperFeature) - degreesOfFreedom(); - myIsComputed = false; -} + // resolve constraints if needed + bool needToUpdate = needToResolve && resolveConstraints(); + releaseFeaturesIfEventsBlocked(); -void SketchSolver_Manager::checkConflictingConstraints(const std::shared_ptr& theMessage) -{ - if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_SOLVER_REPAIRED)) { - std::shared_ptr aMessage = - std::dynamic_pointer_cast(theMessage); - std::set aSentObjs = aMessage->objects(); - if (!aSentObjs.empty()) { - // Obtain sketch where the constraints are placed. - // It is enough to check only one constraint. - CompositeFeaturePtr aSketch; - FeaturePtr aConstraint = ModelAPI_Feature::feature(*aSentObjs.begin()); - std::list::const_iterator aGrIt = myGroups.begin(); - for (; aGrIt != myGroups.end(); ++aGrIt) - if ((*aGrIt)->isInteract(aConstraint)) { - aSketch = (*aGrIt)->getWorkplane(); - break; - } + // Features may be updated => now send events, but for all changed at once + if (isUpdateFlushed) + allowSendUpdate(); - // Search failed groups built on the same sketch - if (aSketch) { - for (aGrIt = myGroups.begin(); aGrIt != myGroups.end(); ++aGrIt) { - SketchSolver_Group* aGroup = *aGrIt; - if (aGroup->isBaseWorkplane(aSketch) && aGroup->isFailed() && - !aGroup->isInteract(aConstraint)) { - // reset error message on the sketch - aGroup->getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue( - SketchSolver_Error::CONSTRAINTS()); - break; - } - } - } - } - } -} + myIsComputed = false; -// ============================================================================ -// Function: changeWorkplane -// Purpose: update workplane by given parameters of the sketch -// ============================================================================ -bool SketchSolver_Manager::changeWorkplane(CompositeFeaturePtr theSketch) -{ - bool aResult = true; // changed when a workplane wrongly updated - bool isUpdated = false; - // Try to update specified workplane in all groups - std::list::iterator aGroupIter; - for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) - if ((*aGroupIter)->isBaseWorkplane(theSketch)) { - isUpdated = true; - aResult = false; - } - // If the workplane is not updated, so this is a new workplane - if (!isUpdated) { - SketchSolver_Group* aNewGroup = new SketchSolver_Group(theSketch); - // Verify that the group is created successfully - if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) { - delete aNewGroup; - return false; - } - myGroups.push_back(aNewGroup); - } - return aResult; + // send update for movement in any case + if (needToUpdate || isMovedEvt) + Events_Loop::loop()->flush(anUpdateEvent); } // ============================================================================ // Function: changeConstraintOrEntity // Purpose: create/update the constraint or the feature and place it into appropriate group // ============================================================================ -bool SketchSolver_Manager::changeFeature(std::shared_ptr theFeature) +bool SketchSolver_Manager::updateFeature(std::shared_ptr theFeature, + bool theMoved) { - // Search the groups which this feature touches - std::set aGroups; - findGroups(theFeature, aGroups); - - std::shared_ptr aConstraint = + // Check feature validity and find a group to place it. + // If the feature is not valid, the returned group will be empty. + // This will protect to deal with wrong (not fully initialized) features. + SketchGroupPtr aGroup = findGroup(theFeature); + if (!aGroup) + return false; + aGroup->blockEvents(true); + + 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; - 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 feature into it - GroupID aGroupId = *(aGroups.begin()); - std::list::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)->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::list::iterator aFirstGroupIter; - for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++) - if ((*aFirstGroupIter)->getId() == *aGroupsIter) - break; - if (aFirstGroupIter == myGroups.end()) - return false; - - // Append other groups to the first one - std::list::iterator anOtherGroupIter = aFirstGroupIter; - ++anOtherGroupIter; - for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) { - for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++) - if ((*anOtherGroupIter)->getId() == *aGroupsIter) - break; - if (anOtherGroupIter == myGroups.end()) { // Group disappears - anOtherGroupIter = aFirstGroupIter; - ++anOtherGroupIter; - continue; - } - - (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter); - std::list::iterator aRemoveIt = anOtherGroupIter++; - delete *aRemoveIt; - myGroups.erase(aRemoveIt); - } - - if (aConstraint) - (*aFirstGroupIter)->changeConstraint(aConstraint); - else - (*aFirstGroupIter)->updateFeature(theFeature); - // groups are merged => need to resolve them - return true; - } - - // Something goes wrong - return false; -} - -// ============================================================================ -// Function: moveEntity -// Purpose: update element moved on the sketch, which is used by constraints -// ============================================================================ -bool SketchSolver_Manager::moveEntity(std::shared_ptr theFeature) -{ - bool isMoved = false; - std::list::iterator aGroupIt = myGroups.begin(); - for (; aGroupIt != myGroups.end(); aGroupIt++) - if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature)) - isMoved = (*aGroupIt)->moveFeature(theFeature) || isMoved; - - if (!isMoved && theFeature->getKind() == SketchPlugin_Arc::ID()) { - // Workaround to move arc. - // If the arc has not been constrained, we will push it into empty group and apply movement. - for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); aGroupIt++) - if ((*aGroupIt)->isEmpty()) - isMoved = (*aGroupIt)->moveFeature(theFeature) || isMoved; - } - return isMoved; + bool isOk = false; + if (aConstraint) + isOk = aGroup->changeConstraint(aConstraint); + else if (theMoved) + isOk = aGroup->moveFeature(theFeature); + else + isOk = aGroup->updateFeature(theFeature); + return isOk; } // ============================================================================ -// Function: findGroups +// Function: findGroup // Purpose: search groups of entities interacting with given feature // ============================================================================ -void SketchSolver_Manager::findGroups( - std::shared_ptr theFeature, - std::set& theGroupIDs) const +SketchGroupPtr SketchSolver_Manager::findGroup( + std::shared_ptr theFeature) { - std::shared_ptr aWP = findWorkplane(theFeature); - - SketchSolver_Group* anEmptyGroup = 0; // appropriate empty group for specified constraint - std::list::const_iterator aGroupIter; - for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) - if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) { - if (!(*aGroupIter)->isEmpty()) - theGroupIDs.insert((*aGroupIter)->getId()); - else if (!anEmptyGroup) - anEmptyGroup = *aGroupIter; + if (!isFeatureValid(theFeature)) + return SketchGroupPtr(); // do not process wrong features + + // Obtain sketch, containing the feature + CompositeFeaturePtr aSketch; + const std::set& aRefsList = theFeature->data()->refsToMe(); + std::set::const_iterator aRefIt = aRefsList.begin(); + for (; aRefIt != aRefsList.end(); ++aRefIt) { + FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner()); + if (anOwner && anOwner->getKind() == SketchPlugin_Sketch::ID()) { + aSketch = std::dynamic_pointer_cast(anOwner); + break; } + } - // When only empty group is found, use it - if (anEmptyGroup && theGroupIDs.empty()) - theGroupIDs.insert(anEmptyGroup->getId()); -} + if (!aSketch) + return SketchGroupPtr(); // not a sketch's feature -// ============================================================================ -// Function: findWorkplane -// Purpose: search workplane containing given feature -// ============================================================================ -std::shared_ptr SketchSolver_Manager -::findWorkplane(std::shared_ptr theFeature) const -{ - // Already verified workplanes - std::set > aVerified; - - std::list::const_iterator aGroupIter; - for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) { - std::shared_ptr aWP = (*aGroupIter)->getWorkplane(); - if (aVerified.find(aWP) != aVerified.end()) - continue; - - 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); - } + std::list::const_iterator aGroupIt; + for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); ++aGroupIt) + if ((*aGroupIt)->getWorkplane() == aSketch) + return *aGroupIt; - return std::shared_ptr(); + // group for the sketch does not created yet + SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(aSketch)); + myGroups.push_back(aNewGroup); + return aNewGroup; } // ============================================================================ // Function: resolveConstraints // Purpose: change entities according to available constraints // ============================================================================ -bool SketchSolver_Manager::resolveConstraints(const std::list& theGroups) +bool SketchSolver_Manager::resolveConstraints() { bool needToUpdate = false; - const std::list& aGroupsToResolve = theGroups.empty() ? myGroups : theGroups; - std::list::const_iterator aGroupIter = aGroupsToResolve.begin(); - for (; aGroupIter != aGroupsToResolve.end(); aGroupIter++) + std::list::const_iterator aGroupIter = myGroups.begin(); + for (; aGroupIter != myGroups.end(); ++aGroupIter) { if ((*aGroupIter)->resolveConstraints()) needToUpdate = true; + } return needToUpdate; } -// ============================================================================ -// Function: degreesOfFreedom -// Purpose: calculate DoFs for each sketch -// ============================================================================ -void SketchSolver_Manager::degreesOfFreedom() +void SketchSolver_Manager::releaseFeaturesIfEventsBlocked() const { - static std::map aDoFDelta; // indicates how many DoF adds or decreases a feature - static bool isNeedInit = true; - if (isNeedInit) { - aDoFDelta[SketchPlugin_Point::ID()] = 2; - aDoFDelta[SketchPlugin_Line::ID()] = 4; - aDoFDelta[SketchPlugin_Circle::ID()] = 3; - aDoFDelta[SketchPlugin_Arc::ID()] = 5; - - aDoFDelta[SketchPlugin_ConstraintAngle::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintCollinear::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintDistance::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintEqual::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintHorizontal::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintLength::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintMiddle::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintParallel::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintPerpendicular::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintRadius::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintTangent::ID()] = -1; - aDoFDelta[SketchPlugin_ConstraintVertical::ID()] = -1; - - isNeedInit = false; - } - - std::map aSketchDoF; - - std::list::const_iterator aGroupIt = myGroups.begin(); - for (; aGroupIt != myGroups.end(); ++aGroupIt) { - CompositeFeaturePtr aSketch = (*aGroupIt)->getWorkplane(); - bool isSketchValid = aSketch->data() && aSketch->data()->isValid(); - - if (isSketchValid) { - std::shared_ptr aNormal = - std::dynamic_pointer_cast(aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); - isSketchValid = aNormal && aNormal->isInitialized(); - } - - if (!isSketchValid) { - myDoF.erase(aSketch); - continue; - } - - // check conflicting constraints in the group - if ((*aGroupIt)->isFailed()) - aSketchDoF[aSketch] = -1; - // check the sketch is already processed - if (aSketchDoF.find(aSketch) != aSketchDoF.end() || aSketchDoF[aSketch] < 0) - continue; - - std::set aCoincidentPoints; - int aDoF = 0; - int aNbSubs = aSketch->numberOfSubs(); - for (int i = 0; i < aNbSubs; ++i) { - FeaturePtr aFeature = aSketch->subFeature(i); - // check DoF delta for invariant types - std::map::const_iterator aFound = aDoFDelta.find(aFeature->getKind()); - if (aFound != aDoFDelta.end()) { - aDoF += aFound->second; - continue; - } - - // DoF delta in specific cases - if (aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { - AttributePtr aCoincPoint[2] = {AttributePtr(), AttributePtr()}; - for (int j = 0; j < 2; ++j) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - aFeature->attribute(SketchPlugin_Constraint::ATTRIBUTE(j))); - if (!aRefAttr) - continue; - bool isPoint = !aRefAttr->isObject(); - if (isPoint) - aCoincPoint[j] = aRefAttr->attr(); - else { - FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object()); - isPoint = anAttr && anAttr->getKind() == SketchPlugin_Point::ID(); - if (isPoint) - aCoincPoint[j] = anAttr->attribute(SketchPlugin_Point::COORD_ID()); - } - } - if (aCoincPoint[0] && aCoincPoint[1]) { - // point-point coincidence - if (aCoincidentPoints.find(aCoincPoint[0]) == aCoincidentPoints.end() || - aCoincidentPoints.find(aCoincPoint[1]) == aCoincidentPoints.end()) - aDoF -= 2; - } else - aDoF -= 1; - for (int j = 0; j < 2; ++j) - if (aCoincPoint[j]) - aCoincidentPoints.insert(aCoincPoint[j]); - } - else if (aFeature->getKind() == SketchPlugin_ConstraintRigid::ID()) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - aFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); - assert(aRefAttr); - if (!aRefAttr->isObject()) - aDoF -= 2; // attribute is a point - else { - FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object()); - if (anAttr) - aDoF -= aDoFDelta[anAttr->getKind()]; - } - } - else if (aFeature->getKind() == SketchPlugin_ConstraintMirror::ID() || - aFeature->getKind() == SketchPlugin_MultiRotation::ID() || - aFeature->getKind() == SketchPlugin_MultiTranslation::ID()) { - int aNbCopies = 1; - std::string anAttrName; - if (aFeature->getKind() == SketchPlugin_ConstraintMirror::ID()) - anAttrName = SketchPlugin_Constraint::ENTITY_B(); - else { - if (aFeature->getKind() == SketchPlugin_MultiRotation::ID()) - aNbCopies = aFeature->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1; - else if (aFeature->getKind() == SketchPlugin_MultiTranslation::ID()) - aNbCopies = aFeature->integer(SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID())->value() - 1; - anAttrName = SketchPlugin_Constraint::ENTITY_A(); - } - - AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast( - aFeature->attribute(anAttrName)); - std::list anObjList = aRefListOfShapes->list(); - std::list::const_iterator anObjIt = anObjList.begin(); - for (; anObjIt != anObjList.end(); ++anObjIt) { - FeaturePtr aSub = ModelAPI_Feature::feature(*anObjIt); - aDoF -= aDoFDelta[aSub->getKind()] * aNbCopies; - } - } - } - - aSketchDoF[aSketch] = aDoF; - } - - // Check the degrees of freedom are changed - std::map::const_iterator aDoFIt = aSketchDoF.begin(); - std::map::iterator aFound; - for (; aDoFIt != aSketchDoF.end(); ++aDoFIt) { - if (aDoFIt->second < 0) - continue; // conflicting constraints on the current sketch - aFound = myDoF.find(aDoFIt->first); - if (aFound != myDoF.end() && aFound->second == aDoFIt->second) - continue; // nothing is changed - myDoF[aDoFIt->first] = aDoFIt->second; - // change attribute value - std::ostringstream aStream; - if (aDoFIt->second == 0) - aStream << "Sketch fully fixed (DOF = " << aDoFIt->second << ")"; - else - aStream << "DOF (degree of freedom) = " << aDoFIt->second; - aDoFIt->first->data()->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aStream.str()); - } + std::list::const_iterator aGroupIter = myGroups.begin(); + for (; aGroupIter != myGroups.end(); ++aGroupIter) + (*aGroupIter)->blockEvents(false); } bool SketchSolver_Manager::stopSendUpdate() const { +static const 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) { @@ -625,5 +263,5 @@ bool SketchSolver_Manager::stopSendUpdate() const void SketchSolver_Manager::allowSendUpdate() const { - Events_Loop::loop()->setFlushed(anUpdateEvent, true); + Events_Loop::loop()->setFlushed(Events_Loop::eventByName(EVENT_OBJECT_UPDATED), true); }