确实如此,并且涉及对三次函数进行求根。一种直接的方法是实施卡尔达诺算法 http://www.trans4mind.com/personal_development/mathematics/polynomials/cubicAlgebra.htm用于求三阶多项式的根 - 可以找到该函数的 JavaScript 实现here http://jsbin.com/mutaracihafi/1/edit?js,output。根据曲线的参数,您将获得最多三个同样正确的答案,因此取决于您试图找到的内容t
值,您将需要做更多的工作来找出您需要的最多三个值中的哪一个。
// Not in every toolbox, so: how to implement the cubic root
// equivalent of the sqrt function (note that there are actually
// three roots: one real, two complex, and we don't care about the latter):
function crt(v) { if (v<0) return -pow(-v,1/3); return pow(v,1/3); }
// Cardano's algorithm, based on
// http://www.trans4mind.com/personal_development/mathematics/polynomials/cubicAlgebra.htm
function cardano(curve, line) {
// align curve with the intersecting line, translating/rotating
// so that the first point becomes (0,0), and the last point
// ends up lying on the line we're trying to use as root-intersect.
var aligned = align(curve, line),
// rewrite from [a(1-t)^3 + 3bt(1-t)^2 + 3c(1-t)t^2 + dt^3] form...
pa = aligned[0].y,
pb = aligned[1].y,
pc = aligned[2].y,
pd = aligned[3].y,
// ...to [t^3 + at^2 + bt + c] form:
d = ( -pa + 3*pb - 3*pc + pd),
a = ( 3*pa - 6*pb + 3*pc) / d,
b = (-3*pa + 3*pb) / d,
c = pa / d,
// then, determine p and q:
p = (3*b - a*a)/3,
p3 = p/3,
q = (2*a*a*a - 9*a*b + 27*c)/27,
q2 = q/2,
// and determine the discriminant:
discriminant = q2*q2 + p3*p3*p3,
// and some reserved variables for later
u1,v1,x1,x2,x3;
// If the discriminant is negative, use polar coordinates
// to get around square roots of negative numbers
if (discriminant < 0) {
var mp3 = -p/3,
mp33 = mp3*mp3*mp3,
r = sqrt( mp33 ),
t = -q/(2*r),
// deal with IEEE rounding yielding <-1 or >1
cosphi = t<-1 ? -1 : t>1 ? 1 : t,
phi = acos(cosphi),
crtr = crt(r),
t1 = 2*crtr;
x1 = t1 * cos(phi/3) - a/3;
x2 = t1 * cos((phi+tau)/3) - a/3;
x3 = t1 * cos((phi+2*tau)/3) - a/3;
return [x1, x2, x3];
}
else if(discriminant === 0) {
u1 = q2 < 0 ? crt(-q2) : -crt(q2);
x1 = 2*u1-a/3;
x2 = -u1 - a/3;
return [x1,x2];
}
// one real root, and two imaginary roots
else {
var sd = sqrt(discriminant),
tt = -q2+sd;
u1 = crt(-q2+sd);
v1 = crt(q2+sd);
x1 = u1 - v1 - a/3;
return [x1];
}
}