Flex4 Arc class (for Beta 2)
The Wedge FilledElement for Flex4 previously posted is not compatible with Flex4 Beta2.
The updated class (called Arc) is as follows.
package
{
import flash.display.Graphics;
import spark.primitives.Ellipse;
public class Arc extends Ellipse
{
public function Arc()
{
super();
}
private var _angle:Number = 0;
[Inspectable(category="General")]
/**
* Start angle for the wedge, in degrees. Zero degrees is 3 O'clock, or East.
*/
public function get angle():Number
{
return _angle;
}
public function set angle(value:Number):void
{
if (value != _angle)
{
_angle = value;
invalidateSize();
invalidateDisplayList();
invalidateParentSizeAndDisplayList();
}
}
private var _arc:Number = 0;
[Inspectable(category="General")]
/**
* Arc angle for the wedge, in degrees.
*/
public function get arc():Number
{
return _arc;
}
public function set arc(value:Number):void
{
if (value != _arc)
{
_arc = value;
invalidateSize();
invalidateDisplayList();
invalidateParentSizeAndDisplayList();
}
}
private var _thickness:Number = 0;
[Inspectable(category="General")]
/**
* Thickness of the wedge, measured inward from radius.
*/
public function get thickness():Number
{
return _thickness;
}
public function set thickness(value:Number):void
{
if (value != _thickness)
{
_thickness = value;
invalidateSize();
invalidateDisplayList();
invalidateParentSizeAndDisplayList();
}
}
private var _radius:Number = 0;
[Inspectable(category="General")]
/**
* Exterior radius of the wedge
*/
public function get radius():Number
{
return _radius;
}
public function set radius(value:Number):void
{
if (value != _radius)
{
_radius = value;
invalidateSize();
invalidateDisplayList();
invalidateParentSizeAndDisplayList();
}
}
override protected function draw(g:Graphics):void
{
var xo:Number = drawX + (width/2);
var yo:Number = drawY + (width/2);
var workingArc:Number = _arc;
// limit sweep to reasonable numbers
if (Math.abs(workingArc) > 360)
workingArc = 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.
var segs:Number = Math.ceil(Math.abs(workingArc) / 45);
// Now calculate the sweep of each segment.
var segAngle_a:Number = workingArc / segs
var segAngle_b:Number = -workingArc / segs;
// The math requires radians rather than degrees. To convert from degrees
// use the formula (degrees/180)*Math.PI to get radians.
var theta_a:Number = -(segAngle_a / 180) * Math.PI;
var theta_b:Number = -(segAngle_b / 180) * Math.PI;
// convert angle workingAngle to radians
var workingAngle:Number = _angle;
var angle:Number = -(workingAngle / 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
var workingRadius:Number = _radius;
var ax:Number = xo + Math.cos(workingAngle / 180 * Math.PI) * workingRadius;
var ay:Number = yo + Math.sin(-workingAngle / 180 * Math.PI) * workingRadius;
g.moveTo(ax, ay);
// Loop for drawing exterior curve segments
for (var i:int = 0; i < segs; i++)
{
angle += theta_a;
var angleMid:Number;
angleMid = angle - (theta_a / 2);
var bx:Number = xo + Math.cos(angle) * workingRadius;
var by:Number = yo + Math.sin(angle) * workingRadius;
var cx:Number = xo + Math.cos(angleMid) * (workingRadius / Math.cos(theta_a / 2));
var cy:Number = yo + Math.sin(angleMid) * (workingRadius / Math.cos(theta_a / 2));
g.curveTo(cx, cy, bx, by);
}
// draw a line from the end of the exterior curve to the start of the interior curve
workingAngle += workingArc;
angle = -(workingAngle / 180) * Math.PI;
// draw the interior (subtractive) wedge
// draw a line from the center to the start of the interior curve
var interiorRadius:Number = workingRadius - _thickness;
var dx:Number = xo + Math.cos(workingAngle / 180 * Math.PI) * interiorRadius;
var dy:Number = yo + Math.sin(-workingAngle / 180 * Math.PI) * interiorRadius;
g.lineTo(dx, dy);
// Loop for drawing interior curve segments
for (i = 0; i < segs; i++)
{
angle += theta_b;
angleMid = angle - (theta_b / 2);
bx = xo + Math.cos(angle) * interiorRadius;
by = yo + Math.sin(angle) * interiorRadius;
cx = xo + Math.cos(angleMid) * (interiorRadius / Math.cos(theta_b / 2));
cy = yo + Math.sin(angleMid) * (interiorRadius / Math.cos(theta_b / 2));
g.curveTo(cx, cy, bx, by);
}
g.lineTo(ax, ay);
}
}
}
}
