UNPKG

cerceis-lib

Version:

Contains list of quality of life functions that is written in TypeScript and es6

290 lines (281 loc) 9.75 kB
export interface VectorObject { isVectorObject: boolean; x: number, y: number, z: number, // Maths add: (x: VectorObject | number[] | number, y?: number, z?: number) => VectorObject, limit: (max: number) => VectorObject, div: (x: VectorObject | number[] | number, y?: number, z?: number) => VectorObject, mult: (x: VectorObject | number[] | number, y?: number, z?: number) => VectorObject, heading: () => number, sub: (x: VectorObject | number[] | number, y?: number, z?: number) => VectorObject, setMag: (n: number) => VectorObject, magSq: () => number, mag: () => number, normalize: () => VectorObject, copy: () => VectorObject, dist: (x: VectorObject | number, y?: number) => number, // exports toVector2: () => number[] toVector3: () => number[] } /** * Structure and logic are based on p5js. */ export const createVector = (x: number, y: number, z: number = 0) => { const vectorObject: VectorObject = { isVectorObject: true, x, y, z, /** * @param x { VectorObject | Number[] | number } * @returns */ add(x: any, y: number = 0, z: number = 0) { if (x instanceof Array) { this.x += x[0] || 0; this.y += x[1] || 0; this.z += x[2] || 0; return this; } if (x.isVectorObject) { this.x += x.x || 0; this.y += x.y || 0; this.z += x.z || 0; return this; } this.x += x || 0; this.y += y || 0; this.z += z || 0; return this; }, limit(max: number) { const mSq = this.magSq(); if (mSq > max * max) { this.div(Math.sqrt(mSq)) //normalize it .mult(max); } return this; }, /** * * @param x { VectorObject | Number[] | number } * @param y { number } * @param z { number } * @returns */ div(x: any, y: number = 0, z: number = 0) { if (x.isVectorObject) { if ( Number.isFinite(x.x) && Number.isFinite(x.y) && Number.isFinite(x.z) && typeof x.x === 'number' && typeof x.y === 'number' && typeof x.z === 'number' ) { this.x /= x.x; this.y /= x.y; this.z /= x.z; } return this; } if (x instanceof Array) { if ( x.every(element => Number.isFinite(element)) && x.every(element => typeof element === 'number') ) { if (x.some(element => element === 0)) { console.warn('Divide by 0'); return this; } if (x.length === 1) { this.x /= x[0]; this.y /= x[0]; this.z /= x[0]; } else if (x.length === 2) { this.x /= x[0]; this.y /= x[1]; } else if (x.length === 3) { this.x /= x[0]; this.y /= x[1]; this.z /= x[2]; } } else { console.warn( 'x contains components that are either undefined or not finite numbers' ); } return this; } const vectorComponents = [...arguments]; if ( vectorComponents.every(element => Number.isFinite(element)) && vectorComponents.every(element => typeof element === 'number') ) { if (vectorComponents.some(element => element === 0)) { console.warn('Divide by 0'); return this; } if (arguments.length === 1) { this.x /= x; this.y /= x; this.z /= x; } if (arguments.length === 2) { this.x /= x; this.y /= y; } if (arguments.length === 3) { this.x /= x; this.y /= y; this.z /= z; } } else { console.warn( 'x, y, or z arguments are either undefined or not a finite number' ); } return this; }, /** * * @param x { VectorObject | Number[] | number } * @param y { number } * @param z { number } * @returns */ mult(x: any, y: number = 0, z: number = 0) { if (x.isVectorObject) { // new p5.Vector will check that values are valid upon construction but it's possible // that someone could change the value of a component after creation, which is why we still // perform this check if ( Number.isFinite(x.x) && Number.isFinite(x.y) && Number.isFinite(x.z) && typeof x.x === 'number' && typeof x.y === 'number' && typeof x.z === 'number' ) { this.x *= x.x; this.y *= x.y; this.z *= x.z; } else { console.warn( 'x contains components that are either undefined or not finite numbers' ); } return this; } if (x instanceof Array) { if ( x.every(element => Number.isFinite(element)) && x.every(element => typeof element === 'number') ) { if (x.length === 1) { this.x *= x[0]; this.y *= x[0]; this.z *= x[0]; } else if (x.length === 2) { this.x *= x[0]; this.y *= x[1]; } else if (x.length === 3) { this.x *= x[0]; this.y *= x[1]; this.z *= x[2]; } } else { console.warn( 'x contains elements that are either undefined or not finite numbers' ); } return this; } const vectorComponents = [...arguments]; if ( vectorComponents.every(element => Number.isFinite(element)) && vectorComponents.every(element => typeof element === 'number') ) { if (arguments.length === 1) { this.x *= x; this.y *= x; this.z *= x; } if (arguments.length === 2) { this.x *= x; this.y *= y; } if (arguments.length === 3) { this.x *= x; this.y *= y; this.z *= z; } } else { console.warn( 'x, y, or z arguments are either undefined or not a finite number' ); } return this; }, heading() { const h = Math.atan2(this.y, this.x); return h; }, /* * @method sub * @param {VectorObject | Number[]} value the vector to subtract * @chainable */ sub(x: any, y: number = 0, z: number = 0) { if (x.isVectorObject) { 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; }, setMag(n) { return this.normalize().mult(n); }, magSq() { const x = this.x; const y = this.y; const z = this.z; return x * x + y * y + z * z; }, mag() { return Math.sqrt(this.magSq()); }, normalize() { const 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; }, copy() { return createVector(this.x, this.y, this.z); }, dist(x: any, y: number = 0) { if (x.isVectorObject) { return Math.hypot(x.x - this.x, x.y - this.y); } return Math.hypot(x - this.x, y - this.y); }, toVector2(){ return [this.x, this.y] }, toVector3(){ return [this.x, this.y, this.z] }, } return vectorObject; } export const FromVector = { create: createVector }