在Cubic Bezier曲线上找到Y给定的X?

时间:2012-07-03 00:21:47

标签: c++ bezier curve cubic

我需要一种方法,允许我在给定x坐标的情况下在Cubic Bezier曲线上找到Y坐标。

我遇到很多地方告诉我把它当作一个立方函数然后试图找到根,我明白了。然而,对于Cubic Bezier曲线的等式是(对于x-coords):

X(t) = (1-t)^3 * X0 + 3*(1-t)^2 * t * X1 + 3*(1-t) * t^2 * X2 + t^3 * X3

让我感到困惑的是添加(1-t)值。例如,如果我用一些随机数填写X值:

400 = (1-t)^3 * 100 + 3*(1-t)^2 * t * 600 + 3*(1-t) * t^2 * 800 + t^3 * 800

然后重新安排它:

800t^3 + 3*(1-t)*800t^2 + 3*(1-t)^2*600t + (1-t)^3*100 -400 = 0

我仍然不知道(1-t)系数的值。当(1-t)还未知时,我该如何解决这个问题?

5 个答案:

答案 0 :(得分:6)

表达三次贝塞尔曲线有三种常用方法。

第一个x作为t

的函数
x(t) = sum( f_i(t) a_i )
     = (1-t)^3 * x0 + 3*(1-t)^2 * t * x1 + 3*(1-t) * t^2 * x2 + t^3 * x3

其次y是x

的函数
y(x) = sum( f_i(x) a_i )
     = (1-x)^3 * y0 + 3*(1-x)^2 * x * y1 + 3*(1-x) * x^2 * y2 + x^3 * y3

前两个在数学上是相同的,只是为变量使用不同的名称。

根据您的描述判断“在Cubic Bezier曲线上找到Y坐标,给出一个x坐标。”我猜你使用第二个方程得到一个问题是试图重新排列第一个方程以帮助你解决它,你应该使用第二个方程。如果是这样的话,那么就不需要重新安排或解决 - 只需插入你的x值就可以得到解决方案。

你可能有第三种情况的等式,这是丑陋和困难的情况。 这是x和y参数都是第三个变量t的立方贝塞尔数。

x(t) = sum( f_i(t) x_i )
y(t) = sum( f_i(t) y_i )

如果是这种情况。让我知道,我可以详细说明你需要做些什么来解决它。

答案 1 :(得分:2)

我认为这是一个公平的CS问题,所以我将尝试展示我是如何解决这个问题的。请注意,给定的x可能具有超过1 y的值。在我需要这个的情况下,保证不是这样,所以你必须弄清楚如何确定你想要的那个。

我迭代t生成一个x和y值的数组。为了我的目的,我以相当高的分辨率做到了。 (我当时想要生成一个8位的查找表,所以我使用了~1000点。)我只是将t插入到下一个x的bezier方程中,并将下一个y坐标存储在数组中。一旦我生成了整个事物,我就会扫描数组以找到最近的2个x值。 (或者,如果存在精确匹配,则使用它。)然后,我在该非常小的线段上进行线性插值,以获得我需要的y值。

答案 2 :(得分:1)

进一步开发表达式可以让你摆脱(1 - t)因素

如果你跑:

expand(800*t^3 + 3*(1-t)*800*t^2 + 3*(1-t)^2*600*t + (1-t)^3*100 -400 = 0);

wxMaximaMaple中(您必须在此处添加参数t),您会得到:

100*t^3 - 900*t^2 + 1500*t - 300 = 0

解决t的新三次方程式(您可以使用the cubic equation formula),在得到t后,您可以找到x

x = (x4 - x0) * t      (asuming x4 > x0) 

答案 3 :(得分:0)

Bezier曲线的方程式(得到x值):

Bx = (-t^3 + 3*t^2 - 3*t + 1) * P0x + 
     (3*t^3 - 6*t^2 + 3*t) * P1x + 
     (-3*t^3 + 3*t^2) * P2x + 
     (t^3) * P3x

以立方t

的形式重排
0  = (-P0x + 3*P1x - 3*P2x + P3x) * t^3+ 
     (3*P0x - 6*P1x + 3*P2x) * t^2 + 
     (-3*P0x + 3*P1x) * t + 
     (P0x) * P3x - Bx

使用立方公式求解t以找到t的值。可能存在多个t的实际值(如果您的曲线两次跨越相同的x点)。在我的情况下,我正处理的情况是,x的任何值都只有一个y值。所以我能够把唯一真正的根作为t的值。

a = -P0x + 3.0 * P1x - 3.0 * P2x + P3x;
b = 3.0 * P0x - 6.0 * P1x + 3.0 * P2x;
c = -3.0 * P0x + 3.0 * P1x;
d = P0x;
t = CubicFormula(a, b, c, d);

接下来将t的值放回到y

的贝塞尔曲线中
By = (1-t)^3 * P0x + 
     3t(1-t)^2 * P1x + 
     3t^2(1-t) * P2x + 
     t^3 * P3x

答案 4 :(得分:-1)

  

所以我一直在寻找某种方法让我在Cubic Bezier曲线上找到Y坐标,给出一个x坐标。

考虑点(0,0)和(0,100)之间的三次贝塞尔曲线,控制点位于(0,33)和(0,66)。对于给定的X,存在无限数量的Y.因此,对于任意的三次贝塞尔曲线,没有任何方程可以解决Y给定的X.

对于强大的解决方案,您可能希望从De Casteljau's algorithm

开始

递归地分割曲线,直到各个线段接近直线。然后,您可以检测这些不同线段是否以及在何处拦截您的x,或者它们是否是x对应于您正在寻找的x的垂直线段(我的上例)。