#

API Docs for: 0.6.0
Show: Inherited Protected Private Deprecated

# File: src/math/Vec3.js

    module.exports = Vec3;

    var Mat3 = require('./Mat3');

    /**
     * 3-dimensional vector
     * @class Vec3
     * @constructor
     * @param {Number} x
     * @param {Number} y
     * @param {Number} z
     * @author schteppe
     * @example
     *     var v = new Vec3(1, 2, 3);
     *     console.log('x=' + v.x); // x=1
     */
    function Vec3(x,y,z){
        /**
         * @property x
         * @type {Number}
         */
        this.x = x||0.0;

        /**
         * @property y
         * @type {Number}
         */
        this.y = y||0.0;

        /**
         * @property z
         * @type {Number}
         */
        this.z = z||0.0;
    }

    Vec3.ZERO = new Vec3(0, 0, 0);

    /**
     * Vector cross product
     * @method cross
     * @param {Vec3} v
     * @param {Vec3} target Optional. Target to save in.
     * @return {Vec3}
     */
    Vec3.prototype.cross = function(v,target){
        var vx=v.x, vy=v.y, vz=v.z, x=this.x, y=this.y, z=this.z;
        target = target || new Vec3();

        target.x = (y * vz) - (z * vy);
        target.y = (z * vx) - (x * vz);
        target.z = (x * vy) - (y * vx);

        return target;
    };

    /**
     * Set the vectors' 3 elements
     * @method set
     * @param {Number} x
     * @param {Number} y
     * @param {Number} z
     * @return Vec3
     */
    Vec3.prototype.set = function(x,y,z){
        this.x = x;
        this.y = y;
        this.z = z;
        return this;
    };

    /**
     * Set all components of the vector to zero.
     * @method setZero
     */
    Vec3.prototype.setZero = function(){
        this.x = this.y = this.z = 0;
    };

    /**
     * Vector addition
     * @method vadd
     * @param {Vec3} v
     * @param {Vec3} target Optional.
     * @return {Vec3}
     */
    Vec3.prototype.vadd = function(v,target){
        if(target){
            target.x = v.x + this.x;
            target.y = v.y + this.y;
            target.z = v.z + this.z;
        } else {
            return new Vec3(this.x + v.x,
                                   this.y + v.y,
                                   this.z + v.z);
        }
    };

    /**
     * Vector subtraction
     * @method vsub
     * @param {Vec3} v
     * @param {Vec3} target Optional. Target to save in.
     * @return {Vec3}
     */
    Vec3.prototype.vsub = function(v,target){
        if(target){
            target.x = this.x - v.x;
            target.y = this.y - v.y;
            target.z = this.z - v.z;
        } else {
            return new Vec3(this.x-v.x,
                                   this.y-v.y,
                                   this.z-v.z);
        }
    };

    /**
     * Get the cross product matrix a_cross from a vector, such that a x b = a_cross * b = c
     * @method crossmat
     * @see http://www8.cs.umu.se/kurser/TDBD24/VT06/lectures/Lecture6.pdf
     * @return {Mat3}
     */
    Vec3.prototype.crossmat = function(){
        return new Mat3([     0,  -this.z,   this.y,
                                this.z,        0,  -this.x,
                               -this.y,   this.x,        0]);
    };

    /**
     * Normalize the vector. Note that this changes the values in the vector.
     * @method normalize
     * @return {Number} Returns the norm of the vector
     */
    Vec3.prototype.normalize = function(){
        var x=this.x, y=this.y, z=this.z;
        var n = Math.sqrt(x*x + y*y + z*z);
        if(n>0.0){
            var invN = 1/n;
            this.x *= invN;
            this.y *= invN;
            this.z *= invN;
        } else {
            // Make something up
            this.x = 0;
            this.y = 0;
            this.z = 0;
        }
        return n;
    };

    /**
     * Get the version of this vector that is of length 1.
     * @method unit
     * @param {Vec3} target Optional target to save in
     * @return {Vec3} Returns the unit vector
     */
    Vec3.prototype.unit = function(target){
        target = target || new Vec3();
        var x=this.x, y=this.y, z=this.z;
        var ninv = Math.sqrt(x*x + y*y + z*z);
        if(ninv>0.0){
            ninv = 1.0/ninv;
            target.x = x * ninv;
            target.y = y * ninv;
            target.z = z * ninv;
        } else {
            target.x = 1;
            target.y = 0;
            target.z = 0;
        }
        return target;
    };

    /**
     * Get the 2-norm (length) of the vector
     * @method norm
     * @return {Number}
     */
    Vec3.prototype.norm = function(){
        var x=this.x, y=this.y, z=this.z;
        return Math.sqrt(x*x + y*y + z*z);
    };

    /**
     * Get the squared length of the vector
     * @method norm2
     * @return {Number}
     */
    Vec3.prototype.norm2 = function(){
        return this.dot(this);
    };

    /**
     * Get distance from this point to another point
     * @method distanceTo
     * @param  {Vec3} p
     * @return {Number}
     */
    Vec3.prototype.distanceTo = function(p){
        var x=this.x, y=this.y, z=this.z;
        var px=p.x, py=p.y, pz=p.z;
        return Math.sqrt((px-x)*(px-x)+
                         (py-y)*(py-y)+
                         (pz-z)*(pz-z));
    };

    /**
     * Multiply the vector with a scalar
     * @deprecated Use .scale instead
     * @method mult
     * @param {Number} scalar
     * @param {Vec3} target
     * @return {Vec3}
     */
    Vec3.prototype.mult = function(scalar,target){
        target = target || new Vec3();
        var x = this.x,
            y = this.y,
            z = this.z;
        target.x = scalar * x;
        target.y = scalar * y;
        target.z = scalar * z;
        return target;
    };

    /**
     * Multiply the vector with a scalar.
     * @method scale
     * @param {Number} scalar
     * @param {Vec3} target
     * @return {Vec3}
     */
    Vec3.prototype.scale = Vec3.prototype.mult;

    /**
     * Calculate dot product
     * @method dot
     * @param {Vec3} v
     * @return {Number}
     */
    Vec3.prototype.dot = function(v){
        return this.x * v.x + this.y * v.y + this.z * v.z;
    };

    /**
     * @method isZero
     * @return bool
     */
    Vec3.prototype.isZero = function(){
        return this.x===0 && this.y===0 && this.z===0;
    };

    /**
     * Make the vector point in the opposite direction.
     * @method negate
     * @param {Vec3} target Optional target to save in
     * @return {Vec3}
     */
    Vec3.prototype.negate = function(target){
        target = target || new Vec3();
        target.x = -this.x;
        target.y = -this.y;
        target.z = -this.z;
        return target;
    };

    /**
     * Compute two artificial tangents to the vector
     * @method tangents
     * @param {Vec3} t1 Vector object to save the first tangent in
     * @param {Vec3} t2 Vector object to save the second tangent in
     */
    var Vec3_tangents_n = new Vec3();
    var Vec3_tangents_randVec = new Vec3();
    Vec3.prototype.tangents = function(t1,t2){
        var norm = this.norm();
        if(norm>0.0){
            var n = Vec3_tangents_n;
            var inorm = 1/norm;
            n.set(this.x*inorm,this.y*inorm,this.z*inorm);
            var randVec = Vec3_tangents_randVec;
            if(Math.abs(n.x) < 0.9){
                randVec.set(1,0,0);
                n.cross(randVec,t1);
            } else {
                randVec.set(0,1,0);
                n.cross(randVec,t1);
            }
            n.cross(t1,t2);
        } else {
            // The normal length is zero, make something up
            t1.set(1,0,0).normalize();
            t2.set(0,1,0).normalize();
        }
    };

    /**
     * Converts to a more readable format
     * @method toString
     * @return string
     */
    Vec3.prototype.toString = function(){
        return this.x+","+this.y+","+this.z;
    };

    /**
     * Converts to an array
     * @method toArray
     * @return Array
     */
    Vec3.prototype.toArray = function(){
        return [this.x, this.y, this.z];
    };

    /**
     * Copies value of source to this vector.
     * @method copy
     * @param {Vec3} source
     * @return {Vec3} this
     */
    Vec3.prototype.copy = function(source){
        this.x = source.x;
        this.y = source.y;
        this.z = source.z;
        return this;
    };

    /**
     * Do a linear interpolation between two vectors
     * @method lerp
     * @param {Vec3} v
     * @param {Number} t A number between 0 and 1. 0 will make this function return u, and 1 will make it return v. Numbers in between will generate a vector in between them.
     * @param {Vec3} target
     */
    Vec3.prototype.lerp = function(v,t,target){
        var x=this.x, y=this.y, z=this.z;
        target.x = x + (v.x-x)*t;
        target.y = y + (v.y-y)*t;
        target.z = z + (v.z-z)*t;
    };

    /**
     * Check if a vector equals is almost equal to another one.
     * @method almostEquals
     * @param {Vec3} v
     * @param {Number} precision
     * @return bool
     */
    Vec3.prototype.almostEquals = function(v,precision){
        if(precision===undefined){
            precision = 1e-6;
        }
        if( Math.abs(this.x-v.x)>precision ||
            Math.abs(this.y-v.y)>precision ||
            Math.abs(this.z-v.z)>precision){
            return false;
        }
        return true;
    };

    /**
     * Check if a vector is almost zero
     * @method almostZero
     * @param {Number} precision
     */
    Vec3.prototype.almostZero = function(precision){
        if(precision===undefined){
            precision = 1e-6;
        }
        if( Math.abs(this.x)>precision ||
            Math.abs(this.y)>precision ||
            Math.abs(this.z)>precision){
            return false;
        }
        return true;
    };

    var antip_neg = new Vec3();

    /**
     * Check if the vector is anti-parallel to another vector.
     * @method isAntiparallelTo
     * @param  {Vec3}  v
     * @param  {Number}  precision Set to zero for exact comparisons
     * @return {Boolean}
     */
    Vec3.prototype.isAntiparallelTo = function(v,precision){
        this.negate(antip_neg);
        return antip_neg.almostEquals(v,precision);
    };

    /**
     * Clone the vector
     * @method clone
     * @return {Vec3}
     */
    Vec3.prototype.clone = function(){
        return new Vec3(this.x, this.y, this.z);
    };