UNPKG

@js-basics/vector

Version:

A 3D Vector lib including arithmetic operator overloading (+ - * / % **).

226 lines (213 loc) 4.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ZERO = exports.Point = exports.LEFT = exports.IPoint = exports.FORWARD = void 0; exports.calc = calc; exports.point = exports.ipoint = void 0; var _math = require("./utils/math.cjs"); var _operator = require("./operator.cjs"); var _css = require("./utils/css.cjs"); const X = 0; const Y = 1; const AXES = Symbol('axes'); function angleOverGround(y1, x1, y2, x2) { const atanOne = Math.atan2(y1, x1); const atanTwo = Math.atan2(y2, x2); return (0, _math.normRad)(atanOne - atanTwo); } function square(val) { return val * val; } class APoint { constructor(...args) { if (typeof args[0] === 'function') { (0, _operator.operatorCalc)(args[0], (nx, ny) => { this[AXES] = [nx, ny]; }); } else if ((0, _math.isArray)(args[0])) { this[AXES] = [...args[0]]; } else if (args[0] && (0, _math.isNumber)(args[0].x)) { this[AXES] = [args[0].x || 0, args[0].y || 0]; } else { this[AXES] = [args[0] || 0, args[1] || 0]; } } valueOf() { throw new Error('valueOf() not implemented, looks like you try to calculate outside of calc'); } /** * @returns {this} */ normalize() { const { length } = this; return new this.constructor(this.x / length, this.y / length); } /** * @returns {this} */ norm() { return this.normalize(); } // methods ispired by // https://evanw.github.io/lightgl.js/docs/point.html dot(v) { return this.x * v.x + this.y * v.y; } getRad() { return (0, _math.normRad)(Math.atan2(this.y, this.x)); } /** * @param {APoint} v */ angleTo(v) { return angleOverGround(this.y, this.x, v.y, v.x); } /** * @param {number} angle * @returns {this} */ rotate(angle) { const sa = Math.sin(angle); const ca = Math.cos(angle); const x = this.x * ca - this.y * sa; const y = this.x * sa + this.y * ca; return new this.constructor(x, y); } /** * @param {APoint} v */ distance(v) { return Math.sqrt(square(this.x - v.x) + square(this.y - v.y)); } /** * @param {APoint} v */ dist(v) { return this.distance(v); } /** * @returns {[number, number]} */ toArray() { return [this.x, this.y]; } // eslint-disable-next-line no-unused-vars calc(alg) { throw new Error('calc() not implemented'); } clone() { throw new Error('clone() not implemented'); } equals(v) { return this.x === v.x && this.y === v.y; } toJSON() { return { x: this.x, y: this.y }; } toString() { return JSON.stringify(this.toJSON()); } toCSSVars(name, target) { return (0, _css.convertToCSSVars)(name, this.toJSON(), target); } get lengthSq() { return this.dot(this); } get length() { return Math.sqrt(this.lengthSq); } get lensq() { return this.lengthSq; } get len() { return this.length; } get x() { return this[AXES][X]; } set x(_) { throw new Error('set x() not implemented'); } get y() { return this[AXES][Y]; } set y(_) { throw new Error('set y() not implemented'); } get z() { throw new Error('get z() not implemented'); } set z(_) { throw new Error('set z() not implemented'); } [Symbol.iterator]() { return this[AXES].values(); } } (0, _operator.cachedValueOf)(APoint); (0, _operator.defineVectorLength)(APoint, 2); (0, _operator.cachedMethod)(APoint, 'dot'); (0, _operator.cachedMethod)(APoint, 'angleTo'); (0, _operator.cachedMethod)(APoint, 'distance'); (0, _operator.cachedMethod)(APoint, 'toArray'); (0, _operator.cachedMethod)(APoint, 'getRad'); (0, _operator.cachedGetter)(APoint, 'length'); (0, _operator.cachedGetter)(APoint, 'lengthSq'); class Point extends APoint { set x(x) { this[AXES][X] = x; } set y(y) { this[AXES][Y] = y; } get x() { return this[AXES][X]; } get y() { return this[AXES][Y]; } calc(alg) { return (0, _operator.operatorCalc)(alg, this); } clone() { return new Point(this.x, this.y); } } exports.Point = Point; class IPoint extends APoint { /** * @returns {Point & number} */ toPoint() { return new Point(this.x, this.y); } } exports.IPoint = IPoint; function calc(alg) { return (0, _operator.operatorCalc)(alg); } const pointFactory = (0, _operator.cachedFunction)((x, y) => new Point(x, y)); /** * @param {number | () => number} x * @param {number} [y] * @returns {Point & number} */ const point = (x, y) => pointFactory(x, y); exports.point = point; const ipointFactory = (0, _operator.cachedFunction)((x, y) => new IPoint(x, y)); /** * @param {number | () => number} x * @param {number} [y] * @returns {IPoint & number} */ const ipoint = (x, y) => ipointFactory(x, y); exports.ipoint = ipoint; const ZERO = exports.ZERO = ipoint(0, 0); const FORWARD = exports.FORWARD = ipoint(0, -1); const LEFT = exports.LEFT = ipoint(-1, 0);