import { port } from './model.js'; import { measure } from './motion.js'; function bezier(a, b, c, d) { return Array.from({ length: 37 }, (_, i) => { const t = i / 36, u = 1 - t; return { x: u ** 3 * a.x + 3 * u * u * t * b.x + 3 * u * t * t * c.x + t ** 3 * d.x, y: u ** 3 * a.y + 3 * u * u * t * b.y + 3 * u * t * t * c.y + t ** 3 * d.y }; }); } export function departure(route, kind, screen, perimeter) { const points = route.points.map(screen), end = points.at(-1), dir = port(kind, route.exitDir); const direction = { x: dir.x * 2, y: dir.y * 2 }; const hit = perimeter.intersect(end, direction); const a = hit.parameter + 26 / perimeter.unit; const entry = perimeter.at(a), tangent = { x: Math.cos(entry.angle), y: Math.sin(entry.angle) }; const join = bezier(end, { x: end.x + direction.x * hit.distance * .65, y: end.y + direction.y * hit.distance * .65 }, { x: entry.x - tangent.x * 18, y: entry.y - tangent.y * 18 }, entry); return { path: measure([...points, ...join.slice(1)]), boardLength: measure(points).length, entry: a, connector: join }; } export function garagePath(perimeter, width) { const finish = perimeter.at(0); return measure(bezier(finish, { x: finish.x + Math.cos(finish.angle) * 22, y: finish.y + Math.sin(finish.angle) * 22 }, { x: width - 76, y: finish.y - 8 }, { x: width - 62, y: finish.y - 36 })); }