我需要在画布中找出贝塞尔曲线特定点的Y坐标。你知道吗,如何找到它?谢谢
答案 0 :(得分:29)
使用de Casteljau算法,您可以找到任何t,百分比或插值步长的贝塞尔曲线的坐标x和y。所以.1的t会给你从开头起10%曲线的x和y。 .9的t从开头就是90%,依此类推。
在我们的三次贝塞尔曲线中,我们有p0(点0),cp0(控制点0),cp1(控制点1)和p1(点1)。
在算法的第一步中,我们绘制一条连接p0和cp0的线,另一条线连接cp0和cp1,另一条线连接cp1和p1。然后对于所有这3行,我们将在它们的起点找到它们的t%点。
我会将这些要点称为:
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%。我很快就会添加一些图片。
答案 1 :(得分:6)
剪切并粘贴准备好的答案:
// 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;
}
答案 2 :(得分: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个或更多控制点的贝塞尔曲线,根本无法求解该等式。
<强>结论强>
最后,最好的办法是简单地将贝塞尔曲线转换为直线,这样可以更容易地计算出来。
答案 3 :(得分:1)
圆的等式是:
(x-h)^ 2 +(y-k)^ 2 = r ^ 2其中h,k是中心的x,y坐标。因此y的等式将是y = sqrt(r ^ 2 - (x-h)^ 2)+ k。大多数语言都带有Math包,所以我假设你可以做某种Math.sqrt(..)
和Math.pow(..)
如果我的数学已关闭,任何人都会纠正我。
答案 4 :(得分:0)
@DerekR:虽然你在这里介绍的内容很清楚,可能对很多人有帮助,但我认为答案以及你自己和immo的所有以下评论都没有解决问题。
(我的数学很糟糕,我一直试图解决同样的问题,所以我可能不理解后续评论。)
我认为问题是: 知道两个端点和两个控制点的X,Y坐标,假设范围是0到1,那么给定Y,Y是什么?
我是新手,无法发布图片,但您可以在duck.cc/images/beziercurve_findY.png看到曲线