Tutorials, extensions, and source files for ActionScript, Flash, and other Adobe products.

 

senocular.com ActionScript Library

PathCircleSegment.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import flash.geom.Point;
import com.senocular.drawing.PathSegment;
import com.senocular.drawing.PathLineSegment;

class com.senocular.drawing.PathCircleSegment extends PathLineSegment {
	
	private var _control:Point;
	private var _center:Point;
	private var radius:Number = 0;
	private var angleStart:Number = 0;
	private var angleEnd:Number = 0;
	private var arc:Number = 0;
	
	// Constructor
	public function PathCircleSegment(startPt:Point, controlPt:Point, endPt:Point) {
		super(startPt, endPt);
		_control = controlPt.clone();
		_command = "circleTo";
		_center = getCircleCenter(_start, _control, _end);
		if (_center) {
			radius = lineLength(_start, _center);
			angleStart = Math.atan2(_start.y - _center.y, _start.x - _center.x);
			angleEnd = Math.atan2(_end.y - _center.y, _end.x - _center.x);
			if (angleEnd < angleStart) {
				angleEnd += Math.PI*2;
			}
			arc = angleEnd - angleStart;
		}
	}
		
	// Public Properties
	public function get length():Number {
		if (isNaN(_length)){
			_length = circleLength();
		}
		return _length;
	}
	public function get control():Point {
		return _control.clone();
	}
	
	// Public Methods
	public function draw(target:Object):Void {
		if (!_center) {
			return;
		}
		var a1:Number = angleStart;
		var a2:Number;
		var n:Number = Math.floor(arc/(Math.PI/4)) + 1;
		var span:Number = arc/(2*n);
		var spanCos:Number = Math.cos(span);
		var rc:Number = (spanCos) ? radius/spanCos : 0;
		var i:Number;
		for (i=0; i<n; i++) {
			a2 = a1 + span;
			a1 = a2 + span;
			target.curveTo(
				_center.x + Math.cos(a2)*rc,
				_center.y + Math.sin(a2)*rc,
				_center.x + Math.cos(a1)*radius,
				_center.y + Math.sin(a1)*radius
			);
		}
	}
	public function pointAt(t:Number):Point {
		if (!_center) {
			return _start.clone();
		}
		var angle:Number = angleStart + t*arc;
		return new Point(_center.x + Math.cos(angle)*radius, _center.y + Math.sin(angle)*radius);
	}
	public function angleAt(t:Number):Number {
		var angle:Number = (angleStart + t*arc + (Math.PI/2)) % (Math.PI*2);
		if (angle > Math.PI) {
			angle -= Math.PI*2;
		}else if (angle < -Math.PI) {
			angle += Math.PI*2;
		}
		return angle;
	}
	
	// Private Methods
	private function trim(t:Number, fromStart:Boolean):PathSegment {
		var startPt:Point;
		var endPt:Point;
		if (fromStart){
			endPt = _start;
			startPt = _end;
		}else{
			startPt = _start;
			endPt = _end;
		}
		var newstart:Point = startPt;
		var newcontrol:Point;
		var newend:Point = startPt;
		var angle:Number = angleStart + t*arc;
		if (fromStart){
			newstart = new Point(_center.x + Math.cos(angle)*radius, _center.y + Math.sin(angle)*radius);
			angle = (angleEnd + angle)/2;
		}else{
			newend = new Point(_center.x + Math.cos(angle)*radius, _center.y + Math.sin(angle)*radius);
			angle = (angleStart + angle)/2;
		}
		newcontrol = new Point(_center.x + Math.cos(angle)*radius, _center.y + Math.sin(angle)*radius);
		return new __constructor__(newstart, newcontrol, newend);
	}
	
	private function circleLength():Number {
		return radius*arc;
	}
	
	private function getCircleCenter(p1:Point, p2:Point, p3:Point):Point {
		var tmp:Point;
		if (p1.x == p2.x || p1.y == p2.y) {
			tmp = p1;
			p1 = p3;
			p3 = tmp;
		}
		if (p2.x == p3.x) {
			tmp = p1;
			p1 = p2;
			p2 = tmp;
		}
		if (p1.x == p2.x || p2.x == p3.x) return null;
		var ma:Number = (p2.y - p1.y)/(p2.x - p1.x);
		var mb:Number = (p3.y - p2.y)/(p3.x - p2.x);
		if (ma == mb) return null;
		var x12:Number = p1.x + p2.x;
		var x23:Number = p2.x + p3.x;
		var x:Number = (ma*mb*(p1.y - p3.y) + mb*x12 - ma*x23)/(2*(mb - ma));
		var y:Number = (ma) ? (p1.y + p2.y)/2 - (x - x12/2)/ma : (p2.y + p3.y)/2 - (x - x23/2)/mb;
		return new Point(x,y);
	}
}