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);
			}
		}
		
	}
}

 
 
 

Leave a Reply