eleqtriq

This is my technique of drawing cubic Bezier-curves in Flash. If you are new to cubic and quadratic bezier-curves, you should check wikipedia first.

Show Example

One drawback of flash is its inability to display cubic bezier curves. If you draw cubic curves manually in the Flash-IDE, it will be spliced into several segments and the cubic curve will be approximated from a number of quadratic bezier curves (most designers run into this sooner or later: draw a simple bezier-curve with 3 or few anchors to the stage. Deselect and select again. Suddenly you will find your shape splitted into a number of segments). If you draw a curve by calling actionscript's drawing-api, there simply is no other option than the quadratic "curveTo()"-method anyway, offering a start- and an endpoint but only one lousy quadratic control-point.

Generic Midpoint Approximation

The common way to deal with this problem is a technique called "generic midpoint-approximation". There are some classes around, that use this technique to trick flash into displaying cubic bezieres. The basics behind this technique can be seen in the diagram to the left. Basically it is an algorithm for splicing a cubic bezier into 4 quadratic segments. Anyway this method comes at a cost, mainly a lack of precision. You won't notice in most situations, but sometimes (curve extremely steep, self-intersecting, etc.) the method produces somehow "bumpy" results. It is not the best solution for all use-cases.

The good news: it has not been noticed widely, but flash indeed *has* a class for cubic bezieres. It is called "BezierSegment" and is buried deeply within the "fl.motion" package. The bad news: it is not intended for being drawn to the stage, but for animations via actionscript. But with some tweaking and tinkering we will be able to force it into displaying high precision cubic bezieres on the stage as well.

Drawing A Cubic Bezier with BezierSegment-Class:

1. Import the class:

import fl.motion.BezierSegment;

2. Create a cubic bezierSegment:

var bezier:BezierSegment=new BezierSegment(point_1, control_1, point_2, control_2);

3. split the segment into slices

The coordinates of a point on the BezierSegment can be determined with its getValue(t:Number)-Method. t interpolates a value on the bezier, with t=1 the maximum possible value. I. e. if we want to find the value of our bezier at 50% we simply call:

var val:Point=bezier.getValue(0.5)

Is that cool?

Example: dotted line:

Lets try something easy: a dotted line. First we determine a resolution, lets say 20. All we have to do now is draw a circle every (1/20)th position:

Sorry, no Flash
var resolution:uint=20; var step:Number =1/resolution; var t:Number=0; while(t<=1){ var pos:Point=bezier.getValue(t); with(this.graphics){ beginFill(0x990000, 1); drawCircle(pos.x, pos.y, 5); endFill; } t+=step; }

The result is a nice dotted line.

O. k, you gave me a dotted line. Cool. But how about connecting the dots?

Slicing BezierSegment

This is the tricky part: If we want to connect the dots with curves, we need the coordinates for a quadratic control-point. Here is how to find it:

1. determine the tangents of the beginning-point of our slice and of the end-point of our slice. This is achieved with the help of the so called Decasteljau-Algorithm.

2. find the intersection-point of the tangents and

3. use this intersection-point as the control point of our quadratic-segment.

BezierSegment Slicing-Error

In some situations, when the curve is too weird and the resolution is too low, we have to divide our segment once more. Afterwards we must check again and slice the segments until we found the right intersection-point. How do we Know wether the intersection point is calculated correctly? The distance point1-handle or point2-handle may not be greater then the distance point1-point2.

Finally we've got a nice class for drawing very precise cubic bezier-curves in flash. Check out the example where you can play with a motion-bezier and a GMP-Bezier at the same time. Of course we have to pay for the higher precision with more computations. But it is in your hand to set the resolution to the lowest necessary value. And besides its smoother appearance it has other advantages. For example there exist several more or less complicated interpolation-methods for finding intersections of bezier-curves. But as we already do have a number of segments, we can use a brute force-Method by looping through all our segments, check if some bounding-boxes intersect, Split up our segments again, loop again until we are close enough to a valid intersection-point.

Show Source

If you want to play with the code, download the source files here. As always, I don't give any warrantys and it is not allowed to use my code for building cruise-missiles or tormenting hamsters. Have fun!

Trackback

2 Responses to “Cubic Bezier in Flash”

  1. Comment by Daniel Fri Sep 10th, 2010, 04:23

    Beautifull !… congratulations !.

    Daniel.

  2. Comment by Eke Wed Apr 20th, 2011, 13:21

    Thanks, it helped me a lot :)