Recently 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.

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:

- Wikipedia
- Jim Armstrong’s
- Timothée Groleau – Approximating Cubic Bezier Curves in Flash MX
- Interpolation with Bezier Curves

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:

- 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:

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.

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.

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.

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

great man!!!

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

lovely code .. thanks!

You might want to check out the BezierSegment class in the fl.motion package – it provides native support for cubic beziers. You have to draw them yourself, but the x/y calculations are a magnitude faster than doing them yourself.

Hi,

it is possible to have a .fla file that use this bezier library.

Hi,

it is possible to have a .fla file that use this bezier library?

Thank you very much and sorry for the double post

Best regards

Davide C.

Hi Davide,

That’s indeed possible and it’s quite easy as well. All you need to do is set your classpath in flash to the source folder (included in the download from above). Once that is done you can import my custom classes and use them within the Flash IDE. I’ve send you an e-mail with an example of this.

Paul

well im not a actionscript coder but i was looking for something like this. it worked perfect. thank u.

Is there a way to split a quadratic bezier into smaller parts WITH EQUAL LENGTHS??

That too in AS2

There are some very complicated math equations… I was hoping a simpler way is possible… basically for constant motion along a quad bezier path

http://www.youtube.com/watch?v=jEjZl2nqcAU

I think this lecture “The Marriage of Fractals and Splines” may be relevant. He talks about a spline subdivision method into line segments that rapidly converge to the curve.

On Nov 2008, you wrote:

“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.”

Coming a bit late, but try this: http://www.caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html (adaptive splitting: at the same precision, results in smaller quad segs that half-subdivision)

Regards,

Adrian

Paul… many thanks for this beautifully clear explanation of the cubic Bezier! It was extremely useful and a breeze to follow and adapt.

Regards,

Tim

Good and useful post.

Hi Adrian,

Due to the writing of my book I’ve not been able yet to create an updated class, so your comment is still of use. The page you refer to seems very helpful and is definitely worth looking at once I start working on this.

Thanks!

Paul

can you please tell me how to calculate the control points as you have mentioned in your above example?

I tried using my own maths logic and the result came out nothing as i expected.

My assumptions :

1) Every curve(in my case a s curve) between 2 points is made up of 2 simple curves. and it intersects the straight line between the 2 points at its midpoint.

2) The controlpoint is the point where the tangents of the single curve meet.

so to calculate the control point i use a simple triangle equation where 2 sides of the triangle are my tangents to the curve and the third side is half of line joining the 2 points. to calculate the angle i use the 2 point slope formula and after calculating the control points coordinates; i use it in the equation you mentioned draw a curve.

please tell me where i am going wrong,

thanks and regards

Vikram

Hi Paul,

thank you very much for this example-tutorial.

Any ideas or guides on how we can place some movieclips at equal distances along the curve’s length?

Hi,

if i want to display the sprite in mxml file which calls this actionscript class’s function.

how to do?

regards,

Risabh

I want to have Flash AS3 produce 3 curly lines of “aroma” coming out of a perfume bottle for my opening page on my perfumery website. The idea is to have the lines grow over three or four seconds from zero to full length. They should curl out and up like stylized “smoke.”

I know this is very doable, but I just can’t seem to find out where to begin. I’ve already drawn the bezier lines out in Illustrator as guides.

This means that the entire information for producing the lines already exists, including directionality, although not the delayed time I want. Perhaps the formulas for the lines could be gotten somehow straight from Illustrator?

Dear sir ,

By doing some modification in your code i have created a closed shape by Quadratic bezier curve ,and fill it by beginFill method,but the closed shape is not filled with color,it is filled in bezier curve with straight line.the internal area is not filled,

Kindly help me.

I need too much in my project .Thanks in advance…………………………………………………………………………….

Hello Paul,

better late than never: you must find the tangents through the bezier at each of your steps. The intersection-point of the tangent and its predecessors tangent is the control-point for your quadratic approximated segment. See http://www.eleqtriq.com/2010/04/cubic-bezier-in-flash/

Awesome Article.

This is how I optimize the number of steps needed in drawing the curve.

What i have done is calculated the distance between the points of the handles and also the distance between the start point and end point you are going to. Then taking the longest distance of those and using that to determine how many steps to use. I then ended up dividing by 10 to give it just enough steps. I can then kind of see some sharp edges, but only at a couple of angles.

It works really well that if it is a longer string then it does more points and then a shorter one it does less rather than plugging in a fixed value of 100 points that just overlap each other if they are too close.

Point.distance(pointA,pointB); // this is how you calculate distance between points in AS3

Hey there,

Thanks for all your help with this. I came to the same conclusions as you did, in terms of dividing the curve into points to which join them with lines.

If you want to join them with a curveTo that is almost perfect, the code should look like this:

curve_sp.graphics.curveTo(p1_2.x*2-p0.x/2-p1.x/2, p1_2.y*2-p0.y/2-p1.y/2, p1.x, p1.y);

Where:

p0 is the point of orgin,

p1 is the destination anchor point

p1_2 is a point on the cubic bezier curve that is exactly 1/2 way from p0 – p1

Hope this helps anyone who was looking for that solution as I was.

I love it, thanks for sharing! Good explanation as well.

Hi, beatiful code.. but i have a problem.. i need fill the bezier curve.. that is posible?

Thanks

Thanks a ton Paul for this amazing algorithm. I was having problem converting 2 control point bezier data to flex recognizable (1control point format) data. This algorithm works very smoothly

You can use the built-in cubicCurveTo() method.

You give it two control points and the anchor point.

Thanks for pointing this out Alex. As of Flash Player 11, this is indeed part of the AS3 API.

Could you provide source code as a plain text please

I relish, result in I found exactly what I used to be looking for.

You’ve ended my four day lengthy hunt! God Bless you man. Have a nice day.

Bye

Good information. Lucky me I recently found your site

by chance (stumbleupon). I’ve saved it for later!