- 새 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>
74 lines
3.0 KiB
TypeScript
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,
|
|
),
|
|
};
|
|
}
|