/* ============================================================================= * B05_Profile/logic/B05_Profile_Profile_Planted.ts * 종단도에 심는 비정규 측점 → 그래프 측점 · 노선 최대 누가거리(511-B B-3) — 화면 * `B05_Profile_UI_IrregularStations.ts` · `B05_Profile_UI_Profile_Layout.ts` 에서 옮김(순수 · 두 파일이 * 다시 내보냄). 서버 Node 묶음 planline 저장 기준(`design_planted_base.ts`)이 화면 파일을 안 끌게. * ========================================================================== */ import type { IrregularStation } from "../B05_Profile_UI_IrregularStations"; import type { LongitudinalSection, SectionStation } from "../../B06_Section/B06_Section_Api_Fetch"; import { stationPartsLabel } from "../../common_util/common_util_station"; import { PLUS_OWNER_PREFIX } from "../../common_util/common_util_structure_station"; import { normalizedLongitudinal } from "./B05_Profile_UI_Profile_Data"; /** 비정규 측점의 그래프·3D·테이블 공용 식별자. 주입 측점의 station_id로도 쓴다. */ export function irregularStationId(id: string): string { return `irregular:${id}`; } /** 측점번호+잔여거리 표기 (예: 3+18 · 공용 표기 한 벌 — 거리는 정수로 보이기만). */ export function irregularLabel(station: IrregularStation): string { return stationPartsLabel(station.station, station.remainder); } /** 유효 표고 샘플 기준의 노선 최대 chainage(m). 그래프·테이블이 같은 값을 써야 X축이 맞물린다. */ export function maxChainageOf(data: LongitudinalSection): number { const samples = normalizedLongitudinal(data).samples.filter( (sample) => sample.valid !== false && Number.isFinite(sample.elevation_m ?? NaN), ); return Math.max(data.length_m, samples[samples.length - 1]?.chainage_m ?? 1, 1); } /** * 비정규 측점을 그래프용 `SectionStation`으로 만든다. 그래프 렌더러는 chainage·라벨·kind만 * 쓰므로 월드 좌표는 0으로 둔다(3D 마커용 좌표는 Page가 따로 보간). 범위 밖은 제외. */ export function irregularGraphStations( list: IrregularStation[], maxChainage: number, ): SectionStation[] { return list .filter((entry) => entry.chainage_m >= 0 && entry.chainage_m <= maxChainage + 1e-6) .map((entry) => ({ station_id: irregularStationId(entry.id), chainage_m: entry.chainage_m, label: irregularLabel(entry), kind: "irregular" as const, // 추가 측점(368-2) = 일반측점 색 점선 · 끌기 없음 ...(entry.id.startsWith(PLUS_OWNER_PREFIX) ? { plus: true } : {}), center_z: null, azimuth_deg: null, center_x: 0, center_y: 0, frame: { left_xy: [0, 0] as [number, number] }, })); }