问题
Is it possible to get float t back given the resulting value and the four points? If so, how?
public static Vector3 GetPoint (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) {
t = Mathf.Clamp01(t);
float oneMinusT = 1f - t;
return
oneMinusT * oneMinusT * oneMinusT * p0 +
3f * oneMinusT * oneMinusT * t * p1 +
3f * oneMinusT * t * t * p2 +
t * t * t * p3;
}
Code from this Tutorial by Jasper Flick
回答1:
It is, and involves implementing root finding for third degree functions. One direct way of doing that is to implement Cardano's Algorithm for finding the roots for a polynomial of degree three - a JavaScript implementation of that can be found here. Depending on the curve's parameters, you will get up to three equally correcet answers, so depending on what you were trying to find the t
value for, you'll have to do more work to find out which of those up-to-three values you need.
// 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];
}
}
回答2:
Solving the following cubic polynomial should reveal your original t:
(p3 - (3 * p2) + (3 * p1) - p0) * t^3
+ ((3 * p2) - (6 * p1) + (3 * p0)) * t^2
+ ((3 * p1) - (3 * p0)) * t
+ p0
= 0
I put it in standard form so you could easily get the roots from the coefficients.
来源:https://stackoverflow.com/questions/26823024/cubic-bezier-reverse-getpoint-equation-float-for-vector-vector-for-float