From 9efa92279505c0eb7a3a2aaa6c38704266cba61e Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Mon, 20 Apr 2009 23:56:17 -0800 Subject: [PATCH] Add a solver option to not calculate the failing constraints if we're inconsistent (singular Jacobian). That's slow, so we should provide a library interface to disable it. [git-p4: depot-paths = "//depot/solvespace/": change = 1946] --- exposed/example.c | 23 ++++++++++++++++++++--- exposed/lib.cpp | 3 ++- exposed/slvs.h | 9 ++++++++- generate.cpp | 2 +- solvespace.h | 3 ++- system.cpp | 6 ++++-- 6 files changed, 37 insertions(+), 9 deletions(-) diff --git a/exposed/example.c b/exposed/example.c index 87936a8c..cb1d49ca 100644 --- a/exposed/example.c +++ b/exposed/example.c @@ -1,3 +1,15 @@ +//----------------------------------------------------------------------------- +// Some sample code for slvs.lib. We draw some geometric entities, provide +// initial guesses for their positions, and then constrain them. The solver +// calculates their new positions, in order to satisfy the constraints. +// +// This code is provide for evaluation purposes only. To purchase a license, +// please visit: +// +// http://solvespace.com/ +// +// Copyright 2009, Jonathan Westhues +//----------------------------------------------------------------------------- #include #include @@ -141,14 +153,19 @@ void Example2d(void) 200, 15.0, 301, 101, 0, 0); - - // And the distance from one endpoint to the origin is 15.0 units. +/* + // And same for the other endpoint; so if you add this constraint then + // the sketch is overconstrained and will signal an error. sys.constraint[sys.constraints++] = Slvs_MakeConstraint( 5, g, SLVS_C_PT_PT_DISTANCE, 200, 18.0, - 302, 101, 0, 0); + 302, 101, 0, 0); */ + + // If the solver fails, then ask it to report which constraints caused + // the problem. + sys.calculateFaileds = 1; // And solve. Slvs_Solve(&sys, g); diff --git a/exposed/lib.cpp b/exposed/lib.cpp index bf1cea51..2e10916b 100644 --- a/exposed/lib.cpp +++ b/exposed/lib.cpp @@ -187,7 +187,8 @@ default: dbp("bad constraint type %d", sc->type); return; ZERO(&bad); // Now we're finally ready to solve! - int how = SYS.Solve(&g, &(ssys->dof), &bad, false); + bool andFindBad = ssys->calculateFaileds ? true : false; + int how = SYS.Solve(&g, &(ssys->dof), &bad, andFindBad, false); switch(how) { case System::SOLVED_OKAY: diff --git a/exposed/slvs.h b/exposed/slvs.h index 528c4b53..eb87b79c 100644 --- a/exposed/slvs.h +++ b/exposed/slvs.h @@ -128,7 +128,14 @@ typedef struct { // Unused members of this array should be set to zero. Slvs_hParam dragged[4]; - //// OUTPUT PARAMETERS + // If the solver fails, then it can determine which constraints are + // causing the problem. But this is a relatively slow process (for + // a system with n constraints, about n times as long as just solving). + // If calculateFaileds is set, then the solver will do so, otherwise + // not. + int calculateFaileds; + + //// OUTPUT VARIABLES // // If the solver fails, then it can report which constraints are causing // the problem. The caller should allocate the array failed[], and pass diff --git a/generate.cpp b/generate.cpp index dcc85a96..8cd103eb 100644 --- a/generate.cpp +++ b/generate.cpp @@ -410,7 +410,7 @@ void SolveSpace::SolveGroup(hGroup hg, bool andFindFree) { MarkDraggedParams(); g->solved.remove.Clear(); int how = sys.Solve(g, &(g->solved.dof), - &(g->solved.remove), andFindFree); + &(g->solved.remove), true, andFindFree); if((how != System::SOLVED_OKAY) || (how == System::SOLVED_OKAY && g->solved.how != System::SOLVED_OKAY)) { diff --git a/solvespace.h b/solvespace.h index b2768129..2572ee45 100644 --- a/solvespace.h +++ b/solvespace.h @@ -271,7 +271,8 @@ public: static const int DIDNT_CONVERGE = 10; static const int SINGULAR_JACOBIAN = 11; static const int TOO_MANY_UNKNOWNS = 20; - int Solve(Group *g, int *dof, List *bad, bool andFindFree); + int Solve(Group *g, int *dof, List *bad, + bool andFindBad, bool andFindFree); }; class TtfFont { diff --git a/system.cpp b/system.cpp index d3562991..9cbe5a0f 100644 --- a/system.cpp +++ b/system.cpp @@ -363,7 +363,7 @@ void System::FindWhichToRemoveToFixJacobian(Group *g, List *bad) { } int System::Solve(Group *g, int *dof, List *bad, - bool andFindFree) + bool andFindBad, bool andFindFree) { WriteEquationsExceptFor(Constraint::NO_CONSTRAINT, g); @@ -420,7 +420,9 @@ int System::Solve(Group *g, int *dof, List *bad, int rank = CalculateRank(); if(rank != mat.m) { - FindWhichToRemoveToFixJacobian(g, bad); + if(andFindBad) { + FindWhichToRemoveToFixJacobian(g, bad); + } return System::SINGULAR_JACOBIAN; } // This is not the full Jacobian, but any substitutions or single-eq