    /*
    	This file was derived from the p5.js source code at
    	https://github.com/processing/p5.js

    	Copyright (c) the p5.js contributors and Andre Seidelt <superilu@yahoo.com>

        This library is free software; you can redistribute it and/or
        modify it under the terms of the GNU Lesser General Public
        License as published by the Free Software Foundation; either
        version 2.1 of the License, or (at your option) any later version.

        This library is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        Lesser General Public License for more details.

        You should have received a copy of the GNU Lesser General Public
        License along with this library; if not, write to the Free Software
        Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     */

    /**
    * @module p5compat.PVector
    */

    /**
     * A class to describe a two or three dimensional vector, specifically
     * a Euclidean (also known as geometric) vector. A vector is an entity
     * that has both magnitude and direction. The datatype, however, stores
     * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude
     * and direction can be accessed via the methods mag() and heading().
     * <br><br>
     * In many of the examples, you will see PVector used to describe a
     * position, velocity, or acceleration. For example, if you consider a rectangle
     * moving across the screen, at any given instant it has a position (a vector
     * that points from the origin to its location), a velocity (the rate at which
     * the object's position changes per time unit, expressed as a vector), and
     * acceleration (the rate at which the object's velocity changes per time
     * unit, expressed as a vector).
     * <br><br>
     * Since vectors represent groupings of values, we cannot simply use
     * traditional addition/multiplication/etc. Instead, we'll need to do some
     * "vector" math, which is made easy by the methods inside the PVector class.
     *
     * @class p5compat.PVector
     * @param {Number} [x] x component of the vector
     * @param {Number} [y] y component of the vector
     * @param {Number} [z] z component of the vector
     * @example
     * let v1 = createVector(40, 50);
     * let v2 = createVector(40, 50);
     *
     * ellipse(v1.x, v1.y, 50, 50);
     * ellipse(v2.x, v2.y, 50, 50);
     * v1.add(v2);
     * ellipse(v1.x, v1.y, 50, 50);
     */
    exports.PVector = function PVector() {
    	var x, y, z;
    	x = arguments[0] || 0;
    	y = arguments[1] || 0;
    	z = arguments[2] || 0;
    	/**
    	 * The x component of the vector
    	 * @property x {Number}
    	 */
    	this.x = x;
    	/**
    	 * The y component of the vector
    	 * @property y {Number}
    	 */
    	this.y = y;
    	/**
    	 * The z component of the vector
    	 * @property z {Number}
    	 */
    	this.z = z;
    };

    /**
     * Returns a string representation of a vector v by calling String(v)
     * or v.toString(). This method is useful for logging vectors in the
     * console.
     * @method  toString
     * @return {String}
     * @example
     * function setup() {
     *   let v = createVector(20, 30);
     *   print(String(v)); // prints "PVector Object : [20, 30, 0]"
     * }
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 0);
     *   let v1 = createVector(mouseX, mouseY);
     *   drawArrow(v0, v1, 'black');
     *
     *   noStroke();
     *   text(v1.toString(), 10, 25, 90, 75);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.toString = function p5VectorToString() {
    	return 'PVector Object : [' + this.x + ', ' + this.y + ', ' + this.z + ']';
    };

    /**
     * Sets the x, y, and z component of the vector using two or three separate
     * variables, the data from a PVector, or the values from a float array.
     * @method set
     * @param {Number} [x] the x component of the vector
     * @param {Number} [y] the y component of the vector
     * @param {Number} [z] the z component of the vector
     * @example
     * function setup() {
     *   let v = createVector(1, 2, 3);
     *   v.set(4, 5, 6); // Sets vector to [4, 5, 6]
     *
     *   let v1 = createVector(0, 0, 0);
     *   let arr = [1, 2, 3];
     *   v1.set(arr); // Sets vector to [1, 2, 3]
     * }
     *
     * let v0, v1;
     * function setup() {
     *   createCanvas(100, 100);
     *
     *   v0 = createVector(0, 0);
     *   v1 = createVector(50, 50);
     * }
     *
     * function draw() {
     *   background(240);
     *
     *   drawArrow(v0, v1, 'black');
     *   v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1));
     *
     *   noStroke();
     *   text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.set = function set(x, y, z) {
    	if (x instanceof PVector) {
    		this.x = x.x || 0;
    		this.y = x.y || 0;
    		this.z = x.z || 0;
    		return this;
    	}
    	if (x instanceof Array) {
    		this.x = x[0] || 0;
    		this.y = x[1] || 0;
    		this.z = x[2] || 0;
    		return this;
    	}
    	this.x = x || 0;
    	this.y = y || 0;
    	this.z = z || 0;
    	return this;
    };

    /**
     * Gets a copy of the vector, returns a PVector object.
     *
     * @method copy
     * @return {PVector} the copy of the PVector object
     * @example
     * let v1 = createVector(1, 2, 3);
     * let v2 = v1.copy();
     * print(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z);
     * // Prints "true"
     */
    exports.PVector.prototype.copy = function copy() {
    	return new PVector(this.x, this.y, this.z);
    };

    /**
     * Adds x, y, and z components to a vector, adds one vector to another, or
     * adds two independent vectors together. The version of the method that adds
     * two vectors together is a static method and returns a PVector, the others
     * acts directly on the vector. See the examples for more context.
     *
     * @method add
     * @param  {Number} x   the x component of the vector to be added
     * @param  {Number} [y] the y component of the vector to be added
     * @param  {Number} [z] the z component of the vector to be added
     * @example
     * let v = createVector(1, 2, 3);
     * v.add(4, 5, 6);
     * // v's components are set to [5, 7, 9]
     * // Static method
     * let v1 = createVector(1, 2, 3);
     * let v2 = createVector(2, 3, 4);
     *
     * let v3 = PVector.add(v1, v2);
     * // v3 has components [3, 5, 7]
     * print(v3);
     *
     * // red vector + blue vector = purple vector
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 0);
     *   let v1 = createVector(mouseX, mouseY);
     *   drawArrow(v0, v1, 'red');
     *
     *   let v2 = createVector(-30, 20);
     *   drawArrow(v1, v2, 'blue');
     *
     *   let v3 = PVector.add(v1, v2);
     *   drawArrow(v0, v3, 'purple');
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.add = function add(x, y, z) {
    	if (x instanceof PVector) {
    		this.x += x.x || 0;
    		this.y += x.y || 0;
    		this.z += x.z || 0;
    		return this;
    	}
    	if (x instanceof Array) {
    		this.x += x[0] || 0;
    		this.y += x[1] || 0;
    		this.z += x[2] || 0;
    		return this;
    	}
    	this.x += x || 0;
    	this.y += y || 0;
    	this.z += z || 0;
    	return this;
    };

    /**
     * Subtracts x, y, and z components from a vector, subtracts one vector from
     * another, or subtracts two independent vectors. The version of the method
     * that subtracts two vectors is a static method and returns a PVector, the
     * other acts directly on the vector. See the examples for more context.
     *
     * @method sub
     * @param  {Number} x   the x component of the vector to subtract
     * @param  {Number} [y] the y component of the vector to subtract
     * @param  {Number} [z] the z component of the vector to subtract
     * @example
     * let v = createVector(4, 5, 6);
     * v.sub(1, 1, 1);
     * // v's components are set to [3, 4, 5]
     *
     * // Static method
     * let v1 = createVector(2, 3, 4);
     * let v2 = createVector(1, 2, 3);
     *
     * let v3 = PVector.sub(v1, v2);
     * // v3 has components [1, 1, 1]
     * print(v3);
     *
     * // red vector - blue vector = purple vector
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 0);
     *   let v1 = createVector(70, 50);
     *   drawArrow(v0, v1, 'red');
     *
     *   let v2 = createVector(mouseX, mouseY);
     *   drawArrow(v0, v2, 'blue');
     *
     *   let v3 = PVector.sub(v1, v2);
     *   drawArrow(v2, v3, 'purple');
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.sub = function sub(x, y, z) {
    	if (x instanceof PVector) {
    		this.x -= x.x || 0;
    		this.y -= x.y || 0;
    		this.z -= x.z || 0;
    		return this;
    	}
    	if (x instanceof Array) {
    		this.x -= x[0] || 0;
    		this.y -= x[1] || 0;
    		this.z -= x[2] || 0;
    		return this;
    	}
    	this.x -= x || 0;
    	this.y -= y || 0;
    	this.z -= z || 0;
    	return this;
    };

    /**
     * Multiply the vector by a scalar. The static version of this method
     * creates a new PVector while the non static version acts on the vector
     * directly. See the examples for more context.
     *
     * @method mult
     * @param  {Number}    n the number to multiply with the vector
     * @example
     * let v = createVector(1, 2, 3);
     * v.mult(2);
     * // v's components are set to [2, 4, 6]
     *
     * // Static method
     * let v1 = createVector(1, 2, 3);
     * let v2 = PVector.mult(v1, 2);
     * // v2 has components [2, 4, 6]
     * print(v2);
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(50, 50);
     *   let v1 = createVector(25, -25);
     *   drawArrow(v0, v1, 'red');
     *
     *   let num = map(mouseX, 0, width, -2, 2, true);
     *   let v2 = PVector.mult(v1, num);
     *   drawArrow(v0, v2, 'blue');
     *
     *   noStroke();
     *   text('multiplied by ' + num.toFixed(2), 5, 90);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.mult = function mult(n) {
    	if (!(typeof n === 'number' && isFinite(n))) {
    		Println(
    			'PVector.prototype.mult:',
    			'n is undefined or not a finite number'
    		);
    		return this;
    	}
    	this.x *= n;
    	this.y *= n;
    	this.z *= n;
    	return this;
    };

    /**
     * Divide the vector by a scalar. The static version of this method creates a
     * new PVector while the non static version acts on the vector directly.
     * See the examples for more context.
     *
     * @method div
     * @param  {number}    n the number to divide the vector by
     * @example
     * let v = createVector(6, 4, 2);
     * v.div(2); //v's components are set to [3, 2, 1]
     *
     * // Static method
     * let v1 = createVector(6, 4, 2);
     * let v2 = PVector.div(v1, 2);
     * // v2 has components [3, 2, 1]
     * print(v2);
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 100);
     *   let v1 = createVector(50, -50);
     *   drawArrow(v0, v1, 'red');
     *
     *   let num = map(mouseX, 0, width, 10, 0.5, true);
     *   let v2 = PVector.div(v1, num);
     *   drawArrow(v0, v2, 'blue');
     *
     *   noStroke();
     *   text('divided by ' + num.toFixed(2), 10, 90);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.div = function div(n) {
    	if (!(typeof n === 'number' && isFinite(n))) {
    		Println(
    			'PVector.prototype.div:',
    			'n is undefined or not a finite number'
    		);
    		return this;
    	}
    	if (n === 0) {
    		Println('PVector.prototype.div:', 'divide by 0');
    		return this;
    	}
    	this.x /= n;
    	this.y /= n;
    	this.z /= n;
    	return this;
    };

    /**
     * Calculates the magnitude (length) of the vector and returns the result as
     * a float (this is simply the equation sqrt(x*x + y*y + z*z).)
     *
     * @method mag
     * @return {Number} magnitude of the vector
     * @example
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 0);
     *   let v1 = createVector(mouseX, mouseY);
     *   drawArrow(v0, v1, 'black');
     *
     *   noStroke();
     *   text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     * * * let v = createVector(20.0, 30.0, 40.0);
     * let m = v.mag();
     * print(m); // Prints "53.85164807134504"
     */
    exports.PVector.prototype.mag = function mag() {
    	return Math.sqrt(this.magSq());
    };

    /**
     * Calculates the squared magnitude of the vector and returns the result
     * as a float (this is simply the equation <em>(x*x + y*y + z*z)</em>.)
     * Faster if the real length is not required in the
     * case of comparing vectors, etc.
     *
     * @method magSq
     * @return {number} squared magnitude of the vector
     * @example
     * // Static method
     * let v1 = createVector(6, 4, 2);
     * print(v1.magSq()); // Prints "56"
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 0);
     *   let v1 = createVector(mouseX, mouseY);
     *   drawArrow(v0, v1, 'black');
     *
     *   noStroke();
     *   text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.magSq = function magSq() {
    	var x = this.x;
    	var y = this.y;
    	var z = this.z;
    	return x * x + y * y + z * z;
    };

    /**
     * Calculates the dot product of two vectors. The version of the method
     * that computes the dot product of two independent vectors is a static
     * method. See the examples for more context.
     *
     *
     * @method dot
     * @param  {Number} x   x component of the vector
     * @param  {Number} [y] y component of the vector
     * @param  {Number} [z] z component of the vector
     * @return {Number}       the dot product
     *
     * @example
     * let v1 = createVector(1, 2, 3);
     * let v2 = createVector(2, 3, 4);
     *
     * print(v1.dot(v2)); // Prints "20"
     *
     * //Static method
     * let v1 = createVector(1, 2, 3);
     * let v2 = createVector(3, 2, 1);
     * print(PVector.dot(v1, v2)); // Prints "10"
     */
    /**
     * @method dot
     * @param  {PVector} value value component of the vector or a PVector
     * @return {Number}
     */
    exports.PVector.prototype.dot = function dot(x, y, z) {
    	if (x instanceof PVector) {
    		return this.dot(x.x, x.y, x.z);
    	}
    	return this.x * (x || 0) + this.y * (y || 0) + this.z * (z || 0);
    };

    /**
     * Calculates and returns a vector composed of the cross product between
     * two vectors. Both the static and non static methods return a new PVector.
     * See the examples for more context.
     *
     * @method cross
     * @param  {PVector} v PVector to be crossed
     * @return {PVector}   PVector composed of cross product
     * @example
     * let v1 = createVector(1, 2, 3);
     * let v2 = createVector(1, 2, 3);
     *
     * v1.cross(v2); // v's components are [0, 0, 0]
     *
     * // Static method
     * let v1 = createVector(1, 0, 0);
     * let v2 = createVector(0, 1, 0);
     *
     * let crossProduct = PVector.cross(v1, v2);
     * // crossProduct has components [0, 0, 1]
     * print(crossProduct);
     */
    exports.PVector.prototype.cross = function cross(v) {
    	var x = this.y * v.z - this.z * v.y;
    	var y = this.z * v.x - this.x * v.z;
    	var z = this.x * v.y - this.y * v.x;

    	return new PVector(x, y, z);
    };

    /**
     * Calculates the Euclidean distance between two points (considering a
     * point as a vector object).
     *
     * @method dist
     * @param  {PVector} v the x, y, and z coordinates of a PVector
     * @return {Number}      the distance
     * @example
     * let v1 = createVector(1, 0, 0);
     * let v2 = createVector(0, 1, 0);
     *
     * let distance = v1.dist(v2); // distance is 1.4142...
     * print(distance);
     *
     * // Static method
     * let v1 = createVector(1, 0, 0);
     * let v2 = createVector(0, 1, 0);
     *
     * let distance = PVector.dist(v1, v2);
     * // distance is 1.4142...
     * print(distance);
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 0);
     *
     *   let v1 = createVector(70, 50);
     *   drawArrow(v0, v1, 'red');
     *
     *   let v2 = createVector(mouseX, mouseY);
     *   drawArrow(v0, v2, 'blue');
     *
     *   noStroke();
     *   text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.dist = function dist(v) {
    	return v
    		.copy()
    		.sub(this)
    		.mag();
    };

    /**
     * Normalize the vector to length 1 (make it a unit vector).
     *
     * @method normalize
     * @return {PVector} normalized PVector
     * @example
     * let v = createVector(10, 20, 2);
     * // v has components [10.0, 20.0, 2.0]
     * v.normalize();
     * // v's components are set to
     * // [0.4454354, 0.8908708, 0.089087084]
     * * * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(50, 50);
     *   let v1 = createVector(mouseX - 50, mouseY - 50);
     *
     *   drawArrow(v0, v1, 'red');
     *   v1.normalize();
     *   drawArrow(v0, v1.mult(35), 'blue');
     *
     *   noFill();
     *   ellipse(50, 50, 35 * 2);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.normalize = function normalize() {
    	var len = this.mag();
    	// here we multiply by the reciprocal instead of calling 'div()'
    	// since div duplicates this zero check.
    	if (len !== 0) this.mult(1 / len);
    	return this;
    };

    /**
     * Limit the magnitude of this vector to the value used for the <b>max</b>
     * parameter.
     *
     * @method limit
     * @param  {Number}    max the maximum magnitude for the vector
     * @example
     * let v = createVector(10, 20, 2);
     * // v has components [10.0, 20.0, 2.0]
     * v.limit(5);
     * // v's components are set to
     * // [2.2271771, 4.4543543, 0.4454354]
     * * * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(50, 50);
     *   let v1 = createVector(mouseX - 50, mouseY - 50);
     *
     *   drawArrow(v0, v1, 'red');
     *   drawArrow(v0, v1.limit(35), 'blue');
     *
     *   noFill();
     *   ellipse(50, 50, 35 * 2);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.limit = function limit(max) {
    	var mSq = this.magSq();
    	if (mSq > max * max) {
    		this.div(Math.sqrt(mSq)) //normalize it
    			.mult(max);
    	}
    	return this;
    };

    /**
     * Set the magnitude of this vector to the value used for the <b>len</b>
     * parameter.
     *
     * @method setMag
     * @param  {number}    len the new length for this vector
     * @example
     * let v = createVector(10, 20, 2);
     * // v has components [10.0, 20.0, 2.0]
     * v.setMag(10);
     * // v's components are set to [6.0, 8.0, 0.0]
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(0, 0);
     *   let v1 = createVector(50, 50);
     *
     *   drawArrow(v0, v1, 'red');
     *
     *   let length = map(mouseX, 0, width, 0, 141, true);
     *   v1.setMag(length);
     *   drawArrow(v0, v1, 'blue');
     *
     *   noStroke();
     *   text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30);
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.setMag = function setMag(n) {
    	return this.normalize().mult(n);
    };

    /**
     * Calculate the angle of rotation for this vector (only 2D vectors)
     *
     * @method heading
     * @return {Number} the angle of rotation
     * @example
     * * function setup() {
     *   let v1 = createVector(30, 50);
     *   print(v1.heading()); // 1.0303768265243125
     *
     *   v1 = createVector(40, 50);
     *   print(v1.heading()); // 0.8960553845713439
     *
     *   v1 = createVector(30, 70);
     *   print(v1.heading()); // 1.1659045405098132
     * }
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(50, 50);
     *   let v1 = createVector(mouseX - 50, mouseY - 50);
     *
     *   drawArrow(v0, v1, 'black');
     *
     *   let myHeading = v1.heading();
     *   noStroke();
     *   text(
     *     'vector heading: ' +
     *       myHeading.toFixed(2) +
     *       ' radians or ' +
     *       degrees(myHeading).toFixed(2) +
     *       ' degrees',
     *     10,
     *     50,
     *     90,
     *     50
     *   );
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.heading = function heading() {
    	var h = Math.atan2(this.y, this.x);
    	return _fromRadians(h);
    };

    /**
     * Rotate the vector by an angle (only 2D vectors), magnitude remains the
     * same
     *
     * @method rotate
     * @param  {number}    angle the angle of rotation
     * @example
     * let v = createVector(10.0, 20.0);
     * // v has components [10.0, 20.0, 0.0]
     * v.rotate(HALF_PI);
     * // v's components are set to [-20.0, 9.999999, 0.0]
     *
     * let angle = 0;
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(50, 50);
     *   let v1 = createVector(50, 0);
     *
     *   drawArrow(v0, v1.rotate(angle), 'black');
     *   angle += 0.01;
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.rotate = function rotate(a) {
    	var newHeading = this.heading() + a;
    	newHeading = _toRadians(newHeading);
    	var mag = this.mag();
    	this.x = Math.cos(newHeading) * mag;
    	this.y = Math.sin(newHeading) * mag;
    	return this;
    };

    /**
     * Calculates and returns the angle (in radians) between two vectors.
     * @method angleBetween
     * @param  {PVector}    the x, y, and z components of a PVector
     * @return {Number}       the angle between (in radians)
     * @example
     * let v1 = createVector(1, 0, 0);
     * let v2 = createVector(0, 1, 0);
     *
     * let angle = v1.angleBetween(v2);
     * // angle is PI/2
     * print(angle);
     *
     * function draw() {
     *   background(240);
     *   let v0 = createVector(50, 50);
     *
     *   let v1 = createVector(50, 0);
     *   drawArrow(v0, v1, 'red');
     *
     *   let v2 = createVector(mouseX - 50, mouseY - 50);
     *   drawArrow(v0, v2, 'blue');
     *
     *   let angleBetween = v1.angleBetween(v2);
     *   noStroke();
     *   text(
     *     'angle between: ' +
     *       angleBetween.toFixed(2) +
     *       ' radians or ' +
     *       degrees(angleBetween).toFixed(2) +
     *       ' degrees',
     *     10,
     *     50,
     *     90,
     *     50
     *   );
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.angleBetween = function angleBetween(v) {
    	var dotmagmag = this.dot(v) / (this.mag() * v.mag());
    	// Mathematically speaking: the dotmagmag variable will be between -1 and 1
    	// inclusive. Practically though it could be slightly outside this range due
    	// to floating-point rounding issues. This can make Math.acos return NaN.
    	//
    	// Solution: we'll clamp the value to the -1,1 range
    	var angle = Math.acos(Math.min(1, Math.max(-1, dotmagmag)));
    	return _fromRadians(angle);
    };

    /**
     * Linear interpolate the vector to another vector
     *
     * @method lerp
     * @param  {Number}    x   the x component
     * @param  {Number}    y   the y component
     * @param  {Number}    z   the z component
     * @param  {Number}    amt the amount of interpolation; some value between 0.0
     *                         (old vector) and 1.0 (new vector). 0.9 is very near
     *                         the new vector. 0.5 is halfway in between.
     * @example
     * let v = createVector(1, 1, 0);
     *
     * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]
     *
     * let v1 = createVector(0, 0, 0);
     * let v2 = createVector(100, 100, 0);
     *
     * let v3 = PVector.lerp(v1, v2, 0.5);
     * // v3 has components [50,50,0]
     * print(v3);
     *
     * let step = 0.01;
     * let amount = 0;
     *
     * function draw() {
     *   background(240);
     *   let v0 = createVector(0, 0);
     *
     *   let v1 = createVector(mouseX, mouseY);
     *   drawArrow(v0, v1, 'red');
     *
     *   let v2 = createVector(90, 90);
     *   drawArrow(v0, v2, 'blue');
     *
     *   if (amount > 1 || amount < 0) {
     *     step *= -1;
     *   }
     *   amount += step;
     *   let v3 = PVector.lerp(v1, v2, amount);
     *
     *   drawArrow(v0, v3, 'purple');
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.prototype.lerp = function lerp(x, y, z, amt) {
    	if (x instanceof PVector) {
    		return this.lerp(x.x, x.y, x.z, y);
    	}
    	this.x += (x - this.x) * amt || 0;
    	this.y += (y - this.y) * amt || 0;
    	this.z += (z - this.z) * amt || 0;
    	return this;
    };

    /**
     * Return a representation of this vector as a float array. This is only
     * for temporary use. If used in any other fashion, the contents should be
     * copied by using the PVector.copy() method to copy into your own
     * array.
     *
     * @method array
     * @return {Number[]} an Array with the 3 values
     * @example
     * * function setup() {
     *   let v = createVector(20, 30);
     *   print(v.array()); // Prints : Array [20, 30, 0]
     * }
     *
     * let v = createVector(10.0, 20.0, 30.0);
     * let f = v.array();
     * print(f[0]); // Prints "10.0"
     * print(f[1]); // Prints "20.0"
     * print(f[2]); // Prints "30.0"
     */
    exports.PVector.prototype.array = function array() {
    	return [this.x || 0, this.y || 0, this.z || 0];
    };

    /**
     * Equality check against a PVector
     *
     * @method equals
     * @param {Number} [x] the x component of the vector
     * @param {Number} [y] the y component of the vector
     * @param {Number} [z] the z component of the vector
     * @return {Boolean} whether the vectors are equals
     * @example
     * * let v1 = createVector(5, 10, 20);
     * let v2 = createVector(5, 10, 20);
     * let v3 = createVector(13, 10, 19);
     *
     * print(v1.equals(v2.x, v2.y, v2.z)); // true
     * print(v1.equals(v3.x, v3.y, v3.z)); // false
     *
     * let v1 = createVector(10.0, 20.0, 30.0);
     * let v2 = createVector(10.0, 20.0, 30.0);
     * let v3 = createVector(0.0, 0.0, 0.0);
     * print(v1.equals(v2)); // true
     * print(v1.equals(v3)); // false
     */
    /**
     * @method equals
     * @param {PVector|Array} value the vector to compare
     * @return {Boolean}
     */
    exports.PVector.prototype.equals = function equals(x, y, z) {
    	var a, b, c;
    	if (x instanceof PVector) {
    		a = x.x || 0;
    		b = x.y || 0;
    		c = x.z || 0;
    	} else if (x instanceof Array) {
    		a = x[0] || 0;
    		b = x[1] || 0;
    		c = x[2] || 0;
    	} else {
    		a = x || 0;
    		b = y || 0;
    		c = z || 0;
    	}
    	return this.x === a && this.y === b && this.z === c;
    };

    // Static Methods

    /**
     * Make a new 2D vector from an angle
     *
     * @method fromAngle
     * @static
     * @param {Number}     angle the desired angle, in radians
     * @param {Number}     [length] the length of the new vector (defaults to 1)
     * @return {PVector}       the new PVector object
     * @example
     * function draw() {
     *   background(200);
     *
     *   // Create a variable, proportional to the mouseX,
     *   // varying from 0-360, to represent an angle in degrees.
     *   angleMode(DEGREES);
     *   let myDegrees = map(mouseX, 0, width, 0, 360);
     *
     *   // Display that variable in an onscreen text.
     *   // (Note the nfc() function to truncate additional decimal places,
     *   // and the "\xB0" character for the degree symbol.)
     *   let readout = 'angle = ' + nfc(myDegrees, 1) + '\xB0';
     *   noStroke();
     *   fill(0);
     *   text(readout, 5, 15);
     *
     *   // Create a PVector using the fromAngle function,
     *   // and extract its x and y components.
     *   let v = PVector.fromAngle(radians(myDegrees), 30);
     *   let vx = v.x;
     *   let vy = v.y;
     *
     *   push();
     *   translate(width / 2, height / 2);
     *   noFill();
     *   stroke(150);
     *   line(0, 0, 30, 0);
     *   stroke(0);
     *   line(0, 0, vx, vy);
     *   pop();
     * }
     */
    exports.PVector.fromAngle = function fromAngle(angle, length) {
    	if (typeof length === 'undefined') {
    		length = 1;
    	}
    	return new exports.PVector(length * Math.cos(angle), length * Math.sin(angle), 0);
    };

    /**
     * Make a new 3D vector from a pair of ISO spherical angles
     *
     * @method fromAngles
     * @static
     * @param {Number}     theta    the polar angle, in radians (zero is up)
     * @param {Number}     phi      the azimuthal angle, in radians
     *                               (zero is out of the screen)
     * @param {Number}     [length] the length of the new vector (defaults to 1)
     * @return {PVector}          the new PVector object
     * @example
     * * function setup() {
     *   createCanvas(100, 100, WEBGL);
     *   fill(255);
     *   noStroke();
     * }
     * function draw() {
     *   background(255);
     *
     *   let t = millis() / 1000;
     *
     *   // add three point lights
     *   pointLight(color('#f00'), PVector.fromAngles(t * 1.0, t * 1.3, 100));
     *   pointLight(color('#0f0'), PVector.fromAngles(t * 1.1, t * 1.2, 100));
     *   pointLight(color('#00f'), PVector.fromAngles(t * 1.2, t * 1.1, 100));
     *
     *   sphere(35);
     * }
     */
    exports.PVector.fromAngles = function (theta, phi, length) {
    	if (typeof length === 'undefined') {
    		length = 1;
    	}
    	var cosPhi = Math.cos(phi);
    	var sinPhi = Math.sin(phi);
    	var cosTheta = Math.cos(theta);
    	var sinTheta = Math.sin(theta);

    	return new exports.PVector(
    		length * sinTheta * sinPhi,
    		-length * cosTheta,
    		length * sinTheta * cosPhi
    	);
    };

    /**
     * Make a new 2D unit vector from a random angle
     *
     * @method random2D
     * @static
     * @return {PVector} the new PVector object
     * @example
     * let v = PVector.random2D();
     * // May make v's attributes something like:
     * // [0.61554617, -0.51195765, 0.0] or
     * // [-0.4695841, -0.14366731, 0.0] or
     * // [0.6091097, -0.22805278, 0.0]
     * print(v);
     *
     * function setup() {
     *   frameRate(1);
     * }
     *
     * function draw() {
     *   background(240);
     *
     *   let v0 = createVector(50, 50);
     *   let v1 = PVector.random2D();
     *   drawArrow(v0, v1.mult(50), 'black');
     * }
     *
     * // draw an arrow for a vector at a given base position
     * function drawArrow(base, vec, myColor) {
     *   push();
     *   stroke(myColor);
     *   strokeWeight(3);
     *   fill(myColor);
     *   translate(base.x, base.y);
     *   line(0, 0, vec.x, vec.y);
     *   rotate(vec.heading());
     *   let arrowSize = 7;
     *   translate(vec.mag() - arrowSize, 0);
     *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
     *   pop();
     * }
     */
    exports.PVector.random2D = function random2D() {
    	return this.fromAngle(Math.random() * TWO_PI);
    };

    /**
     * Make a new random 3D unit vector.
     *
     * @method random3D
     * @static
     * @return {PVector} the new PVector object
     * @example
     * let v = PVector.random3D();
     * // May make v's attributes something like:
     * // [0.61554617, -0.51195765, 0.599168] or
     * // [-0.4695841, -0.14366731, -0.8711202] or
     * // [0.6091097, -0.22805278, -0.7595902]
     * print(v);
     */
    exports.PVector.random3D = function random3D() {
    	var angle = Math.random() * constants.TWO_PI;
    	var vz = Math.random() * 2 - 1;
    	var vzBase = Math.sqrt(1 - vz * vz);
    	var vx = vzBase * Math.cos(angle);
    	var vy = vzBase * Math.sin(angle);
    	return new exports.PVector(vx, vy, vz);
    };

    // Adds two vectors together and returns a new one.
    /**
     * @method add
     * @static
     * @param  {PVector} v1 a PVector to add
     * @param  {PVector} v2 a PVector to add
     * @param  {PVector} target the vector to receive the result
     */
    exports.PVector.add = function add(v1, v2, target) {
    	if (!target) {
    		target = v1.copy();
    	} else {
    		target.set(v1);
    	}
    	target.add(v2);
    	return target;
    };

    /**
     * Subtracts one PVector from another and returns a new one.  The second
     * vector (v2) is subtracted from the first (v1), resulting in v1-v2.
     *
     * @method sub
     * @static
     * @param  {PVector} v1 a PVector to subtract from
     * @param  {PVector} v2 a PVector to subtract
     * @param  {PVector} target if undefined a new vector will be created
     */
    exports.PVector.sub = function sub(v1, v2, target) {
    	if (!target) {
    		target = v1.copy();
    	} else {
    		target.set(v1);
    	}
    	target.sub(v2);
    	return target;
    };

    /**
     * Multiplies a vector by a scalar and returns a new vector.
     *
     * @method mult
     * @static
     * @param  {PVector} v the vector to multiply
     * @param  {Number}  n
     * @param  {PVector} target if undefined a new vector will be created
     */
    exports.PVector.mult = function mult(v, n, target) {
    	if (!target) {
    		target = v.copy();
    	} else {
    		target.set(v);
    	}
    	target.mult(n);
    	return target;
    };

    /**
     * Divides a vector by a scalar and returns a new vector.
     *
     * @method div
     * @static
     * @param  {PVector} v the vector to divide
     * @param  {Number}  n
     * @param  {PVector} target if undefined a new vector will be created
     */
    exports.PVector.div = function div(v, n, target) {
    	if (!target) {
    		target = v.copy();
    	} else {
    		target.set(v);
    	}
    	target.div(n);
    	return target;
    };

    /**
     * Calculates the dot product of two vectors.
     *
     * @method dot
     * @static
     * @param  {PVector} v1 the first PVector
     * @param  {PVector} v2 the second PVector
     * @return {Number}     the dot product
     */
    exports.PVector.dot = function dot(v1, v2) {
    	return v1.dot(v2);
    };

    /**
     * Calculates the cross product of two vectors.
     *
     * @method cross
     * @static
     * @param  {PVector} v1 the first PVector
     * @param  {PVector} v2 the second PVector
     * @return {Number}     the cross product
     */
    exports.PVector.cross = function cross(v1, v2) {
    	return v1.cross(v2);
    };

    /**
     * Calculates the Euclidean distance between two points (considering a
     * point as a vector object).
     *
     * @method dist
     * @static
     * @param  {PVector} v1 the first PVector
     * @param  {PVector} v2 the second PVector
     * @return {Number}     the distance
     */
    exports.PVector.dist = function dist(v1, v2) {
    	return v1.dist(v2);
    };

    /**
     * Linear interpolate a vector to another vector and return the result as a
     * new vector.
     *
     * @method lerp
     * @static
     * @param {PVector} v1
     * @param {PVector} v2
     * @param {Number} amt
     * @return {Number}      the lerped value
     */
    exports.PVector.lerp = function lerp(v1, v2, amt, target) {
    	if (!target) {
    		target = v1.copy();
    	} else {
    		target.set(v1);
    	}
    	target.lerp(v2, amt);
    	return target;
    };

    /**
     * @method mag
     * @param {PVector} vecT the vector to return the magnitude of
     * @return {Number}        the magnitude of vecT
     * @static
     */
    exports.PVector.mag = function mag(vecT) {
    	var x = vecT.x,
    		y = vecT.y,
    		z = vecT.z;
    	var magSq = x * x + y * y + z * z;
    	return Math.sqrt(magSq);
    };

    exports.p5 = {};
    exports.p5.Vector = exports.PVector;