90 lines
1.9 KiB
TypeScript
90 lines
1.9 KiB
TypeScript
import type { Point } from "./types";
|
|
|
|
const { hypot, cos, sin, atan2 } = Math;
|
|
|
|
export class Vector {
|
|
static zero(): Point {
|
|
return { x: 0, y: 0 };
|
|
}
|
|
|
|
static sub(a: Point, b: Point): Point {
|
|
return { x: a.x - b.x, y: a.y - b.y };
|
|
}
|
|
|
|
static add(a: Point, b: Point): Point {
|
|
return { x: a.x + b.x, y: a.y + b.y };
|
|
}
|
|
|
|
static scale(v: Point, scaleFactor: number): Point {
|
|
return { x: v.x * scaleFactor, y: v.y * scaleFactor };
|
|
}
|
|
|
|
static mag(v: Point): number {
|
|
return Math.sqrt(v.x * v.x + v.y * v.y);
|
|
}
|
|
|
|
static normalized(v: Point): Point {
|
|
const { x, y } = v;
|
|
const magnitude = hypot(x, y);
|
|
if (magnitude === 0) return { x: 0, y: 0 };
|
|
const invMag = 1 / magnitude;
|
|
return { x: x * invMag, y: y * invMag };
|
|
}
|
|
|
|
static distance(a: Point, b: Point): number {
|
|
const dx = a.x - b.x;
|
|
const dy = a.y - b.y;
|
|
return Math.sqrt(dx * dx + dy * dy);
|
|
}
|
|
|
|
static distanceSquared(a: Point, b: Point): number {
|
|
const dx = a.x - b.x;
|
|
const dy = a.y - b.y;
|
|
return dx * dx + dy * dy;
|
|
}
|
|
|
|
static lerp(a: Point, b: Point, t: number): Point {
|
|
return {
|
|
x: a.x + (b.x - a.x) * t,
|
|
y: a.y + (b.y - a.y) * t,
|
|
};
|
|
}
|
|
|
|
static rotate(v: Point, angle: number): Point {
|
|
const _cos = cos(angle);
|
|
const _sin = sin(angle);
|
|
return {
|
|
x: v.x * _cos - v.y * _sin,
|
|
y: v.x * _sin + v.y * _cos,
|
|
};
|
|
}
|
|
|
|
static rotateAround(point: Point, pivot: Point, angle: number): Point {
|
|
const dx = point.x - pivot.x;
|
|
const dy = point.y - pivot.y;
|
|
const c = cos(angle);
|
|
const s = sin(angle);
|
|
return {
|
|
x: pivot.x + dx * c - dy * s,
|
|
y: pivot.y + dx * s + dy * c,
|
|
};
|
|
}
|
|
|
|
static angle(v: Point): number {
|
|
return atan2(v.y, v.x);
|
|
}
|
|
|
|
static angleTo(a: Point, b: Point = { x: 1, y: 0 }): number {
|
|
const angleA = Vector.angle(a);
|
|
const angleB = Vector.angle(b);
|
|
return angleA - angleB;
|
|
}
|
|
|
|
static angleFromOrigin(point: Point, origin: Point): number {
|
|
return Vector.angleTo({
|
|
x: point.x - origin.x,
|
|
y: point.y - origin.y,
|
|
});
|
|
}
|
|
}
|