【问题标题】:Cubic Bezier reverse GetPoint equation: float for Vector <=> Vector for float三次贝塞尔逆 GetPoint 方程:float for Vector <=> Vector for float
【发布时间】:2014-11-09 14:15:44
【问题描述】:

根据结果值和四个点是否可以返回 float t? 如果有,怎么做?

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

【问题讨论】:

  • 这个问题似乎跑题了,因为它不是编程问题。
  • 这相当于求解三次多项式的根。
  • 感谢您的链接,但所有这些答案都超出了我的想象

标签: c# math computational-geometry vector-graphics bezier


【解决方案1】:

它是,并且涉及实现三阶函数的求根。一种直接的方法是实现Cardano's Algorithm 来查找三次多项式的根——可以在here 中找到它的JavaScript 实现。根据曲线的参数,您将获得最多三个同样正确的答案,因此根据您试图找到 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];
  }
}

【讨论】:

  • 谢谢你,它非常膨胀,我想我要把曲线分成 100 个单位,然后看看哪个单位最接近结果向量
  • 没有人说maths and theory behind Bezier curves 很容易。如果您要使用 LUT 方法,请记住最多可以有三个坐标,而不仅仅是一个。
  • 非常感谢,有了那个教程页面,我觉得我完全不可能最终绕过这些曲线:)
  • @nick 记得接受答案,不要让这个问题悬而未决。
【解决方案2】:

解决以下三次多项式应该会显示您的原始 t:

(p3 - (3 * p2) + (3 * p1) - p0) * t^3
+ ((3 * p2) - (6 * p1) + (3 * p0)) * t^2
+ ((3 * p1) - (3 * p0)) * t
+ p0
= 0

我把它放在标准形式,这样你就可以很容易地从系数中得到根。

【讨论】:

  • 另外,求解三次三次也不是“容易”完成的。这个答案缺乏关于如何从三次多项式到解的实际解释。
猜你喜欢
  • 2021-01-26
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多