Spaces:
Sleeping
Sleeping
| import type { GlobalPoint, LocalPoint, Vector } from "./types"; | |
| /** | |
| * Create a vector from the x and y coordiante elements. | |
| * | |
| * @param x The X aspect of the vector | |
| * @param y T Y aspect of the vector | |
| * @returns The constructed vector with X and Y as the coordinates | |
| */ | |
| export function vector( | |
| x: number, | |
| y: number, | |
| originX: number = 0, | |
| originY: number = 0, | |
| ): Vector { | |
| return [x - originX, y - originY] as Vector; | |
| } | |
| /** | |
| * Turn a point into a vector with the origin point. | |
| * | |
| * @param p The point to turn into a vector | |
| * @param origin The origin point in a given coordiante system | |
| * @param threshold The threshold to consider the vector as 'undefined' | |
| * @param defaultValue The default value to return if the vector is 'undefined' | |
| * @returns The created vector from the point and the origin or default | |
| */ | |
| export function vectorFromPoint<Point extends GlobalPoint | LocalPoint>( | |
| p: Point, | |
| origin: Point = [0, 0] as Point, | |
| threshold?: number, | |
| defaultValue: Vector = [0, 1] as Vector, | |
| ): Vector { | |
| const vec = vector(p[0] - origin[0], p[1] - origin[1]); | |
| if (threshold && vectorMagnitudeSq(vec) < threshold * threshold) { | |
| return defaultValue; | |
| } | |
| return vec; | |
| } | |
| /** | |
| * Cross product is a binary operation on two vectors in 2D space. | |
| * It results in a vector that is perpendicular to both vectors. | |
| * | |
| * @param a One of the vectors to use for the directed area calculation | |
| * @param b The other vector to use for the directed area calculation | |
| * @returns The directed area value for the two vectos | |
| */ | |
| export function vectorCross(a: Vector, b: Vector): number { | |
| return a[0] * b[1] - b[0] * a[1]; | |
| } | |
| /** | |
| * Dot product is defined as the sum of the products of the | |
| * two vectors. | |
| * | |
| * @param a One of the vectors for which the sum of products is calculated | |
| * @param b The other vector for which the sum of products is calculated | |
| * @returns The sum of products of the two vectors | |
| */ | |
| export function vectorDot(a: Vector, b: Vector) { | |
| return a[0] * b[0] + a[1] * b[1]; | |
| } | |
| /** | |
| * Determines if the value has the shape of a Vector. | |
| * | |
| * @param v The value to test | |
| * @returns TRUE if the value has the shape and components of a Vectors | |
| */ | |
| export function isVector(v: unknown): v is Vector { | |
| return ( | |
| Array.isArray(v) && | |
| v.length === 2 && | |
| typeof v[0] === "number" && | |
| !isNaN(v[0]) && | |
| typeof v[1] === "number" && | |
| !isNaN(v[1]) | |
| ); | |
| } | |
| /** | |
| * Add two vectors by adding their coordinates. | |
| * | |
| * @param a One of the vectors to add | |
| * @param b The other vector to add | |
| * @returns The sum vector of the two provided vectors | |
| */ | |
| export function vectorAdd(a: Readonly<Vector>, b: Readonly<Vector>): Vector { | |
| return [a[0] + b[0], a[1] + b[1]] as Vector; | |
| } | |
| /** | |
| * Add two vectors by adding their coordinates. | |
| * | |
| * @param start One of the vectors to add | |
| * @param end The other vector to add | |
| * @returns The sum vector of the two provided vectors | |
| */ | |
| export function vectorSubtract( | |
| start: Readonly<Vector>, | |
| end: Readonly<Vector>, | |
| ): Vector { | |
| return [start[0] - end[0], start[1] - end[1]] as Vector; | |
| } | |
| /** | |
| * Scale vector by a scalar. | |
| * | |
| * @param v The vector to scale | |
| * @param scalar The scalar to multiply the vector components with | |
| * @returns The new scaled vector | |
| */ | |
| export function vectorScale(v: Vector, scalar: number): Vector { | |
| return vector(v[0] * scalar, v[1] * scalar); | |
| } | |
| /** | |
| * Calculates the sqare magnitude of a vector. Use this if you compare | |
| * magnitudes as it saves you an SQRT. | |
| * | |
| * @param v The vector to measure | |
| * @returns The scalar squared magnitude of the vector | |
| */ | |
| export function vectorMagnitudeSq(v: Vector) { | |
| return v[0] * v[0] + v[1] * v[1]; | |
| } | |
| /** | |
| * Calculates the magnitude of a vector. | |
| * | |
| * @param v The vector to measure | |
| * @returns The scalar magnitude of the vector | |
| */ | |
| export function vectorMagnitude(v: Vector) { | |
| return Math.sqrt(vectorMagnitudeSq(v)); | |
| } | |
| /** | |
| * Normalize the vector (i.e. make the vector magnitue equal 1). | |
| * | |
| * @param v The vector to normalize | |
| * @returns The new normalized vector | |
| */ | |
| export const vectorNormalize = (v: Vector): Vector => { | |
| const m = vectorMagnitude(v); | |
| if (m === 0) { | |
| return vector(0, 0); | |
| } | |
| return vector(v[0] / m, v[1] / m); | |
| }; | |
| /** | |
| * Calculate the right-hand normal of the vector. | |
| */ | |
| export const vectorNormal = (v: Vector): Vector => vector(v[1], -v[0]); | |