by Jim
Jun 12, 2007 5:23 PM
I've been working on some stuff lately that requires vector manipulation in ActionScript. Specifically I need to hit test lines to see if the mouse has been clicked near them. This class provides a function for that and some other basic vector operations.
package Utils
{
import flash.geom.Point;
// Derived from and converted from code at:
// http://msdn2.microsoft.com/en-us/library/ms969920.aspx
// Defines a Vector object and various associated functions
public class Vector
{
public var x:Number;
public var y:Number;
public function Vector(xValue:Number = 0, yValue:Number = 0)
{
x = xValue;
y = yValue;
}
// Get the magnitude of this vector
public function get magnitude():Number
{
return Math.sqrt(x * x + y * y);
}
// Subtract the given vector from this one
public function subtract(v1:Vector):Vector
{
return new Vector(x - v1.x, y - v1.y);
}
// Get a dot product with the passed in vector
public function dot(v1:Vector):Number
{
return (x * v1.x) + (y * v1.y);
}
// Multiple the vector by the given scalar number
public function times(m:Number):Vector
{
return new Vector(x * m, y * m);
}
public function toString():String
{
return "Vector (" + x.toString() + ", " + y.toString() + ")";
}
/* ********************** Static functions **************************** */
// Create a new vector defined by the given points
public static function pointsToVector(pt0:Point, pt1:Point):Vector
{
return new Vector(pt1.x - pt0.x, pt1.y - pt0.y);
}
public static function hitTestLine(
pt0:Point, pt1:Point, ptMouse:Point, width:Number):Boolean
{
var tt0:Vector;
var tt1:Vector;
var dist:Number;
var nHalfWidth:int;
// Get the half width of the line to adjust for hit testing of wide lines.
nHalfWidth = (width / 2 < 1) ? 1 : width / 2;
// Convert the line into a vector using the two endpoints.
tt0 = Vector.pointsToVector(pt0, pt1);
// Convert the line from the left endpoint to the mouse point into a vector.
tt1 = Vector.pointsToVector(pt0, ptMouse);
// Get the distance of the point from the line.
dist = getLengthOfNormal(tt1, tt0);
// Return true if we're within the width of the line
return (dist >= -nHalfWidth && dist <= nHalfWidth);
}
// Get the projection of the given vector onto this one
public function projectionOf(a:Vector):Vector
{
// c = ((a * b)/(|b|^2))*b
return this.times(a.dot(this) / this.dot(this));
}
// Get length of the normal vector between the endpoint of vector a and vector b
public static function getLengthOfNormal(a:Vector, b:Vector):Number
{
var c:Vector;
var vNormal:Vector;
c = b.projectionOf(a);
// Obtain perpendicular projection : e = a - c
vNormal = a.subtract(c);
return vNormal.magnitude;
}
}
}