diff --git a/B05_Profile/B05_Profile_UI_RouteEdit.ts b/B05_Profile/B05_Profile_UI_RouteEdit.ts index 46525e10..47599d47 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit.ts @@ -667,17 +667,46 @@ export async function openRouteEditModal( // 잡는 것은 **노드**다 — 폴리라인 정점에는 원호 위 점이 섞여 있어 편집 대상이 아니다 // (2026-09-06 사용자 지시: 노드를 제어해 계획노선을 고친다). const nodes = plan.nodes ?? []; - planned = nodes.map((node) => [node.x, node.y] as Vertex); - nodeInfo = nodes.map((node) => ({ - radius_m: node.radius_m, - inner_angle_deg: node.inner_angle_deg, - violations: node.violations ?? [], - })); minRadiusM = plan.min_radius_m ?? 0; - curveInfo = plan.curves ?? []; - // 편집값은 「서버가 준 그대로」에서 시작한다 — 곡선이 있는 자리는 켬, 반지름은 자동. - curveOn = planned.map(() => true); - curveRadius = planned.map(() => null); + // 곡선 성분을 **편집할 수 있는 꼴로 펴 둔다**(2026-09-07). + // + // 서버는 처음 만들 때 이어진 꺾임을 한 곡선으로 묶는다 — 그 곡선의 교각점은 앞뒤 직선을 + // 늘려 만나는 자리라 **원본 꺾임점 중 어느 것도 아니다**. 그런데 편집은 「꺾임점 하나 = + // 곡선 하나」로 표현되므로, 묶인 곡선을 그대로 두면 한 번만 손대도 그 묶음이 낱개로 + // 흩어지고 **맞춰 둔 반지름이 전부 법정 하한으로 되돌아간다**(실측: R 12~199m → 전부 12m). + // + // 그래서 **묶인 구간을 그 교각점 하나로 갈아 끼운다** — 안쪽 꺾임점은 그 곡선이 대신하므로 + // 뺀다. 앞뒤 직선과 반지름이 그대로라 **그려지는 선은 똑같고**, 이제 손대도 안 흩어진다. + const curves = plan.curves ?? []; + const replaced = new Map(); + const dropped = new Set(); + curves.forEach((curve) => { + replaced.set(curve.node_first, curve); + for (let index = curve.node_first + 1; index <= curve.node_last; index += 1) { + dropped.add(index); + } + }); + planned = []; + nodeInfo = []; + curveOn = []; + curveRadius = []; + curveInfo = []; + nodes.forEach((node, index) => { + if (dropped.has(index)) return; + const curve = replaced.get(index); + const at: Vertex = curve ? [curve.apex[0], curve.apex[1]] : [node.x, node.y]; + const seat = planned.length; + planned.push(at); + nodeInfo.push({ + radius_m: curve ? curve.radius_m : node.radius_m, + inner_angle_deg: curve ? curve.inner_angle_deg : node.inner_angle_deg, + violations: curve ? (curve.violations ?? []) : (node.violations ?? []), + }); + curveOn.push(true); + // 서버가 고른 반지름을 **그대로 들고 간다** — 안 그러면 편집 한 번에 하한으로 눌린다. + curveRadius.push(curve ? Math.round(curve.radius_m * 100) / 100 : null); + if (curve) curveInfo.push({ ...curve, node_first: seat, node_last: seat }); + }); picked = -1; syncCurveBar(); if (!planned.length) planned = plannedLine.map((vertex) => [vertex[0], vertex[1]]);