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 65ea7704..de85b8e7 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 24634c0b..86073c7b 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 5c466d8d..acf82637 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 74f0d3a1..c0ba6822 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 28a653a1..3fd468e0 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 7ff8c3d2..5e6b8070 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