Files
walkersim/src/math.js

67 lines
1.3 KiB
JavaScript

export const TAU = Math.PI * 2;
export function vec(x, y) {
return { x, y };
}
export function add(a, b) {
return vec(a.x + b.x, a.y + b.y);
}
export function sub(a, b) {
return vec(a.x - b.x, a.y - b.y);
}
export function scale(a, s) {
return vec(a.x * s, a.y * s);
}
export function len(a) {
return Math.hypot(a.x, a.y);
}
export function dist(a, b) {
return len(sub(a, b));
}
export function clamp(v, lo, hi) {
return Math.max(lo, Math.min(hi, v));
}
export function normalizeAngleRad(theta) {
let t = theta % TAU;
if (t < 0) t += TAU;
return t;
}
export function radToDeg(rad) {
return (rad * 180) / Math.PI;
}
export function degToRad(deg) {
return (deg * Math.PI) / 180;
}
export function circleCircleIntersection(c0, r0, c1, r1, eps = 1e-9) {
const d = dist(c0, c1);
if (d < eps) return null;
if (d > r0 + r1 + eps) return null;
if (d < Math.abs(r0 - r1) - eps) return null;
const a = (r0 * r0 - r1 * r1 + d * d) / (2 * d);
let h2 = r0 * r0 - a * a;
if (h2 < 0 && h2 > -1e-8) h2 = 0;
if (h2 < 0) return null;
const h = Math.sqrt(h2);
const p2 = add(c0, scale(sub(c1, c0), a / d));
const rx = -((c1.y - c0.y) * (h / d));
const ry = (c1.x - c0.x) * (h / d);
return {
p1: vec(p2.x + rx, p2.y + ry),
p2: vec(p2.x - rx, p2.y - ry),
};
}