X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSketchSolver%2FSketchSolver_Group.cpp;h=9371607d2d6511b13336b394ea32ed078e7a237c;hb=20d233731eaae06b9a75280a2ca675bc9a11cc72;hp=8a5267be2c6fb42a56f027737ec2fe34e580f743;hpb=7f92207f4b32a1c02462c40f002e8d7d870529f1;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 8a5267be2..9371607d2 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -20,19 +20,25 @@ #include #include #include +#include #include #include #include +#include +#include #include +#include #include #include #include -#include #include #include #include #include +#include +#include +#include #include #include @@ -65,6 +71,14 @@ private: Slvs_hGroup GroupIndexer::myGroupIndex = 0; +static void sendMessage(const char* theMessageName) +{ + std::shared_ptr aMessage = std::shared_ptr( + new Events_Message(Events_Loop::eventByName(theMessageName))); + Events_Loop::loop()->send(aMessage); +} + + // ======================================================== // ========= SketchSolver_Group =============== @@ -72,7 +86,8 @@ Slvs_hGroup GroupIndexer::myGroupIndex = 0; SketchSolver_Group::SketchSolver_Group( std::shared_ptr theWorkplane) - : myID(GroupIndexer::NEW_GROUP()) + : myID(GroupIndexer::NEW_GROUP()), + myPrevSolved(true) { // Initialize workplane myWorkplaneID = SLVS_E_UNKNOWN; @@ -180,6 +195,9 @@ bool SketchSolver_Group::changeConstraint( if (!theConstraint) return false; + if (!checkFeatureValidity(theConstraint)) + return false; + bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end(); if (isNewConstraint) { // Add constraint to the current group @@ -206,8 +224,13 @@ bool SketchSolver_Group::changeConstraint( std::shared_ptr aCoinc2 = std::dynamic_pointer_cast(aConstraint); if (aCoincidence != aCoinc2 && aCoincidence->isCoincide(aCoinc2)) { - aCoincidence->attach(aCoinc2); - aConstraint = aCoincidence; + aCoinc2->attach(aCoincidence); + // update other coincidences + ConstraintConstraintMap::iterator anIt = aCIter; + for (++anIt; anIt != myConstraints.end(); ++anIt) + if (anIt->second == aCIter->second) + anIt->second = aCoinc2; + aCIter->second = aCoinc2; } } } @@ -236,12 +259,23 @@ bool SketchSolver_Group::changeConstraint( setTemporary(aConstraint); } } - //// Fix base features for mirror - //if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) { - // AttributeRefListPtr aRefList = std::dynamic_pointer_cast( - // theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_B())); - // fixFeaturesList(aRefList); - //} + // Fix mirror line + if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A())); + if (aRefAttr && aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + if (aFeature) { + SolverConstraintPtr aConstraint = + SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature); + if (aConstraint) { + aConstraint->setGroup(this); + aConstraint->setStorage(myStorage); + setTemporary(aConstraint); + } + } + } + } if (!myFeatureStorage) myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage); @@ -251,8 +285,34 @@ bool SketchSolver_Group::changeConstraint( } +void SketchSolver_Group::updateConstraints() +{ + std::set aPostponed; // postponed constraints Multi-Rotation and Multi-Translation + + ConstraintConstraintMap::iterator anIt = myConstraints.begin(); + for (; anIt != myConstraints.end(); ++anIt) { + if (myChangedConstraints.find(anIt->first) == myChangedConstraints.end()) + continue; + if (anIt->first->getKind() == SketchPlugin_MultiRotation::ID() || + anIt->first->getKind() == SketchPlugin_MultiTranslation::ID()) + aPostponed.insert(anIt->second); + else + anIt->second->update(); + } + + // Update postponed constraints + std::set::iterator aSCIter = aPostponed.begin(); + for (; aSCIter != aPostponed.end(); ++aSCIter) + (*aSCIter)->update(); + + myChangedConstraints.clear(); +} + bool SketchSolver_Group::updateFeature(std::shared_ptr theFeature) { + if (!checkFeatureValidity(theFeature)) + return false; + std::set aConstraints = myFeatureStorage->getConstraints(std::dynamic_pointer_cast(theFeature)); if (aConstraints.empty()) @@ -264,24 +324,26 @@ bool SketchSolver_Group::updateFeature(std::shared_ptr the !aSolConIter->first->data()->isValid()) continue; myFeatureStorage->changeFeature(theFeature, aSolConIter->first); + aSolConIter->second->addFeature(theFeature); - aSolConIter->second->update(); + myChangedConstraints.insert(aSolConIter->first); } return true; } void SketchSolver_Group::moveFeature(std::shared_ptr theFeature) { - updateFeature(theFeature); - // Temporary rigid constraint + // Firstly, create temporary rigid constraint SolverConstraintPtr aConstraint = - SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature); + SketchSolver_Builder::getInstance()->createMovementConstraint(theFeature); if (!aConstraint) return; aConstraint->setGroup(this); aConstraint->setStorage(myStorage); if (aConstraint->error().empty()) setTemporary(aConstraint); + // Secondly, update the feature + updateFeature(theFeature); } // ============================================================================ @@ -402,6 +464,9 @@ bool SketchSolver_Group::updateWorkplane() // ============================================================================ bool SketchSolver_Group::resolveConstraints() { + if (!myChangedConstraints.empty()) + updateConstraints(); + bool aResolved = false; if (myStorage->isNeedToResolve() && !isEmpty()) { myConstrSolver.setGroupID(myID); @@ -414,17 +479,30 @@ bool SketchSolver_Group::resolveConstraints() else { // To avoid overconstraint situation, we will remove temporary constraints one-by-one // and try to find the case without overconstraint - int aNbTemp = (int)myTempConstraints.size(); + bool isLastChance = false; + int aNbTemp = myStorage->numberTemporary(); while (true) { aResult = myConstrSolver.solve(); - if (aResult == SLVS_RESULT_OKAY || aNbTemp <= 0) + if (aResult == SLVS_RESULT_OKAY || isLastChance) break; - aNbTemp = myStorage->deleteTemporaryConstraint(); + if (aNbTemp <= 0) { + // try to update parameters and resolve once again + ConstraintConstraintMap::iterator aConstrIt = myConstraints.begin(); + for (; aConstrIt != myConstraints.end(); ++aConstrIt) + aConstrIt->second->update(); + isLastChance = true; + } else + aNbTemp = myStorage->deleteTemporaryConstraint(); myStorage->initializeSolver(myConstrSolver); } } } catch (...) { - Events_Error::send(SketchSolver_Error::SOLVESPACE_CRASH(), this); +// Events_Error::send(SketchSolver_Error::SOLVESPACE_CRASH(), this); + if (myPrevSolved) { + sendMessage(EVENT_SOLVER_FAILED); + myPrevSolved = false; + } + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::SOLVESPACE_CRASH()); return false; } if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes @@ -433,8 +511,19 @@ bool SketchSolver_Group::resolveConstraints() for (; aConstrIter != myConstraints.end(); aConstrIter++) aConstrIter->second->refresh(); myFeatureStorage->blockEvents(false); - } else if (!myConstraints.empty()) - Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this); + if (!myPrevSolved) { + sendMessage(EVENT_SOLVER_REPAIRED); + myPrevSolved = true; + } + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(""); + } else if (!myConstraints.empty()) { +// Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this); + if (myPrevSolved) { + sendMessage(EVENT_SOLVER_FAILED); + myPrevSolved = false; + } + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::CONSTRAINTS()); + } aResolved = true; } @@ -536,22 +625,15 @@ bool SketchSolver_Group::isConsistent() bool aResult = myFeatureStorage->isConsistent(); if (!aResult) { // remove invalid entities + std::set anInvalidConstraints; ConstraintConstraintMap::iterator aCIter = myConstraints.begin(); - while (aCIter != myConstraints.end()) { - std::list aConstraints = aCIter->second->constraints(); - std::list::iterator anIt = aConstraints.begin(); - for (; anIt != aConstraints.end(); anIt++) - if (!(*anIt)->data() || !(*anIt)->data()->isValid()) - if (aCIter->second->remove(*anIt)) { - // the constraint is fully removed, detach it from the list - ConstraintConstraintMap::iterator aTmpIt = aCIter++; - myFeatureStorage->removeConstraint(aTmpIt->first); - myConstraints.erase(aTmpIt); - break; - } - if (anIt == aConstraints.end()) - aCIter++; + for (; aCIter != myConstraints.end(); ++aCIter) { + if (!aCIter->first->data() || !aCIter->first->data()->isValid()) + anInvalidConstraints.insert(aCIter->first); } + std::set::const_iterator aRemoveIt = anInvalidConstraints.begin(); + for (; aRemoveIt != anInvalidConstraints.end(); ++aRemoveIt) + removeConstraint(*aRemoveIt); } return aResult; } @@ -565,7 +647,8 @@ bool SketchSolver_Group::isConsistent() void SketchSolver_Group::removeTemporaryConstraints() { myTempConstraints.clear(); - myStorage->removeTemporaryConstraints(); + while (myStorage->numberTemporary()) + myStorage->deleteTemporaryConstraint(); // Clean lists of removed entities in the storage std::set aRemPar; std::set aRemEnt; @@ -581,16 +664,41 @@ void SketchSolver_Group::removeTemporaryConstraints() // ============================================================================ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) { + bool isFullyRemoved = true; myFeatureStorage->removeConstraint(theConstraint); ConstraintConstraintMap::iterator aCIter = myConstraints.begin(); for (; aCIter != myConstraints.end(); aCIter++) if (aCIter->second->hasConstraint(theConstraint)) { if (!aCIter->second->remove(theConstraint)) // the constraint is not fully removed - aCIter = myConstraints.end(); + isFullyRemoved = false; break; } - if (aCIter != myConstraints.end()) + if (aCIter == myConstraints.end()) + return; + + if (isFullyRemoved) myConstraints.erase(aCIter); + else if (aCIter != myConstraints.end() && + aCIter->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { + // Update multicoincidence + std::list aMultiCoinc; + SolverConstraintPtr aCoincidence = aCIter->second; + while (aCIter != myConstraints.end()) { + if (aCIter->second != aCoincidence) { + ++aCIter; + continue; + } + if (aCIter->first != theConstraint) + aMultiCoinc.push_back(aCIter->first); + aCIter->second->remove(aCIter->first); + ConstraintConstraintMap::iterator aRemoveIt = aCIter++; + myConstraints.erase(aRemoveIt); + } + + std::list::iterator anIt = aMultiCoinc.begin(); + for (; anIt != aMultiCoinc.end(); ++anIt) + changeConstraint(*anIt); + } } // ============================================================================ @@ -616,3 +724,19 @@ void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint) myTempConstraints.insert(theConstraint); } + +// ============================================================================ +// Function: checkFeatureValidity +// Class: SketchSolver_Group +// Purpose: verifies is the feature valid +// ============================================================================ +bool SketchSolver_Group::checkFeatureValidity(FeaturePtr theFeature) +{ + if (!theFeature || !theFeature->data()->isValid()) + return true; + + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + return aFactory->validate(theFeature); +} +