From 05d9c0fab9398841325f3112d3b40cccb4b0c3ee 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 2784098..581add6 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -308,7 +308,7 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForB // 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(); @@ -491,6 +491,23 @@ void SolveSpaceUI::MarkDraggedParams(void) { } } +void SolveSpaceUI::SolveGroupAndReport(hGroup hg, bool andFindFree) { + SolveGroup(hg, andFindFree); + + Group *g = SK.GetGroup(hg); + if(g->solved.how == System::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 == System::SOLVED_OKAY || + (g->allowRedundant && g->solved.how == System::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. @@ -518,12 +535,6 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) { g->solved.remove.Clear(); int how = sys.Solve(g, &(g->solved.dof), &(g->solved.remove), true, andFindFree); - bool isOkay = how == System::SOLVED_OKAY || - (g->allowRedundant && how == System::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 a543d5e..6cb59c7 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -912,6 +912,7 @@ public: void GenerateAll(GenerateType type = GENERATE_DIRTY, bool andFindFree = false, bool genForBBox = false); void SolveGroup(hGroup hg, bool andFindFree); + void SolveGroupAndReport(hGroup hg, bool andFindFree); void MarkDraggedParams(void); void ForceReferences(void);