From 9148d0cb91ad4bf6800ba722a9c8ef6378b5aa1e Mon Sep 17 00:00:00 2001 From: EvilSpirit Date: Sat, 22 Oct 2016 22:08:41 +0700 Subject: [PATCH] Force DOF check every time a constraint is added. Before this commit, it was possible to add some redundant constraints (e.g. vertical, horizontal or midpoint) without failing the sketch, because SolveBySubstitution() removed the redundant equations. However, this could result in the solve failing later because the system didn't converge, without any pointers as to the true cause of the failure. --- CHANGELOG.md | 2 ++ src/constraint.cpp | 1 + src/generate.cpp | 8 +++++++- src/sketch.h | 1 + src/solvespace.h | 4 ++-- src/system.cpp | 14 +++++++++----- 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ea770..de85b8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ Bugs fixed: causes the line length to collapse. * Curve-line constraints (in 3d), parallel constraints (in 3d), and same orientation constraints are more robust. + * Adding some constraints (vertical, midpoint, etc) twice will now error out + immediately, instead of later and in a confusing way. 2.3 --- diff --git a/src/constraint.cpp b/src/constraint.cpp index 24634c0..86073c7 100644 --- a/src/constraint.cpp +++ b/src/constraint.cpp @@ -85,6 +85,7 @@ hConstraint Constraint::AddConstraint(Constraint *c, bool rememberForUndo) { SK.constraint.AddAndAssignId(c); SS.MarkGroupDirty(c->group); + SK.GetGroup(c->group)->dofCheckOk = false; SS.ScheduleGenerateAll(); return c->h; } diff --git a/src/generate.cpp b/src/generate.cpp index 5c466d8..acf8263 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -528,7 +528,13 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) { MarkDraggedParams(); g->solved.remove.Clear(); SolveResult how = sys.Solve(g, &(g->solved.dof), - &(g->solved.remove), /*andFindBad=*/true, andFindFree); + &(g->solved.remove), + /*andFindBad=*/true, + /*andFindFree=*/andFindFree, + /*forceDofCheck=*/!g->dofCheckOk); + if(how == SolveResult::OKAY) { + g->dofCheckOk = true; + } g->solved.how = how; FreeAllTemporary(); } diff --git a/src/sketch.h b/src/sketch.h index 74f0d3a..c0ba682 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -141,6 +141,7 @@ public: double scale; bool clean; + bool dofCheckOk; hEntity activeWorkplane; double valA; double valB; diff --git a/src/solvespace.h b/src/solvespace.h index 28a653a..3fd468e 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -444,7 +444,7 @@ public: void EvalJacobian(); void WriteEquationsExceptFor(hConstraint hc, Group *g); - void FindWhichToRemoveToFixJacobian(Group *g, List *bad); + void FindWhichToRemoveToFixJacobian(Group *g, List *bad, bool forceDofCheck); void SolveBySubstitution(); bool IsDragged(hParam p); @@ -452,7 +452,7 @@ public: bool NewtonSolve(int tag); SolveResult Solve(Group *g, int *dof, List *bad, - bool andFindBad, bool andFindFree); + bool andFindBad, bool andFindFree, bool forceDofCheck = false); void Clear(); }; diff --git a/src/system.cpp b/src/system.cpp index 7ff8c3d..5e6b807 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -359,7 +359,7 @@ void System::WriteEquationsExceptFor(hConstraint hc, Group *g) { g->GenerateEquations(&eq); } -void System::FindWhichToRemoveToFixJacobian(Group *g, List *bad) { +void System::FindWhichToRemoveToFixJacobian(Group *g, List *bad, bool forceDofCheck) { int a, i; for(a = 0; a < 2; a++) { @@ -382,7 +382,9 @@ void System::FindWhichToRemoveToFixJacobian(Group *g, List *bad) { // It's a major speedup to solve the easy ones by substitution here, // and that doesn't break anything. - SolveBySubstitution(); + if(!forceDofCheck) { + SolveBySubstitution(); + } WriteJacobian(0); EvalJacobian(); @@ -397,7 +399,7 @@ void System::FindWhichToRemoveToFixJacobian(Group *g, List *bad) { } SolveResult System::Solve(Group *g, int *dof, List *bad, - bool andFindBad, bool andFindFree) + bool andFindBad, bool andFindFree, bool forceDofCheck) { WriteEquationsExceptFor(Constraint::NO_CONSTRAINT, g); @@ -418,7 +420,9 @@ SolveResult System::Solve(Group *g, int *dof, List *bad, param.ClearTags(); eq.ClearTags(); - SolveBySubstitution(); + if(!forceDofCheck) { + SolveBySubstitution(); + } // Before solving the big system, see if we can find any equations that // are soluble alone. This can be a huge speedup. We don't know whether @@ -465,7 +469,7 @@ SolveResult System::Solve(Group *g, int *dof, List *bad, rankOk = TestRank(); if(!rankOk) { if(!g->allowRedundant) { - if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad); + if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, forceDofCheck); } } else { // This is not the full Jacobian, but any substitutions or single-eq