moved Vector2 from contrib.core to nenya
git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@414 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
@@ -0,0 +1,339 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Nenya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/nenya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.flash {
|
||||
|
||||
import flash.geom.Point;
|
||||
|
||||
/**
|
||||
* Basic 2D vector implementation.
|
||||
*/
|
||||
public class Vector2
|
||||
{
|
||||
public var x :Number = 0;
|
||||
public var y :Number = 0;
|
||||
|
||||
/**
|
||||
* Infinite vector - often the result of normalizing a zero vector.
|
||||
*/
|
||||
public static const INFINITE :Vector2 = new Vector2(Infinity, Infinity);
|
||||
|
||||
/**
|
||||
* Converts Point p to a Vector2.
|
||||
*/
|
||||
public static function fromPoint (p :Point) :Vector2
|
||||
{
|
||||
return new Vector2(p.x, p.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Vector2 of magnitude 'len' that has been rotated about the origin by 'radians'.
|
||||
*/
|
||||
public static function fromAngle (radians :Number, len :Number = 1) :Vector2
|
||||
{
|
||||
// we use the unit vector (1, 0)
|
||||
|
||||
return new Vector2(
|
||||
Math.cos(radians) * len, // == len * (cos(theta)*x - sin(theta)*y)
|
||||
Math.sin(radians) * len); // == len * (sin(theta)*x + cos(theta)*y)
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Vector2 from the given values.
|
||||
*/
|
||||
public function Vector2 (x :Number = 0, y :Number = 0)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vector's components to the given values.
|
||||
*/
|
||||
public function set (x :Number, y :Number) :void
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dot product of this vector with vector v.
|
||||
*/
|
||||
public function dot (v :Vector2) :Number
|
||||
{
|
||||
return x * v.x + y * v.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the Vector2 to a Point.
|
||||
*/
|
||||
public function toPoint () :Point
|
||||
{
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this Vector2.
|
||||
*/
|
||||
public function clone () :Vector2
|
||||
{
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the angle represented by this Vector2, in radians.
|
||||
*/
|
||||
public function get angle () :Number
|
||||
{
|
||||
var angle :Number = Math.atan2(y, x);
|
||||
return (angle >= 0 ? angle : angle + (2 * Math.PI));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this vector's length.
|
||||
*/
|
||||
public function get length () :Number
|
||||
{
|
||||
return Math.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this vector's length.
|
||||
*/
|
||||
public function set length (newLen :Number) :void
|
||||
{
|
||||
var scale :Number = newLen / this.length;
|
||||
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of this vector's length.
|
||||
*/
|
||||
public function get lengthSquared () :Number
|
||||
{
|
||||
return (x * x + y * y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the vector in place by 'radians'.
|
||||
* Returns a reference to 'this', for chaining.
|
||||
*/
|
||||
public function rotateLocal (radians :Number) :Vector2
|
||||
{
|
||||
var cosTheta :Number = Math.cos(radians);
|
||||
var sinTheta :Number = Math.sin(radians);
|
||||
|
||||
var oldX :Number = x;
|
||||
x = (cosTheta * oldX) - (sinTheta * y);
|
||||
y = (sinTheta * oldX) + (cosTheta * y);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rotated copy of this vector.
|
||||
*/
|
||||
public function rotate (radians :Number) :Vector2
|
||||
{
|
||||
return this.clone().rotateLocal(radians);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the vector in place and returns its original length.
|
||||
*/
|
||||
public function normalizeLocalAndGetLength () :Number
|
||||
{
|
||||
var length :Number = this.length;
|
||||
|
||||
x /= length;
|
||||
y /= length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes this vector in place.
|
||||
* Returns a reference to 'this', for chaining.
|
||||
*/
|
||||
public function normalizeLocal () :Vector2
|
||||
{
|
||||
var lengthInverse :Number = 1 / this.length;
|
||||
|
||||
x *= lengthInverse;
|
||||
y *= lengthInverse;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a normalized copy of the vector.
|
||||
*/
|
||||
public function normalize () :Vector2
|
||||
{
|
||||
return this.clone().normalizeLocal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds another Vector2 to this, in place.
|
||||
* Returns a reference to 'this', for chaining.
|
||||
*/
|
||||
public function addLocal (v :Vector2) :Vector2
|
||||
{
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this vector added to 'v'.
|
||||
*/
|
||||
public function add (v :Vector2) :Vector2
|
||||
{
|
||||
return this.clone().addLocal(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts another vector from this one, in place.
|
||||
* Returns a reference to 'this', for chaining.
|
||||
*/
|
||||
public function subtractLocal (v :Vector2) :Vector2
|
||||
{
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns (this - v).
|
||||
*/
|
||||
public function subtract (v :Vector2) :Vector2
|
||||
{
|
||||
return this.clone().subtractLocal(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector that is perpendicular to this.
|
||||
* If ccw = true, the perpendicular vector is rotated 90 degrees counter-clockwise from this vector,
|
||||
* otherwise it's rotated 90 degrees clockwise.
|
||||
*/
|
||||
public function getPerp (ccw :Boolean = true) :Vector2
|
||||
{
|
||||
if (ccw) {
|
||||
return new Vector2(-y, x);
|
||||
} else {
|
||||
return new Vector2(y, -x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales this vector by value.
|
||||
*/
|
||||
public function scaleLocal (value :Number) :Vector2
|
||||
{
|
||||
x *= value;
|
||||
y *= value;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns (this * value). */
|
||||
public function scale (value :Number) :Vector2
|
||||
{
|
||||
return this.clone().scaleLocal(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the vector.
|
||||
*/
|
||||
public function invertLocal () :Vector2
|
||||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the vector, inverted.
|
||||
*/
|
||||
public function invert () :Vector2
|
||||
{
|
||||
return this.clone().invertLocal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this vector is equal to v.
|
||||
*/
|
||||
public function equals (v :Vector2) :Boolean
|
||||
{
|
||||
return (x == v.x && y == v.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the components of v are equal to the components of this Vector2,
|
||||
* within the given epsilon.
|
||||
*/
|
||||
public function similar (v :Vector2, epsilon :Number) :Boolean
|
||||
{
|
||||
return ((Math.abs(x - v.x) <= epsilon) && (Math.abs(y - v.y) <= epsilon));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new vector that is the linear interpolation of vectors a and b
|
||||
* at proportion p, where p is in [0, 1], p = 0 means the result is equal to a,
|
||||
* and p = 1 means the result is equal to b.
|
||||
*/
|
||||
public static function interpolate (a :Vector2, b :Vector2, p :Number) :Vector2
|
||||
{
|
||||
// todo: maybe convert this into a non-static function, to fit the rest of the class?
|
||||
var q :Number = 1 - p;
|
||||
return new Vector2(q * a.x + p * b.x,
|
||||
q * a.y + p * b.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the smaller of the two angles between v1 and v2, in radians.
|
||||
* Result will be in range [0, pi].
|
||||
*/
|
||||
public static function smallerAngleBetween (v1 :Vector2, v2 :Vector2) :Number
|
||||
{
|
||||
// v1 dot v2 == |v1||v2|cos(theta)
|
||||
// theta = acos ((v1 dot v2) / (|v1||v2|))
|
||||
|
||||
var dot :Number = v1.dot(v2);
|
||||
var len1 :Number = v1.length;
|
||||
var len2 :Number = v2.length;
|
||||
|
||||
return Math.acos(dot / (len1 * len2));
|
||||
}
|
||||
|
||||
/** Returns a string representation of the Vector2. */
|
||||
public function toString () :String
|
||||
{
|
||||
return "[" + x + ", " + y + "]";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user