Cubic Bezier reverse GetPoint equation: float for Vector <=> Vector for float

后端 未结 2 1139
说谎
说谎 2021-01-23 17:23

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,         


        
相关标签:
2条回答
  • 2021-01-23 17:57

    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];
      }
    }
    
    0 讨论(0)
  • 2021-01-23 18:21

    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.

    0 讨论(0)
提交回复
热议问题