Index: lams_common/src/flash/com/polymercode/Draw.as
===================================================================
diff -u
--- lams_common/src/flash/com/polymercode/Draw.as (revision 0)
+++ lams_common/src/flash/com/polymercode/Draw.as (revision f21f23f651433de36707cac2e3962e0567626d81)
@@ -0,0 +1,639 @@
+/**
+ * Draw is a static toolbox class that provides a number of functions
+ * to draw shapes that are not part of the standard ActionScript Drawing
+ * API.
+ *
+ * To call this code from the timeline you must include this class in the
+ * classpath in the publish settings menu.
+ *
+ * File -> Publish Settings (Ctrl+Shift+F12 on windows)
+ * - Click "Flash" tab
+ * - Set ActionScript Version to "ActionScript 2.0" or higher...
+ * - Click "Settings"
+ * - click the target icon and select the directory you've extracted
+ * - this code into. You should select the directory that has
+ * - the com directory in it. NOT the directory
+ * - that has the Draw.as file.
+ *
+ * based on source code found at:
+ * http://www.macromedia.com/devnet/mx/flash/articles/adv_draw_methods.html
+ *
+ * @author Ric Ewing - version 1.4 - 4.7.2002
+ * @author Kevin Williams - version 2.0 - 4.7.2005
+ */
+class com.polymercode.Draw
+{
+ /**
+ *
+ * This class has all static functions. To call them simply call
+ * com.polymercode.Draw.functionName(parameters);
+ *
+ * You should never have to call new Draw();
+ *
+ */
+ private function Draw(){}
+
+ /**
+ * dashTo
+ * Draws a dashed line from the point x1,y1 to the point x2,y2
+ * The line may is drawn on the movie clips specified by the
+ * target parameter (default is _root). The line may
+ * be any color or transparency and width, length of dashes,
+ * and space between dashes may all be specified.
+ *
+ * @param target MovieClip the movie clip on which the dashed
+ * line will be drawn.
+ * @param x1 Number starting position on x axis - required
+ * @param y1 Number starting position on y axis - required
+ * @param x2 Number finishing position on x axis - required
+ * @param y2 Number finishing position on y axis - required
+ * @param dashLength [optional] Number the number of pixels long each dash
+ * will be. Default = 5
+ * @param spaceLength [optional] Number the number of pixels between each
+ * dash. Default = 5
+ * @param strokWidth [optional] Number the width of each dash.
+ * Default = 1
+ * @param rgbHex [optional] the Hex color value of the dashed line.
+ * Default = 0x000000
+ * @param alpha [optional] Number the alpha transparancy that the dashed
+ * line will have. Default = 100;
+ */
+ public static function dashTo(target:MovieClip, x1:Number,
+ y1:Number,x2:Number, y2:Number, dashLength:Number,
+ spaceLength:Number,strokeWidth:Number,rgbHex:Number ):Void
+ {
+ trace("com.polymercode.Draw.dashTo - arguments:"+arguments.toString());
+ if ( arguments < 5 ){
+ trace("com.polymercode.Draw.dashTo - too few parameters.");
+ return;
+ }
+ if ( spaceLength == undefined )
+ spaceLength = 5;
+ if ( dashLength == undefined )
+ dashLength = 5;
+
+ //added to this
+ target.lineStyle(strokeWidth,rgbHex);
+
+ var x = x2 - x1;
+ var y = y2 - y1;
+ var hyp = Math.sqrt((x)*(x) + (y)*(y));
+ var units = hyp/(dashLength+spaceLength);
+ var dashSpaceRatio = dashLength/(dashLength+spaceLength);
+ var dashX = (x/units)*dashSpaceRatio;
+ var spaceX = (x/units)-dashX;
+ var dashY = (y/units)*dashSpaceRatio;
+ var spaceY = (y/units)-dashY;
+ target.moveTo(x1, y1);
+ while (hyp > 0) {
+ x1 += dashX;
+ y1 += dashY;
+ hyp -= dashLength;
+ if (hyp < 0) {
+ x1 = x2;
+ y1 = y2;
+ }
+ target.lineTo(x1, y1);
+ x1 += spaceX;
+ y1 += spaceY;
+ target.moveTo(x1, y1);
+ hyp -= spaceLength;
+ }
+ target.moveTo(x2, y2);
+ }
+
+
+ /**
+ * Draws an arc from the starting position of x,y.
+ *
+ * @param target the movie clip that the Arc is drawn on.
+ * @param x x coordinate of the starting pen position
+ * @param y y coordinate of the starting pen position
+ * @param radius radius of Arc.
+ * @param arc = sweep of the arc. Negative values draw clockwise.
+ * @param startAngle = [optional] starting offset angle in degrees.
+ * @param yRadius = [optional] y radius of arc. if different than
+ * radius, then the arc will draw as the arc of an oval.
+ * default = radius.
+ *
+ * Based on mc.drawArc by Ric Ewing.
+ * the version by Ric assumes that the pen is at x:y before this
+ * method is called. I explictily move the pen to x:y to be
+ * consistent with the behaviour of the other methods.
+ */
+ public static function arcTo(target:MovieClip, x:Number,
+ y:Number, radius:Number, arc:Number, startAngle:Number,
+ yRadius:Number):Void
+ {
+ if (arguments.length<5) {
+ trace("com.polymercode.Draw.arcTo - too few parameters.");
+ return;
+ }
+
+ // if startAngle is undefined, startAngle = 0
+ if( startAngle == undefined ){
+ startAngle = 0;
+ }
+ // if yRadius is undefined, yRadius = radius
+ if (yRadius == undefined) {
+ yRadius = radius;
+ }
+
+ // Init vars
+ var segAngle, theta, angle, angleMid, segs, ax, ay, bx, by, cx, cy;
+ // no sense in drawing more than is needed :)
+ 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 = arc/segs;
+ // The math requires radians rather than degrees. To convert from degrees
+ // use the formula (degrees/180)*Math.PI to get radians.
+ theta = -(segAngle/180)*Math.PI;
+ // convert angle startAngle to radians
+ angle = -(startAngle/180)*Math.PI;
+ // find our starting points (ax,ay) relative to the secified x,y
+ ax = x-Math.cos(angle)*radius;
+ ay = y-Math.sin(angle)*yRadius;
+ // if our arc is larger than 45 degrees, draw as 45 degree segments
+ // so that we match Flash's native circle routines.
+ if (segs>0) {
+ target.moveTo(x,y);
+ // Loop for drawing arc segments
+ for (var i = 0; i2) {
+ // init vars
+ var step, halfStep, qtrStep, start, n, dx, dy, cx, cy;
+ // calculate length of sides
+ step = (Math.PI*2)/sides;
+ halfStep = step/2;
+ qtrStep = step/4;
+ // calculate starting angle in radians
+ start = (angle/180)*Math.PI;
+ target.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius));
+ // draw curves
+ for (n=1; n<=sides; n++) {
+ cx = x+Math.cos(start+(step*n)-(qtrStep*3))*(innerRadius/Math.cos(qtrStep));
+ cy = y-Math.sin(start+(step*n)-(qtrStep*3))*(innerRadius/Math.cos(qtrStep));
+ dx = x+Math.cos(start+(step*n)-halfStep)*innerRadius;
+ dy = y-Math.sin(start+(step*n)-halfStep)*innerRadius;
+ target.curveTo(cx, cy, dx, dy);
+ cx = x+Math.cos(start+(step*n)-qtrStep)*(innerRadius/Math.cos(qtrStep));
+ cy = y-Math.sin(start+(step*n)-qtrStep)*(innerRadius/Math.cos(qtrStep));
+ dx = x+Math.cos(start+(step*n))*outerRadius;
+ dy = y-Math.sin(start+(step*n))*outerRadius;
+ target.curveTo(cx, cy, dx, dy);
+ }
+ }
+ }
+
+ /**
+ * draws a gear shape on the MovieClip target. The gear position
+ * is indicated by the x and y arguments.
+ *
+ * @param target MovieClip on which the gear is to be drawn.
+ * @param x x coordinate of the center of the gear
+ * @param y y coordinate of the center of the gear
+ * @param sides number of teeth on gear. (must be > 2)
+ * @param innerRadius radius of the indent of the teeth.
+ * @param outerRadius outer radius of the teeth.
+ * @param angle = [optional] starting angle in degrees. Defaults to 0.
+ * @param holeSides [optional] draw a polygonal hole with this many sides (must be > 2)
+ * @param holeRadius [optional] size of hole. Default = innerRadius/3.
+ *
+ * based on mc.drawGear() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002
+ */
+ public static function gear(target:MovieClip, x:Number, y:Number,
+ sides:Number, innerRadius:Number, outerRadius:Number,
+ angle:Number, holeSides:Number, holeRadius:Number ):Void
+ {
+ if(arguments<6){
+ trace("com.polymercode.Draw.gear - too few parameters");
+ return;
+ }
+ if ( angle == undefined )
+ angle = 0;
+ if ( holeSides == undefined )
+ holeSides = 0;
+
+ if (sides>2) {
+ // init vars
+ var step, qtrStep, start, n, dx, dy;
+ // calculate length of sides
+ step = (Math.PI*2)/sides;
+ qtrStep = step/4;
+ // calculate starting angle in radians
+ start = (angle/180)*Math.PI;
+ target.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius));
+ // draw lines
+ for (n=1; n<=sides; n++) {
+ dx = x+Math.cos(start+(step*n)-(qtrStep*3))*innerRadius;
+ dy = y-Math.sin(start+(step*n)-(qtrStep*3))*innerRadius;
+ target.lineTo(dx, dy);
+ dx = x+Math.cos(start+(step*n)-(qtrStep*2))*innerRadius;
+ dy = y-Math.sin(start+(step*n)-(qtrStep*2))*innerRadius;
+ target.lineTo(dx, dy);
+ dx = x+Math.cos(start+(step*n)-qtrStep)*outerRadius;
+ dy = y-Math.sin(start+(step*n)-qtrStep)*outerRadius;
+ target.lineTo(dx, dy);
+ dx = x+Math.cos(start+(step*n))*outerRadius;
+ dy = y-Math.sin(start+(step*n))*outerRadius;
+ target.lineTo(dx, dy);
+ }
+ // This is complete overkill... but I had it done already. :)
+ if (holeSides>2) {
+ if(holeRadius == undefined) {
+ holeRadius = innerRadius/3;
+ }
+ step = (Math.PI*2)/holeSides;
+ target.moveTo(x+(Math.cos(start)*holeRadius), y-(Math.sin(start)*holeRadius));
+ for (n=1; n<=holeSides; n++) {
+ dx = x+Math.cos(start+(step*n))*holeRadius;
+ dy = y-Math.sin(start+(step*n))*holeRadius;
+ target.lineTo(dx, dy);
+ }
+ }
+ }
+ }
+
+ /**
+ * oval draws used to draw circles or ovals.
+ * According to Ric Ewing - This method, like most of
+ * the others, is not as optimized as it could be. This was a
+ * conscious decision to keep the code as accessible as
+ * possible for those either new to AS or to the math
+ * involved in plotting points on a curve.
+ *
+ * @param target the MovieClip that the oval/circle is drawn on.
+ * @param x x coordinate of the center of the oval/circle
+ * @param y y coordinate of the center of the oval/circle
+ * @param radius the radius of the oval/circle
+ * @param yRadius [optional] y radius of the oval. if not defined
+ * then yRadius = radius and therefore, it draws a circle.
+ *
+ * based on mc.drawOval() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002
+ */
+ public static function oval(target:MovieClip, x:Number, y:Number,
+ radius:Number, yRadius:Number):Void
+ {
+ if (arguments.length<4)
+ {
+ trace("com.polymercode.Draw.oval - too few parameters");
+ return;
+ }
+ // if only yRadius is undefined, yRadius = radius
+ if (yRadius == undefined) {
+ yRadius = radius;
+ }
+
+ // init variables
+ var theta, xrCtrl, yrCtrl, angle, angleMid, px, py, cx, cy;
+ // covert 45 degrees to radians for our calculations
+ theta = Math.PI/4;
+ // calculate the distance for the control point
+ xrCtrl = radius/Math.cos(theta/2);
+ yrCtrl = yRadius/Math.cos(theta/2);
+ // start on the right side of the circle
+ angle = 0;
+ target.moveTo(x+radius, y);
+ // this loop draws the circle in 8 segments
+ for (var i = 0; i<8; i++) {
+ // increment our angles
+ angle += theta;
+ angleMid = angle-(theta/2);
+ // calculate our control point
+ cx = x+Math.cos(angleMid)*xrCtrl;
+ cy = y+Math.sin(angleMid)*yrCtrl;
+ // calculate our end point
+ px = x+Math.cos(angle)*radius;
+ py = y+Math.sin(angle)*yRadius;
+ // draw the circle segment
+ target.curveTo(cx, cy, px, py);
+ }
+ }
+
+ /**
+ * a method for creating polygon shapes. Negative values will draw
+ * the polygon in reverse direction. Negative drawing may be useful
+ * for creating knock-outs in masks.
+ *
+ * @param target the MovieClip that the polygon is to be drawn on
+ * @param x x coordinate of the center of the polygon
+ * @param y y coordinate of the center of the polygon
+ * @param sides the number of sides (must be > 2)
+ * @param radius the radius from the center point to the points
+ * on the polygon
+ * @param angle [optional] the starting offset angle (degrees) from
+ * 0. Default = 0
+ *
+ * based on mc.drawPoly() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002
+ */
+ public static function polygon(target:MovieClip, x:Number,
+ y:Number, sides:Number, radius:Number, angle:Number):Void
+ {
+ if (arguments.length<5)
+ {
+ trace("com.polymercode.Draw.polygon - too few parameters");
+ return;
+ }
+ if ( angle == undefined )
+ angle = 0;
+
+ // convert sides to positive value
+ var count = Math.abs(sides);
+ // check that count is sufficient to build polygon
+ if (count>2) {
+ // init vars
+ var step, start, n, dx, dy;
+ // calculate span of sides
+ step = (Math.PI*2)/sides;
+ // calculate starting angle in radians
+ start = (angle/180)*Math.PI;
+ target.moveTo(x+(Math.cos(start)*radius), y-(Math.sin(start)*radius));
+ // draw the polygon
+ for (n=1; n<=count; n++) {
+ dx = x+Math.cos(start+(step*n))*radius;
+ dy = y-Math.sin(start+(step*n))*radius;
+ target.lineTo(dx, dy);
+ }
+ }
+ }
+
+ /**
+ * roundedRectangle draws rectangles with rounded corners.
+ * This is similar to the Flash rectangle tool. If the
+ * rectangle is smaller in either dimension than the
+ * rounding permits then rounding is scaled down to fit
+ *
+ * @param target the MovieClip that the rouded rectangle is to be
+ * drawn on.
+ * @param x x coordinate of the top left corner of the rectangle
+ * @param y y coordinate of the top right corner of the rectangle
+ * @param width width of the rectangle
+ * @param height height of the rectangle
+ * @param cornerRadius the radius of the rounding of the corners of
+ * the rectangle. [optional]
+ *
+ * based on mc.drawRect() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002
+ */
+ public static function roundedRectangle(target:MovieClip,
+ x:Number, y:Number, width:Number, height:Number,
+ cornerRadius:Number ):Void
+ {
+ if ( arguments.length<5 )
+ {
+ trace("com.polymercode.Draw.roundedRectangle - too few parameters");
+ return;
+ }
+ if ( cornerRadius == undefined )
+ cornerRadius = 0;
+
+ // if the user has defined cornerRadius our task is a bit more complex. :)
+ if (cornerRadius>0) {
+ // init vars
+ var theta, angle, cx, cy, px, py;
+ // make sure that w + h are larger than 2*cornerRadius
+ if (cornerRadius>Math.min(width, height)/2) {
+ cornerRadius = Math.min(width, height)/2;
+ }
+ // theta = 45 degrees in radians
+ theta = Math.PI/4;
+ // draw top line
+ target.moveTo(x+cornerRadius, y);
+ target.lineTo(x+width-cornerRadius, y);
+ //angle is currently 90 degrees
+ angle = -Math.PI/2;
+ // draw tr corner in two parts
+ cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+
+ target.curveTo(cx, cy, px, py);
+ angle += theta;
+ cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+ target.curveTo(cx, cy, px, py);
+ // draw right line
+ target.lineTo(x+width, y+height-cornerRadius);
+ // draw br corner
+ angle += theta;
+ cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+ target.curveTo(cx, cy, px, py);
+ angle += theta;
+ cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+ target.curveTo(cx, cy, px, py);
+ // draw bottom line
+ target.lineTo(x+cornerRadius, y+height);
+ // draw bl corner
+ angle += theta;
+ cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+ target.curveTo(cx, cy, px, py);
+ angle += theta;
+ cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+ target.curveTo(cx, cy, px, py);
+ // draw left line
+ target.lineTo(x, y+cornerRadius);
+ // draw tl corner
+ angle += theta;
+ cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+ target.curveTo(cx, cy, px, py);
+ angle += theta;
+ cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2));
+ px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius);
+ py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius);
+ target.curveTo(cx, cy, px, py);
+ } else {
+ // cornerRadius was not defined or = 0. This makes it easy.
+ target.moveTo(x, y);
+ target.lineTo(x+width, y);
+ target.lineTo(x+width, y+height);
+ target.lineTo(x, y+height);
+ target.lineTo(x, y);
+ }
+ }
+
+ /**
+ * start draws a star shaped polygon.
+ *
+ * Note that the stars by default 'point' to
+ * the right. This is because the method starts drawing
+ * at 0 degrees by default, putting the first point to
+ * the right of center. Negative values for points
+ * draws the star in reverse direction, allowing for
+ * knock-outs when used as part of a mask.
+ *
+ * @param x x coordinate of the center of the star
+ * @param y y coordinate of the center of the star
+ * @param points the number of points on the star
+ * @param innerRadius the radius of the inside angles of the star
+ * @param outerRadius the radius of the outside angles of the star
+ * @param angle [optional] the offet angle that the start is rotated
+ * @param target the MovieClip that the star is drawn on
+ *
+ * based on mc.drawStar() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002
+ */
+ public static function star(target:MovieClip, x:Number, y:Number,
+ points:Number, innerRadius:Number, outerRadius:Number,
+ angle:Number ):Void
+ {
+ if( arguments.length < 6)
+ {
+ trace("com.polymercode.Draw.star - too few parameters");
+ return;
+ }
+ if( angle == undefined )
+ angle = 0;
+
+ var count = Math.abs(points);
+ if (count>2) {
+ // init vars
+ var step, halfStep, start, n, dx, dy;
+ // calculate distance between points
+ step = (Math.PI*2)/points;
+ halfStep = step/2;
+ // calculate starting angle in radians
+ start = (angle/180)*Math.PI;
+ target.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius));
+ // draw lines
+ for (n=1; n<=count; n++) {
+ dx = x+Math.cos(start+(step*n)-halfStep)*innerRadius;
+ dy = y-Math.sin(start+(step*n)-halfStep)*innerRadius;
+ target.lineTo(dx, dy);
+ dx = x+Math.cos(start+(step*n))*outerRadius;
+ dy = y-Math.sin(start+(step*n))*outerRadius;
+ target.lineTo(dx, dy);
+ }
+ }
+ }
+
+ /**
+ * draws pie shaped wedges. Could be employeed to draw pie charts.
+ *
+ * @param target the MovieClip on which the wedge is to be drawn.
+ * @param x x coordinate of the center point of the wedge
+ * @param y y coordinate of the center point of the wedge
+ * @param startAngle the starting angle in degrees
+ * @param arc the sweep of the wedge. negative values draw clockwise
+ * @param radius the radius of the wedge
+ * @param yRadius [optional] the y axis radius of the wedge.
+ * If not defined, then yRadius = radius.
+ *
+ * based on mc.drawWedge() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002
+ */
+ public static function wedge(target:MovieClip, x:Number, y:Number,
+ startAngle:Number, arc:Number, radius:Number,
+ yRadius:Number):Void
+ {
+ if (arguments.length<5) {
+ trace("com.polymercode.Draw.wedge - too few parameters");
+ return;
+ }
+ // move to x,y position
+ target.moveTo(x, y);
+ // if yRadius is undefined, yRadius = radius
+ if (yRadius == undefined) {
+ yRadius = radius;
+ }
+ // Init vars
+ var segAngle, theta, angle, angleMid, segs, ax, ay, bx, by, cx, cy;
+ // 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 = arc/segs;
+ // The math requires radians rather than degrees. To convert from degrees
+ // use the formula (degrees/180)*Math.PI to get radians.
+ theta = -(segAngle/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 center to the start of the curve
+ ax = x+Math.cos(startAngle/180*Math.PI)*radius;
+ ay = y+Math.sin(-startAngle/180*Math.PI)*yRadius;
+ target.lineTo(ax, ay);
+ // Loop for drawing curve segments
+ for (var i = 0; i