/* ============================================================================= * D03_PlanAnalysis_UI_Cross.ts * D03 하 패널 — 누른 측점의 지반선 횡단(PLAN 530-3). 계산 = 화면 TS 즉시(① 짝 `sectionsGround` ↔ * `generate_sections` · 격자 = 그 연도 DEM 평활본) · 그림 = B05 `buildCrossSvg` 지반만. * ========================================================================== */ import "../B05_Profile/B05_Profile_UI_Style_RouteEdit.css"; import { createWorkflowPanelHandle } from "@ui/ui_template_overlay"; import { stationLabel } from "../common_util/common_util_station"; import type { DtmGrid } from "../common_util/common_util_surface_sampler"; import { buildCrossSvg } from "../B05_Profile/B05_Profile_UI_RouteEdit_Cross_Draw"; import { sectionsGround, type StationGround, } from "../B05_Profile/logic/B05_Profile_Sections_Ground"; import type { Vertex } from "./logic/D03_PlanAnalysis_Plan"; import { PLAN_STATION_INTERVAL_M } from "./D03_PlanAnalysis_UI_Map"; export interface PlanCross { root: HTMLElement; /** `chainage` = 등록 누가 · `localM` = 그 연도 노선 위 누가 · 돌려줌 = 그린 측점 지반(못 읽으면 null). */ show: ( chainage: number, year: number, line: Vertex[], localM: number, grid: DtmGrid, ) => StationGround | null; clear: (text: string) => void; } export function createPlanCross(): PlanCross { const root = document.createElement("section"); root.className = "d03-plan__cross"; const handle = createWorkflowPanelHandle("bottom", "down", "횡단"); const head = document.createElement("div"); head.className = "d03-plan__cross-head"; const body = document.createElement("div"); body.className = "d03-plan__cross-body"; root.append(handle.root, head, body); let open = true; handle.setOpen(open); handle.root.addEventListener("click", () => { open = !open; root.classList.toggle("is-collapsed", !open); handle.setOpen(open); }); const clear = (text: string): void => { head.textContent = ""; body.replaceChildren(Object.assign(document.createElement("p"), { textContent: text })); delete root.dataset.chainage; }; clear("평면에서 측점을 누르면 그 자리 지반선 횡단이 보입니다."); return { root, clear, show(chainage, year, line, localM, grid) { const station = sectionsGround(line, [localM], grid).stations[0]; if (!station) { clear("이 측점의 지반을 읽지 못했습니다."); return null; } const name = stationLabel(chainage, PLAN_STATION_INTERVAL_M, 1); const z = station.center_z === null ? "—" : `${station.center_z.toFixed(2)} m`; head.textContent = `${year}년 · ${name} · 중심 지반고 ${z}`; root.dataset.chainage = String(chainage); const rect = body.getBoundingClientRect(); const plot = buildCrossSvg( { status: "success", chainage_m: chainage, label: name, uphill_side: station.uphill_side, plan_radius_m: null, curve_widening_m: null, cross_half_width_m: 20, samples: station.samples, design: null, }, Math.max(rect.width, 320), Math.max(rect.height, 160), true, ); body.replaceChildren(plot.svg); return station; }, }; }