/*************************************************************************************************************** Vector2D Class For Actionscript 1.0 --------------------------------------------------------------------------------------------------------------- method listing: state-altering methods: Vector2D(x, y) - create vector and set the components to x and y Vector2D(v) - create vector and set the components to the components of vector v set(x, y) - set the components to x and y set(v) - set the components to the components of vector v setX(x) - set the x component of the vector setY(y) - set the y component of the vector setAngle(a) - set the angle of the vector to angle a in degrees setMagnitude(m) - set the magnitude of the vector to magnitude m (always positive) plus(v1 ... vn) - add the components of the given vectors to the components of the vector minus(v1 ... vn) - subtract the components of given vectors from the components of the vector times(x, y) - multiply the components of vector by x and y times(scalar) - multiply the components of vector by number scalar times(v) - multiply the components of vector by the components of vector v invert() - invert (or reverse) the vector project(v) - set the vector to be the projection of the vector onto vector v reflect(v) - reflect the vector over vector v rotate(a) - rotate the vector by angle a in degrees swap(v) - swap the components of the vector and vector v (note: also alters vector v) state-safe methods: getX() - return the current value of the x component getY() - return the current value of the y component getAngle() - return the current angle of the vector getMagnitude() - return the current magnitude of the vector getLeftNormal() - return a new vector which is left hand normal to the vector getRightNormal() - return a new vector which is right hand normal to the vector cross(v) - return the magnitude of the cross product of the vector and vector v dot(v) - return the dot product of the vector and vector v angleBetween(v) - return the angle between the vector and vector v angleBetweenCos(v) - return the cosine of the angle between the vector and vector v angleBetweenSin(v) - return the sine of the angle between the vector and vector v comparison methods: isEqualTo(v) - test for equality between the vector and vector v isNormalTo(v) - test for normality between the vector and vector v utility methods: makeNumber() - convert all inputs to a number of fixed precision display(mc, color) - draw vector in given movieclip using a given color toString() - override of built in method to provide meaningful output property listing: x - property representing the current x component of the vector y - property representing the current y component of the vector angle - property representing the current angle of the vector magnitude - property representing the current magnitude of the vector Feel free to use this code as you wish, Have Fun! Please send bug reports && ( gripes || praise ) to nick[at]zambetti[dot]com ***************************************************************************************************************/ trace("Appending Vector2D Class ..."); /**************************************************************************************************************/ // // description: constructor for Vector2D // parameters: x:number, y:number || v:Vector2D // returns: reference to the newly created vector _global.Vector2D = function() { if (undefined == this.properties) { this.properties = new Object(); this.properties.type = "Vector2D"; } if (2 == arguments.length) { // x and y were passed this.properties.x = this.makeNumber(arguments[0]); this.properties.y = this.makeNumber(arguments[1]); } else if ((1 == arguments.length) && ("Vector2D" === arguments[0].properties.type)) { // an existing vector was passed this.properties.x = arguments[0].properties.x; this.properties.y = arguments[0].properties.y; } else { // nothing or too much was passed this.properties.x = 0; this.properties.y = 0; } return this; }; // // description: sets the properties of the vector // parameters: x:number, y:number || v:Vector2D // returns: reference to the vector _global.Vector2D.prototype.set = function() { if (2 == arguments.length) { this.constructor(arguments[0], arguments[1]); } else if (1 == arguments.length) { this.constructor(arguments[0]); } else { this.constructor(); } return this; }; // // description: hard sets x value of the vector // parameters: x:number // returns: value of x after operation _global.Vector2D.prototype.setX = function(x) { return this.properties.x = this.makeNumber(x); }; // // description: retrieves the current x value of the vector // parameters: none // returns: current value of x _global.Vector2D.prototype.getX = function() { return this.properties.x; }; // // description: hard sets y value of the vector // parameters: y:number // returns: value of y after operation _global.Vector2D.prototype.setY = function(y) { return this.properties.y = this.makeNumber(y); }; // // description: retrieves the current y value of the vector // parameters: none // returns: current value of y _global.Vector2D.prototype.getY = function() { return this.properties.y; }; // // description: sets the angle of the vector to the given angle (in degrees) // parameters: newAngle:number // returns: number representing angle in degrees _global.Vector2D.prototype.setAngle = function(newAngle) { var angleRadians = 0; if (!isNaN(Number(newAngle))) { angleRadians = Number(newAngle) * (Math.PI / 180); } var currentMagnitude = Math.sqrt(Math.pow(this.properties.x, 2) + Math.pow(this.properties.y, 2)); this.properties.x = this.makeNumber(currentMagnitude * Math.cos(angleRadians)); this.properties.y = this.makeNumber(currentMagnitude * Math.sin(angleRadians)); return this.getAngle(); }; // // description: calculates the angle of the vector // parameters: none // returns: number representing angle in degrees _global.Vector2D.prototype.getAngle = function() { return this.makeNumber(Math.atan2(this.properties.y, this.properties.x) * (180 / Math.PI)); }; // // description: sets the magnitude (aka: length) to the given scalar // parameters: newMagnitude:number // returns: magnitude after set operation _global.Vector2D.prototype.setMagnitude = function(newMagnitude) { if (isNaN(Number(newMagnitude))) { return this.properties.x = this.properties.y = 0; } var currentMagnitude = Math.sqrt(Math.pow(this.properties.x, 2) + Math.pow(this.properties.y, 2)); if (0 < currentMagnitude) { this.times(Number(newMagnitude) / currentMagnitude); return this.getMagnitude(); } else { return this.properties.x = this.makeNumber(newMagnitude); } }; // // description: returns the magnitude of the vector (aka: length) // parameters: none // returns: 0 <= number _global.Vector2D.prototype.getMagnitude = function() { return this.makeNumber(Math.sqrt(Math.pow(this.properties.x, 2) + Math.pow(this.properties.y, 2))); }; // // description: rotates the vector by the given angle (in degrees) // parameters: rotationAngle:number // returns: reference to the vector _global.Vector2D.prototype.rotate = function(rotationAngle) { if (isNaN(Number(rotationAngle))) { return this; } var currentMagnitude = Math.sqrt(Math.pow(this.properties.x, 2) + Math.pow(this.properties.y, 2)); var newAngleRadians = ((Math.atan2(this.properties.y, this.properties.x) * (180 / Math.PI)) + Number(rotationAngle)) * (Math.PI / 180); this.properties.x = this.makeNumber(currentMagnitude * Math.cos(newAngleRadians)); this.properties.y = this.makeNumber(currentMagnitude * Math.sin(newAngleRadians)); return this; }; // // description: exchanges data of the vector and the given vector // parameters: v:Vector2D // returns: reference to the vector _global.Vector2D.prototype.swap = function(v) { if ("Vector2D" === v.properties.type) { var tempX = this.properties.x; var tempY = this.properties.y; this.properties.x = v.properties.x; this.properties.y = v.properties.y; v.properties.x = tempX; v.properties.y = tempY; } return this; }; // // description: adds given vectors to the vector // parameters: v1:Vector2D ... vn:Vector2D // returns: reference to the vector _global.Vector2D.prototype.plus = function() { for (var i = 0; i < arguments.length; ++i) { if ("Vector2D" === arguments[i].properties.type) { this.properties.x += arguments[i].properties.x; this.properties.y += arguments[i].properties.y; } } return this; }; // // description: subtracts given vectors from the vector // parameters: v1:Vector2D ... vn:Vector2D // returns: reference to the vector _global.Vector2D.prototype.minus = function() { for (var i = 0; i < arguments.length; ++i) { if ("Vector2D" === arguments[i].properties.type) { this.properties.x -= arguments[i].properties.x; this.properties.y -= arguments[i].properties.y; } } return this; }; // // description: multiplies the components by the x and y args or by the given vector // parameters: x:number, y:number || scalar:number || v:Vector2D // returns: reference to the vector _global.Vector2D.prototype.times = function() { if (1 == arguments.length) { if ("Vector2D" === arguments[0].properties.type) { this.properties.x *= arguments[0].properties.x; this.properties.y *= arguments[0].properties.y; } else { if (isNaN(Number(arguments[0]))) { this.properties.x = this.properties.y = 0; } else { this.properties.x *= Number(arguments[0]); this.properties.y *= Number(arguments[0]); } } } else if (2 == arguments.length) { isNaN(Number(arguments[0])) ? this.properties.x = 0 : this.properties.x *= Number(arguments[0]); isNaN(Number(arguments[1])) ? this.properties.y = 0 : this.properties.y *= Number(arguments[1]); } this.properties.x = this.makeNumber(this.properties.x); this.properties.y = this.makeNumber(this.properties.y); return this; }; // // description: inverts the vector // parameters: none // returns: reference to the vector _global.Vector2D.prototype.invert = function() { this.properties.x *= -1; this.properties.y *= -1; return this; }; // // description: calculates the the angle between the vector and vector v in degrees // parameters: v:Vector2D // returns: number _global.Vector2D.prototype.angleBetween = function(v) { if ("Vector2D" === v.properties.type) { return this.makeNumber(Math.acos(this.dot(v) / (this.getMagnitude() * v.getMagnitude())) * (180 / Math.PI)); } return 0; }; // // description: calculates the sine of the angle between the vector and vector v // parameters: v:Vector2D // returns: number _global.Vector2D.prototype.angleBetweenSin = function(v) { if ("Vector2D" === v.properties.type) { return this.makeNumber((this.cross(v) / (this.getMagnitude() * v.getMagnitude()))); } return 0; }; // // description: calculates the cpsine of the angle between the vector and vector v // parameters: v:Vector2D // returns: number _global.Vector2D.prototype.angleBetweenCos = function(v) { if ("Vector2D" === v.properties.type) { return this.makeNumber(this.dot(v) / (this.getMagnitude() * v.getMagnitude())); } return 0; }; // // description: calculates the dot product of the vector and vector v // parameters: v:Vector2D // returns: number _global.Vector2D.prototype.dot = function(v) { if ("Vector2D" === v.properties.type) { return this.makeNumber((this.properties.x * v.properties.x) + (this.properties.y * v.properties.y)); } return 0; }; // // description: calculates the cross product of the vector and vector v // parameters: v:Vector2D // returns: number (representing the magnitude of the theoretical vector result) _global.Vector2D.prototype.cross = function(v) { if ("Vector2D" === v.properties.type) { return Math.abs(this.makeNumber((this.properties.x * v.properties.y) - (this.properties.y * v.properties.x))); } return 0; }; // // description: projects the vector onto vector v // parameters: v:Vector2D // returns: reference to the vector _global.Vector2D.prototype.project = function(v) { if ("Vector2D" === v.properties.type) { var scalar = this.dot(v) / Math.pow(v.getMagnitude(), 2); this.set(v); this.times(scalar); } return this; }; // // description: relects the vector over vector v // parameters: v:Vector2D // returns: reference to the vector _global.Vector2D.prototype.reflect = function(v) { if ("Vector2D" === v.properties.type) { var vAfterHorizReflect = new Vector2D(v.properties.y, -v.properties.x); var rotationAngle = 2 * this.angleBetween(v); if (0 >= this.angleBetweenCos(vAfterHorizReflect)) { rotationAngle *= -1; } this.rotate(rotationAngle); } return this; }; // // description: creates a new vector which is normal (clockwise) to the vector // parameters: none // returns: reference to the newly created vector _global.Vector2D.prototype.getRightNormal = function() { return new Vector2D(this.properties.y, -this.properties.x); }; // // description: creates a new vector which is normal (anti-clockwise) to the vector // parameters: none // returns: reference to the newly created vector _global.Vector2D.prototype.getLeftNormal = function() { return new Vector2D(-this.properties.y, this.properties.x); }; // // description: tests if two vectors are normal to each other // parameters: none // returns: boolean indicating normality _global.Vector2D.prototype.isNormalTo = function(v) { if ("Vector2D" === v.properties.type) { return (this.dot(v) === 0); } else { return false; } }; // // description: tests if two vectors are equal to each other // parameters: none // returns: boolean indicating equality _global.Vector2D.prototype.isEqualTo = function(v) { if ("Vector2D" === v.properties.type) { if ((this.properties.x === v.properties.x) && (this.properties.y === v.properties.y)) { return true; } else { return false; } } else { return false; } }; // // description: converts all inputs to a number of fixed precision // parameters: none // returns: number _global.Vector2D.prototype.makeNumber = function(numberValue) { return isNaN(Number(numberValue)) ? 0 : Math.round(Number(numberValue) * 100000) / 100000; }; // // description: draws a vector in a given mc using a given color // parameters: mc:movieClipReference color:hexNumber // returns: nothing _global.Vector2D.prototype.display = function(mc, color) { if ("movieclip" === typeof mc) { mc.lineStyle(0, color, 100); mc.moveTo(0, 0); mc.lineTo(this.properties.x, this.properties.y); } return; }; // // description: override of toString() that produces meaningful output // parameters: none // returns: string _global.Vector2D.prototype.toString = function() { return "[" + this.properties.x + "," + this.properties.y + "]"; }; // // Set up properties with their associated getter and setter functions with (_global.Vector2D.prototype) { addProperty("x", getX, setX); addProperty("y", getY, setY); addProperty("magnitude", getMagnitude, setMagnitude); addProperty("angle", getAngle, setAngle); }