From 53137bb38745e513e524055309d0abaaac18d3ba Mon Sep 17 00:00:00 2001 From: azv Date: Fri, 26 Sep 2014 09:47:35 +0400 Subject: [PATCH] Issue #154: Crash on Undo-Redo operations Implemented removing multiple constraints Added verification of the data validity --- src/SketchSolver/SketchSolver_Constraint.cpp | 24 ++++--- .../SketchSolver_ConstraintGroup.cpp | 71 ++++++++++++++++--- .../SketchSolver_ConstraintGroup.h | 5 ++ 3 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index 19af99788..8360d0af5 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -63,6 +63,10 @@ const int& SketchSolver_Constraint::getType( if (!theConstraint) return getType(); + DataPtr aConstrData = theConstraint->data(); + if (!aConstrData || !aConstrData->isValid()) + return getType(); + // Assign empty names of attributes myAttributesList.clear(); for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++) @@ -76,8 +80,8 @@ const int& SketchSolver_Constraint::getType( int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point int aPt3d = 0; // bit-mapped field, the same information for 3D points for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - boost::shared_ptr anAttr = theConstraint->data()->attribute( - SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + boost::shared_ptr anAttr = + aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); if (!anAttr) continue; switch (typeOfAttribute(anAttr)) { @@ -107,8 +111,8 @@ const int& SketchSolver_Constraint::getType( int aNbPoints = 0; int aNbEntities = 0; for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - boost::shared_ptr anAttr = theConstraint->data()->attribute( - SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + boost::shared_ptr anAttr = + aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); switch (typeOfAttribute(anAttr)) { case POINT2D: case POINT3D: @@ -133,8 +137,8 @@ const int& SketchSolver_Constraint::getType( if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0) { int aNbLines = 0; for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - boost::shared_ptr anAttr = theConstraint->data()->attribute( - SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + boost::shared_ptr anAttr = + aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); if (typeOfAttribute(anAttr) == LINE) myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); } @@ -149,8 +153,8 @@ const int& SketchSolver_Constraint::getType( if (isParallel || isPerpendicular) { int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - boost::shared_ptr anAttr = theConstraint->data()->attribute( - SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + boost::shared_ptr anAttr = + aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); if (typeOfAttribute(anAttr) == LINE) myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); } @@ -163,8 +167,8 @@ const int& SketchSolver_Constraint::getType( if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0) { int aNbEntities = 2; // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - boost::shared_ptr anAttr = theConstraint->data()->attribute( - SketchPlugin_Constraint::ATTRIBUTE(indAttr)); + boost::shared_ptr anAttr = + aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); AttrType aType = typeOfAttribute(anAttr); if (aType == CIRCLE || aType == ARC) myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); diff --git a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp index bfdc89060..642654407 100644 --- a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp @@ -730,8 +730,14 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vectorfind(aConstrEnt[i]) != aGrEntIter->end()); + // Also we need to check sub-entities + int aEntPos = Search(aConstrEnt[i], myEntities); + Slvs_hEntity* aSub = myEntities[aEntPos].point; + for (int j = 0; *aSub != 0 && j < 4 && !isFound; aSub++) + isFound = (aGrEntIter->find(*aSub) != aGrEntIter->end()); + } if (isFound) anIndexes.push_back(aGrEntIter - aGroupsEntities.begin()); } @@ -825,17 +831,50 @@ bool SketchSolver_ConstraintGroup::updateGroup() myConstraintMap.rbegin(); bool isAllValid = true; bool isCCRemoved = false; // indicates that at least one of coincidence constraints was removed - while (isAllValid && aConstrIter != myConstraintMap.rend()) { + int aConstrIndex = 0; + while (/*isAllValid && */aConstrIter != myConstraintMap.rend()) { if (!aConstrIter->first->data() || !aConstrIter->first->data()->isValid()) { if (aConstrIter->first->getKind().compare(SketchPlugin_ConstraintCoincidence::ID()) == 0) isCCRemoved = true; - std::map, Slvs_hConstraint>::reverse_iterator aCopyIter = - aConstrIter++; - removeConstraint(aCopyIter->first); + removeConstraint(aConstrIter->first); isAllValid = false; - } else + // Get back the correct position of iterator after the "remove" operation + aConstrIter = myConstraintMap.rbegin(); + for (int i = 0; i < aConstrIndex && aConstrIter != myConstraintMap.rend(); i++) + aConstrIter++; + } else { aConstrIter++; + aConstrIndex++; + } + } + + // Check if some entities are invalid too + std::set anEntToRemove; + std::map, Slvs_hEntity>::iterator + anAttrIter = myEntityAttrMap.begin(); + while (anAttrIter != myEntityAttrMap.end()) { + if (!anAttrIter->first->owner() || !anAttrIter->first->owner()->data() || + !anAttrIter->first->owner()->data()->isValid()) { + anEntToRemove.insert(anAttrIter->second); + std::map, Slvs_hEntity>::iterator + aRemovedIter = anAttrIter; + anAttrIter++; + myEntityAttrMap.erase(aRemovedIter); + } else + anAttrIter++; + } + std::map::iterator aFeatIter = myEntityFeatMap.begin(); + while (aFeatIter != myEntityFeatMap.end()) { + if (!aFeatIter->first || !aFeatIter->first->data() || + !aFeatIter->first->data()->isValid()) { + anEntToRemove.insert(aFeatIter->second); + std::map::iterator aRemovedIter = aFeatIter; + aFeatIter++; + myEntityFeatMap.erase(aRemovedIter); + } else + aFeatIter++; } + removeEntitiesById(anEntToRemove); // Probably, need to update coincidence constraints if (isCCRemoved && !myExtraCoincidence.empty()) { @@ -1103,8 +1142,22 @@ void SketchSolver_ConstraintGroup::removeConstraint( } else anEntFeatIter++; } - std::set::const_reverse_iterator aRemIter = anEntToRemove.rbegin(); - for (; aRemIter != anEntToRemove.rend(); aRemIter++) { + + removeEntitiesById(anEntToRemove); + + if (myCoincidentPoints.size() == 1 && myCoincidentPoints.front().empty()) + myCoincidentPoints.clear(); +} + +// ============================================================================ +// Function: removeEntitiesById +// Class: SketchSolver_ConstraintGroup +// Purpose: Removes specified entities and their parameters +// ============================================================================ +void SketchSolver_ConstraintGroup::removeEntitiesById(const std::set& theEntities) +{ + std::set::const_reverse_iterator aRemIter = theEntities.rbegin(); + for (; aRemIter != theEntities.rend(); aRemIter++) { unsigned int anEntPos = Search(*aRemIter, myEntities); if (anEntPos >= myEntities.size()) continue; @@ -1129,8 +1182,6 @@ void SketchSolver_ConstraintGroup::removeConstraint( for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) aCoPtIter->erase(*aRemIter); } - if (myCoincidentPoints.size() == 1 && myCoincidentPoints.front().empty()) - myCoincidentPoints.clear(); } // ============================================================================ diff --git a/src/SketchSolver/SketchSolver_ConstraintGroup.h b/src/SketchSolver/SketchSolver_ConstraintGroup.h index 8c5a72e36..6024f8cae 100644 --- a/src/SketchSolver/SketchSolver_ConstraintGroup.h +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.h @@ -146,6 +146,11 @@ protected: Slvs_hParam changeParameter(const double& theParam, std::vector::const_iterator& thePrmIter); + /** \brief Removes specified entities and their parameters + * \param[in] theEntities list of IDs of the entities to be removed + */ + void removeEntitiesById(const std::set& theEntities); + /** \brief Removes constraints from the group * \param[in] theConstraint constraint to be removed */ -- 2.39.2