From a500a52a60724971fa61a3871979c54a1ce9c1d8 Mon Sep 17 00:00:00 2001 From: azv Date: Mon, 6 Mar 2017 17:34:09 +0300 Subject: [PATCH] Adjust processing of Coincidence constraint by PlaneGCSSolver Fix misprint in Test1673.py --- src/SketchPlugin/Test/Test1673.py | 3 +- src/SketchPlugin/Test/TestFillet.py | 2 +- .../PlaneGCSSolver/PlaneGCSSolver_Solver.cpp | 18 ++++--- .../PlaneGCSSolver/PlaneGCSSolver_Solver.h | 5 +- .../PlaneGCSSolver_UpdateCoincidence.cpp | 47 +++++++++++-------- 5 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/SketchPlugin/Test/Test1673.py b/src/SketchPlugin/Test/Test1673.py index 550515673..6bb2d8b02 100644 --- a/src/SketchPlugin/Test/Test1673.py +++ b/src/SketchPlugin/Test/Test1673.py @@ -260,13 +260,12 @@ for ang in range(0, 50): aEndPoint.setValue(X, Y) model.do() movementTime = timer() - movementTime - print movementTime assert movementTime < expectedTime, "Time to move point {0} is greater than expected {1}".format(movementTime, expectedTime) assert math.fabs(aEndPoint.x() - X) < TOLERANCE and math.fabs(aEndPoint.y() - Y) < TOLERANCE, "({0}, {1}) != ({2}, {3})".format(aEndPoint.x(), aEndPoint.y(), X, Y) averageTime += movementTime nbMoves += 1 aDeltaX = aEndPoint.x() - aCenter.x() - aDeltaY - aEndPoint.y() - aCenter.y() + aDeltaY = aEndPoint.y() - aCenter.y() print "Movement average time: {0}".format(averageTime / nbMoves) model.end() diff --git a/src/SketchPlugin/Test/TestFillet.py b/src/SketchPlugin/Test/TestFillet.py index e58e27ba8..45d0d09d5 100644 --- a/src/SketchPlugin/Test/TestFillet.py +++ b/src/SketchPlugin/Test/TestFillet.py @@ -225,7 +225,7 @@ aRadius.setValue(FILLET_RADIUS2) aFillet.execute() aSession.finishOperation() checkFillet(aResObjects, FILLET_RADIUS2) -assert model.dof(aSketchFeature) == 14, "PlaneGCS limitation: if you see this message, then PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 10, observed = {0}".format(model.dof(aSketchFeature)) +assert model.dof(aSketchFeature) == 8, "PlaneGCS limitation: if you see this message, then PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 10, observed = {0}".format(model.dof(aSketchFeature)) #========================================================================= # Create another sketch diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp index fb64ef10a..5b34fd59a 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp @@ -38,14 +38,17 @@ void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint, // Workaround: avoid tangent constraint in the list of redundant if (theType == CONSTRAINT_TANGENT_CIRCLE_LINE || - theType == CONSTRAINT_TANGENT_CIRCLE_CIRCLE) - myTangentIDs.insert(theConstraint->getTag()); + theType == CONSTRAINT_TANGENT_CIRCLE_CIRCLE || + theType == CONSTRAINT_PT_PT_COINCIDENT || + theType == CONSTRAINT_PT_ON_CIRCLE || + theType == CONSTRAINT_PT_ON_LINE) + myConstraintIDsNotRedundant.insert(theConstraint->getTag()); } void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID) { myConstraints.erase(theID); - myTangentIDs.erase(theID); + myConstraintIDsNotRedundant.erase(theID); if (myConstraints.empty()) { myEquationSystem->clear(); myDOF = (int)myParameters.size(); @@ -91,8 +94,11 @@ PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve() GCS::VEC_I aRedundant; myEquationSystem->getRedundant(aRedundant); - if (!aRedundant.empty()) - aResult = GCS::Failed; + if (!aRedundant.empty()) { + collectConflicting(); + if (!myConflictingIDs.empty()) + aResult = GCS::Failed; + } SolveStatus aStatus; if (aResult == GCS::Success) { @@ -129,7 +135,7 @@ void PlaneGCSSolver_Solver::collectConflicting() 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()) + if (myConstraintIDsNotRedundant.find(*anIt) == myConstraintIDsNotRedundant.end()) aConflict.push_back(*anIt); myConflictingIDs.insert(aConflict.begin(), aConflict.end()); diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h index 810b5fab5..b019a314c 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h @@ -63,7 +63,10 @@ private: GCS::VEC_pD myParameters; ///< list of unknowns ConstraintMap myConstraints; ///< list of constraints - GCS::SET_I myTangentIDs; ///< IDs of tangent constraints + + /// IDs of constraints (coincidence, tangency) which will not be treated as conflicting + /// if they are reported as redundant + GCS::SET_I myConstraintIDsNotRedundant; std::shared_ptr myEquationSystem; ///< set of equations for solving in FreeGCS diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp index 01f30a4bf..1ac316855 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_UpdateCoincidence.cpp @@ -39,11 +39,12 @@ void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature) myNext->update(theFeature); } -static bool hasExternalPoint(const std::set& theCoincidences) +static bool hasAnotherExternalPoint(const std::set& theCoincidences, + const EntityWrapperPtr& thePoint) { std::set::const_iterator anIt = theCoincidences.begin(); for (; anIt != theCoincidences.end(); ++anIt) - if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal()) + if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal() && *anIt != thePoint) return true; return false; } @@ -55,41 +56,49 @@ bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence( bool isAccepted = true; std::list >::iterator anIt = myCoincident.begin(); - std::list >::iterator aFound1 = myCoincident.end(); - std::list >::iterator aFound2 = myCoincident.end(); + std::list >::iterator + aFound[2] = {myCoincident.end(), myCoincident.end()}; + for (; anIt != myCoincident.end(); ++anIt) { - if (aFound1 == myCoincident.end() && anIt->find(theEntity1) != anIt->end()) - aFound1 = anIt; - if (aFound2 == myCoincident.end() && anIt->find(theEntity2) != anIt->end()) - aFound2 = anIt; - if (aFound1 != myCoincident.end() && aFound2 != myCoincident.end()) + if (aFound[0] == myCoincident.end() && anIt->find(theEntity1) != anIt->end()) + aFound[0] = anIt; + if (aFound[1] == myCoincident.end() && anIt->find(theEntity2) != anIt->end()) + aFound[1] = anIt; + if (aFound[0] != myCoincident.end() && aFound[1] != myCoincident.end()) break; } - if (aFound1 == myCoincident.end() && aFound2 == myCoincident.end()) { + if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) { // new group of coincidence std::set aNewCoinc; aNewCoinc.insert(theEntity1); aNewCoinc.insert(theEntity2); myCoincident.push_back(aNewCoinc); - } else if (aFound1 == aFound2) // same group => already coincident + } else if (aFound[0] == aFound[1]) // same group => already coincident isAccepted = false; 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)); + bool hasExternal = false; + for (int i = 0; i < 2 && !hasExternal; ++i) { + if (aFound[i] != myCoincident.end()) { + if (theEntity1->isExternal()) + hasExternal = hasAnotherExternalPoint(*aFound[i], theEntity1); + if (!hasExternal && theEntity2->isExternal()) + hasExternal = hasAnotherExternalPoint(*aFound[i], theEntity2); + } + } if (hasExternal) isAccepted = false; } - if (aFound1 == myCoincident.end()) - aFound2->insert(theEntity1); - else if (aFound2 == myCoincident.end()) - aFound1->insert(theEntity2); + if (aFound[0] == myCoincident.end()) + aFound[1]->insert(theEntity1); + else if (aFound[1] == myCoincident.end()) + aFound[0]->insert(theEntity2); else { // merge two groups - aFound1->insert(aFound2->begin(), aFound2->end()); - myCoincident.erase(aFound2); + aFound[0]->insert(aFound[1]->begin(), aFound[1]->end()); + myCoincident.erase(aFound[1]); } } -- 2.39.2