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]
solver
Jonathan Westhues 2009-04-20 23:56:17 -08:00
parent 1554402b30
commit 9efa922795
6 changed files with 37 additions and 9 deletions

View File

@ -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 <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
@ -141,14 +153,19 @@ void Example2d(void)
200, 200,
15.0, 15.0,
301, 101, 0, 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( sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
5, g, 5, g,
SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_PT_DISTANCE,
200, 200,
18.0, 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. // And solve.
Slvs_Solve(&sys, g); Slvs_Solve(&sys, g);

View File

@ -187,7 +187,8 @@ default: dbp("bad constraint type %d", sc->type); return;
ZERO(&bad); ZERO(&bad);
// Now we're finally ready to solve! // 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) { switch(how) {
case System::SOLVED_OKAY: case System::SOLVED_OKAY:

View File

@ -128,7 +128,14 @@ typedef struct {
// Unused members of this array should be set to zero. // Unused members of this array should be set to zero.
Slvs_hParam dragged[4]; 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 // If the solver fails, then it can report which constraints are causing
// the problem. The caller should allocate the array failed[], and pass // the problem. The caller should allocate the array failed[], and pass

View File

@ -410,7 +410,7 @@ void SolveSpace::SolveGroup(hGroup hg, bool andFindFree) {
MarkDraggedParams(); MarkDraggedParams();
g->solved.remove.Clear(); g->solved.remove.Clear();
int how = sys.Solve(g, &(g->solved.dof), int how = sys.Solve(g, &(g->solved.dof),
&(g->solved.remove), andFindFree); &(g->solved.remove), true, andFindFree);
if((how != System::SOLVED_OKAY) || if((how != System::SOLVED_OKAY) ||
(how == System::SOLVED_OKAY && g->solved.how != System::SOLVED_OKAY)) (how == System::SOLVED_OKAY && g->solved.how != System::SOLVED_OKAY))
{ {

View File

@ -271,7 +271,8 @@ public:
static const int DIDNT_CONVERGE = 10; static const int DIDNT_CONVERGE = 10;
static const int SINGULAR_JACOBIAN = 11; static const int SINGULAR_JACOBIAN = 11;
static const int TOO_MANY_UNKNOWNS = 20; static const int TOO_MANY_UNKNOWNS = 20;
int Solve(Group *g, int *dof, List<hConstraint> *bad, bool andFindFree); int Solve(Group *g, int *dof, List<hConstraint> *bad,
bool andFindBad, bool andFindFree);
}; };
class TtfFont { class TtfFont {

View File

@ -363,7 +363,7 @@ void System::FindWhichToRemoveToFixJacobian(Group *g, List<hConstraint> *bad) {
} }
int System::Solve(Group *g, int *dof, List<hConstraint> *bad, int System::Solve(Group *g, int *dof, List<hConstraint> *bad,
bool andFindFree) bool andFindBad, bool andFindFree)
{ {
WriteEquationsExceptFor(Constraint::NO_CONSTRAINT, g); WriteEquationsExceptFor(Constraint::NO_CONSTRAINT, g);
@ -420,7 +420,9 @@ int System::Solve(Group *g, int *dof, List<hConstraint> *bad,
int rank = CalculateRank(); int rank = CalculateRank();
if(rank != mat.m) { if(rank != mat.m) {
if(andFindBad) {
FindWhichToRemoveToFixJacobian(g, bad); FindWhichToRemoveToFixJacobian(g, bad);
}
return System::SINGULAR_JACOBIAN; return System::SINGULAR_JACOBIAN;
} }
// This is not the full Jacobian, but any substitutions or single-eq // This is not the full Jacobian, but any substitutions or single-eq