X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Group.cpp;h=5a9652fe6955ae404f23f248f5d8da9605bf81c3;hb=8da5ddb2feeb29c481a51530a435be524bf720e9;hp=5bce44595b775ffba4e86e6b01407eff52da7dff;hpb=96c4ea302ca42050e2461ce940c13601c3ee6e43;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 5bce44595..5a9652fe6 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -75,7 +76,7 @@ private: static Slvs_hGroup myGroupIndex; ///< index of the group }; -Slvs_hGroup GroupIndexer::myGroupIndex = 0; +Slvs_hGroup GroupIndexer::myGroupIndex = SLVS_G_OUTOFGROUP; static void sendMessage(const char* theMessageName) @@ -137,6 +138,15 @@ bool SketchSolver_Group::isInteract( return myFeatureStorage->isInteract(std::dynamic_pointer_cast(theFeature)); } +// check the entity is really exists +static void checkEntity(StoragePtr theStorage, Slvs_hEntity& theEntity) +{ + if (theEntity == SLVS_E_UNKNOWN) + return; + Slvs_Entity anEnt = theStorage->getEntity(theEntity); + theEntity = anEnt.h; +} + // ============================================================================ // Function: getFeatureId // Class: SketchSolver_Group @@ -147,19 +157,21 @@ Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const Slvs_hEntity aResult = SLVS_E_UNKNOWN; if (!myFeatureStorage) return aResult; - std::set aConstraints = myFeatureStorage->getConstraints(theFeature); - if (aConstraints.empty()) - return aResult; - std::set::iterator aConstrIter = aConstraints.begin(); - for (; aConstrIter != aConstraints.end(); aConstrIter++) { - ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstrIter); - if (aCIter == myConstraints.end()) - continue; + // Obtain regular constraints interacting with the feature and find its ID + ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); ++aCIter) { aResult = aCIter->second->getId(theFeature); + checkEntity(myStorage, aResult); if (aResult != SLVS_E_UNKNOWN) return aResult; } - return SLVS_E_UNKNOWN; + // The feature is not found, check it in the temporary constraints + std::set::iterator aTmpCIter = myTempConstraints.begin(); + for (; aTmpCIter != myTempConstraints.end() && aResult == SLVS_E_UNKNOWN; ++aTmpCIter) { + aResult = (*aTmpCIter)->getId(theFeature); + checkEntity(myStorage, aResult); + } + return aResult; } // ============================================================================ @@ -172,19 +184,28 @@ Slvs_hEntity SketchSolver_Group::getAttributeId(AttributePtr theAttribute) const Slvs_hEntity aResult = SLVS_E_UNKNOWN; if (!myFeatureStorage) return aResult; - std::set aConstraints = myFeatureStorage->getConstraints(theAttribute); - if (aConstraints.empty()) - return aResult; - std::set::iterator aConstrIter = aConstraints.begin(); - for (; aConstrIter != aConstraints.end(); aConstrIter++) { - ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstrIter); - if (aCIter == myConstraints.end()) - continue; + // Obtain regular constraints interacting with the attribute and find its ID + ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); ++aCIter) { aResult = aCIter->second->getId(theAttribute); + checkEntity(myStorage, aResult); if (aResult != SLVS_E_UNKNOWN) return aResult; } - return SLVS_E_UNKNOWN; + // The attribute is not found, check it in the temporary constraints + std::set::const_iterator aTmpCIter = myTempConstraints.begin(); + for (; aTmpCIter != myTempConstraints.end() && aResult == SLVS_E_UNKNOWN; ++aTmpCIter) { + aResult = (*aTmpCIter)->getId(theAttribute); + checkEntity(myStorage, aResult); + } + // Last chance to find attribute in parametric constraints + std::map::const_iterator aParIter = + myParametricConstraints.find(theAttribute); + if (aParIter != myParametricConstraints.end()) { + aResult = aParIter->second->getId(theAttribute); + checkEntity(myStorage, aResult); + } + return aResult; } // ============================================================================ @@ -199,7 +220,7 @@ bool SketchSolver_Group::changeConstraint( if (myWorkplaneID == SLVS_E_UNKNOWN) return false; - if (!theConstraint) + if (!theConstraint || !theConstraint->data()) return false; if (!checkFeatureValidity(theConstraint)) @@ -222,8 +243,9 @@ bool SketchSolver_Group::changeConstraint( // Additional verification of coincidence of several points if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { + bool hasMultiCoincidence = false; ConstraintConstraintMap::iterator aCIter = myConstraints.begin(); - for (; aCIter != myConstraints.end(); aCIter++) { + for (; aCIter != myConstraints.end(); ++aCIter) { std::shared_ptr aCoincidence = std::dynamic_pointer_cast(aCIter->second); if (!aCoincidence) @@ -238,8 +260,12 @@ bool SketchSolver_Group::changeConstraint( if (anIt->second == aCIter->second) anIt->second = aCoinc2; aCIter->second = aCoinc2; + hasMultiCoincidence = true; } } + + if (hasMultiCoincidence) + notifyMultiConstraints(); } myConstraints[theConstraint] = aConstraint; } @@ -288,6 +314,43 @@ bool SketchSolver_Group::changeConstraint( myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage); myFeatureStorage->changeConstraint(theConstraint); + // Check the attributes of constraint are given by parametric expression + std::list anAttributes = + theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list::iterator anAttrIt = anAttributes.begin(); + for (; anAttrIt != anAttributes.end(); ++anAttrIt) { + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(*anAttrIt); + if (!aRefAttr) + continue; + + std::shared_ptr aPoint; + if (aRefAttr->isObject()) { + FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object()); + if (aFeat->getKind() != SketchPlugin_Point::ID()) + continue; + aPoint = std::dynamic_pointer_cast( + aFeat->attribute(SketchPlugin_Point::COORD_ID())); + } else + aPoint = std::dynamic_pointer_cast(aRefAttr->attr()); + + if (!aPoint || (aPoint->textX().empty() && aPoint->textY().empty())) + continue; + + std::map::iterator aFound = + myParametricConstraints.find(aPoint); + if (aFound == myParametricConstraints.end()) { + SolverConstraintPtr aConstraint = + SketchSolver_Builder::getInstance()->createParametricConstraint(aPoint); + if (!aConstraint) + continue; + aConstraint->setGroup(this); + aConstraint->setStorage(myStorage); + myParametricConstraints[aPoint] = aConstraint; + } else + aFound->second->update(); + } + return true; } @@ -335,6 +398,31 @@ bool SketchSolver_Group::updateFeature(std::shared_ptr the aSolConIter->second->addFeature(theFeature); myChangedConstraints.insert(aSolConIter->first); } + + // Search attributes of the feature in the set of parametric constraints and update them + std::list anAttrList = + theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::iterator anAttrIt = anAttrList.begin(); + for (; anAttrIt != anAttrList.end(); ++anAttrIt) { + std::map::iterator aFound = + myParametricConstraints.find(*anAttrIt); + if (aFound != myParametricConstraints.end()) + aFound->second->update(); + else { + std::shared_ptr aPoint = + std::dynamic_pointer_cast(*anAttrIt); + if (aPoint && (!aPoint->textX().empty() || !aPoint->textY().empty())) { + // Create new parametric constraint + SolverConstraintPtr aConstraint = + SketchSolver_Builder::getInstance()->createParametricConstraint(*anAttrIt); + if (!aConstraint) + continue; + aConstraint->setGroup(this); + aConstraint->setStorage(myStorage); + myParametricConstraints[*anAttrIt] = aConstraint; + } + } + } return true; } @@ -428,13 +516,13 @@ bool SketchSolver_Group::updateWorkplane() std::vector::iterator aParIter = aParams.begin(); for (; aParIter != aParams.end(); aParIter++) { aParIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage - aParIter->group = myID; + aParIter->group = SLVS_G_OUTOFGROUP; aParIter->h = myStorage->addParameter(*aParIter); } std::vector::iterator anEntIter = anEntities.begin(); for (; anEntIter != anEntities.end(); anEntIter++) { anEntIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage - anEntIter->group = myID; + anEntIter->group = SLVS_G_OUTOFGROUP; anEntIter->wrkpl = myWorkplaneID; for (int i = 0; i < 4; i++) if (anEntIter->param[i] != SLVS_E_UNKNOWN) @@ -477,6 +565,7 @@ bool SketchSolver_Group::resolveConstraints() bool aResolved = false; if (myStorage->isNeedToResolve() && !isEmpty()) { myConstrSolver.setGroupID(myID); + myConstrSolver.calculateFailedConstraints(false); myStorage->initializeSolver(myConstrSolver); int aResult = SLVS_RESULT_OKAY; @@ -500,36 +589,45 @@ bool SketchSolver_Group::resolveConstraints() isLastChance = true; } else aNbTemp = myStorage->deleteTemporaryConstraint(); + myConstrSolver.calculateFailedConstraints(true); // something failed => need to find it myStorage->initializeSolver(myConstrSolver); } } } catch (...) { // Events_Error::send(SketchSolver_Error::SOLVESPACE_CRASH(), this); + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::SOLVESPACE_CRASH()); if (myPrevSolved) { + // the error message should be changed before sending the message 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 myFeatureStorage->blockEvents(true); + // First refresh parametric constraints to satisfy parameters + std::map::iterator aParIter = myParametricConstraints.begin(); + for (; aParIter != myParametricConstraints.end(); ++aParIter) + aParIter->second->refresh(); + // Update all other constraints ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin(); - for (; aConstrIter != myConstraints.end(); aConstrIter++) + for (; aConstrIter != myConstraints.end(); ++aConstrIter) aConstrIter->second->refresh(); myFeatureStorage->blockEvents(false); if (!myPrevSolved) { + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(""); + // the error message should be changed before sending the message sendMessage(EVENT_SOLVER_REPAIRED); myPrevSolved = true; - getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(""); } } else if (!myConstraints.empty()) { // Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this); + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::CONSTRAINTS()); if (myPrevSolved) { + // the error message should be changed before sending the message sendMessage(EVENT_SOLVER_FAILED); myPrevSolved = false; } - getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::CONSTRAINTS()); } aResolved = true; @@ -592,9 +690,9 @@ void SketchSolver_Group::splitGroup(std::vector& theCuts) std::vector::iterator aUnuseIt = anUnusedConstraints.begin(); while (aUnuseIt != anUnusedConstraints.end()) { if (aNewFeatStorage->isInteract(*aUnuseIt)) { - size_t aShift = aUnuseIt - anUnusedConstraints.begin(); + aNewFeatStorage->changeConstraint(*aUnuseIt); anUnusedConstraints.erase(aUnuseIt); - aUnuseIt = anUnusedConstraints.begin() + aShift; + aUnuseIt = anUnusedConstraints.begin(); continue; } aUnuseIt++; @@ -618,6 +716,9 @@ void SketchSolver_Group::splitGroup(std::vector& theCuts) theCuts.push_back(aGroup); } } + + // Update feature storage + myFeatureStorage = aNewFeatStorage; } // ============================================================================ @@ -654,7 +755,11 @@ bool SketchSolver_Group::isConsistent() // ============================================================================ void SketchSolver_Group::removeTemporaryConstraints() { + std::set::iterator aTmpIt = myTempConstraints.begin(); + for (; aTmpIt != myTempConstraints.end(); ++aTmpIt) + (*aTmpIt)->remove(); myTempConstraints.clear(); + while (myStorage->numberTemporary()) myStorage->deleteTemporaryConstraint(); // Clean lists of removed entities in the storage @@ -684,6 +789,9 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) if (aCIter == myConstraints.end()) return; + // Remove entities not used by constraints + myStorage->removeUnusedEntities(); + if (isFullyRemoved) myConstraints.erase(aCIter); else if (aCIter != myConstraints.end() && @@ -706,6 +814,8 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) std::list::iterator anIt = aMultiCoinc.begin(); for (; anIt != aMultiCoinc.end(); ++anIt) changeConstraint(*anIt); + + notifyMultiConstraints(); } } @@ -748,6 +858,23 @@ bool SketchSolver_Group::checkFeatureValidity(FeaturePtr theFeature) return aFactory->validate(theFeature); } +// ============================================================================ +// Function: notifyMultiConstraints +// Class: SketchSolver_Group +// Purpose: Update Multi-Translation/-Rotation constraints due to multi coincidence appears/disappears +// ============================================================================ +void SketchSolver_Group::notifyMultiConstraints() +{ + ConstraintConstraintMap::iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); ++aCIter) { + if (aCIter->first->getKind() == SketchPlugin_MultiRotation::ID() || + aCIter->first->getKind() == SketchPlugin_MultiTranslation::ID()) { + std::shared_ptr aMulti = + std::dynamic_pointer_cast(aCIter->second); + aMulti->checkCoincidence(); + } + } +}