/* ============================================================================= * D03_PlanAnalysis_PointEdit.ts * D03 지점 칸 손 고침 계산(PLAN 597-2 · 요구 463 7 · 8) — 화면 · fetch 없음(logic/). * 이름 규칙 = `Plan.ts` 의 `nameError`(20 자 · 파일 이름 못 쓰는 글자 · 서버 400 짝) · 빈 값 = 「지점 N」 보임. * 좌표 = 경위도 손 고침 → 작업 좌표(TM) · 그 자리 노선 노드도 같이(`moveNodesAt`). * ========================================================================== */ import { moveNodesAt, type PlanNetwork, type Vertex } from "./D03_PlanAnalysis_Plan"; import { lonLatToTm, type TmParams } from "./D03_PlanAnalysis_Tm"; /** 지점 상한 — 서버 `MAX_POINTS` 와 같음. */ export const MAX_POINTS = 40; /** 보이는 이름 — 빈 값 = 「지점 N」. */ export function pointLabel(names: string[], index: number): string { return names[index]?.trim() || `지점 ${index + 1}`; } /** 경위도 글 → 값 · 못 읽거나 범위 밖이면 까닭 글. */ export function parseLonLat(lonText: string, latText: string): [number, number] | string { const lon = Number(lonText.trim()); const lat = Number(latText.trim()); if (!lonText.trim() || !Number.isFinite(lon) || Math.abs(lon) > 180) return "경도는 −180 ~ 180"; if (!latText.trim() || !Number.isFinite(lat) || Math.abs(lat) > 90) return "위도는 −90 ~ 90"; return [lon, lat]; } export interface PointsState { points: Vertex[]; names: string[]; network: PlanNetwork; } /** 지점 더함 — 이름 비움. 상한이면 그대로. */ export function addPoint(state: PointsState, at: Vertex): PointsState { if (state.points.length >= MAX_POINTS) return state; return { ...state, points: [...state.points, [at[0], at[1]]], names: [...state.names, ""], }; } /** 이름 바꿈 — 빈 값 허용. */ export function renamePoint(state: PointsState, index: number, name: string): PointsState { const names = state.points.map((_, k) => state.names[k] ?? ""); names[index] = name.trim(); return { ...state, names }; } /** 경위도로 옮김 — 그 자리 노선 노드도 같이. */ export function movePointTo( state: PointsState, index: number, tm: TmParams, lon: number, lat: number, ): PointsState { const to = lonLatToTm(tm, lon, lat); const from = state.points[index]; return { ...state, points: state.points.map((p, k): Vertex => (k === index ? to : p)), network: moveNodesAt(state.network, from, to), }; } /** 선 이름 바꿈(597-3) — 빈 값 = 차례 이름으로 돌아감(`name` 비움). */ export function setLineName(network: PlanNetwork, lineId: string, name: string): PlanNetwork { const text = name.trim(); return { ...network, lines: network.lines.map((line) => line.id === lineId ? { ...line, name: text || null } : line, ), }; }