Path: blob/trunk/third_party/closure/goog/math/vec2.js
4515 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Defines a 2-element vector class that can be used for8* coordinate math, useful for animation systems and point manipulation.9*10* Vec2 objects inherit from goog.math.Coordinate and may be used wherever a11* Coordinate is required. Where appropriate, Vec2 functions accept both Vec212* and Coordinate objects as input.13*/1415goog.provide('goog.math.Vec2');1617goog.require('goog.math');18goog.require('goog.math.Coordinate');1920goog.require('goog.utils');21222324/**25* Class for a two-dimensional vector object and assorted functions useful for26* manipulating points.27*28* @param {number} x The x coordinate for the vector.29* @param {number} y The y coordinate for the vector.30* @struct31* @constructor32* @extends {goog.math.Coordinate}33*/34goog.math.Vec2 = function(x, y) {35'use strict';36/**37* X-value38* @type {number}39*/40this.x = x;4142/**43* Y-value44* @type {number}45*/46this.y = y;47};48goog.utils.inherits(goog.math.Vec2, goog.math.Coordinate);495051/**52* @return {!goog.math.Vec2} A random unit-length vector.53*/54goog.math.Vec2.randomUnit = function() {55'use strict';56var angle = Math.random() * Math.PI * 2;57return new goog.math.Vec2(Math.cos(angle), Math.sin(angle));58};596061/**62* @return {!goog.math.Vec2} A random vector inside the unit-disc.63*/64goog.math.Vec2.random = function() {65'use strict';66var mag = Math.sqrt(Math.random());67var angle = Math.random() * Math.PI * 2;6869return new goog.math.Vec2(Math.cos(angle) * mag, Math.sin(angle) * mag);70};717273/**74* Returns a new Vec2 object from a given coordinate.75* @param {!goog.math.Coordinate} a The coordinate.76* @return {!goog.math.Vec2} A new vector object.77*/78goog.math.Vec2.fromCoordinate = function(a) {79'use strict';80return new goog.math.Vec2(a.x, a.y);81};828384/**85* @return {!goog.math.Vec2} A new vector with the same coordinates as this one.86* @override87*/88goog.math.Vec2.prototype.clone = function() {89'use strict';90return new goog.math.Vec2(this.x, this.y);91};929394/**95* Returns the magnitude of the vector measured from the origin.96* @return {number} The length of the vector.97*/98goog.math.Vec2.prototype.magnitude = function() {99'use strict';100return Math.hypot(this.x, this.y);101};102103104/**105* Returns the squared magnitude of the vector measured from the origin.106* NOTE(brenneman): Leaving out the square root is not a significant107* optimization in JavaScript.108* @return {number} The length of the vector, squared.109*/110goog.math.Vec2.prototype.squaredMagnitude = function() {111'use strict';112return this.x * this.x + this.y * this.y;113};114115116/**117* @param {number} sx The scale factor to use for the x dimension.118* @param {number=} opt_sy The scale factor to use for the y dimension.119* @return {!goog.math.Vec2} This vector after scaling.120* @override121*/122// Since the implementation of Coordinate.scale() returns "this", we123// can reuse that implementation here, and just recast the return type.124goog.math.Vec2.prototype.scale =125/** @type {function(number, number=):!goog.math.Vec2} */126(goog.math.Coordinate.prototype.scale);127128129/**130* Reverses the sign of the vector. Equivalent to scaling the vector by -1.131* @return {!goog.math.Vec2} The inverted vector.132*/133goog.math.Vec2.prototype.invert = function() {134'use strict';135this.x = -this.x;136this.y = -this.y;137return this;138};139140141/**142* Normalizes the current vector to have a magnitude of 1.143* @return {!goog.math.Vec2} The normalized vector.144*/145goog.math.Vec2.prototype.normalize = function() {146'use strict';147return this.scale(1 / this.magnitude());148};149150151/**152* Adds another vector to this vector in-place.153* @param {!goog.math.Coordinate} b The vector to add.154* @return {!goog.math.Vec2} This vector with `b` added.155*/156goog.math.Vec2.prototype.add = function(b) {157'use strict';158this.x += b.x;159this.y += b.y;160return this;161};162163164/**165* Subtracts another vector from this vector in-place.166* @param {!goog.math.Coordinate} b The vector to subtract.167* @return {!goog.math.Vec2} This vector with `b` subtracted.168*/169goog.math.Vec2.prototype.subtract = function(b) {170'use strict';171this.x -= b.x;172this.y -= b.y;173return this;174};175176177/**178* Rotates this vector in-place by a given angle, specified in radians.179* @param {number} angle The angle, in radians.180* @return {!goog.math.Vec2} This vector rotated `angle` radians.181*/182goog.math.Vec2.prototype.rotate = function(angle) {183'use strict';184var cos = Math.cos(angle);185var sin = Math.sin(angle);186var newX = this.x * cos - this.y * sin;187var newY = this.y * cos + this.x * sin;188this.x = newX;189this.y = newY;190return this;191};192193194/**195* Rotates a vector by a given angle, specified in radians, relative to a given196* axis rotation point. The returned vector is a newly created instance - no197* in-place changes are done.198* @param {!goog.math.Vec2} v A vector.199* @param {!goog.math.Vec2} axisPoint The rotation axis point.200* @param {number} angle The angle, in radians.201* @return {!goog.math.Vec2} The rotated vector in a newly created instance.202*/203goog.math.Vec2.rotateAroundPoint = function(v, axisPoint, angle) {204'use strict';205var res = v.clone();206return res.subtract(axisPoint).rotate(angle).add(axisPoint);207};208209210/** @override */211goog.math.Vec2.prototype.equals = function(b) {212'use strict';213if (this === b) {214return true;215}216return b instanceof goog.math.Vec2 && !!b && this.x == b.x && this.y == b.y;217};218219220/**221* Returns the distance between two vectors.222* @param {!goog.math.Coordinate} a The first vector.223* @param {!goog.math.Coordinate} b The second vector.224* @return {number} The distance.225*/226goog.math.Vec2.distance = goog.math.Coordinate.distance;227228229/**230* Returns the squared distance between two vectors.231* @param {!goog.math.Coordinate} a The first vector.232* @param {!goog.math.Coordinate} b The second vector.233* @return {number} The squared distance.234*/235goog.math.Vec2.squaredDistance = goog.math.Coordinate.squaredDistance;236237238/**239* Compares vectors for equality.240* @param {!goog.math.Coordinate} a The first vector.241* @param {!goog.math.Coordinate} b The second vector.242* @return {boolean} Whether the vectors have the same x and y coordinates.243*/244goog.math.Vec2.equals = goog.math.Coordinate.equals;245246247/**248* Returns the sum of two vectors as a new Vec2.249* @param {!goog.math.Coordinate} a The first vector.250* @param {!goog.math.Coordinate} b The second vector.251* @return {!goog.math.Vec2} The sum vector.252*/253goog.math.Vec2.sum = function(a, b) {254'use strict';255return new goog.math.Vec2(a.x + b.x, a.y + b.y);256};257258259/**260* Returns the difference between two vectors as a new Vec2.261* @param {!goog.math.Coordinate} a The first vector.262* @param {!goog.math.Coordinate} b The second vector.263* @return {!goog.math.Vec2} The difference vector.264*/265goog.math.Vec2.difference = function(a, b) {266'use strict';267return new goog.math.Vec2(a.x - b.x, a.y - b.y);268};269270271/**272* Returns the dot-product of two vectors.273* @param {!goog.math.Coordinate} a The first vector.274* @param {!goog.math.Coordinate} b The second vector.275* @return {number} The dot-product of the two vectors.276*/277goog.math.Vec2.dot = function(a, b) {278'use strict';279return a.x * b.x + a.y * b.y;280};281282283/**284* Returns the determinant of two vectors.285* @param {!goog.math.Vec2} a The first vector.286* @param {!goog.math.Vec2} b The second vector.287* @return {number} The determinant of the two vectors.288*/289goog.math.Vec2.determinant = function(a, b) {290'use strict';291return a.x * b.y - a.y * b.x;292};293294295/**296* Returns a new Vec2 that is the linear interpolant between vectors a and b at297* scale-value x.298* @param {!goog.math.Coordinate} a Vector a.299* @param {!goog.math.Coordinate} b Vector b.300* @param {number} x The proportion between a and b.301* @return {!goog.math.Vec2} The interpolated vector.302*/303goog.math.Vec2.lerp = function(a, b, x) {304'use strict';305return new goog.math.Vec2(306goog.math.lerp(a.x, b.x, x), goog.math.lerp(a.y, b.y, x));307};308309310/**311* Returns a new Vec2 that is a copy of the vector a, but rescaled by a factors312* sx and sy in the x and y directions. If only sx is specified, then y is313* scaled by the same factor as x.314* @param {!goog.math.Coordinate} a Vector a.315* @param {number} sx X scale factor.316* @param {number=} sy Y scale factor (optional).317* @return {!goog.math.Vec2} A new rescaled vector.318*/319goog.math.Vec2.rescaled = function(a, sx, sy = sx) {320return new goog.math.Vec2(a.x * sx, a.y * sy);321};322323324