From 407f8ee4d60b986fc6da2f8a6038787cae7a87ba Mon Sep 17 00:00:00 2001 From: azv Date: Mon, 6 Mar 2017 10:14:48 +0300 Subject: [PATCH] Process redundant constraints reported by PlaneGCS as conflicting. --- .../PlaneGCSSolver/PlaneGCSSolver_Solver.cpp | 20 ++++++++++- .../PlaneGCSSolver/PlaneGCSSolver_Solver.h | 3 +- .../PlaneGCSSolver/PlaneGCSSolver_Storage.cpp | 10 +++--- .../PlaneGCSSolver_UpdateCoincidence.cpp | 33 +++++++++++++++---- src/SketchSolver/SketchSolver_Group.cpp | 3 +- src/SketchSolver/SketchSolver_Storage.cpp | 4 +-- 6 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp index 3e77208aa..fb64ef10a 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp @@ -29,16 +29,23 @@ void PlaneGCSSolver_Solver::clear() myDOF = 0; } -void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint) +void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint, + const SketchSolver_ConstraintType theType) { myEquationSystem->addConstraint(theConstraint.get()); myConstraints[theConstraint->getTag()].insert(theConstraint); myDOF = -1; + + // Workaround: avoid tangent constraint in the list of redundant + if (theType == CONSTRAINT_TANGENT_CIRCLE_LINE || + theType == CONSTRAINT_TANGENT_CIRCLE_CIRCLE) + myTangentIDs.insert(theConstraint->getTag()); } void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID) { myConstraints.erase(theID); + myTangentIDs.erase(theID); if (myConstraints.empty()) { myEquationSystem->clear(); myDOF = (int)myParameters.size(); @@ -82,6 +89,11 @@ PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve() GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters); Events_LongOp::end(this); + GCS::VEC_I aRedundant; + myEquationSystem->getRedundant(aRedundant); + if (!aRedundant.empty()) + aResult = GCS::Failed; + SolveStatus aStatus; if (aResult == GCS::Success) { myEquationSystem->applySolution(); @@ -113,6 +125,12 @@ void PlaneGCSSolver_Solver::collectConflicting() myConflictingIDs.insert(aConflict.begin(), aConflict.end()); myEquationSystem->getRedundant(aConflict); + // Workaround: avoid conflicting tangent constraints + GCS::VEC_I aTemp = aConflict; + aConflict.clear(); + for (GCS::VEC_I::iterator anIt = aTemp.begin(); anIt != aTemp.end(); ++anIt) + if (myTangentIDs.find(*anIt) == myTangentIDs.end()) + aConflict.push_back(*anIt); myConflictingIDs.insert(aConflict.begin(), aConflict.end()); myConfCollected = true; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h index 0465924cb..810b5fab5 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h @@ -32,7 +32,7 @@ public: void clear(); /// \brief Add constraint to the system of equations - void addConstraint(GCSConstraintPtr theConstraint); + void addConstraint(GCSConstraintPtr theConstraint, const SketchSolver_ConstraintType theType); /// \brief Remove constraint from the system of equations void removeConstraint(ConstraintID theID); @@ -63,6 +63,7 @@ private: GCS::VEC_pD myParameters; ///< list of unknowns ConstraintMap myConstraints; ///< list of constraints + GCS::SET_I myTangentIDs; ///< IDs of tangent constraints std::shared_ptr myEquationSystem; ///< set of equations for solving in FreeGCS diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index 62451f130..073586719 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -27,16 +27,11 @@ static void constraintsToSolver(const ConstraintWrapperPtr& theConstraint, const SolverPtr& theSolver) { - std::shared_ptr aSolver = - std::dynamic_pointer_cast(theSolver); - if (!aSolver) - return; - const std::list& aConstraints = std::dynamic_pointer_cast(theConstraint)->constraints(); std::list::const_iterator anIt = aConstraints.begin(); for (; anIt != aConstraints.end(); ++anIt) - aSolver->addConstraint(*anIt); + theSolver->addConstraint(*anIt, theConstraint->type()); } @@ -270,6 +265,9 @@ bool PlaneGCSSolver_Storage::removeConstraint(ConstraintPtr theConstraint) // Remove constraint myConstraintMap.erase(aFound); + if (anID != CID_MOVEMENT) + myNeedToResolve = true; + // notify subscibers notify(theConstraint); } diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp index bc79c7c3e..01f30a4bf 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp @@ -39,6 +39,15 @@ void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature) myNext->update(theFeature); } +static bool hasExternalPoint(const std::set& theCoincidences) +{ + std::set::const_iterator anIt = theCoincidences.begin(); + for (; anIt != theCoincidences.end(); ++anIt) + if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal()) + return true; + return false; +} + bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence( const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2) @@ -65,13 +74,23 @@ bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence( myCoincident.push_back(aNewCoinc); } else if (aFound1 == aFound2) // same group => already coincident isAccepted = false; - else if (aFound1 == myCoincident.end()) - aFound2->insert(theEntity1); - else if (aFound2 == myCoincident.end()) - aFound1->insert(theEntity2); - else { // merge two groups - aFound1->insert(aFound2->begin(), aFound2->end()); - myCoincident.erase(aFound2); + else { + if (theEntity1->type() == ENTITY_POINT && theEntity2->type() == ENTITY_POINT && + (theEntity1->isExternal() || theEntity2->isExternal())) { + bool hasExternal = aFound1 != myCoincident.end() && hasExternalPoint(*aFound1); + hasExternal = hasExternal || (aFound2 != myCoincident.end() && hasExternalPoint(*aFound2)); + if (hasExternal) + isAccepted = false; + } + + if (aFound1 == myCoincident.end()) + aFound2->insert(theEntity1); + else if (aFound2 == myCoincident.end()) + aFound1->insert(theEntity2); + else { // merge two groups + aFound1->insert(aFound2->begin(), aFound2->end()); + myCoincident.erase(aFound2); + } } return isAccepted; diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 1360e1b6a..7e01d45f9 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -257,8 +257,7 @@ void SketchSolver_Group::repairConsistency() void SketchSolver_Group::removeTemporaryConstraints() { if (!myTempConstraints.empty()) { - std::dynamic_pointer_cast( - mySketchSolver)->removeConstraint(CID_MOVEMENT); + mySketchSolver->removeConstraint(CID_MOVEMENT); std::set::iterator aTmpIt = myTempConstraints.begin(); for (; aTmpIt != myTempConstraints.end(); ++aTmpIt) diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index 7c6f87be0..61694df94 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -238,10 +238,8 @@ std::set SketchSolver_Storage::getConflictingConstraints(SolverPtr th std::map::const_iterator aConstrIt = myConstraintMap.begin(); for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) { - if (theSolver->isConflicting(aConstrIt->second->id())) { + if (theSolver->isConflicting(aConstrIt->second->id())) aConflicting.insert(aConstrIt->first); - break; - } } return aConflicting; } -- 2.39.2