In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: Arc editing control

/**
 * Copyright flex_axis ( http://wonderfl.net/user/flex_axis )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/gOwr
 */

// forked from flex_axis's Arc editing control
package
{
	import flash.display.*;
	import flash.display.Stage;
	import flash.display.StageScaleMode;
	import flash.events.*;
	import flash.filters.GlowFilter;
	import flash.geom.*;
	import flash.text.*;
	
	public class Main extends Sprite 
	{
		private var frameBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
		private var bitmap:Bitmap;
		private var p0:ControlPoint;
		private var p1:ControlPoint;
		private var p2:ControlPoint;
		
		private var shape:Shape = new Shape();
		private var g:Graphics = shape.graphics;
		private var caption:TextField = new TextField();
		
		public function Main():void 
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			bitmap = new Bitmap(frameBuffer);
			addChild(bitmap);
			
			p0 = new ControlPoint(this, 200, 200, 0x888888);
			p1 = new ControlPoint(this, 100, 250, 0x99ff99);
			p2 = new ControlPoint(this, 130, 170, 0xff9999);
			
			caption.defaultTextFormat = new TextFormat("_sans", 10, 0x0044aa);
			caption.width = 0;
			caption.autoSize = TextFieldAutoSize.CENTER;
			caption.filters = [ new GlowFilter(0xffffff, .95, 8, 8, 20, 1) ];
			
			paint();
		}
		
		public function paint():void 
		{
			var v1:Point = sub(p1, p0);
			var v2:Point = sub(p2, p0);
			
			frameBuffer.fillRect(frameBuffer.rect, 0xffffff);
			
			g.clear();
			
			drawArrow(p0, p1, 0x00aa00);
			drawArrow(p0, p2, 0xaa0000);
			
			var startAngle:Number = getAngle(v1);
			var endAngle:Number = getAngle(v2);

			g.clear();
			g.beginFill(0x0044aa, 0.4);
			drawArc(p0, [distance(p0, p1), distance(p0, p2)], 0x0044aa, startAngle, endAngle);			
			g.endFill();			
			frameBuffer.draw(shape);
			
			drawCaption(format("{0}°", Math.round(toDegree(startAngle))), 
				midpoint(p0, p1));
			
			drawCaption(format("{0}°", Math.round(toDegree(endAngle))), 
				midpoint(p0, p2));
			
			/*
			drawCaption(format("{0}°\n[x:{1}, y:{2}]\n{3}", 
				Math.round(toDegree(startAngle)), p1.x, p1.y, distance(p0, p1).toFixed(0)), 
				midpoint(p0, p1));
			
			drawCaption(format("{0}°\n[x:{1}, y:{2}]\n{3}", 
				Math.round(toDegree(endAngle)), p2.x, p2.y, distance(p0, p2).toFixed(0)), 
				midpoint(p0, p2));
				*/
		}
		
		private function moveTo(p:Point):void
		{
			g.moveTo(p.x, p.y);
		}
		
		private function lineTo(p:Point):void
		{
			g.lineTo(p.x, p.y);
		}
		
		private function drawArrow(start:Point, end:Point, color:uint):void
		{
			g.clear();
			g.lineStyle(3, color, 1, false, "normal", null, JointStyle.MITER);
			moveTo(start);
			lineTo(end);
			
			var len:Number = distance(start, end);
			var arrowLen:Number = Math.min(len, 30) / 3;
			var arrowWidth:Number = arrowLen / 3;
			
			if (arrowLen > 0) {
				var v:Point = sub(end, start);
				var c:Point = sub(end, cut(v, arrowLen));
				var l:Point = add(c, cut(normal(v), arrowWidth));
				var r:Point = add(c, cut(normal(v), -arrowWidth));
				
				g.beginFill(color);
				moveTo(end);
				lineTo(l);
				lineTo(r);
				lineTo(end);
				g.endFill();
			}
			frameBuffer.draw(shape);
		}
		
		private function drawCaption(text:String, pos:Point):void
		{
			caption.text = text + "";
			var m:Matrix = new Matrix();
			m.translate(pos.x, pos.y - 12);
			frameBuffer.draw(caption, m);
		}
		
		private function drawArc(center:Point, radius:Array, color:uint, start:Number, end:Number):void
		{
			const SEGMENT:int = 128;
			g.lineStyle(0.5, color);
			for (var i:int = 0; i <= SEGMENT; i++) {
				var angle:Number = start + (end - start) * (i / SEGMENT);
				var p:Point = pointOnCircle(center, angle, radius[0]);
				if (i == 0) {
					moveTo(p);
					var o:Point = p;
				} else {
					lineTo(p);
				}
			}
			
			for (i=SEGMENT; i>=0; i--)  {
				angle = start +(end - start) * (i/SEGMENT);
				p = pointOnCircle(center, angle, radius[1]);
				lineTo(p);
			}
		}
	}
}

import flash.geom.Point;
import flash.display.*;
import flash.events.MouseEvent;

class ControlPoint extends Point
{
	private var main:Main;	
	private var sprite:Sprite = new Sprite();
	private var g:Graphics = sprite.graphics;
	
	function ControlPoint(_main:Main, _x:Number, _y:Number, color:uint)
	{
		main = _main;
		x = _x;
		y = _y;

		g.beginFill(color, 0.4);
		g.drawCircle(0, 0, 10);
		g.endFill();
		
		sprite.x = x;
		sprite.y = y;
		sprite.buttonMode = true;
		
		sprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
		sprite.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		
		main.addChild(sprite);
	}
	
	private function mouseDownHandler(e:MouseEvent):void 
	{
		main.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
	}
	
	private function mouseUpHandler(e:MouseEvent):void 
	{
		main.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
	}
	
	private function mouseMoveHandler(e:MouseEvent):void 
	{
		// Don't use drag, so we have more options to 
		// limit movement (instead of just a box.)
		x = sprite.x = main.mouseX;
		y = sprite.y = main.mouseY;		
		main.paint();
		e.updateAfterEvent();
	}
	
}

function toDegree(radian:Number):Number
{
	return radian * 180 / Math.PI;
}

function toRadian(degree:Number):Number
{
	return degree * Math.PI / 180;
}

function minus(v:Point):Point
{
	return new Point( -v.x, -v.y);
}

function normal(v:Point):Point
{
	return new Point(v.y, -v.x);
}

function norm(v:Point):Number
{
	return Math.sqrt(v.x * v.x + v.y * v.y);
}

function normalize(v:Point):Point
{
	return div(v, norm(v));
}

function add(n:Point, m:Point):Point
{
	return new Point(n.x + m.x, n.y + m.y);
}

function addto(n:Point, m:Point):void
{
	n.x += m.x;
	n.y += m.y;
}

function sub(n:Point, m:Point):Point
{
	return new Point(n.x - m.x, n.y - m.y);
}

function mul(v:Point, f:Number):Point
{
	return new Point(v.x * f, v.y * f);
}

function div(v:Point, f:Number):Point
{
	return new Point(v.x / f, v.y / f);
}

function dot(a:Point, b:Point):Number
{
	return a.x * b.x + a.y * b.y;
}

function cross(a:Point, b:Point):Number
{
	return a.x * b.y - a.y * b.x;
}

function distanceSquared(a:Point, b:Point):Number
{
	var dx:Number = b.x - a.x;
	var dy:Number = b.y - a.y;
	return dx * dx + dy * dy;
}

function hypot(p:Point):Number
{
	return Math.sqrt(p.x*p.x + p.y*p.y);
}

function distance(a:Point, b:Point):Number
{
	return Math.sqrt(distanceSquared(a, b));
}

function lerp(n:Point, m:Point, p:Number):Point
{
	return add(mul(n, 1 - p), mul(m, p));
}

function midpoint(n:Point, m:Point):Point
{
	return new Point((n.x + m.x) * 0.5, (n.y + m.y) * 0.5);
}

function cut(v:Point, len:Number):Point
{
	return mul(normalize(v), len);
}

function getAngle(v:Point):Number
{
	return Math.atan2(v.y, v.x);
}

function pointOnCircle(center:Point, angle:Number, radius:Number):Point
{
	return new Point (
		center.x + Math.cos(angle) * radius, 
		center.y + Math.sin(angle) * radius
	);
}

function format(str:String, ... args):String
{
     for (var i:int = 0; i < args.length; i++)
         str = str.replace(new RegExp("\\{"+i+"\\}", "g"), args[i]);
     return str;
}