Drawing a cubic bezier curve using actionscript 3

Flash curve exampleRecently I came up with an idea for a project to work on and where I plan to write about soon on this blog. As a part of this project I need to draw curved lines. I thought it would be a good idea to make this similar as the curves which you can draw with the pen tool in Flash and Illustrator. An example of this kind of curve is on the left. I expected this would be really simple and it was just a standard drawing API which I had to use to draw this kind of curve…
Adobe’s documentation shows the following image which suggests we have the option to draw a quadratic bezier and a cubic bezier.

Quadric bezier vs cubic bezier

Unfortunately only a quadratic bezier is supported and nothing is written about the cubic bezier. I really want to have the cubic bezier curve, since we can make more advanced curves with a cubic curve. For example, the curve at the beginning of this article is already too advanced for being a quadratic curve. I found some articles online talking about these curves which you might find interesting to read:

It’s quite simple to make these curves. There’s just a simple formula to calculate the exact x and y position on a position of the curve between 0 and 1:cubic bezier formula

  • B represents the curve
  • Px represents one of the four points which makes the curve. P0 and P3 are points which we know as anchor points, where P1 and P2 are the control points.
  • u is the position of the curve which we want to calculate.

In actionscript this would look like the following:

 posx = Math.pow(u,3)*(anchor2.x+3*(control1.x-control2.x)-anchor1.x)
           +3*Math.pow(u,2)*(anchor1.x-2*control1.x+control2.x)
           +3*u*(control1.x-anchor1.x)+anchor1.x;

posy = Math.pow(u,3)*(anchor2.y+3*(control1.y-control2.y)-anchor1.y)
          +3*Math.pow(u,2)*(anchor1.y-2*control1.y+control2.y)
          +3*u*(control1.y-anchor1.y)+anchor1.y;

Note that you have to calculate this for x and y separately.

 

When we need to draw a curved line, we need to calculate this for let’s say in a 100 steps between 0 and 1 to see the curve:

Cubic bezier steps

As you can see this is almost the curve! If we divide the curve up in 1000 steps instead of 100, we will in this case see a perfect curve! But as you can imagine calculating this a 1000 times might be a little heavy, especially when you want that a interactive curve which we can change on the fly. Beside that when you want to draw a huge curve, 1000 steps might again be to little.
It’s better to connect each point with another so there won’t be any white-space in the curve and it seems fluent.

var line:Shape = new Shape();
line.graphics.lineStyle(2,0x000000);
line.graphics.moveTo(anchor1.x,anchor1.y);

// store values where to lineTo
var posx:Number;
var posy:Number;

//loop through 100 steps of the curve
for (var u:Number = 0; u <= 1; u += 1/100) {

posx = Math.pow(u,3)*(anchor2.x+3*(control1.x-control2.x)-anchor1.x)
+3*Math.pow(u,2)*(anchor1.x-2*control1.x+control2.x)
+3*u*(control1.x-anchor1.x)+anchor1.x;

posy = Math.pow(u,3)*(anchor2.y+3*(control1.y-control2.y)-anchor1.y)
+3*Math.pow(u,2)*(anchor1.y-2*control1.y+control2.y)
+3*u*(control1.y-anchor1.y)+anchor1.y;

line.graphics.lineTo(posx,posy);

}

//Let the curve end on the second anchorPoint

line.graphics.lineTo(anchor2.x,anchor2.y);

addChild(line);

Although this works and it’s a better option than drawing 1000 points of a curve, I’m not sure this is the best option. I’m looking for a way to divide the curve up in for example 5 point’s and use the built in curveTo function to draw a quadratic curve between them. But so far I don’t know how to solve this yet and if this will boost performance at all. That’s something which I want to sort out soon. If you have any idea’s I really would like to here from you.

 

To make this cubic bezier easy to work with, I made a class (included in the download at the bottom of this article) which draws this curve. I’ve used this class in the working example from below. You can move the anchors, control-points and add new points by clicking a random position on the line.

Download the source files here