mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
Use better epsilon values in Numerical.solveQuadratic() and solveCubic()
To finally satisfy both #541 and #708. With this change in place, https://github.com/paperjs/boolean-test is also finally back to run with 0 errors. Woop!
This commit is contained in:
parent
098ddda3bc
commit
e476672748
2 changed files with 28 additions and 35 deletions
|
@ -617,13 +617,7 @@ statics: {
|
||||||
p2 = v[coord + 6],
|
p2 = v[coord + 6],
|
||||||
c = 3 * (c1 - p1),
|
c = 3 * (c1 - p1),
|
||||||
b = 3 * (c2 - c1) - c,
|
b = 3 * (c2 - c1) - c,
|
||||||
a = p2 - p1 - c - b,
|
a = p2 - p1 - c - b;
|
||||||
isZero = Numerical.isZero;
|
|
||||||
// If both a and b are near zero, we should treat the curve as a line in
|
|
||||||
// order to find the right solutions in some edge-cases in
|
|
||||||
// Curve.getParameterOf()
|
|
||||||
if (isZero(a) && isZero(b))
|
|
||||||
a = b = 0;
|
|
||||||
return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
|
return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -161,10 +161,12 @@ var Numerical = new function() {
|
||||||
* http://www.cs.berkeley.edu/~wkahan/Math128/Cubic.pdf
|
* http://www.cs.berkeley.edu/~wkahan/Math128/Cubic.pdf
|
||||||
* Blinn J. - "How to solve a Quadratic Equation"
|
* Blinn J. - "How to solve a Quadratic Equation"
|
||||||
*
|
*
|
||||||
* @param {Number} a The quadratic term
|
* @param {Number} a the quadratic term
|
||||||
* @param {Number} b The linear term
|
* @param {Number} b the linear term
|
||||||
* @param {Number} c The constant term
|
* @param {Number} c the constant term
|
||||||
* @param {Number[]} roots The array to store the roots in
|
* @param {Number[]} roots the array to store the roots in
|
||||||
|
* @param {Number} [min] the lower bound of the allowed roots
|
||||||
|
* @param {Number} [max] the upper bound of the allowed roots
|
||||||
* @return {Number} The number of real roots found, or -1 if there are
|
* @return {Number} The number of real roots found, or -1 if there are
|
||||||
* infinite solutions
|
* infinite solutions
|
||||||
*
|
*
|
||||||
|
@ -177,21 +179,15 @@ var Numerical = new function() {
|
||||||
D;
|
D;
|
||||||
b /= 2;
|
b /= 2;
|
||||||
D = b * b - a * c; // Discriminant
|
D = b * b - a * c; // Discriminant
|
||||||
/*
|
// If the discriminant is very small, we can try to pre-condition
|
||||||
* If the discriminant is very small, we can try to pre-condition
|
// the coefficients, so that we may get better accuracy
|
||||||
* the coefficients, so that we may get better accuracy
|
|
||||||
*/
|
|
||||||
if (D !== 0 && abs(D) < MACHINE_EPSILON) {
|
if (D !== 0 && abs(D) < MACHINE_EPSILON) {
|
||||||
// If the geometric mean of the coefficients is small enough
|
// If the geometric mean of the coefficients is small enough
|
||||||
var pow = Math.pow,
|
var gmC = pow(abs(a * b * c), 1 / 3);
|
||||||
gmC = pow(abs(a*b*c), 1/3);
|
|
||||||
if (gmC < 1e-8) {
|
if (gmC < 1e-8) {
|
||||||
/*
|
// We multiply with a factor to normalize the coefficients.
|
||||||
* we multiply with a factor to normalize the
|
// The factor is just the nearest exponent of 10, big enough
|
||||||
* coefficients. The factor is just the nearest exponent
|
// to raise all the coefficients to nearly [-1, +1] range.
|
||||||
* of 10, big enough to raise all the coefficients to
|
|
||||||
* nearly [-1, +1] range.
|
|
||||||
*/
|
|
||||||
var mult = pow(10, abs(
|
var mult = pow(10, abs(
|
||||||
Math.floor(Math.log(gmC) * Math.LOG10E)));
|
Math.floor(Math.log(gmC) * Math.LOG10E)));
|
||||||
if (!isFinite(mult))
|
if (!isFinite(mult))
|
||||||
|
@ -203,10 +199,10 @@ var Numerical = new function() {
|
||||||
D = b * b - a * c;
|
D = b * b - a * c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (abs(a) < MACHINE_EPSILON) {
|
if (abs(a) < EPSILON) {
|
||||||
// This could just be a linear equation
|
// This could just be a linear equation
|
||||||
if (abs(B) < MACHINE_EPSILON)
|
if (abs(B) < EPSILON)
|
||||||
return abs(c) < MACHINE_EPSILON ? -1 : 0;
|
return abs(c) < EPSILON ? -1 : 0;
|
||||||
x1 = -c / B;
|
x1 = -c / B;
|
||||||
} else {
|
} else {
|
||||||
// No real roots if D < 0
|
// No real roots if D < 0
|
||||||
|
@ -251,26 +247,29 @@ var Numerical = new function() {
|
||||||
* W. Kahan's paper contains inferences on accuracy of cubic
|
* W. Kahan's paper contains inferences on accuracy of cubic
|
||||||
* zero-finding methods. Also testing methods for robustness.
|
* zero-finding methods. Also testing methods for robustness.
|
||||||
*
|
*
|
||||||
* @param {Number} a The cubic term (x³ term).
|
* @param {Number} a the cubic term (x³ term)
|
||||||
* @param {Number} b The quadratic term (x² term).
|
* @param {Number} b the quadratic term (x² term)
|
||||||
* @param {Number} c The linear term (x term).
|
* @param {Number} c the linear term (x term)
|
||||||
* @param {Number} d The constant term
|
* @param {Number} d the constant term
|
||||||
* @param {Number[]} roots The array to store the roots in
|
* @param {Number[]} roots the array to store the roots in
|
||||||
* @return {Number} The number of real roots found, or -1 if there are
|
* @param {Number} [min] the lower bound of the allowed roots
|
||||||
|
* @param {Number} [max] the upper bound of the allowed roots
|
||||||
|
* @return {Number} the number of real roots found, or -1 if there are
|
||||||
* infinite solutions
|
* infinite solutions
|
||||||
*
|
*
|
||||||
* @author Harikrishnan Gopalakrishnan
|
* @author Harikrishnan Gopalakrishnan
|
||||||
*/
|
*/
|
||||||
solveCubic: function(a, b, c, d, roots, min, max) {
|
solveCubic: function(a, b, c, d, roots, min, max) {
|
||||||
var x, b1, c2, count = 0;
|
var count = 0,
|
||||||
|
x, b1, c2;
|
||||||
// If a or d is zero, we only need to solve a quadratic, so we set
|
// If a or d is zero, we only need to solve a quadratic, so we set
|
||||||
// the coefficients appropriately.
|
// the coefficients appropriately.
|
||||||
if (a === 0) {
|
if (abs(a) < EPSILON) {
|
||||||
a = b;
|
a = b;
|
||||||
b1 = c;
|
b1 = c;
|
||||||
c2 = d;
|
c2 = d;
|
||||||
x = Infinity;
|
x = Infinity;
|
||||||
} else if (d === 0) {
|
} else if (abs(d) < EPSILON) {
|
||||||
b1 = b;
|
b1 = b;
|
||||||
c2 = c;
|
c2 = c;
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
Loading…
Reference in a new issue