78 lines
2.8 KiB
TypeScript
78 lines
2.8 KiB
TypeScript
/* =============================================================================
|
||
* 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,
|
||
),
|
||
};
|
||
}
|