From 171168995ff6ef55815a68c857d1ed10c2476137 Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 17 Sep 2015 09:41:17 +0300 Subject: [PATCH] Check multi coincidence and remove fixing of copied entities in MultiRotation/MultiTranslation (issue #982) --- .../SketchSolver_ConstraintMulti.cpp | 67 +++++++++++++++++++ .../SketchSolver_ConstraintMulti.h | 3 + src/SketchSolver/SketchSolver_Group.cpp | 27 +++++++- src/SketchSolver/SketchSolver_Group.h | 3 + src/SketchSolver/SketchSolver_Storage.cpp | 38 ++++++++++- src/SketchSolver/SketchSolver_Storage.h | 2 + 6 files changed, 138 insertions(+), 2 deletions(-) diff --git a/src/SketchSolver/SketchSolver_ConstraintMulti.cpp b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp index e68a881be..0980dab4e 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMulti.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp @@ -237,3 +237,70 @@ void SketchSolver_ConstraintMulti::adjustConstraint() myPointsJustUpdated.clear(); myAdjusted = true; } + +void SketchSolver_ConstraintMulti::checkCoincidence() +{ + std::vector< std::vector > aFilteredPoints; // points are filtered by their positions + + std::vector< std::vector >::const_iterator aPCIt = myPointsAndCopies.begin(); + std::vector::const_iterator aCIt; + for (; aPCIt != myPointsAndCopies.end(); ++aPCIt) { + aCIt = aPCIt->begin(); + // Skip first element, focus the copies only + for (++aCIt; aCIt != aPCIt->end(); ++aCIt) { + std::vector< std::vector >::iterator aFilterIt = aFilteredPoints.begin(); + for (; aFilterIt != aFilteredPoints.end(); ++aFilterIt) + if (myStorage->isEqual(*aCIt, aFilterIt->front())) { + aFilterIt->push_back(*aCIt); + break; + } + if (aFilterIt == aFilteredPoints.end()) { + std::vector aNewFilter(1, *aCIt); + aFilteredPoints.push_back(aNewFilter); + } + } + } + + // Check the coicidence of filtered points and remove extra fixation. + // Also check separated points which are not fixed. + std::vector< std::vector >::iterator aFPIt = aFilteredPoints.begin(); + for (; aFPIt != aFilteredPoints.end(); ++aFPIt) { + if (aFPIt->size() <= 1) + continue; + std::vector::iterator anIt1, anIt2; + for (anIt1 = aFPIt->begin(); anIt1 != aFPIt->end(); ++anIt1) { + for (anIt2 = anIt1 + 1; anIt2 != aFPIt->end(); ++anIt2) { + Slvs_hConstraint aFixed1, aFixed2; + bool isFixed1 = myStorage->isPointFixed(*anIt1, aFixed1); + bool isFixed2 = myStorage->isPointFixed(*anIt2, aFixed2); + if (myStorage->isCoincident(*anIt1, *anIt2)) { + if (!isFixed1 && isFixed2) { + Slvs_hEntity aTmp = *anIt1; + *anIt1 = *anIt2; + *anIt2 = aTmp; + } else if (isFixed1 && isFixed2) { + // remove fixing of the second point + myStorage->removeConstraint(aFixed2); + std::vector::iterator aRemoveIt = mySlvsConstraints.begin(); + for (; aRemoveIt != mySlvsConstraints.end(); ++aRemoveIt) + if (*aRemoveIt == aFixed2) { + mySlvsConstraints.erase(aRemoveIt); + break; + } + } + } else { + bool isFixed[2] = {isFixed1, isFixed2}; + Slvs_hEntity aPoint[2] = {*anIt1, *anIt2}; + for (int i = 0; i < 2; i++) + if (!isFixed[i]) { + Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), + SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0, + aPoint[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + } + } + } + } + } +} diff --git a/src/SketchSolver/SketchSolver_ConstraintMulti.h b/src/SketchSolver/SketchSolver_ConstraintMulti.h index bbc4992be..2d76cee2b 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMulti.h +++ b/src/SketchSolver/SketchSolver_ConstraintMulti.h @@ -46,6 +46,9 @@ public: SketchSolver_Constraint::refresh(); } + /// \brief Verifies, the coincidence between points of copied entities appears or disappears, + /// and removes or adds fixing of corresponding points. + void checkCoincidence(); protected: /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 35f90dc74..560550f6e 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -235,8 +236,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) @@ -251,8 +253,12 @@ bool SketchSolver_Group::changeConstraint( if (anIt->second == aCIter->second) anIt->second = aCoinc2; aCIter->second = aCoinc2; + hasMultiCoincidence = true; } } + + if (hasMultiCoincidence) + notifyMultiConstraints(); } myConstraints[theConstraint] = aConstraint; } @@ -784,6 +790,8 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) std::list::iterator anIt = aMultiCoinc.begin(); for (; anIt != aMultiCoinc.end(); ++anIt) changeConstraint(*anIt); + + notifyMultiConstraints(); } } @@ -826,6 +834,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(); + } + } +} diff --git a/src/SketchSolver/SketchSolver_Group.h b/src/SketchSolver/SketchSolver_Group.h index 6c842caef..6a5f02b03 100644 --- a/src/SketchSolver/SketchSolver_Group.h +++ b/src/SketchSolver/SketchSolver_Group.h @@ -169,6 +169,9 @@ private: /// \brief Update just changed constraints void updateConstraints(); + /// \brief Update Multi-Translation/-Rotation constraints due to multi coincidence appears/disappears + void notifyMultiConstraints(); + private: Slvs_hGroup myID; ///< Index of the group Slvs_hEntity myWorkplaneID; ///< Index of workplane, the group is based on diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index 485b81565..1e7755787 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -372,13 +372,17 @@ bool SketchSolver_Storage::isPointFixed( } // Search the Rigid constraint + theFixed = SLVS_C_UNKNOWN; std::vector::const_iterator aConstrIter = myConstraints.begin(); for (; aConstrIter != myConstraints.end(); aConstrIter++) if (aConstrIter->type == SLVS_C_WHERE_DRAGGED && aCoincident.find(aConstrIter->ptA) != aCoincident.end()) { theFixed = aConstrIter->h; - return true; + if (aConstrIter->ptA == thePointID) + return true; } + if (theFixed != SLVS_C_UNKNOWN) + return true; if (theAccurate) { // Try to find the fixed entity which uses such point or its coincidence @@ -580,6 +584,9 @@ bool SketchSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstrain myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h; myNeedToResolve = true; myRemovedConstraints.insert(theConstraintID); + if (aConstraint.type == SLVS_C_POINTS_COINCIDENT) + removeCoincidence(aConstraint); + // Remove all entities Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB, aConstraint.entityA, aConstraint.entityB, @@ -773,6 +780,35 @@ void SketchSolver_Storage::removeCoincidentPoint(const Slvs_hEntity& thePoint) } } +void SketchSolver_Storage::removeCoincidence(const Slvs_Constraint& theCoincidence) +{ + // Find set of coincident points + std::vector< std::set >::iterator aCIt = myCoincidentPoints.begin(); + for (; aCIt != myCoincidentPoints.end(); ++aCIt) + if (aCIt->find(theCoincidence.ptA) != aCIt->end() || + aCIt->find(theCoincidence.ptB) != aCIt->end()) + break; + if (aCIt == myCoincidentPoints.end()) + return; + + // Leave only the points which are still coincident + std::set aRemainCoincidence; + std::vector::const_iterator aConstrIt = myConstraints.begin(); + for (; aConstrIt != myConstraints.end(); ++aConstrIt) { + if (aConstrIt->type != SLVS_C_POINTS_COINCIDENT) + continue; + if (aCIt->find(aConstrIt->ptA) != aCIt->end() || + aCIt->find(aConstrIt->ptB) != aCIt->end()) { + aRemainCoincidence.insert(aConstrIt->ptA); + aRemainCoincidence.insert(aConstrIt->ptB); + } + } + if (aRemainCoincidence.size() <= 1) + myCoincidentPoints.erase(aCIt); + else + aCIt->swap(aRemainCoincidence); +} + bool SketchSolver_Storage::isCoincident( const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const { diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index 8e808e52b..fb8e79eb2 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -146,6 +146,8 @@ private: void addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2); /// \brief Remove point from lists of coincidence void removeCoincidentPoint(const Slvs_hEntity& thePoint); + /// \brief Remove point-point coincidence + void removeCoincidence(const Slvs_Constraint& theCoincidence); public: /// \brief Check two points are coincident -- 2.39.2