Canvas 如何在画布中找到bezier曲线中特定点的Y坐标?

Canvas 如何在画布中找到bezier曲线中特定点的Y坐标?,canvas,point,bezier,curve,coordinate,Canvas,Point,Bezier,Curve,Coordinate,我需要找出画布上贝塞尔曲线特定点的Y坐标。你知道怎么找到它吗?谢谢圆的方程式是: (x-h)^2+(y-k)^2=r^2,其中h,k是中心的x,y坐标。所以y的方程是y=sqrt(r^2-(x-h)^2)+k。大多数语言都有一个数学包,所以我假设你可以做一些Math.sqrt(…)和Math.pow(…) 如果我的数学不好,有人纠正我吗 使用de Casteljau算法,您可以找到任意t、百分比或插值步长的bezier曲线的坐标x和y。所以t等于,1会给出,从一开始,曲线10%处的x和y。t=0

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

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


如果我的数学不好,有人纠正我吗

使用de Casteljau算法,您可以找到任意t、百分比或插值步长的bezier曲线的坐标x和y。所以t等于,1会给出,从一开始,曲线10%处的x和y。t=0.9,从一开始就是90%,依此类推

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

在算法的第一步,我们画了一条连接p0和cp0的线,另一条连接cp0和cp1的线,还有一条连接cp1和p1的线。然后,对于这三条线,我们将找到它们上的点,从它们开始的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个点,并在其上找到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%。我很快会添加一些图片


@DerekR:虽然你在这里介绍的内容很清楚,可能对很多人都有帮助,但我认为答案以及你和immo的以下所有评论并没有解决这个问题

(我的数学糟透了,我一直在试图解决同一个问题,所以我可能不理解后面的评论。)

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


我是新来的,现在还不能发布图片,但是你可以在duck.cc/images/beziercrove\u findY.png上看到曲线。我一直在尝试解决同样的问题,我想我至少解决了方形贝塞尔曲线的问题,它们是只有一个控制点的贝塞尔曲线

数学解释

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

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

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

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

现在为了确定属于X的Y,我们需要确定X坐标的‘t’

我们可以用二次型()写出同样的贝塞尔方程:

这使我们能够使用二次公式推导出求解方程的‘t’值。二次公式实际上是两个公式

由此得出的公式是:

代码解决方案

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

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以下数字的平方根”

此解决方案的问题

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

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

结论


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

剪切粘贴就绪答案:

// 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;
}

哇!看起来真的很棒;)非常感谢。你能帮我写代码得到Y位置吗?非常感谢你!你应该试着自己写代码,如果你在某个点上卡住了,我很乐意帮你解决。@lmno:如果他想找到一个三次贝塞尔的y坐标,我认为圆的方程不会给他点,除非他用一个以上的贝塞尔近似一个圆。y=sqrt(r^2-(x-h)^2中的“k”是什么意思+k“?谢谢Derekr:那我怎么才能得到Y坐标呢?Imno:y=sqrt(r^2-(x-h)^2)+k中的“k”是什么意思?谢谢你你有什么信息要解决?x坐标?贝塞尔曲线的一部分,t?我知道曲线的起点和终点位置(x和y坐标)。我知道曲线的两个点(x和y坐标)嘿@DerekR,你能看看这个吗?我被困在BezierPath上了。@DerekR这正是我要找的。即使数学不是很好,我现在(用这个)能够继续我的脚本(我被卡住了)。非常好和明确的回答:非常感谢。工程完全按照广告!