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
parent
1554402b30
commit
9efa922795
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue