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

6 Responses to “Drawing a cubic bezier curve using actionscript 3”

  1. You may want to check out the cubic to quadratic bezier conversion code inside the SVG example at flash-creations.com (as2) and also in packages like animationpackage (alex ullhman I think - as2 and as3 code) and also if you use flex, check out degrafa - degrafa.com. They all use similar recursive methods to split the cubic bezier into quadratic beziers for a specified tolerance/accuracy into flash native curveTo quadratics.

  2. Thank you for providing these useful tips. Splitting the cubic curve into quadratic curves is something I’ve been thinking about too, but I didn’t figured out so far how to do this.

    I’ll soon dive into these examples you gave and write down on this blog how to implement it regarding to this article.

  3. i was wondering if we can restrict the curvature of the curve in the pencil points. m developin an app wre i need to let the user draw a figure but i need to restrict the angle of twisting and rotation of the curves that the user can perform .can u pls tell me how do u implement it here

  4. great man!!!

  5. Dear sir or madam
    I want to make a Bezier curve for three anchor points and two control points. Can you send me the the right formula for that case, please.

    hte second anchor is exactly between the two othe points. Can you right down the x- value of two control points, which is both of contro points tangent to the middle anchor point.

    Kindest regards
    Idres

  6. […] when thought of scrolling a bit, I discovered that linked to the wikipedia page was an excellent post by a guy named Paul Tondeur, who had already done this successfully. […]

Discussion Area - Leave a Comment