Written by: Patrick Mineault, , http://www.5etdemi.com
Difficulty Level: Advanced
Requirements: MX and experience with actionscript
Topics Covered: Drawing API, curveTo, bezier curves
Assumed Knowledge: some actionscript, college math (algebra, trig and
some calculus)

Understanding curves and control point placement

In a previous tutorial, Dynamic masking using the drawing API II (see related articles), I've introduced the use of control points in Flash curves to morph between different curves. In that context, it was useful to think of control points as "magnetic points" to which the curve is "attracted" to. In this tutorial, we will study Flash curves in a more systematic way in order to plot mathematically correct figures and functions. We'll then analyze a sine curve drawing tool which can be downloaded here.

Bezier curves are an integral part of vector-drawing applications such as Illustrator and Freehand. Bezier curves are a general type of spline, a mathematical curve determined by a certain number of control points. While most drawing applications use cubic Bezier curves, Flash uses quad Bezier curves, which use 3 control points instead of four.

cubic vs quad

Quad Bezier curves are useful at several levels in Flash. Curves that are drawn with the built-in cubic Bezier tool are converted to quad beziers when the curve is unselected. The method outlined here may be used with the curveTo drawing API function and also for the function by the same name in the JS extension API (for custom tool development).

Bezier curves are defined by a formula (which can seen in this excellent article) which takes a parameter u varying from 0 to 1 and spits out the intermediate points of the curve. As can be seen from the previous link, Bezier curves have this nice property:

"At u=0 the curve is tangent to the line (P0, P1) and at u=1, the curve is tangent to the line (PN, PN-1)"

Since quads use only three control points, that means the second control point constrains the tangent of both the start point and the end point.

This gives us a straightforward and general method for finding out the location of the middle control point in a curve that is made to fit a mathematical figure or curve.

1. Find the slope at the beginning and end points of the curve, using geometry or calculus
2. From the slopes, determine the equations of the tangent curves
3. Determine the intersection of the tangent curves in a single coordinate (x or y)
4. Use the equation of one of the tangents to find the location of the control point in the other coordinate

algorithm

Degenerate cases

Before going any further, it's important to note that there are a few degenerate cases in which the preceding algorithm will fail to work properly. We'll have to take these into account. In the first case, the curve to be approximated crosses the line between the beginning and end points.

degenerate case

Here we have the curve to be approximated in blue, the tangents at the end point in red, the line joining p0 and p2 and the final curve in gray. As you see, since the curve to be approximated crosses the p0-p2 line, the results of the algorithm are erroneous. In fact, the results will be even worse when the tangents are close to parallel; in the extreme case of exactly parallel slopes, the algorithm will not find an intersection between the two tangents and will produce erratic results. These kinds of problems may also happen in the case of an almost straight line, where numeric instability can cause a straight line to be approximated with an extremely curved one, for example when slopes differ by as little as 10E-15.

In order for our algorithm to work correctly, we'll have to detect these cases and eliminate them. A sophisticated way to do so would be to split the curve in two parts and then draw a curve for each part. In our case, we'll assume that the resolution of the curve is already sufficient, and that we will only correct for cases where the two tangents are almost parallel. In these cases, we'll approximate the problematic curves with a straight line joining p0 and p2.

In addition, since beziers are parametric and not functional curves, it's entirely possible that one of the tangent slopes will be infinite. It will be important to detect and eliminate these cases where appropriate, for example if we want to draw a spiral, circle or lemniscate.

With this background in hand, we're ready to apply this method to create a sine curve.