/* ============================================================================= * A00_Common/design/logic/design_calc_node_route.ts * 계산 Node 입구(`design_calc_node.ts`)의 노선 몫(PLAN 511-B B-5) — 화면 노선 편집과 같은 TS. * * route.polyline 입력 route_polyline { points · curve_flags · radii · locks · arcs · min_radius_m } → * { cleaned: 겹친 점(0.5 m) 뺀 노드 · nodes: 노드 요약(cleaned 자리) · vertices: 선 · * curves: 곡선(node_first · last = cleaned 자리) · edits: 곡선표 편집표 } * — 서버 노선 저장 `_write_planned_polyline`(편집 갈래 · 파이썬은 파일 꼴 반올림만) * ========================================================================== */ import { buildEditedPolyline, DUPLICATE_TOLERANCE_M, type Vertex, } from "../../../B05_Profile/logic/B05_Profile_UI_RouteEdit_Curve"; import { nodeEdits } from "../../../B05_Profile/logic/B05_Profile_UI_RouteEdit_Edits"; export interface RouteInputs { route_polyline?: { points: Vertex[]; curve_flags?: Array | null; radii?: Array | null; locks?: Array | null; arcs?: Array | null; min_radius_m: number; }; } /** id → 셈(입구 `RUNNERS` 에 얹음). */ export function routeRunners(inputs: RouteInputs): Record unknown> { return { "route.polyline": () => { const at = inputs.route_polyline; if (!at) throw new Error("노선 입력(route_polyline) 없음"); const flags = at.curve_flags ?? null; const radii = at.radii ?? null; // 겹친 점을 편집값과 함께 거름 — 곡선 자리 번호 = 저장 노드 자리(파이썬 `build_planned_polyline`) const cleaned: Vertex[] = []; const on: boolean[] = []; const forced: Array = []; at.points.forEach((point, index) => { const last = cleaned[cleaned.length - 1]; if (last && Math.hypot(point[0] - last[0], point[1] - last[1]) <= DUPLICATE_TOLERANCE_M) return; cleaned.push(point); on.push(flags && index < flags.length ? Boolean(flags[index]) : true); forced.push(radii && index < radii.length ? radii[index] : null); }); const line = buildEditedPolyline(cleaned, on, forced, at.min_radius_m); return { cleaned, nodes: line.nodes, vertices: line.vertices, curves: line.curves, edits: nodeEdits(at.points, flags, radii, at.locks ?? null, at.arcs ?? null), }; }, }; }