@rdme/curve-2d
Version:
2d curves in typescript
122 lines (98 loc) • 2.98 kB
text/typescript
import { lerp } from "src/util";
const { atan2, sqrt, pow, cos, sin, PI } = Math;
const taw = PI * 2;
export interface Vec2dLike {
x: number;
y: number;
}
export class Vec2d {
x: number;
y: number;
public constructor();
public constructor(x: number, y: number);
public constructor(init: Vec2dLike);
public constructor(init: [x: number, y: number]);
constructor(initOrX?: number | Vec2dLike | [number, number], y?: number) {
if (typeof initOrX === "object") {
if (Array.isArray(initOrX)) {
this.x = initOrX[0] ?? 0;
this.y = initOrX[1] ?? 0;
} else {
this.x = initOrX.x ?? 0;
this.y = initOrX.y ?? 0;
}
} else {
this.x = initOrX ?? 0;
this.y = y ?? 0;
}
}
public clone() {
return new Vec2d(this);
}
public get angle(): number {
const angle = atan2(this.x, this.y);
return angle < 0 ? angle + taw : angle;
}
public set angle(val: number) {
const len = this.length;
this.x = sin(val) * len;
this.y = cos(val) * len;
}
public get length(): number {
return sqrt(pow(this.x, 2) + pow(this.y, 2));
}
public set length(val: number) {
const angle = this.angle;
this.x = sin(angle) * val;
this.y = cos(angle) * val;
}
public get normal(): Vec2d {
return Vec2d.fromAngle(this.angle);
}
public get values(): [number, number] {
return [this.x, this.y];
}
public rotate(angle: number, origin: Vec2dLike = { x: 0, y: 0 }): Vec2d {
const offset = this.subtract(origin);
offset.angle += angle;
return offset.add(origin);
}
public add(other: Vec2dLike): Vec2d {
return new Vec2d(this.x + other.x, this.y + other.y);
}
public subtract(other: Vec2dLike): Vec2d {
return new Vec2d(this.x - other.x, this.y - other.y);
}
public distance(other: Vec2dLike): number {
return sqrt(pow(this.x - other.x, 2) + pow(this.y - other.y, 2));
}
public scale(factor: number, origin: Vec2dLike = { x: 0, y: 0 }): Vec2d {
const direction = this.subtract(origin);
direction.length *= factor;
return direction.add(origin);
}
public exponentiate(exponent: number): Vec2d {
return Vec2d.fromAngle(this.angle, pow(this.length, exponent));
}
public multiplySymmetric(other: Vec2dLike): Vec2d {
return new Vec2d(this.x * other.x, this.y * other.y);
}
public multiplyAsymmetric(other: Vec2dLike): Vec2d {
return new Vec2d(this.x * other.y, this.y * other.x);
}
public multiplyValues(factor: number) {
return new Vec2d(this.x * factor, this.y * factor);
}
public divideValues(divisor: number) {
return new Vec2d(this.x / divisor, this.y / divisor);
}
public lerp(other: Vec2dLike, value: number) {
return new Vec2d(
lerp(this.x, other.x, value),
lerp(this.y, other.y, value)
);
}
static fromAngle(angle: number, distance = 1): Vec2d {
return new Vec2d(sin(angle) * distance, cos(angle) * distance);
}
}