Drawing a perfect circle with the .curveTo function

This article is about Actionscript and was originally posted on my personal blog 6 years ago.

I’m guessing most of you already know what the graphics.curveTo function is. As the name suggests, it allows you to draw a curved line that starts at a certain point, bends towards a control point, and ends in an anchor point. The starting point of the curve can be defined in three ways:

  • undefined: the default starting point will be (0,0)
  • the last anchor point: this will be the default starting point when you’ve already drawn a curve. this overrides the default point above.
  • using the moveTo method: you set the starting point by using graphics.moveTo(x,y). this method overrides all of the above.

After leaving the starting point, the curve will work its way to the Control point, and then curve to the Anchor point. That’s basically what curveTo() does.

So why would you draw a circle with the curveTo function when you can just use drawCircle ? One answer to this question is that it’s just fun to experiment with these things in flash, another answer is that when you dynamically draw a circle using this method, you can animate the different points that make up the circle and create even weirder shapes.

First thing we have to do is define all our Anchor points. Since we are drawing a circle, it would be helpful if the anchor points were nicely aligned in a circular fashion. One way to align pretty much everything in a circular order is working with sine and cosine, but right now I would like to try this another way, namely using the Point.polar() method. (no worries, we’ll be needing our trigonometric friends later on).

The polar() function works with polar coordinates, as opposed to cartesian coordinates that are standard in flash. The main idea behind the Polar coordinate system is that instead of working with an X and Y position to define a point, you work with an angle and a distance. The distance tells you how far this point is removed from the Pole (the fixed point in the system) and the angle tells you the angle of the point relative to a horizontal line going through the Pole.

So, if you want to draw a 100 points that are all on the edge of a perfect circle with radius 10, the polar coordinates for the first five points will be:

the Point.polar() method has 2 parameters, the first being the distance to the Pole, the second being the angle (in radians). The method then returns a Point object with the corresponding cartesian coordinates, and this allows you to draw this point on the screen in Flash. so, drawing all of our points (in this case a circle with radius 1) will go as follows:

this.graphics.beginFill(0);
for (var i:int = 0; i < numberOfPoints; i++)
{
var p:Point = Point.polar(10,2*Math.PI * i/numberOfPoints);
this.graphics.drawCircle(p.x,p.y,1);
}
this.graphics.endFill();

Now that I’ve made it clear how to draw the Anchor points in a circular method, all that is left is drawing the Control points. The Control Points will make sure that the curves between the anchor points form a nice circle. We’ll use some trigonometry from back in the high school days to find their coordinates. Because we will also use the Point.polar() method, all we need to do to find the coordinates, is the distance from the Control Points to the center. We can then re-use the for-loop above, with the adjusted distance to the Pole.

We can establish that the COS(delta/2) = r / |AB|. Thanks to this, we can calculate |AB|. the line AB is the angle bisector of Delta (meaning AB splits the angle Delta in 2 evenly divided parts). Point B is where the 2 Perpendicular lines meet with each other AND with the bisector -We are not going into specifics as to why this is, but feel free to prove this yourself :) .

This leaves us with |AB|, the distance from the center of our circle to every Control Point. All that we need to do now is plot these points next to each other and draw Curves through them. Take a look at the following code to see what you need to draw a Circle with 10 Control Points and be amazed when you see how fluid the circle appears.

public class APC extends MovieClip {
	private var ControlPoints:Array = [];
private var AttachPoints:Array = [];
private var diameter:int = 100;
private var Points:int = 10;
	public function APC() {
var xx:int = stage.stageWidth/2;
var yy:int = stage.stageHeight / 2;
var outerDiameter:Number = diameter / Math.cos(Math.PI / Points);
		for (var i:int = 0; i < Points; i++)
{
var Ap:Point = Point.polar(diameter, i * 2 * Math.PI / Points);
var Cp:Point = Point.polar(outerDiameter, i * 2 * Math.PI / Points + (Math.PI / Points ));
Ap.x += xx;
Ap.y += yy;
Cp.x += xx;
Cp.y += yy;
AttachPoints.push(Ap);
ControlPoints.push(Cp);
}
		drawStuff();
}
	private function drawStuff():void
{
this.graphics.beginFill(0);
this.graphics.moveTo(AttachPoints[0].x, AttachPoints[0].y);
for (var i:int = 0; i < Points-1; i++)
{
this.graphics.curveTo(ControlPoints[i].x, ControlPoints[i].y, AttachPoints[i+1].x, AttachPoints[i+1].y);
}
this.graphics.curveTo(ControlPoints[Points-1].x, ControlPoints[Points-1].y, AttachPoints[0].x, AttachPoints[0].y);
this.graphics.endFill();
}
}

Like this post ? Follow me on Twitter !

Like what you read? Give Jaaq Jorissen a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.