Initial project import

This commit is contained in:
drjones
2026-06-13 17:36:44 -07:00
commit ad2a18cc8d
18471 changed files with 4497570 additions and 0 deletions

70
src/routing/vec.ts Normal file
View File

@@ -0,0 +1,70 @@
import type { Vec3 } from '../types';
/** Tolerance used for geometric comparisons throughout the router (ft). */
export const EPS = 1e-6;
export const add = (a: Vec3, b: Vec3): Vec3 => [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
export const sub = (a: Vec3, b: Vec3): Vec3 => [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
export const scale = (a: Vec3, s: number): Vec3 => [a[0] * s, a[1] * s, a[2] * s];
export const dot = (a: Vec3, b: Vec3) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
export const cross = (a: Vec3, b: Vec3): Vec3 => [
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
];
export const length = (a: Vec3) => Math.hypot(a[0], a[1], a[2]);
export const dist = (a: Vec3, b: Vec3) => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
export const manhattan = (a: Vec3, b: Vec3) =>
Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]) + Math.abs(a[2] - b[2]);
export const vecEquals = (a: Vec3, b: Vec3, eps = EPS) =>
Math.abs(a[0] - b[0]) < eps && Math.abs(a[1] - b[1]) < eps && Math.abs(a[2] - b[2]) < eps;
/**
* The six axis-aligned unit directions. Index layout: even = positive,
* odd = negative, so `idx >> 1` is the axis (0=X 1=Y 2=Z) and `idx ^ 1`
* is the reversed direction.
*/
export const AXIS_DIRS: readonly Vec3[] = [
[1, 0, 0],
[-1, 0, 0],
[0, 1, 0],
[0, -1, 0],
[0, 0, 1],
[0, 0, -1],
];
export const axisOfDir = (dirIdx: number) => dirIdx >> 1;
export const signOfDir = (dirIdx: number) => (dirIdx & 1 ? -1 : 1);
export const reverseDir = (dirIdx: number) => dirIdx ^ 1;
/** Index into AXIS_DIRS for an (exactly) axis-aligned unit vector, or -1. */
export function dirIndexOf(v: Vec3, eps = EPS): number {
for (let i = 0; i < 6; i++) {
const d = AXIS_DIRS[i];
if (Math.abs(v[0] - d[0]) < eps && Math.abs(v[1] - d[1]) < eps && Math.abs(v[2] - d[2]) < eps) {
return i;
}
}
return -1;
}
/**
* Snap a roughly axis-aligned direction to the nearest exact axis direction.
* Returns null when the vector is degenerate or too far from any axis
* (more than ~25° off).
*/
export function snapAxisDir(v: Vec3): Vec3 | null {
const l = length(v);
if (l < EPS) return null;
const n: Vec3 = [v[0] / l, v[1] / l, v[2] / l];
let best = -1;
let bestDot = 0.9; // cos(~25°) — refuse wildly diagonal directions
for (let i = 0; i < 6; i++) {
const d = dot(n, AXIS_DIRS[i]);
if (d > bestDot) {
bestDot = d;
best = i;
}
}
return best >= 0 ? ([...AXIS_DIRS[best]] as Vec3) : null;
}