Perform rank test after solving the system.

Before this change, it was possible to adjust constraints in a way
that removes a degree of freedom and makes the sketch unsolvable,
but rank test was performed before solving the system, and an error
was not displayed immediately. Instead, a solution would seemingly
be found, but it would be very unstable--unrelated changes to
the sketch would cause rank test to fail.

To reproduce the bug, do this:
  * Draw a triangle.
  * Create a length constraint for all sides.
  * Set side lengths to a, b, and c such that a + b = c.
  * Add a line segment.
pull/4/head
whitequark 2016-01-21 08:24:58 +00:00
parent 55cde18c5a
commit c011444045
1 changed files with 5 additions and 5 deletions

View File

@ -446,6 +446,11 @@ int System::Solve(Group *g, int *dof, List<hConstraint> *bad,
return System::TOO_MANY_UNKNOWNS; return System::TOO_MANY_UNKNOWNS;
} }
// And do the leftovers as one big system
if(!NewtonSolve(0)) {
goto didnt_converge;
}
EvalJacobian(); EvalJacobian();
int rank; rank = CalculateRank(); int rank; rank = CalculateRank();
@ -460,11 +465,6 @@ int System::Solve(Group *g, int *dof, List<hConstraint> *bad,
// on the number of DOF. // on the number of DOF.
if(dof) *dof = mat.n - mat.m; if(dof) *dof = mat.n - mat.m;
// And do the leftovers as one big system
if(!NewtonSolve(0)) {
goto didnt_converge;
}
// If requested, find all the free (unbound) variables. This might be // If requested, find all the free (unbound) variables. This might be
// more than the number of degrees of freedom. Don't always do this, // more than the number of degrees of freedom. Don't always do this,
// because the display would get annoying and it's slow. // because the display would get annoying and it's slow.