Files
Aislo/D03_PlanAnalysis/logic/D03_PlanAnalysis_Span.ts
T
eomsangdonandClaude Opus 5.5 3b34301b56 feat(D 예정노선): 다시 긋기 — 고른 구간 앞 노드부터 긋고 원래 뒤 노드에 붙으면 끝 · 다른 구역에 닿아 끝난 본선 = 저절로 갈래 (PLAN 599-3 · 요구 463-12 · 15)
- 새 logic/D03_PlanAnalysis_Span.ts — replaceSpan · respanBlocked(속 점 갈래 막음 · 뒤 갈래 차례 밈 · 마크 길이 비율 · 조각 id 그대로)
- draw.respan(lineId, from, to) — 598 판 [다시 긋기]가 부름 · 속 구간 흐리게(paintNetwork dim) · Enter = 취소 · Backspace = 점 빼기
- 긋기 끝 꼬리가 다른 구역 꺾임점 = 뒤집어 그 점의 갈래(No.0 = 닿은 점)
- 새 시험 599_3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 14:44:25 +09:00

74 lines
3.0 KiB
TypeScript

/* =============================================================================
* D03_PlanAnalysis_Span.ts
* D 예정노선 다시 긋기(PLAN 599-3 · 요구 463-12) — 선 하나의 두 꺾임점 사이를 새로 그은 점들로 바꿈.
* 끝 두 점(앞 노드 · 뒤 노드) 그대로 · 속 꺾임점에 갈래가 붙었으면 막음(까닭 글) · 뒤 갈래 차례 밈 ·
* 마크(조각 경계) = 바뀐 구간 안은 길이 비율 · 뒤는 길이 차만큼 · 조각 id 그대로(업체 열쇠).
* DOM · fetch · sessionStorage 없음 · 길이 셈 = 562-1 짝(`D03_PlanAnalysis_Draw`).
* ========================================================================== */
import { lineLength } from "./D03_PlanAnalysis_Draw";
import type { PlanNetwork, Vertex } from "./D03_PlanAnalysis_Plan";
const round3 = (value: number): number => Math.round(value * 1000) / 1000;
/** `line` 째 선 `from`~`to` 꺾임점 사이를 다시 그을 수 있나 — 못 하면 까닭 글. */
export function respanBlocked(
network: PlanNetwork,
line: number,
from: number,
to: number,
): string | null {
const entry = network.lines[line];
if (!entry || !(from >= 0 && to > from && to < entry.vertices.length))
return "다시 그을 구간을 고르세요.";
if (
network.lines.some(
(o) => o.branch?.line === entry.id && o.branch.vertex > from && o.branch.vertex < to,
)
)
return "구간 속 점에 갈래가 붙어 있습니다 — 갈래를 먼저 지우세요.";
return null;
}
/** `line` 째 선 `from`~`to` 꺾임점 사이 속 점을 `through` 로 바꿈(끝 두 점 그대로) — 막히면 까닭 글. */
export function replaceSpan(
network: PlanNetwork,
line: number,
from: number,
to: number,
through: ReadonlyArray<Vertex>,
): PlanNetwork | string {
const blocked = respanBlocked(network, line, from, to);
if (blocked) return blocked;
const entry = network.lines[line];
const old = entry.vertices;
const vertices: Vertex[] = [
...old.slice(0, from + 1),
...through.map(([x, y]): Vertex => [x, y]),
...old.slice(to),
];
const shift = through.length - (to - from - 1);
const at = (list: ReadonlyArray<Vertex>, i: number): number => lineLength(list.slice(0, i + 1));
const [startM, oldEndM, newEndM] = [at(old, from), at(old, to), at(vertices, to + shift)];
const carry = (m: number): number =>
m <= startM
? m
: m >= oldEndM
? m - oldEndM + newEndM
: startM + ((m - startM) / (oldEndM - startM)) * (newEndM - startM);
return {
lines: network.lines.map((other, i) => {
if (i === line) return { ...other, vertices };
const branch = other.branch;
return branch?.line === entry.id && branch.vertex >= to
? { ...other, branch: { ...branch, vertex: branch.vertex + shift } }
: other;
}),
pieces: network.pieces.map((piece) =>
piece.line === entry.id
? { ...piece, from_m: round3(carry(piece.from_m)), to_m: round3(carry(piece.to_m)) }
: piece,
),
};
}