1 /**
  2  * Returns a {@link pv.Vector} for the specified <i>x</i> and <i>y</i>
  3  * coordinate. This is a convenience factory method, equivalent to <tt>new
  4  * pv.Vector(x, y)</tt>.
  5  *
  6  * @see pv.Vector
  7  * @param {number} x the <i>x</i> coordinate.
  8  * @param {number} y the <i>y</i> coordinate.
  9  * @returns {pv.Vector} a vector for the specified coordinates.
 10  */
 11 pv.vector = function(x, y) {
 12   return new pv.Vector(x, y);
 13 };
 14 
 15 /**
 16  * Constructs a {@link pv.Vector} for the specified <i>x</i> and <i>y</i>
 17  * coordinate. This constructor should not be invoked directly; use
 18  * {@link pv.vector} instead.
 19  *
 20  * @class Represents a two-dimensional vector; a 2-tuple <i>⟨x,
 21  * y⟩</i>.
 22  *
 23  * @param {number} x the <i>x</i> coordinate.
 24  * @param {number} y the <i>y</i> coordinate.
 25  */
 26 pv.Vector = function(x, y) {
 27   this.x = x;
 28   this.y = y;
 29 };
 30 
 31 /**
 32  * Returns a vector perpendicular to this vector: <i>⟨-y, x⟩</i>.
 33  *
 34  * @returns {pv.Vector} a perpendicular vector.
 35  */
 36 pv.Vector.prototype.perp = function() {
 37   return new pv.Vector(-this.y, this.x);
 38 };
 39 
 40 /**
 41  * Returns a normalized copy of this vector: a vector with the same direction,
 42  * but unit length. If this vector has zero length this method returns a copy of
 43  * this vector.
 44  *
 45  * @returns {pv.Vector} a unit vector.
 46  */
 47 pv.Vector.prototype.norm = function() {
 48   var l = this.length();
 49   return this.times(l ? (1 / l) : 1);
 50 };
 51 
 52 /**
 53  * Returns the magnitude of this vector, defined as <i>sqrt(x * x + y * y)</i>.
 54  *
 55  * @returns {number} a length.
 56  */
 57 pv.Vector.prototype.length = function() {
 58   return Math.sqrt(this.x * this.x + this.y * this.y);
 59 };
 60 
 61 /**
 62  * Returns a scaled copy of this vector: <i>⟨x * k, y * k⟩</i>.
 63  * To perform the equivalent divide operation, use <i>1 / k</i>.
 64  *
 65  * @param {number} k the scale factor.
 66  * @returns {pv.Vector} a scaled vector.
 67  */
 68 pv.Vector.prototype.times = function(k) {
 69   return new pv.Vector(this.x * k, this.y * k);
 70 };
 71 
 72 /**
 73  * Returns this vector plus the vector <i>v</i>: <i>⟨x + v.x, y +
 74  * v.y⟩</i>. If only one argument is specified, it is interpreted as the
 75  * vector <i>v</i>.
 76  *
 77  * @param {number} x the <i>x</i> coordinate to add.
 78  * @param {number} y the <i>y</i> coordinate to add.
 79  * @returns {pv.Vector} a new vector.
 80  */
 81 pv.Vector.prototype.plus = function(x, y) {
 82   return (arguments.length == 1)
 83       ? new pv.Vector(this.x + x.x, this.y + x.y)
 84       : new pv.Vector(this.x + x, this.y + y);
 85 };
 86 
 87 /**
 88  * Returns this vector minus the vector <i>v</i>: <i>⟨x - v.x, y -
 89  * v.y⟩</i>. If only one argument is specified, it is interpreted as the
 90  * vector <i>v</i>.
 91  *
 92  * @param {number} x the <i>x</i> coordinate to subtract.
 93  * @param {number} y the <i>y</i> coordinate to subtract.
 94  * @returns {pv.Vector} a new vector.
 95  */
 96 pv.Vector.prototype.minus = function(x, y) {
 97   return (arguments.length == 1)
 98       ? new pv.Vector(this.x - x.x, this.y - x.y)
 99       : new pv.Vector(this.x - x, this.y - y);
100 };
101 
102 /**
103  * Returns the dot product of this vector and the vector <i>v</i>: <i>x * v.x +
104  * y * v.y</i>. If only one argument is specified, it is interpreted as the
105  * vector <i>v</i>.
106  *
107  * @param {number} x the <i>x</i> coordinate to dot.
108  * @param {number} y the <i>y</i> coordinate to dot.
109  * @returns {number} a dot product.
110  */
111 pv.Vector.prototype.dot = function(x, y) {
112   return (arguments.length == 1)
113       ? this.x * x.x + this.y * x.y
114       : this.x * x + this.y * y;
115 };
116