export const Vec2 = { Mutate: { add(target, [x, y]) { target[0] += x; target[1] += y; return target; }, scale(target, factor) { target[0] *= factor; target[1] *= factor; return target; }, normalize(target) { const norm = Vec2.norm2([x, y]); target[0] /= norm; target[1] /= norm; return target; }, set(target, [x, y]) { target[0] = x; target[1] = y; return target; }, }, perpendicular([x, y]) { return [-y, x]; }, distance2(v1, v2) { return Vec2.norm2(Vec2.sub(v1, v2)); }, add([x1, y1], [x2, y2]) { return [x1 + x2, y1 + y2]; }, sub([x1, y1], [x2, y2]) { return [x1 - x2, y1 - y2]; }, dot([x1, y1], [x2, y2]) { return x1 * x2 + y1 * y2; }, scale([x, y], factor) { return [x * factor, y * factor]; }, norm2([x, y]) { return Math.sqrt(x ** 2 + y ** 2); }, normalize([x, y]) { const norm = Vec2.norm2([x, y]); return [x / norm, y / norm]; }, findNearest(curve, pt) { let index = -1; let minDist = +Infinity; for (let i = 0; i < curve.length; i++) { const d = Vec2.distance2(curve[i], pt); if (d < minDist) { index = i; minDist = d; } } return [index, minDist]; }, }; export const Vec3 = { Mutate: { add(target, [x, y, z]) { target[0] += x; target[1] += y; target[2] += z; return target; }, scale(target, factor) { target[0] *= factor; target[1] *= factor; target[2] *= factor; return target; }, normalize(target) { const norm = Vec3.norm2(target); target[0] /= norm; target[1] /= norm; target[2] /= norm; return target; }, }, withMaxLength(v, max) { const d = Vec3.norm2(v); if (d > max) { return Vec3.scale(v, max / d); } return v; }, distance2(v1, v2) { return Vec3.norm2(Vec3.sub(v1, v2)); }, add([x1, y1, z1], [x2, y2, z2]) { return [x1 + x2, y1 + y2, z1 + z2]; }, sub([x1, y1, z1], [x2, y2, z2]) { return [x1 - x2, y1 - y2, z1 - z2]; }, dot([x1, y1, z1], [x2, y2, z2]) { return x1 * x2 + y1 * y2 + z1 * z2; }, scale([x, y, z], factor) { return [x * factor, y * factor, z * factor]; }, norm2([x, y, z]) { return Math.sqrt(x ** 2 + y ** 2 + z ** 2); }, normalize([x, y, z]) { const norm = Vec3.norm2([x, y, z]); return [x / norm, y / norm, z / norm]; }, findNearest(curve, pt) { let index = -1; let minDist = +Infinity; for (let i = 0; i < curve.length; i++) { const d = Vec3.distance2(curve[i], pt); if (d < minDist) { index = i; minDist = d; } } return [index, minDist]; }, }; export function clamp(min, value, max) { return Math.min(max, Math.max(min, value)); }