From 3a585ea7c29e617fa8b1788c921cd912be9bf95b Mon Sep 17 00:00:00 2001 From: EvilSpirit Date: Thu, 13 Oct 2016 20:51:11 +0700 Subject: [PATCH] Try to re-solve groups that fail rank test. Sometimes, after a large change in a sketch, constraints that are geometrically fine may still cause the rank test to fail. One way this can happen is VectorsParallel() pivoting wrong due to the big move, converging anyways but ending up singular. It would then re-pivot correctly on the new solution when you re-solve, making this a transient error. This is visible when dragging the arm in the jansen-asm.slvs example. After this commit, if the rank test fails, equations are regenerated the Jacobian is rewritten, and the rank test is retried, which prevents these transient errors from interfering with dragging. The problem described above was invisible before c011444, as rank test was only performed before solving. --- src/generate.cpp | 25 ++++++++++++++++++------- src/solvespace.h | 1 + 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/generate.cpp b/src/generate.cpp index 4059427..8e6774d 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -268,7 +268,7 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox) // The group falls inside the range, so really solve it, // and then regenerate the mesh based on the solved stuff. if(genForBBox) { - SolveGroup(g->h, andFindFree); + SolveGroupAndReport(g->h, andFindFree); } else { g->GenerateLoops(); g->GenerateShellAndMesh(); @@ -476,6 +476,23 @@ void SolveSpaceUI::MarkDraggedParams() { } } +void SolveSpaceUI::SolveGroupAndReport(hGroup hg, bool andFindFree) { + SolveGroup(hg, andFindFree); + + Group *g = SK.GetGroup(hg); + if(g->solved.how == SolveResult::REDUNDANT_OKAY) { + // Solve again, in case we lost a degree of freedom because of a numeric error. + SolveGroup(hg, andFindFree); + } + + bool isOkay = g->solved.how == SolveResult::OKAY || + (g->allowRedundant && g->solved.how == SolveResult::REDUNDANT_OKAY); + + if(!isOkay || (isOkay && !g->IsSolvedOkay())) { + TextWindow::ReportHowGroupSolved(g->h); + } +} + void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) { int i; // Clear out the system to be solved. @@ -503,12 +520,6 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) { g->solved.remove.Clear(); SolveResult how = sys.Solve(g, &(g->solved.dof), &(g->solved.remove), /*andFindBad=*/true, andFindFree); - bool isOkay = how == SolveResult::OKAY || - (g->allowRedundant && how == SolveResult::REDUNDANT_OKAY); - if(!isOkay || (isOkay && !g->IsSolvedOkay())) - { - TextWindow::ReportHowGroupSolved(g->h); - } g->solved.how = how; FreeAllTemporary(); } diff --git a/src/solvespace.h b/src/solvespace.h index 8249047..05d8a65 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -891,6 +891,7 @@ public: void GenerateAll(Generate type = Generate::DIRTY, bool andFindFree = false, bool genForBBox = false); void SolveGroup(hGroup hg, bool andFindFree); + void SolveGroupAndReport(hGroup hg, bool andFindFree); void MarkDraggedParams(); void ForceReferences();