Sunday, May 27, 2012

Bezier curve

I started on an exploration of the `NSBezierPath` function `curveToPoint:controlPoint1:controlPoint2:` which is used to draw curves in Cocoa.

The math is relatively easy to state (wikipedia). For a cubic curve, we'll have a total of four points, two where the curve starts and stops (P0 and P3) and two control points (P1 and P2). In the screenshots above, P0 and P3 are in black at the top and bottom and the two control points are in red. The blue circle shows the current point along the trajectory. The left one is at an early time, and the right one very late.

[ The purple circles show the current position for the two quadratic Bezier curves from which the cubic one may be constructed. ]

The curve is represented as a parametric equation in the variable `t` (standing for time, since curves are often thought of as trajectories).

A standard equation is:

`P0(1-t)3 + P1(3)(t)(1-t)2 + P2(3)(t)2(1-t) + P3(t)3`

At t = 0 we're at P0 and at t = 1 we're at P3. Beyond that, it's hard to visualize. According to wikipedia:

The curve starts at P0 going toward P1 and arrives at P3 coming from the direction of P2. Usually, it will not pass through P1 or P2; these points are only there to provide directional information. The distance between P0 and P1 determines "how long" the curve moves into direction P2 before turning towards P3.

Writing `BPi,Pj,Pk(t)` for the quadratic Bézier curve defined by points Pi, Pj, and Pk, the cubic Bézier curve can be defined as a linear combination of two quadratic Bézier curves:

`B(t) = (1-t)BP0,P1,P2 + (t)BP1,P2, P3; 0 <= t <= 1`

where

`BP0,P1,P2 = P0(1-t)2 + P1(t)(1-t) + P2(t)2`

As I say, I found it hard to visualize. So I wrote a little Xcode project that does two things. It presents an animation of the progress of the trajectory. At the moment it can be stopped and restarted, but not paused.

Also, the two control points P1 and P2 can be dragged to different positions to explore how they influence the curve.

I took the dragging and animation code from two earlier PyObjC projects (here and here).

My hope was to reproduce the animations shown in the wikipedia article, and see how the curves combine to produce the result. But I've run out of time for the moment, so I thought I'd just show my progress to date. The zipped project is on Dropbox (here).