/* ============================================================================= * common_util_station_key.ts * 측점 열쇠 한 규칙(PLAN 344-3) — 노선이 바뀌어도 같은 측점을 같은 이름으로 부름. * 일반 = `grid:k`(누가거리 ÷ 측점 간격 반올림) · 관 = `pipe:` · 구조물 = `structure:` · * 시종점 = `end:BP` · `end:EP` · id 를 모르는 구조물 측점 = `at:<누가거리 0.01 m>`(옛 초안 열쇠와 같은 몫). * * ⚠ 파이썬·TS 짝 — `common_util_station_key.py` `station_key` ↔ `stationKey`. 한쪽을 고치면 다른 쪽도 * 고치고 거울 시험 `resources/tester/test_344_3_station_key_mirror.py`. * ========================================================================== */ /** 측점 종류 — 서버 측점 `kind`(bp · ep · regular · irregular) 그대로 받음. */ export type StationKeyKind = "bp" | "ep" | "regular" | "irregular" | "pipe" | "structure"; /** 누가거리 0.01 m — 옛 초안 열쇠(`toFixed(2)`)와 같은 자릿수. */ export const chainageKey = (chainageM: number): string => (Math.round(chainageM * 100) / 100).toFixed(2); /** * 측점 열쇠. irregular 는 id 가 있으면 `pipe:` · `structure:`(종류는 `idKind`) · 없으면 `at:`. * 간격이 없거나 0 이하면 일반 측점도 `at:`. */ export function stationKey( kind: StationKeyKind, chainageM: number, intervalM: number | null, id: string | null = null, idKind: "pipe" | "structure" = "structure", ): string { if (kind === "bp") return "end:BP"; if (kind === "ep") return "end:EP"; if (kind === "pipe" || kind === "structure") return id ? `${kind}:${id}` : `at:${chainageKey(chainageM)}`; if (kind === "irregular") return id ? `${idKind}:${id}` : `at:${chainageKey(chainageM)}`; if (intervalM && intervalM > 0) return `grid:${Math.round(chainageM / intervalM)}`; return `at:${chainageKey(chainageM)}`; } /** 옛 초안 열쇠(누가거리 글 `"85.05"`) · `at:` 열쇠의 누가거리 — 측점 열쇠면 null. */ export function looseChainage(key: string): number | null { const text = key.startsWith("at:") ? key.slice(3) : key; if (!/^-?\d+(\.\d+)?$/.test(text)) return null; return Number(text); }