package shared.math
{
public class Vec2Const
{
public static const Zero:Vec2Const = new Vec2Const;
public static const Epsilon:Number = 0.0000001;
public static const EpsilonSqr:Number = Epsilon * Epsilon;
public function get x():Number { return _x; }
public function get y():Number { return _y; }
public function Vec2Const(x:Number = 0, y:Number = 0)
{
_x = x;
_y = y;
}
public function clone():Vec2 { return new Vec2(_x, _y); }
public function add(pos:Vec2Const):Vec2 { return new Vec2(_x + pos._x, _y + pos._y); }
public function addXY(x:Number, y:Number):Vec2 { return new Vec2(_x + x, _y + y); }
public function sub(pos:Vec2Const):Vec2 { return new Vec2(_x - pos._x, _y - pos._y); }
public function subXY(x:Number, y:Number):Vec2 { return new Vec2(_x - x, _y - y); }
public function mul(vec:Vec2Const):Vec2 { return new Vec2(_x * vec._x, _y * vec._y); }
public function mulXY(x:Number, y:Number):Vec2 { return new Vec2(_x * x, _y * y); }
public function div(vec:Vec2Const):Vec2 { return new Vec2(_x / vec._x, _y / vec._y); }
public function divXY(x:Number, y:Number):Vec2 { return new Vec2(_x / x, _y / y); }
public function scale(s:Number):Vec2 { return new Vec2(_x * s, _y * s); }
public function normalize():Vec2
{
const nf:Number = 1 / Math.sqrt(_x * _x + _y * _y);
return new Vec2(_x * nf, _y * nf);
}
public function length():Number { return Math.sqrt(_x * _x + _y * _y); }
public function lengthSqr():Number { return _x * _x + _y * _y; }
public function distance(vec:Vec2Const):Number
{
const xd:Number = _x - vec._x;
const yd:Number = _y - vec._y;
return Math.sqrt(xd * xd + yd * yd);
}
public function distanceXY(x:Number, y:Number):Number
{
const xd:Number = _x - x;
const yd:Number = _y - y;
return Math.sqrt(xd * xd + yd * yd);
}
public function distanceSqr(vec:Vec2Const):Number
{
const xd:Number = _x - vec._x;
const yd:Number = _y - vec._y;
return xd * xd + yd * yd;
}
public function distanceXYSqr(x:Number, y:Number):Number
{
const xd:Number = _x - x;
const yd:Number = _y - y;
return xd * xd + yd * yd;
}
public function equals(vec:Vec2Const):Boolean { return _x == vec._x && _y == vec._y; }
public function equalsXY(x:Number, y:Number):Boolean { return _x == x && _y == y; }
public function isNormalized():Boolean { return Math.abs((_x * _x + _y * _y)-1) < EpsilonSqr; }
public function isZero():Boolean { return _x == 0 && _y == 0; }
public function isNear(vec2:Vec2Const):Boolean { return distanceSqr(vec2) < EpsilonSqr; }
public function isNearXY(x:Number, y:Number):Boolean { return distanceXYSqr(x, y) < EpsilonSqr; }
public function isWithin(vec2:Vec2Const, epsilon:Number):Boolean { return distanceSqr(vec2) < epsilon*epsilon; }
public function isWithinXY(x:Number, y:Number, epsilon:Number):Boolean { return distanceXYSqr(x, y) < epsilon*epsilon; }
public function isValid():Boolean { return !isNaN(_x) && !isNaN(_y) && isFinite(_x) && isFinite(_y); }
public function getDegrees():Number { return getRads() * _RadsToDeg; }
public function getRads():Number { return Math.atan2(_y, _x); }
public function dot(vec:Vec2Const):Number { return _x * vec._x + _y * vec._y; }
public function dotXY(x:Number, y:Number):Number { return _x * x + _y * y; }
public function crossDet(vec:Vec2Const):Number { return _x * vec._y - _y * vec._x; }
public function crossDetXY(x:Number, y:Number):Number { return _x * y - _y * x; }
public function rotate(rads:Number):Vec2
{
const s:Number = Math.sin(rads);
const c:Number = Math.cos(rads);
return new Vec2(_x * c - _y * s, _x * s + _y * c);
}
public function normalRight():Vec2 { return new Vec2(-_y, _x); }
public function normalLeft():Vec2 { return new Vec2(_y, -_x); }
public function negate():Vec2 { return new Vec2( -_x, -_y); }
public function rotateSpinor(vec:Vec2Const):Vec2 { return new Vec2(_x * vec._x - _y * vec._y, _x * vec._y + _y * vec._x); }
public function spinorBetween(vec:Vec2Const):Vec2
{
const d:Number = lengthSqr();
const r:Number = (vec._x * _x + vec._y * _y) / d;
const i:Number = (vec._y * _x - vec._x * _y) / d;
return new Vec2(r, i);
}
public function lerp(to:Vec2Const, t:Number):Vec2 { return new Vec2(_x + t * (to._x - _x), _y + t * (to._y - _y)); }
public function slerp(vec:Vec2Const, t:Number):Vec2
{
const cosTheta:Number = dot(vec);
const theta:Number = Math.acos(cosTheta);
const sinTheta:Number = Math.sin(theta);
if (sinTheta <= Epsilon)
return vec.clone();
const w1:Number = Math.sin((1 - t) * theta) / sinTheta;
const w2:Number = Math.sin(t * theta) / sinTheta;
return scale(w1).add(vec.scale(w2));
}
public function reflect(normal:Vec2Const):Vec2
{
const d:Number = 2 * (_x * normal._x + _y * normal._y);
return new Vec2(_x - d * normal._x, _y - d * normal._y);
}
public function toString():String { return "[" + _x + ", " + _y + "]"; }
internal var _x:Number;
internal var _y:Number;
private static const _RadsToDeg:Number = 180 / Math.PI;
}
}