UNPKG

gyrovector

Version:

Gyrovector classes for hyperbolic, Euclidean, and spherical geometries

116 lines (99 loc) 3.31 kB
import { NumberTuple, NumberTuplePrimitive } from './tuples'; import { VectorLike } from './vectorLike'; import { VectorSpaceBase } from './vectorSpaceBase'; import { VectorSpaceLike } from './vectorSpaceLike'; /** * n-dimensional Euclidean vector represented by an array of the correct length */ export class Vector<Dimension extends number> implements VectorLike<Dimension, Vector<Dimension>> { private _tuple: NumberTuple<Dimension>; constructor(...tuple: NumberTuplePrimitive<Dimension>) { this._tuple = new NumberTuple(tuple); } get tuple(): Readonly<NumberTuple<Dimension>> { return this._tuple; } array(): Readonly<NumberTuplePrimitive<Dimension>> { return this._tuple.tuple; } add(v: Vector<Dimension>): Vector<Dimension> { return new Vector<Dimension>( ...this._tuple.map((value, index) => { return value + v.tuple.at(index)!; }).tuple, ); } sub(v: Vector<Dimension>): Vector<Dimension> { return new Vector<Dimension>( ...this._tuple.map((value, index) => { return value - v._tuple.at(index)!; }).tuple, ); } mult(c: number): Vector<Dimension> { return new Vector<Dimension>( ...this._tuple.map((value) => { return c * value; }).tuple, ); } div(c: number): Vector<Dimension> { const reciprocal = 1 / c; return new Vector<Dimension>( ...this._tuple.map((value) => { return reciprocal * value; }).tuple, ); } rotate( radians: number, firstAxis: number = 0, secondAxis: number = 1, ): Vector<Dimension> { const x = this._tuple.at(firstAxis); const y = this._tuple.at(secondAxis); if (x === undefined || y === undefined || firstAxis === secondAxis) { throw new Error( `Vector.rotate(${radians}, ${firstAxis}, ${secondAxis}) called with invalid axes`, ); } return new Vector<Dimension>( ...this._tuple.map((value, index) => { if (index === firstAxis) { return (x * Math.cos(radians)) - (y * Math.sin(radians)); } else if (index === secondAxis) { return (x * Math.sin(radians)) + (y * Math.cos(radians)); } else { return value; } }).tuple, ); } dot(v: Vector<Dimension>): number { return this._tuple.reduce((acc, value, index) => { return acc + (value * v._tuple.at(index)!); }, 0); } magSq(): number { return this.dot(this); } mag(): number { return Math.sqrt(this.magSq()); } } /** * n-dimensional Euclidean vector space for vectors represented by an array of the correct length */ export class VectorSpace<Dimension extends number> extends VectorSpaceBase<Dimension, Vector<Dimension>> implements VectorSpaceLike<Dimension, Vector<Dimension>> { constructor() { super(); } createVector(...tuple: NumberTuplePrimitive<Dimension>): Vector<Dimension> { return new Vector(...tuple); } }