mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-08 05:42:07 -05:00
Add old cubic solver code for comparison, and use console.log() in Curve.solveCubic() to log values with different results.
This commit is contained in:
parent
ab8ef47d68
commit
0168e41be0
2 changed files with 127 additions and 1 deletions
|
@ -582,7 +582,27 @@ statics: {
|
||||||
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;
|
||||||
return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
|
var roots2 = [];
|
||||||
|
var res1 = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
|
||||||
|
var res2 = Numerical._solveCubic(a, b, c, p1 - val, roots2, min, max);
|
||||||
|
var ok = true;
|
||||||
|
if (res1 == res2) {
|
||||||
|
for (var i = 0; i < res1 && ok; i++) {
|
||||||
|
if (Math.abs(roots[i] - roots2[i]) > 0.01)
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
function f(val) {
|
||||||
|
return (val + '').replace(/e/, '*10^');
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
console.log('a = ' + f(a) + '; b = ' + f(b) + '; c = ' + f(c) + '; d = ' + f(p1 - val)
|
||||||
|
+ '; // old:', roots2, 'new:', roots);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res1; //Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
|
||||||
},
|
},
|
||||||
|
|
||||||
getParameterOf: function(v, x, y) {
|
getParameterOf: function(v, x, y) {
|
||||||
|
|
|
@ -67,6 +67,21 @@ var Numerical = new function() {
|
||||||
EPSILON = 1e-14,
|
EPSILON = 1e-14,
|
||||||
MACHINE_EPSILON = 2.220446049250313e-16;
|
MACHINE_EPSILON = 2.220446049250313e-16;
|
||||||
|
|
||||||
|
// Sets up min and max values for roots and returns a add() function that
|
||||||
|
// handles bounds checks and itself returns the amount of added roots.
|
||||||
|
function setupRoots(roots, min, max) {
|
||||||
|
var unbound = min === undefined,
|
||||||
|
minE = min - EPSILON,
|
||||||
|
maxE = max + EPSILON,
|
||||||
|
count = 0;
|
||||||
|
// Returns a function that adds roots with checks
|
||||||
|
return function(root) {
|
||||||
|
if (unbound || root > minE && root < maxE)
|
||||||
|
roots[count++] = root < min ? min : root > max ? max : root;
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return /** @lends Numerical */{
|
return /** @lends Numerical */{
|
||||||
TOLERANCE: TOLERANCE,
|
TOLERANCE: TOLERANCE,
|
||||||
// Precision when comparing against 0
|
// Precision when comparing against 0
|
||||||
|
@ -305,6 +320,97 @@ var Numerical = new function() {
|
||||||
&& x < max + MACHINE_EPSILON)))
|
&& x < max + MACHINE_EPSILON)))
|
||||||
roots[nRoots++] = x < min ? min : x > max ? max : x;
|
roots[nRoots++] = x < min ? min : x > max ? max : x;
|
||||||
return nRoots;
|
return nRoots;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves the quadratic polynomial with coefficients a, b, c for roots
|
||||||
|
* (zero crossings) and and returns the solutions in an array.
|
||||||
|
*
|
||||||
|
* a*x^2 + b*x + c = 0
|
||||||
|
*/
|
||||||
|
_solveQuadratic: function(a, b, c, roots, min, max) {
|
||||||
|
var add = setupRoots(roots, min, max);
|
||||||
|
|
||||||
|
// Code ported over and adapted from Uintah library (MIT license).
|
||||||
|
// If a is 0, equation is actually linear, return 0 or 1 easy roots.
|
||||||
|
if (abs(a) < EPSILON) {
|
||||||
|
if (abs(b) >= EPSILON)
|
||||||
|
return add(-c / b);
|
||||||
|
// If all the coefficients are 0, we have infinite solutions!
|
||||||
|
return abs(c) < EPSILON ? -1 : 0; // Infinite or 0 solutions
|
||||||
|
}
|
||||||
|
// Convert to normal form: x^2 + px + q = 0
|
||||||
|
var p = b / (2 * a);
|
||||||
|
var q = c / a;
|
||||||
|
var p2 = p * p;
|
||||||
|
if (p2 < q - EPSILON)
|
||||||
|
return 0;
|
||||||
|
var s = p2 > q ? sqrt(p2 - q) : 0,
|
||||||
|
count = add(s - p);
|
||||||
|
if (s > 0)
|
||||||
|
count = add(-s - p);
|
||||||
|
return count;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves the cubic polynomial with coefficients a, b, c, d for roots
|
||||||
|
* (zero crossings) and and returns the solutions in an array.
|
||||||
|
*
|
||||||
|
* a*x^3 + b*x^2 + c*x + d = 0
|
||||||
|
*/
|
||||||
|
_solveCubic: function(a, b, c, d, roots, min, max) {
|
||||||
|
// If a is 0, equation is actually quadratic.
|
||||||
|
if (abs(a) < EPSILON)
|
||||||
|
return Numerical._solveQuadratic(b, c, d, roots, min, max);
|
||||||
|
|
||||||
|
// Code ported over and adapted from Uintah library (MIT license).
|
||||||
|
// Normalize to form: x^3 + b x^2 + c x + d = 0:
|
||||||
|
b /= a;
|
||||||
|
c /= a;
|
||||||
|
d /= a;
|
||||||
|
var add = setupRoots(roots, min, max),
|
||||||
|
// Compute discriminants
|
||||||
|
bb = b * b,
|
||||||
|
p = (bb - 3 * c) / 9,
|
||||||
|
q = (2 * bb * b - 9 * b * c + 27 * d) / 54,
|
||||||
|
// Use Cardano's formula
|
||||||
|
ppp = p * p * p,
|
||||||
|
D = q * q - ppp;
|
||||||
|
// Substitute x = y - b/3 to eliminate quadric term: x^3 +px + q = 0
|
||||||
|
b /= 3;
|
||||||
|
if (abs(D) < EPSILON) {
|
||||||
|
if (abs(q) < EPSILON) // One triple solution.
|
||||||
|
return add(-b);
|
||||||
|
// One single and one double solution.
|
||||||
|
var sqp = sqrt(p),
|
||||||
|
snq = q > 0 ? 1 : -1;
|
||||||
|
add(-snq * 2 * sqp - b);
|
||||||
|
return add(snq * sqp - b);
|
||||||
|
}
|
||||||
|
if (D < 0) { // Casus irreducibilis: three real solutions
|
||||||
|
var sqp = sqrt(p),
|
||||||
|
phi = Math.acos(q / (sqp * sqp * sqp)) / 3,
|
||||||
|
t = -2 * sqp,
|
||||||
|
o = 2 * PI / 3;
|
||||||
|
add(t * cos(phi) - b);
|
||||||
|
add(t * cos(phi + o) - b);
|
||||||
|
return add(t * cos(phi - o) - b);
|
||||||
|
}
|
||||||
|
// One real solution
|
||||||
|
var A = (q > 0 ? -1 : 1) * pow(abs(q) + sqrt(D), 1 / 3);
|
||||||
|
return add(A + p / A - b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
|
||||||
|
* http://paperjs.org/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
|
||||||
|
* http://scratchdisk.com/ & http://jonathanpuckey.com/
|
||||||
|
*
|
||||||
|
* Distributed under the MIT license. See LICENSE file for details.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in a new issue