67 lines
1.3 KiB
JavaScript
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),
|
|
};
|
|
}
|
|
|