Application: sine curve

Keith Peters of bit-101 created a sine wave tool for Flash using the JSAPI a while ago using straight lines. He challenged the community to modify it to use curves. I came up with the following solution after elaborating the method outlined above. You may download the resulting tool here.

Here we analyze a script based on the tool, modified for ActionScript. The following will draw a single period of a sine wave:

_root.createEmptyMovieClip('sine',0);
res = 100;
xscale = 100;
yscale = 100;
sine.lineStyle(1);
for(i =0; i <= res; i++)
{
        var ang = 2*Math.PI*i/res;
        sine.lineTo(xscale*ang, yscale*Math.sin(ang));
}

So let's see how we can modify this script to use curves instead of lines. First we have to find out what the slope of this curve is at any point. From calculus, you may remember that:

derivate sin(x) = cos(x)

We may conclude immediately that the slope of the sine wave will be proportional to the cosine of the angle. Now the tricky bit here is that we are using a parametric and not functional notation; hence it's important to realize that the slope needs to be multiplied by yscale/xscale.

The generic equation for a straight line is:

y = m*x + b

Here, m is the slope and b is the coordinate at the origin. In our particular case, we know m is equal to yscale/xscale*cos(ang). The line must go through the point (x,y) = (xscale*ang, yscale*sin(ang)) in order to be tangent to the curve. Putting these values into the equation for the straight line, we isolate the value of b:

b = yscale*(sin(ang) - ang*cos(ang))

Now that we know the values for m and b at any point, it's time to find the location of the control point on a segment of curve. We pick any two points p0 and p2 with tangent equations:

y1 = m1*x + b1; y2 = m2*x + b2

Equating y1 and y2, we find that:

(b2 - b1)/(m2 - m1) = x = location of control point

Plugging that value into either of the tangent equations, we find:

y = m1*x + b1 = m2*x + b

All that we need now is to transform these considerations into code:

_root.createEmptyMovieClip('sine',0);

res = 6;
xscale = 100;
yscale = 100;
sine.lineStyle(1);
var m1 = yscale/xscale;
var b1 = 0;
for(i = 1; i <= res; i++)
{
        var ang = 2*Math.PI*i/res;
        var si = Math.sin(ang);
        var co = Math.cos(ang)
        var m2 = yscale/xscale*co;
        var b2 = yscale*(si - ang*co);
        var x = (b1 - b2)/(m2 - m1);
        var y = m2*x + b2;
        if(Math.abs(m1 - m2) < 0.001)
        {
                sine.lineTo(xscale*ang, yscale*si);
        }
        else
        {
                sine.curveTo(x, y, xscale*ang, yscale*si);
        }
        m1 = m2;
        b1 = b2;
}

Voilà! What took a few pages of math analysis shrunk down to a 20-line script. It follows the algorithm outlined above very closely. A few notes: first, a resolution of 6 points is enough to get a very realistic curve. This is a great advance over the previous script which required close to 100 points to get a smooth curve. A sine curve is locally very close to a parabola; this is evidenced by the following Taylor series:

taylor series for cos(x)

The coefficients fall off very rapidly, leaving the x^2 term dominant. Therefore it should not be surprising that the sine curve can be represented easily with few quadratic Bezier curves.

We considered the degenerate case of two parallel slopes, isolating the condition by checking if their difference is less than a very small amount. This is better than to check for actual equality between the two slopes as it is numerically stable and therefore handles a wider variety of cases.

Conclusion

We've covered control points in quad bezier curves systematically, allowing us to find a general method for locating control points on mathematical curves and figures. We've used this method to plot a sine curve accurately with only six points. You can now apply this method to a wide variety of cases, either in conjunction with the drawing API or with the JSAPI to create new and useful tools for Flash.

If you need professional help with Actionscript, Flash or JSAPI extension development, please visit my site 5etdemi.com for my portfolio and contact info. Happy flashing!