Filled Arc’s anyone?
February 28th, 2005
I’ve always loved arc’s, especially in images like this one.

I remember seeing Sci-fi imagery from the 60’s and 70’s with patterns similar to these and I always wondered where they first originated.
Anyway, after playing with Ric Ewing’s advanced drawing API methods for a while I decided I wanted a means of drawing these filled arc shapes, and the draw wedge method was tantalizingly close, so I had a little play with it this afternoon and here’s what I came up with.
The code is fully AS2.0 compliant so you can just drop it into a DrawingMethods class if you have one. There’s nothing wrong with just running it from the timeline either if you’re so inclined.
I’ve also put a little example code at the bottom which will draw images like the one above. I’m also working on a little animated demo which I’ll post up quite soon.
Enjoy.
/*
Function: drawFilledArc
Description:
Draws filled Arc shapes (with interior and exterior radius)
Author: Jason Milkins jason@mentalaxis.com | <http ://www.mentalaxis.com>
Version: 1.0
Note:
Based on code by Ric Ewing </http><http ://www.ricewing.com>
Parameters:
mc - MovieClip target to draw in
x, y - center point of the wedge.
startAngle - starting angle in degrees.
arc - sweep of the wedge. Negative values draw clockwise.
exteriorRadius - exterior radius of wedge.
interiorRadius - interior radius of wedge.
Note:
Comments formatted for NaturalDocs
*/
function drawFilledArc (mc, x, y, startAngle, arc, exteriorRadius, interiorRadius ) : Void
{
// if yRadius is undefined, yRadius = radius
// Init vars
var segAngle_a, segAngle_b, theta_a, theta_b, angle, angleMid, segs, ax, ay, bx, by, cx, cy, dx, dy;
// limit sweep to reasonable numbers
if (Math.abs (arc) > 360)
{
arc = 360;
}
// Flash uses 8 segments per circle, to match that, we draw in a maximum
// of 45 degree segments. First we calculate how many segments are needed
// for our arc.
segs = Math.ceil (Math.abs (arc) / 45);
// Now calculate the sweep of each segment.
segAngle_a = arc / segs
segAngle_b = -arc / segs;
// The math requires radians rather than degrees. To convert from degrees
// use the formula (degrees/180)*Math.PI to get radians.
theta_a = - (segAngle_a / 180) * Math.PI;
theta_b = - (segAngle_b / 180) * Math.PI;
// convert angle startAngle to radians
angle = - (startAngle / 180) * Math.PI;
// draw the curve in segments no larger than 45 degrees.
if (segs > 0)
{
// draw a line from the end of the interior curve to the start of the exterior curve
ax = x + Math.cos (startAngle / 180 * Math.PI) * exteriorRadius;
ay = y + Math.sin ( - startAngle / 180 * Math.PI) * exteriorRadius;
mc.moveTo (ax, ay);
// Loop for drawing exterior curve segments
for (var i = 0; i < segs; i ++)
{
angle += theta_a;
angleMid = angle - (theta_a / 2);
bx = x + Math.cos (angle) * exteriorRadius;
by = y + Math.sin (angle) * exteriorRadius;
cx = x + Math.cos (angleMid) * (exteriorRadius / Math.cos (theta_a / 2));
cy = y + Math.sin (angleMid) * (exteriorRadius / Math.cos (theta_a / 2));
mc.curveTo (cx, cy, bx, by);
}
// draw a line from the end of the exterior curve to the start of the interior curve
startAngle += arc;
angle = - (startAngle / 180) * Math.PI;
// draw the interior (subtractive) wedge
// draw a line from the center to the start of the interior curve
dx = x + Math.cos (startAngle / 180 * Math.PI) * interiorRadius;
dy = y + Math.sin ( - startAngle / 180 * Math.PI) * interiorRadius;
mc.lineTo (dx, dy);
// Loop for drawing interior curve segments
for (var i = 0; i < segs; i ++)
{
angle += theta_b;
angleMid = angle - (theta_b / 2);
bx = x + Math.cos (angle) * interiorRadius;
by = y + Math.sin (angle) * interiorRadius;
cx = x + Math.cos (angleMid) * (interiorRadius / Math.cos (theta_b / 2));
cy = y + Math.sin (angleMid) * (interiorRadius / Math.cos (theta_b / 2));
mc.curveTo (cx, cy, bx, by);
}
mc.lineTo (ax, ay);
}
}
And here’s the demo code…
my_mc = _root.createEmptyMovieClip ("poop", 100);
my_mc.i = 0;
my_mc.inc = 20;
my_mc.cenX = 350;
my_mc.cenY = 350;
innerRad = 20 + (Math.random () * 150);
my_mc.onEnterFrame = function ()
{
if (Math.random () * 100 < 10)
{
my_mc.clear ();
for (n = 0; n < 10; n ++)
{
innerRad = 20 + (Math.random () * 150)
my_mc.lineStyle(2, 0x000000, 10);
my_mc.beginFill (0xAA0000, 20 + (Math.random () * 60));
drawFilledArc (my_mc, my_mc.cenX, my_mc.cenY, Math.random () * 360 , - Math.random () * 360 , innerRad, innerRad + (Math.random () * 40) + 4);
my_mc.endFill ();
}
}
}
can you Digg it?
is it del.icio.us? 
Category: General



1 Comment Add your own
1. Jason Milkins | February 28th, 2009 at 8:23 am
Should’ve mentioned, paste both bits of code onto the timeline (frame 1) and test the flash movie…
Re run the movie for a new pattern.
Leave a Comment
You must be logged in to post a comment .
Trackback this post | Subscribe to the comments via RSS Feed