贝塞尔曲线上给定点的角度?

时间:2012-09-10 18:10:50

标签: actionscript-3 math geometry bezier

我在actionscript中创建了这个类,它返回bezier的给定点。而我想要达到的目的是获得当前点的角度。我在互联网上搜索但我找不到多少。我怎么能这样做?

public static function quadraticBezierPoint(u:Number, anchor1:Point, anchor2:Point, control:Point):Point {
    var uc:Number = 1 - u;
    var posx:Number = Math.pow(uc, 2) * anchor1.x + 2 * uc * u * control.x + Math.pow(u, 2) * anchor2.x;
    var posy:Number = Math.pow(uc, 2) * anchor1.y + 2 * uc * u * control.y + Math.pow(u, 2) * anchor2.y;
    return new Point(posx, posy);
}

2 个答案:

答案 0 :(得分:11)

假设:

  • 控制点p0,p1,p2
  • time t

点B是在时间t由p0,p1和p2描述的二次贝塞尔曲线上的点。
q0是在时间t由p0和p1描述的线性贝塞尔曲线上的点。
q1是在时间t由p1和p2描述的线性贝塞尔曲线上的点。
q0和q1之间的线段与B点的二次贝塞尔曲线相切。

因此,时间t处的贝塞尔曲线的角度等于q0和q1之间的线段的斜率。

维基百科有lovely gif证明这一点。黑点是B点,绿线段的端点是q0和q1。

对于更高尺寸的贝塞尔曲线,原理是相同的。要找到N度贝塞尔曲线上某点的角度,找到q0和q1,它们是控制点[p0,p1,...,p(N-1)的N-1度贝塞尔曲线上的点。 )]和[p1,p2,...,pN]。该角度等于q0-q1线段的斜率。

在伪代码中:

def bezierCurve(controlPoints, t):
    if len(controlPoints) == 1:
        return controlPoints[0]
    else:
        allControlPointsButTheLastOne = controlPoints[:-1]
        allControlPointsButTheFirstOne = controlPoints[1:]
        q0 = bezierCurve(allControlPointsButTheLatOne, t)
        q1 = bezierCurve(allControlPointsButTheFirstOne, t)
        return (1-t) * q0 + t * q1

def bezierAngle(controlPoints, t):
    q0 = bezierCurve(controlPoints[:-1], t)
    q1 = bezierCurve(controlPoints[1:], t)
    return math.atan2(q1.y - q0.y, q1.x - q0.x)

答案 1 :(得分:3)

凯文的解释之后,我做了一个动态但简单的解决方案:

public static function quadraticBezierAngle(u:Number, anchor1:Point, anchor2:Point, control:Point):Number {
    var uc:Number = 1 - u;
    var dx:Number = (uc * control.x + u * anchor2.x) - (uc * anchor1.x + u * control.x);
    var dy:Number = (uc * control.y + u * anchor2.y) - (uc * anchor1.y + u * control.y);
    return Math.atan2(dy, dx);
}
相关问题