UNPKG

@dominicstop/utils

Version:

Yet another event emitter written in typescript.

229 lines (228 loc) 6.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Vector2D = void 0; const Angle_1 = require("./Angle"); const Point_1 = require("./Point"); class Vector2D { constructor(args) { this.epsilon = 1e-10; this.dx = args.dx; this.dy = args.dy; } get asValue() { return { dx: this.dx, dy: this.dy, }; } get asPoint() { return new Point_1.Point({ x: this.dx, y: this.dy, }); } ; get asPointValue() { return { x: this.dx, y: this.dy, }; } ; // MARK: - Computed Properties // --------------------------- get magnitude() { return Math.sqrt(this.dx * this.dx + this.dy * this.dy); } get normalized() { const magnitude = this.magnitude; if (magnitude === 0) { return Vector2D.zero; } ; return this.dividedByScalar(magnitude); } get isZero() { return (Math.abs(this.dx) < this.epsilon && Math.abs(this.dy) < this.epsilon); } get isUnit() { return Math.abs(this.magnitude - 1) < this.epsilon; } get perpendicular() { return new Vector2D({ dx: -this.dy, dy: this.dx }); } get inverse() { return new Vector2D({ dx: -this.dx, dy: -this.dy }); } /** * Returns the angle in radians from the positive x-axis to the vector. */ get angle() { const angle = Math.atan2(this.dy, this.dx); return Angle_1.Angle.initFromRadians(angle); } ; // MARK: - Methods // --------------- clone() { return new Vector2D(this.asValue); } ; computeDistanceFromOtherVector(otherVector) { return Vector2D.distanceBetweenTwoVectors(this, otherVector); } isEqualToOtherVector(otherVector, tolerance = this.epsilon) { return (Math.abs(this.dx - otherVector.dx) < tolerance && Math.abs(this.dy - otherVector.dy) < tolerance); } // MARK: - Mutate Methods (Math Operations) // ------------------------------------- addWithOther(other) { this.dx += other.dx; this.dy += other.dy; } ; subtractFromOther(other) { this.dx -= other.dx; this.dy -= other.dy; } multiplyByScalar(scalar) { this.dx *= scalar; this.dy *= scalar; } divideByScalar(scalar) { if (Math.abs(scalar) < this.epsilon) { this.dx = 0; this.dy = 0; } else { this.dx /= scalar; this.dy /= scalar; } } normalizeInPlace() { const mag = this.magnitude; if (mag >= this.epsilon) { this.divideByScalar(mag); } } // MARK: - Methods (Math Operations) // ----------------------------- addedWithOther(otherVector) { return new Vector2D({ dx: this.dx + otherVector.dx, dy: this.dy + otherVector.dy, }); } subtractedWithOther(otherVector) { return new Vector2D({ dx: this.dx - otherVector.dx, dy: this.dy - otherVector.dy, }); } multipliedByScalar(scalar) { return new Vector2D({ dx: this.dx * scalar, dy: this.dy * scalar, }); } dividedByScalar(scalar) { if (scalar === 0) { throw new Error("Cannot divide by zero."); } return new Vector2D({ dx: this.dx / scalar, dy: this.dy / scalar, }); } dotProductWithOtherVector(otherVector) { return this.dx * otherVector.dx + this.dy * otherVector.dy; } /** * Rotates the vector by a given angle in radians. */ rotateByAngle(angle) { const angleInRadians = angle.radians; const cos = Math.cos(angleInRadians); const sin = Math.sin(angleInRadians); return new Vector2D({ dx: this.dx * cos - this.dy * sin, dy: this.dx * sin + this.dy * cos, }); } projectOntoOtherVector(other) { const scalar = this.dotProductWithOtherVector(other) / other.magnitude ** 2; return other.multipliedByScalar(scalar); } angleBetweenOtherVector(other) { const dot = this.dotProductWithOtherVector(other); const mags = this.magnitude * other.magnitude; const angle = Math.acos(Math.min(Math.max(dot / mags, -1), 1)); return Angle_1.Angle.initFromRadians(angle); } crossProductWithOtherVector(other) { return this.dx * other.dy - this.dy * other.dx; } reflectOverOtherVector(vector) { const vectorNormalized = vector.normalized; const dot = this.dotProductWithOtherVector(vectorNormalized); return vectorNormalized .multipliedByScalar(2 * dot) .subtractedWithOther(this); } limit(maxMagnitude) { return this.magnitude > maxMagnitude ? this.normalized.multipliedByScalar(maxMagnitude) : this.clone(); } // MARK: - Static Alias // -------------------- static get zero() { return new Vector2D({ dx: 0, dy: 0 }); } static get one() { return new Vector2D({ dx: 1, dy: 1 }); } static get unitX() { return new Vector2D({ dx: 1, dy: 0 }); } static get unitY() { return new Vector2D({ dx: 0, dy: 1 }); } // MARK: - Static Init // ------------------- static initFromAngle(angle, magnitude = 1) { const radians = angle.radians; return new Vector2D({ dx: Math.cos(radians) * magnitude, dy: Math.sin(radians) * magnitude, }); } static initFromPoints(p1, p2) { return new Vector2D({ dx: p2.x - p1.x, dy: p2.y - p1.y, }); } // MARK: Static Methods // -------------------- static computeAverage(vectors) { if (vectors.length === 0) return Vector2D.zero; const sum = vectors.reduce((acc, v) => acc.addedWithOther(v), Vector2D.zero); return sum.dividedByScalar(vectors.length); } static distanceBetweenTwoVectors(vectorA, vectorB) { const dx = vectorA.dx - vectorB.dx; const dy = vectorA.dy - vectorB.dy; return Math.sqrt(dx * dx + dy * dy); } } exports.Vector2D = Vector2D;