sujinleeme
9/3/2017 - 3:39 AM

JavaScript 2D Vector Class

JavaScript 2D Vector Class

class Vector {
    constructor(v, w) {
        this.v = v
        this.w = w

        this.decimalPlaces = 2
        this.sign = {
            add : '+',
            subtract: '-',
            multiply: '*',
            division:'/'
        }
    }

    exec(sign) {
        this.convertSinCos()
        return this.v.map((e, i) => this.round(eval(e + sign + '('+this.w[i]+')')))
    }

    //add vectors
    add() {
        return this.exec(this.sign.add)
    }

    //subtract vectors
    sub() {
        return this.exec(this.sign.subtract)
    }

    //scale the vector with multiplication
    mult() {
        return this.exec(this.sign.multiply)
    }
    
    // scale the vector with division
    div() {
        return this.exec(this.sign.division)
    }

    // base logic to get the magnitude of a vector
    baseMagitude(x, y) {
        return Math.sqrt(Math.pow(x, 2)+Math.pow(y, 2))
    }

    // calculate the magnitude of a vector with components
     magnitude(){
        const comp = this.components()
        return this.round(this.baseMagitude(comp[0], comp[1]))
    }
    
    // normalize the vector to a unit length of 1
    normalize() {
        const x = this.v[0]
        const y = this.v[1]
        const magnitude = this.baseMagitude(x, y)
        const base = 1/magnitude
        return [base*x, base*y]
    }
    
    // Find the components of vector
    components() {
        return this.sub().map(e => {return e *-1})
    }
    
    // limit the magnitude of a vector()
    limit() {

    }

    // the 2D heading of a vector expressed as an angle
    heading2D() {

    }

    //Find the direction angle of unitvector
    // eg u = 4i + (-2j)
    directionAngle(){
        const quadrant = this.getQuadrant()
        const rad = Math.atan(this.v[1]/this.v[0])
        let deg = rad * 180 / Math.PI
        switch (quadrant) {
            case 1:
                deg = deg
            case 2:
                deg += 180
            case 3:
                deg += 180
            case 4 :
                deg += 360
        }
        return this.round(deg)
    }

    // the Euclidean distance between two vectors (considered as points)
    dist() {

    }

    // find the angle between two vectors
    angleBetween() {
        const x = this.v[0]
        const y = this.v[1]
    }

    // the dot product of two vectors === Scalar product
    dot() {
        return this.mult().reduce((acc, val) => { return acc+val })
    }

    // the cross product of two vectors (only relevant in three dimensions)
    cross(){

    }


    convertSinCos() {
        const vectors = [this.v, this.w]
        for (let vector of vectors) {
            const isDeg = typeof(vector[1])=== 'string' &&  vector[1].includes("deg")
            if (isDeg) {
                const magnitude = vector[0]
                const dirAngle = vector[1].match(/\d+/g) * (Math.PI / 180);
                vector[0] = magnitude * Math.cos(dirAngle)
                vector[1] = magnitude * Math.sin(dirAngle)
            }
        }
        this.v = vectors[0]
        this.w = vectors[1]
        return this
    }

    round(number) {
        const precision = this.decimalPlaces
        let pair = (number + 'e').split('e')
        let value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
        pair = (value + 'e').split('e')
        return +(pair[0] + 'e' + (+pair[1] - precision))
    }

    getQuadrant() {
        const x = this.v[0]
        const y = this.v[1]
        if (x>=0) {
            return y >= 0 ? 1 : 4
        } else {
            return y >= 0? 2: 3
        }
    }
}