1/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. 2 3Permission is hereby granted, free of charge, to any person obtaining a copy 4of this software and associated documentation files (the "Software"), to deal 5in the Software without restriction, including without limitation the rights 6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7copies of the Software, and to permit persons to whom the Software is 8furnished to do so, subject to the following conditions: 9 10The above copyright notice and this permission notice shall be included in 11all copies or substantial portions of the Software. 12 13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19THE SOFTWARE. */ 20 21var glMatrix = require("./common.js"); 22 23/** 24 * @class 2 Dimensional Vector 25 * @name vec2 26 */ 27var vec2 = {}; 28 29/** 30 * Creates a new, empty vec2 31 * 32 * @returns {vec2} a new 2D vector 33 */ 34vec2.create = function() { 35 var out = new glMatrix.ARRAY_TYPE(2); 36 out[0] = 0; 37 out[1] = 0; 38 return out; 39}; 40 41/** 42 * Creates a new vec2 initialized with values from an existing vector 43 * 44 * @param {vec2} a vector to clone 45 * @returns {vec2} a new 2D vector 46 */ 47vec2.clone = function(a) { 48 var out = new glMatrix.ARRAY_TYPE(2); 49 out[0] = a[0]; 50 out[1] = a[1]; 51 return out; 52}; 53 54/** 55 * Creates a new vec2 initialized with the given values 56 * 57 * @param {Number} x X component 58 * @param {Number} y Y component 59 * @returns {vec2} a new 2D vector 60 */ 61vec2.fromValues = function(x, y) { 62 var out = new glMatrix.ARRAY_TYPE(2); 63 out[0] = x; 64 out[1] = y; 65 return out; 66}; 67 68/** 69 * Copy the values from one vec2 to another 70 * 71 * @param {vec2} out the receiving vector 72 * @param {vec2} a the source vector 73 * @returns {vec2} out 74 */ 75vec2.copy = function(out, a) { 76 out[0] = a[0]; 77 out[1] = a[1]; 78 return out; 79}; 80 81/** 82 * Set the components of a vec2 to the given values 83 * 84 * @param {vec2} out the receiving vector 85 * @param {Number} x X component 86 * @param {Number} y Y component 87 * @returns {vec2} out 88 */ 89vec2.set = function(out, x, y) { 90 out[0] = x; 91 out[1] = y; 92 return out; 93}; 94 95/** 96 * Adds two vec2's 97 * 98 * @param {vec2} out the receiving vector 99 * @param {vec2} a the first operand 100 * @param {vec2} b the second operand 101 * @returns {vec2} out 102 */ 103vec2.add = function(out, a, b) { 104 out[0] = a[0] + b[0]; 105 out[1] = a[1] + b[1]; 106 return out; 107}; 108 109/** 110 * Subtracts vector b from vector a 111 * 112 * @param {vec2} out the receiving vector 113 * @param {vec2} a the first operand 114 * @param {vec2} b the second operand 115 * @returns {vec2} out 116 */ 117vec2.subtract = function(out, a, b) { 118 out[0] = a[0] - b[0]; 119 out[1] = a[1] - b[1]; 120 return out; 121}; 122 123/** 124 * Alias for {@link vec2.subtract} 125 * @function 126 */ 127vec2.sub = vec2.subtract; 128 129/** 130 * Multiplies two vec2's 131 * 132 * @param {vec2} out the receiving vector 133 * @param {vec2} a the first operand 134 * @param {vec2} b the second operand 135 * @returns {vec2} out 136 */ 137vec2.multiply = function(out, a, b) { 138 out[0] = a[0] * b[0]; 139 out[1] = a[1] * b[1]; 140 return out; 141}; 142 143/** 144 * Alias for {@link vec2.multiply} 145 * @function 146 */ 147vec2.mul = vec2.multiply; 148 149/** 150 * Divides two vec2's 151 * 152 * @param {vec2} out the receiving vector 153 * @param {vec2} a the first operand 154 * @param {vec2} b the second operand 155 * @returns {vec2} out 156 */ 157vec2.divide = function(out, a, b) { 158 out[0] = a[0] / b[0]; 159 out[1] = a[1] / b[1]; 160 return out; 161}; 162 163/** 164 * Alias for {@link vec2.divide} 165 * @function 166 */ 167vec2.div = vec2.divide; 168 169/** 170 * Returns the minimum of two vec2's 171 * 172 * @param {vec2} out the receiving vector 173 * @param {vec2} a the first operand 174 * @param {vec2} b the second operand 175 * @returns {vec2} out 176 */ 177vec2.min = function(out, a, b) { 178 out[0] = Math.min(a[0], b[0]); 179 out[1] = Math.min(a[1], b[1]); 180 return out; 181}; 182 183/** 184 * Returns the maximum of two vec2's 185 * 186 * @param {vec2} out the receiving vector 187 * @param {vec2} a the first operand 188 * @param {vec2} b the second operand 189 * @returns {vec2} out 190 */ 191vec2.max = function(out, a, b) { 192 out[0] = Math.max(a[0], b[0]); 193 out[1] = Math.max(a[1], b[1]); 194 return out; 195}; 196 197/** 198 * Scales a vec2 by a scalar number 199 * 200 * @param {vec2} out the receiving vector 201 * @param {vec2} a the vector to scale 202 * @param {Number} b amount to scale the vector by 203 * @returns {vec2} out 204 */ 205vec2.scale = function(out, a, b) { 206 out[0] = a[0] * b; 207 out[1] = a[1] * b; 208 return out; 209}; 210 211/** 212 * Adds two vec2's after scaling the second operand by a scalar value 213 * 214 * @param {vec2} out the receiving vector 215 * @param {vec2} a the first operand 216 * @param {vec2} b the second operand 217 * @param {Number} scale the amount to scale b by before adding 218 * @returns {vec2} out 219 */ 220vec2.scaleAndAdd = function(out, a, b, scale) { 221 out[0] = a[0] + (b[0] * scale); 222 out[1] = a[1] + (b[1] * scale); 223 return out; 224}; 225 226/** 227 * Calculates the euclidian distance between two vec2's 228 * 229 * @param {vec2} a the first operand 230 * @param {vec2} b the second operand 231 * @returns {Number} distance between a and b 232 */ 233vec2.distance = function(a, b) { 234 var x = b[0] - a[0], 235 y = b[1] - a[1]; 236 return Math.sqrt(x*x + y*y); 237}; 238 239/** 240 * Alias for {@link vec2.distance} 241 * @function 242 */ 243vec2.dist = vec2.distance; 244 245/** 246 * Calculates the squared euclidian distance between two vec2's 247 * 248 * @param {vec2} a the first operand 249 * @param {vec2} b the second operand 250 * @returns {Number} squared distance between a and b 251 */ 252vec2.squaredDistance = function(a, b) { 253 var x = b[0] - a[0], 254 y = b[1] - a[1]; 255 return x*x + y*y; 256}; 257 258/** 259 * Alias for {@link vec2.squaredDistance} 260 * @function 261 */ 262vec2.sqrDist = vec2.squaredDistance; 263 264/** 265 * Calculates the length of a vec2 266 * 267 * @param {vec2} a vector to calculate length of 268 * @returns {Number} length of a 269 */ 270vec2.length = function (a) { 271 var x = a[0], 272 y = a[1]; 273 return Math.sqrt(x*x + y*y); 274}; 275 276/** 277 * Alias for {@link vec2.length} 278 * @function 279 */ 280vec2.len = vec2.length; 281 282/** 283 * Calculates the squared length of a vec2 284 * 285 * @param {vec2} a vector to calculate squared length of 286 * @returns {Number} squared length of a 287 */ 288vec2.squaredLength = function (a) { 289 var x = a[0], 290 y = a[1]; 291 return x*x + y*y; 292}; 293 294/** 295 * Alias for {@link vec2.squaredLength} 296 * @function 297 */ 298vec2.sqrLen = vec2.squaredLength; 299 300/** 301 * Negates the components of a vec2 302 * 303 * @param {vec2} out the receiving vector 304 * @param {vec2} a vector to negate 305 * @returns {vec2} out 306 */ 307vec2.negate = function(out, a) { 308 out[0] = -a[0]; 309 out[1] = -a[1]; 310 return out; 311}; 312 313/** 314 * Returns the inverse of the components of a vec2 315 * 316 * @param {vec2} out the receiving vector 317 * @param {vec2} a vector to invert 318 * @returns {vec2} out 319 */ 320vec2.inverse = function(out, a) { 321 out[0] = 1.0 / a[0]; 322 out[1] = 1.0 / a[1]; 323 return out; 324}; 325 326/** 327 * Normalize a vec2 328 * 329 * @param {vec2} out the receiving vector 330 * @param {vec2} a vector to normalize 331 * @returns {vec2} out 332 */ 333vec2.normalize = function(out, a) { 334 var x = a[0], 335 y = a[1]; 336 var len = x*x + y*y; 337 if (len > 0) { 338 //TODO: evaluate use of glm_invsqrt here? 339 len = 1 / Math.sqrt(len); 340 out[0] = a[0] * len; 341 out[1] = a[1] * len; 342 } 343 return out; 344}; 345 346/** 347 * Calculates the dot product of two vec2's 348 * 349 * @param {vec2} a the first operand 350 * @param {vec2} b the second operand 351 * @returns {Number} dot product of a and b 352 */ 353vec2.dot = function (a, b) { 354 return a[0] * b[0] + a[1] * b[1]; 355}; 356 357/** 358 * Computes the cross product of two vec2's 359 * Note that the cross product must by definition produce a 3D vector 360 * 361 * @param {vec3} out the receiving vector 362 * @param {vec2} a the first operand 363 * @param {vec2} b the second operand 364 * @returns {vec3} out 365 */ 366vec2.cross = function(out, a, b) { 367 var z = a[0] * b[1] - a[1] * b[0]; 368 out[0] = out[1] = 0; 369 out[2] = z; 370 return out; 371}; 372 373/** 374 * Performs a linear interpolation between two vec2's 375 * 376 * @param {vec2} out the receiving vector 377 * @param {vec2} a the first operand 378 * @param {vec2} b the second operand 379 * @param {Number} t interpolation amount between the two inputs 380 * @returns {vec2} out 381 */ 382vec2.lerp = function (out, a, b, t) { 383 var ax = a[0], 384 ay = a[1]; 385 out[0] = ax + t * (b[0] - ax); 386 out[1] = ay + t * (b[1] - ay); 387 return out; 388}; 389 390/** 391 * Generates a random vector with the given scale 392 * 393 * @param {vec2} out the receiving vector 394 * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned 395 * @returns {vec2} out 396 */ 397vec2.random = function (out, scale) { 398 scale = scale || 1.0; 399 var r = glMatrix.RANDOM() * 2.0 * Math.PI; 400 out[0] = Math.cos(r) * scale; 401 out[1] = Math.sin(r) * scale; 402 return out; 403}; 404 405/** 406 * Transforms the vec2 with a mat2 407 * 408 * @param {vec2} out the receiving vector 409 * @param {vec2} a the vector to transform 410 * @param {mat2} m matrix to transform with 411 * @returns {vec2} out 412 */ 413vec2.transformMat2 = function(out, a, m) { 414 var x = a[0], 415 y = a[1]; 416 out[0] = m[0] * x + m[2] * y; 417 out[1] = m[1] * x + m[3] * y; 418 return out; 419}; 420 421/** 422 * Transforms the vec2 with a mat2d 423 * 424 * @param {vec2} out the receiving vector 425 * @param {vec2} a the vector to transform 426 * @param {mat2d} m matrix to transform with 427 * @returns {vec2} out 428 */ 429vec2.transformMat2d = function(out, a, m) { 430 var x = a[0], 431 y = a[1]; 432 out[0] = m[0] * x + m[2] * y + m[4]; 433 out[1] = m[1] * x + m[3] * y + m[5]; 434 return out; 435}; 436 437/** 438 * Transforms the vec2 with a mat3 439 * 3rd vector component is implicitly '1' 440 * 441 * @param {vec2} out the receiving vector 442 * @param {vec2} a the vector to transform 443 * @param {mat3} m matrix to transform with 444 * @returns {vec2} out 445 */ 446vec2.transformMat3 = function(out, a, m) { 447 var x = a[0], 448 y = a[1]; 449 out[0] = m[0] * x + m[3] * y + m[6]; 450 out[1] = m[1] * x + m[4] * y + m[7]; 451 return out; 452}; 453 454/** 455 * Transforms the vec2 with a mat4 456 * 3rd vector component is implicitly '0' 457 * 4th vector component is implicitly '1' 458 * 459 * @param {vec2} out the receiving vector 460 * @param {vec2} a the vector to transform 461 * @param {mat4} m matrix to transform with 462 * @returns {vec2} out 463 */ 464vec2.transformMat4 = function(out, a, m) { 465 var x = a[0], 466 y = a[1]; 467 out[0] = m[0] * x + m[4] * y + m[12]; 468 out[1] = m[1] * x + m[5] * y + m[13]; 469 return out; 470}; 471 472/** 473 * Perform some operation over an array of vec2s. 474 * 475 * @param {Array} a the array of vectors to iterate over 476 * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed 477 * @param {Number} offset Number of elements to skip at the beginning of the array 478 * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array 479 * @param {Function} fn Function to call for each vector in the array 480 * @param {Object} [arg] additional argument to pass to fn 481 * @returns {Array} a 482 * @function 483 */ 484vec2.forEach = (function() { 485 var vec = vec2.create(); 486 487 return function(a, stride, offset, count, fn, arg) { 488 var i, l; 489 if(!stride) { 490 stride = 2; 491 } 492 493 if(!offset) { 494 offset = 0; 495 } 496 497 if(count) { 498 l = Math.min((count * stride) + offset, a.length); 499 } else { 500 l = a.length; 501 } 502 503 for(i = offset; i < l; i += stride) { 504 vec[0] = a[i]; vec[1] = a[i+1]; 505 fn(vec, vec, arg); 506 a[i] = vec[0]; a[i+1] = vec[1]; 507 } 508 509 return a; 510 }; 511})(); 512 513/** 514 * Returns a string representation of a vector 515 * 516 * @param {vec2} vec vector to represent as a string 517 * @returns {String} string representation of the vector 518 */ 519vec2.str = function (a) { 520 return 'vec2(' + a[0] + ', ' + a[1] + ')'; 521}; 522 523module.exports = vec2; 524