/** drawing pacakage */ package com.senocular.drawing { import flash.geom.Point; /** * The Path class saves a collection of line drawing commands to represent a path. * Using the path class you can draw all of or a segment of that path in a movie clip * or get locations and orientations along the path to have objects follow it. * * Note: People using Flash MX 2004 will have to use a custom flash.geom.Point class * * @usage *
import com.senocular.drawing.Path;
* // create a path instance that draws in _root
* var myPath:Path = new Path();
* // draw a square in the path
* myPath.moveTo(50, 50);
* myPath.lineTo(100, 50);
* myPath.lineTo(100, 100);
* myPath.lineTo(50, 100);
* myPath.lineTo(50, 50);
* // draw the path in _root
* graphics.lineStyle(0, 0, 100);
* myPath.draw(graphics);
*
* @author Trevor McCauley
* @author senocular.com
* @version 2.2.0
*/
public class Path {
private var _lengthValid:Boolean = true;
protected var _length:Number = 0;
protected var _moveToHasLength:Boolean = false;
protected var _position:Point;
protected var _segments:Array;
// Constructor
/**
* Constructor. Creates a new path instance
*/
public function Path(){
init();
}
// Public Properties
/**
* The approximate length of the total path in pixels.
* @see moveToHasLength
*/
public function get length():Number {
if (!_lengthValid) {
_lengthValid = true;
_length = 0;
var seg:PathSegment;
var i:int = _segments.length;
while (i--){
seg = _segments[i];
if (_moveToHasLength || !(seg is PathMoveSegment)){
_length += seg.length;
}
}
}
return _length;
}
/**
* Determines whether or not moveTo commands are treated
* as line segments therefore adding to the total length of the path
* @see length
*/
public function get moveToHasLength():Boolean {
return _moveToHasLength;
}
public function set moveToHasLength(b:Boolean):void {
_lengthValid = false;
_moveToHasLength = b;
}
/**
* The current position of the drawing pen based on the last drawing command used.
* If you want to move the pen position without invoking a moveTo command, set
* this property to a new point at the desired location
* @see moveTo
* @see lineTo
* @see curveTo
*/
public function get position():Point {
return _position.clone();
}
public function set position(p:Point):void {
_position = p.clone();
_segments.push(new PathSegment(_position));
}
// Public Methods
/**
* Moves the current drawing position to (x, y).
* @param x An integer indicating the horizontal location to move the drawing position
* @param y An integer indicating the vertical location to move the drawing position
* @see lineTo
* @see curveTo
* @return Nothing
*/
public function moveTo(x:Number, y:Number):void {
if (_moveToHasLength){
_lengthValid = false;
}
var end:Point = new Point(x, y);
_segments.push(new PathMoveSegment(_position, end));
_position = end;
}
/**
* Creates a line in the path from the current drawing position
* to (x, y); the current drawing position is then set to (x, y).
* @param x An integer indicating the horizontal position of the end anchor point of the line
* @param y An integer indicating the vertical position of the end anchor point of the line
* @see moveTo
* @see curveTo
* @return Nothing
*/
public function lineTo(x:Number, y:Number):void {
_lengthValid = false;
var end:Point = new Point(x, y);
_segments.push(new PathLineSegment(_position, end));
_position = end;
}
/**
* Creates a curve in the path from the current drawing position to
* (x, y) using the control point specified by (cx, cy). The current drawing position is then set
* to (x, y).
* @param cx An integer that specifies the horizontal position of the control point of the curve
* @param cy An integer that specifies the vertical position of the control point of the curve
* @param x An integer that specifies the horizontal position of the end anchor point of the curve
* @param y An integer that specifies the vertical position of the end anchor point of the curve
* @see moveTo
* @see lineTo
* @return Nothing
*/
public function curveTo(cx:Number, cy:Number, x:Number, y:Number):void {
_lengthValid = false;
var end:Point = new Point(x, y);
_segments.push(new PathCurveSegment(_position, new Point(cx, cy), end));
_position = end;
}
/**
* Creates a circle segment in the path from the current drawing position to
* (x, y) using a third intermediary point (cx, cy) which lies on the circular path
* between the current drawing position and (x, y). The current drawing position is then set
* to (x, y).
* @param cx An integer that specifies the horizontal position of the control point of the circle segment
* @param cy An integer that specifies the vertical position of the control point of the circle segment
* @param x An integer that specifies the horizontal position of the end anchor point of the circle segment
* @param y An integer that specifies the vertical position of the end anchor point of the circle segment
* @see moveTo
* @see lineTo
* @see curveTo
* @return Nothing
*/
public function circleTo(cx:Number, cy:Number, x:Number, y:Number):void {
_lengthValid = false;
var end:Point = new Point(x, y);
_segments.push(new PathCircleSegment(_position, new Point(cx, cy), end));
_position = end;
}
/**
* Clears all drawing commands in the path
* @see moveTo
* @see lineTo
* @see curveTo
* @return nothing
*/
public function clear():void {
init();
}
/**
* Draws the saved path into the target object passed.
* @param target The object receiving a copy of the drawing commands saved to the path instance
* @param startt A float between 0 and 1 where 0 is the start of the path and 1 is the end of
* the path to start drawing in the target
* @param endt A float between 0 and 1 where 0 is the start of the path and 1 is the end of
* the path to stop drawing in the target
* @see moveTo
* @see lineTo
* @see curveTo
* @return Nothing
*/
public function draw(target:*, startt:Number = 0, endt:Number = 1):void {
startt = cleant(startt, 0);
endt = cleant(endt, 1);
if (endt < startt){
draw(target, startt, 1);
draw(target, 0, endt);
return;
}
var segments:Array = getSegmentsToDraw(startt, endt);
if (segments.length){
target.moveTo(segments[0]._start.x, segments[0]._start.y);
var n:int = segments.length;
var i:int;
for (i=0; i