10

我需要找出画布中贝塞尔曲线特定点的 Y 坐标。你知道吗,怎么找出来?谢谢

4

5 回答 5

34

使用 de Casteljau 的算法,您可以找到任何 t、百分比或插值步长的贝塞尔曲线的坐标 x 和 y。所以 at of .1 会给你 x 和 y 从一开始就在曲线的 10% 处。0.9 的 t 从一开始就是 90%,依此类推。

在我们的三次贝塞尔曲线中,我们有 p0(点 0)、cp0(控制点 0)、cp1(控制点 1)和 p1(点 1)。

在算法的第一步,我们画一条连接 p0 和 cp0 的线,另一条连接 cp0 和 cp1 的线,还有一条连接 cp1 和 p1 的线。然后对于所有这 3 行,我们将在它们上找到从它们开始的 t % 的点。

我将要点如下:

  • p0 -> cp0 = A
  • cp0 -> cp1 = B
  • cp1 -> p1 = C

    Ax = ( (1 - t) * p0x ) + (t * cp0x);
    Ay = ( (1 - t) * p0y ) + (t * cp0y);
    Bx = ( (1 - t) * cp0x ) + (t * cp1x);
    By = ( (1 - t) * cp0y ) + (t * cp1y);
    Cx = ( (1 - t) * cp1x ) + (t * p1x);
    Cy = ( (1 - t) * cp1y ) + (t * p1y);
    

第二步与第一步非常相似。首先,我们将这四个点用线连接起来,然后在它们上面找到了 3 个新点。在这一步中,我们将用线连接这 3 个点,在它们上面找到 2 个新点。我将这两个新点称为 D 和 E。

    Dx = ( (1 - t) * Ax ) + (t * Bx);
    Dy = ( (1 - t) * Ay ) + (t * By);

    Ex = ( (1 - t) * Bx ) + (t * Cx);
    Ey = ( (1 - t) * By ) + (t * Cy);

最后,我们可以将这最后两个点与另一条线连接起来,并在其上找到最后一个点,这将为我们提供该 t 的贝塞尔曲线上的点。我将此点称为 P。

    Px = ( (1 - t) * Dx ) + (t * Ex);
    Py = ( (1 - t) * Dy ) + (t * Ey);

好了,我们现在有了贝塞尔曲线上一个点的 x 和 y 坐标,该点距离开始时间为 t%。我会尽快添加一些图片。

在此处输入图像描述

于 2013-01-07T22:26:57.273 回答
8

剪切并粘贴准备好的答案:

// Points are objects with x and y properties
// p0: start point
// p1: handle of start point
// p2: handle of end point
// p3: end point
// t: progression along curve 0..1
// returns an object containing x and y values for the given t
BezierCubicXY = function(p0, p1, p2, p3, t) {
    var ret = {};
    var coords = ['x', 'y'];
    var i, k;

    for (i in coords) {
        k = coords[i];
        ret[k] = Math.pow(1 - t, 3) * p0[k] + 3 * Math.pow(1 - t, 2) * t * p1[k] + 3 * (1 - t) * Math.pow(t, 2) * p2[k] + Math.pow(t, 3) * p3[k];
    }

    return ret;
}
于 2015-07-19T23:20:21.873 回答
2

我一直在试图找出同样的东西,我想我至少解决了方形贝塞尔曲线,这是只有一个控制点的贝塞尔曲线。

数学解释

方形贝塞尔曲线的数学公式是:

其中“X”是结果,“A”是起点位置,“B”是控制点,“C”是终点。

't' 是一个介于 0 和 1 之间的数字,表示您要计算线上的哪个点。0 代表起点,1 代表终点,0.5 代表曲线的中心。

该函数用于计算线上一个点的 X 和 Y 坐标。如果要计算 X,只需填写 A、B 和 C 点的 X 坐标。

现在为了确定属于 X 的 Y,我们需要确定所述 X 坐标的“t”。

我们可以将相同的贝塞尔方程写成二次形式 ( ):

这使我们能够使用二次公式来推导求解方程的“t”值。二次公式实际上是2个公式。

结果公式为:

代码解决方案

我们可以在代码中将其描述为:

GetYValues(StartPoint, ControlPoint, EndPoint, X)
{
    Ax = StartPoint.X
    Bx = ControlPoint.X
    Cx = EndPoint.X

    q1 = 2*Ax - 2*Bx;
    q2 = Sqrt(5*Ax*Ax - 10*Ax*Bx + Ax*Cx - Ax*X + 2*Bx*X + 4*Bx*Bx)
    q3 = 2*Ax - 4*Bx + 2*Cx

    t1 = (q1 + q2) / q3
    t2 = (q1 - q2) / q3

    Ay = StartPoint.Y
    By = ControlPoint.Y
    Cy = EndPoint.Y

    Y1 = Ay*(1-t1)*(1-t1) + By*2*(1-t1)*t1 + Cy*t1
    Y2 = Ay*(1-t2)*(1-t2) + By*2*(1-t2)*t2 + Cy*t2

    return [Y1,Y2]
}

现在,我还没有对此进行测试,并且该函数不会检查实际上是否有任何有效点,因此肯定会有一些值会引发异常。请务必检查“除以 0”和“小于 0 的数字的平方根”。

此解决方案的问题

这个方程的一个大问题是它只适用于方形贝塞尔曲线,而大多数贝塞尔曲线实际上是三次方的。我试图找到一种类似的方法来解决这个问题的三次版本,不幸的是,这要困难一个数量级。我能找到的用于求解三次方程的唯一公式可以在这里找到Cubic function。这个公式包含虚数,我不知道如何处理这些。

另一个问题是,对于有 4 个或更多控制点的贝塞尔曲线,根本没有办法求解方程。

结论

最后,您最好的选择是将贝塞尔曲线简单地转换为直线,这非常容易计算。

于 2014-08-31T10:21:10.933 回答
0

@DerekR:尽管您在此处介绍的内容很清楚,并且可能对许多人有所帮助,但我认为您自己和 immo 的答案以及以下所有评论都没有解决问题。

(我的数学很糟糕,我一直在尝试解决同样的问题,所以我可能无法理解后续评论。)

我认为问题是:知道两个端点和两个控制点的X,Y坐标,并假设范围是0到1,那么给定Y,Y是多少?

我是新手,还不能发布图片,但你可以在duck.cc/images/beziercurve_findY.png 看到曲线

于 2013-02-01T19:58:48.497 回答
0

圆的等式是: (xh)^2 + (yk)^2 = r^2 其中 h,k 是中心的 x,y 坐标。所以 y 的等式是 y = sqrt(r^2 - (xh)^2) + k 。Math.sqrt(..)大多数语言都带有一个数学包,所以我假设你可以做一些Math.pow(..)

如果我的数学不正确,任何人都可以纠正我。

于 2013-01-05T17:32:11.163 回答