Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angle of a given point on a Bezier curve?

I created this class in actionscript, it returns a given point of the bezier. And what I am trying to achieve is to get the angle of the current point. I searched on the internet but I couldn't found much. How can I do this?

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);
}
like image 298
tversteeg Avatar asked Sep 10 '12 18:09

tversteeg


1 Answers

Given:

  • control points p0, p1, p2
  • time t

point B is the point on the quadratic bezier curve described by p0, p1, and p2 at time t.
q0 is the point on the linear bezier curve described by p0 and p1 at time t.
q1 is the point on the linear bezier curve described by p1 and p2 at time t.
The line segment between q0 and q1 is tangent to your quadratic bezier curve at point B.

Therefore, the angle of the bezier curve at time t is equal to the slope of the line segment between q0 and q1.

Wikipedia has a lovely gif demonstrating this. The black dot is point B, and the endpoints of the green line segment are q0 and q1.

The principle is identical for bezier curves of higher dimensions. To find the angle of a point on an N-degree bezier curve, find q0 and q1, which are the points on the N-1-degree bezier curves for control points [p0,p1,...,p(N-1)] and [p1, p2,...,pN]. The angle is equal to the slope of the q0-q1 line segment.

In pseudocode:

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)
like image 198
Kevin Avatar answered Sep 30 '22 19:09

Kevin