1 /** 2 * Copyright (C) 2009-2011 Klaus Reimer <k@ailis.de> 3 * See LICENSE.txt for licensing information. 4 * 5 * @require twodee.js 6 */ 7 8 /** 9 * Constructs a new empty vector. 10 * 11 * @param {number=} x 12 * The X coordinate (Optional) 13 * @param {number=} y 14 * The Y coordinate (Optional) 15 * 16 * @constructor 17 * @class 18 * A vector with two elements. 19 */ 20 twodee.Vector = function(x, y) 21 { 22 if (x) this.x = x; 23 if (y) this.y = y; 24 twodee.Vector.counter++; 25 }; 26 27 /** 28 * Instance counter. 29 * 30 * @type {number} 31 */ 32 twodee.Vector.counter = 0; 33 34 /** 35 * The X coordinate. 36 * 37 * @type {number} 38 */ 39 twodee.Vector.prototype.x = 0; 40 41 /** 42 * The Y coordinate. 43 * 44 * @type {number} 45 */ 46 twodee.Vector.prototype.y = 0; 47 48 /** 49 * Returns a copy of this vector. 50 * 51 * @param {twodee.Vector=} v 52 * Optional target vector 53 * @return {twodee.Vector} A copy of this vector or the target vector 54 */ 55 twodee.Vector.prototype.copy = function(v) 56 { 57 return (v ? v : new twodee.Vector()).set(this.x, this.y); 58 }; 59 60 /** 61 * Checks if this vector is a zero vector. 62 * 63 * @return {boolean} True if vector is a zero vector, false if not 64 */ 65 twodee.Vector.prototype.isZero = function() 66 { 67 return !this.x && !this.y; 68 }; 69 70 /** 71 * Sets the vector coordinates. 72 * 73 * @param {number} x 74 * The X coordinate 75 * @param {number} y 76 * The Y coordinate 77 * @return {twodee.Vector} 78 * This vector 79 */ 80 twodee.Vector.prototype.set = function(x, y) 81 { 82 this.x = x; 83 this.y = y; 84 return this; 85 }; 86 87 /** 88 * Adds the coordinates of the specified vector to this one. 89 * 90 * @param {twodee.Vector} v 91 * The vector to add 92 * @return {twodee.Vector} This vector 93 */ 94 twodee.Vector.prototype.add = function(v) 95 { 96 this.x += v.x; 97 this.y += v.y; 98 return this; 99 }; 100 101 /** 102 * Subtracts the coordinates of the specified vector from this one. 103 * 104 * @param {twodee.Vector} v 105 * The vector to subtract 106 * @return {twodee.Vector} This vector 107 */ 108 twodee.Vector.prototype.sub = function(v) 109 { 110 this.x -= v.x; 111 this.y -= v.y; 112 return this; 113 }; 114 115 /** 116 * Scales the vector with the specified factors. 117 * 118 * @param {number} fx 119 * The X factor 120 * @param {number=} fy 121 * The Y factor (Optional. Defaults to fx) 122 * @return {twodee.Vector} This vector 123 */ 124 twodee.Vector.prototype.scale = function(fx, fy) 125 { 126 this.x *= fx; 127 this.y *= fy === undefined ? fx : fy; 128 return this; 129 }; 130 131 /** 132 * Rotates the vector by the specified angle. 133 * 134 * @param {number} angle 135 * The rotation angle in anti-clockwise RAD. 136 * @return {twodee.Vector} This vector 137 */ 138 twodee.Vector.prototype.rotate = function(angle) 139 { 140 var x, y, s, c; 141 142 s = Math.sin(angle); 143 c = Math.cos(angle); 144 x = this.x; 145 y = this.y; 146 this.x = x * c - y * s; 147 this.y = x * s + y * c; 148 return this; 149 }; 150 151 /** 152 * Creates and returns the dot product of this vector and the specified one. 153 * 154 * @param {twodee.Vector} v 155 * The other vector 156 * @return {number} 157 * The dot product 158 */ 159 twodee.Vector.prototype.dot = function(v) 160 { 161 return this.x * v.x + this.y * v.y; 162 }; 163 164 /** 165 * Creates the cross product of this vector and the specified one and stores 166 * the result back into this vector. 167 * 168 * @param {twodee.Vector} v 169 * The other vector 170 * @return {twodee.Vector} This vector 171 */ 172 twodee.Vector.prototype.cross = function(v) 173 { 174 var x, y; 175 176 x = this.y * v.x - this.x * v.y; 177 y = this.x * v.y - this.y * v.x; 178 this.x = x; 179 this.y = y; 180 return this; 181 }; 182 183 /** 184 * Returns the length of the vector. 185 * 186 * @return {number} The vector length 187 */ 188 twodee.Vector.prototype.getLength = function() 189 { 190 return Math.sqrt(this.x * this.x + this.y * this.y); 191 }; 192 193 /** 194 * Converts this vector into a unit vector with length 1. 195 * 196 * @return {twodee.Vector} This vector 197 */ 198 twodee.Vector.prototype.toUnit = function() 199 { 200 var len; 201 202 len = this.getLength(); 203 this.x /= len; 204 this.y /= len; 205 return this; 206 }; 207 208 /** 209 * Calculate the angle between this vector and the specified one in radians. 210 * It returns always the shortest angle. If the angle is clock-wise then the 211 * returned number is positive. If it's counter-clock-wise then the angle is 212 * negative. So the return value of this method is always between -PI and +PI. 213 * 214 * @param {twodee.Vector=} v 215 * The second vector. Optional. If not specified then the angle 216 * to the vector 0;1 is returned. 217 * @return {number} 218 * The angle between the two vectors, in radians 219 */ 220 twodee.Vector.prototype.getAngle = function(v) 221 { 222 var angle = Math.atan2(this.x, this.y); 223 if (v) angle -= Math.atan2(v.x, v.y); 224 if (angle > Math.PI) angle -= Math.PI * 2; 225 return angle; 226 }; 227 228 /** 229 * Transforms this vector with the specified matrix. 230 * 231 * @param {twodee.Matrix} m 232 * The matrix 233 * @return {twodee.Vector} 234 * This vector 235 */ 236 twodee.Vector.prototype.transform = function(m) 237 { 238 return this.set( 239 m.m00 * this.x + m.m01 * this.y + m.m02, 240 m.m10 * this.x + m.m11 * this.y + m.m12); 241 }; 242 243 /** 244 * Converts the vector into a JSON object with keys 'x' and 'y'. 245 * 246 * @return {Object} The vector as a JSON object 247 */ 248 twodee.Vector.prototype.toJSON = function() 249 { 250 return { "x": this.x, "y": this.y }; 251 }; 252 253 /** 254 * Creates a new vector instance with the data read from the 255 * specified JSON object (with keys 'x', and 'y'). Returns null if data 256 * was empty. 257 * 258 * @param {{x:number,y:number}} data 259 * The vector as JSON object 260 * @return {twodee.Vector} The vector object or null if data was empty 261 */ 262 twodee.Vector.fromJSON = function(data) 263 { 264 if (!data) return null; 265 return new twodee.Vector(data.x, data.y); 266 }; 267 268 /** 269 * Converts this vector into its orthogonal vector and returns a reference to 270 * it. 271 * 272 * @return {twodee.Vector} 273 * The reference to this vector 274 */ 275 twodee.Vector.prototype.orthogonal = function() 276 { 277 var tmp = this.x; 278 this.x = -this.y; 279 this.y = tmp; 280 return this; 281 }; 282