/* ============================================================================= * B05_Profile_UI_RouteEdit_Cross_Card.ts * 평면 「횡단」 · 「이전 횡단」 판 그림 = **B06 횡단 카드 읽기 전용**(393-2) — 구조물 · 포장 · 면적 · 축 · * 종단 계획고 · 횡단 설계가 B06 카드와 같은 그림. * * · 자료 = 새 노선 상세(계산 묶음) · 없으면 받아 둔 저장 상세 · 노선 초안 중 새 상세가 아직 없으면 없음 * (판은 옛 선 그림 `_Cross_Draw` 로 · 종단 임시 횡단 창도 그것 그대로) * · 단면 사본(station_id 앞머리 · design 사본) — B06 고름 · 줌 기억 · 면적 원본을 안 건드림 * · 구조물 자리 · 암 경계 = 정본만 읽는 제어기(`Structure_Layouts` · 세월교 · 박스 조정값) · 누름 막음 * · 그래프만(393-3) — 카드 머리 · 줌 단추 · 발 줄 걷음 · 그래프가 판 칸을 다 씀 * · 가로 범위 = B06 「횡단 반폭」 보기값 한 벌(`Display_Width` · 393-4) — B06 에서 바꾸면 다음 그림부터 * ========================================================================== */ import "../B06_Section/B06_Section_UI_Style_Cross_Controls.css"; import { pipelineDetail } from "../A00_Common/design/design_pipeline_page"; import type { DesignPipeline } from "../A00_Common/design/logic/design_pipeline"; import { nearestWithin } from "../A00_Common/design/design_selection"; import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch"; import { peekSectionDetail } from "../B06_Section/B06_Section_Section_Store"; import { displayHalfWidth } from "../B06_Section/B06_Section_Display_Width"; import { pageRouteId } from "../A00_Common/design/design_page_route"; import { extraWalls, inletStructure, revetOffset, } from "../B06_Section/B06_Section_Structure_Layouts"; import { DEFAULT_BOX_SIDE_ADJUST } from "../B06_Section/B06_Section_UI_Cross_Box_Geom"; import type { BoxControl } from "../B06_Section/B06_Section_UI_Cross_Box_Panel"; import { culvertLinkFor, type CulvertLink } from "../B06_Section/B06_Section_UI_Cross_Culvert_Wire"; import { fordAdjustOf } from "../B06_Section/B06_Section_UI_Cross_Ford_Geom"; import type { FordControl } from "../B06_Section/B06_Section_UI_Cross_Ford_Panel"; import { createCrossSectionCard } from "../B06_Section/B06_Section_UI_Cross_View"; import type { RockBoundaryControl } from "../B06_Section/B06_Section_UI_Cross_Design"; import { designElevationAt } from "../B06_Section/B06_Section_UI_Section_Common"; import { readRockBoundaryDefault } from "../B06_Section/B06_Section_UI_Standard_Panel"; /** 판 하나가 그릴 측점 — 그때 사본(이전 판으로 내려도 그대로). */ export interface RouteCrossSource { section: CrossSection; designZ: number | undefined; link: CulvertLink | undefined; /** 보기 반폭(m) — B06 입력칸과 같은 값 · 그릴 때마다 읽음(B06 에서 바꾸면 다음 그림부터). */ halfWidthM: () => number; /** 암 경계 기본 오프셋(m · config). */ rockDefaultM: number; } const none = (): void => undefined; /** 암 경계선 = 정본 오프셋(없으면 config 기본 · 0 을 넘지 않음 — B06 저장소 규칙) · 조정 없음. */ const rockBoundary = (defaultOffsetM: number): RockBoundaryControl => ({ stepM: 0.1, defaultOffsetM, offsetFor: (section) => Math.min(section.design?.rock_boundary_offset_m ?? defaultOffsetM, 0), adjust: none, reset: none, }); /** config 암 경계 기본(`STANDARD_ROCK_BOUNDARY_DEFAULT_OFFSET_M` · 종단 보기가 context 로 기억 · 416) — * context 전이면 서버 Schema 기본과 같은 값. */ const CONTEXT_PENDING_ROCK_M = -0.5; /** 그 측점 단면 사본 — 상세가 없거나(초안 중 새 상세 전) 측점이 없으면 null. */ export function routeCrossSource( projectId: string, pipe: DesignPipeline | null, chainageM: number, pane: string, ): RouteCrossSource | null { const routeId = pageRouteId(projectId); const detail = pipelineDetail(projectId) ?? (pipe?.input("route") ? null : peekSectionDetail(projectId, routeId)); const sections = detail?.cross_sections ?? []; const found = nearestWithin(sections, chainageM, (entry) => entry.chainage_m); if (!detail || !found) return null; const profiles = detail.longitudinal.design_profiles; const planZ = designElevationAt(profiles, found.chainage_m); return { section: { ...found, station_id: `b05-${pane}-${found.station_id}`, design: found.design && { ...found.design }, }, designZ: planZ === undefined ? undefined : planZ - (found.design?.surface_drop_m ?? 0), link: found.culvert ? undefined : culvertLinkFor(found, sections, (at) => designElevationAt(profiles, at) ?? null), halfWidthM: () => displayHalfWidth(projectId, pageRouteId(projectId), sections), rockDefaultM: readRockBoundaryDefault(projectId) ?? CONTEXT_PENDING_ROCK_M, }; } /** B06 횡단 카드 읽기 전용 — 판 폭 · 그림 높이(px)로. */ export function routeCrossCard( source: RouteCrossSource, intervalM: number, widthPx: number, plotHeightPx: number, ): HTMLElement { const { section } = source; const design = section.design; const ford: FordControl = { adjustFor: () => fordAdjustOf(design?.ford_adjust), update: none, reset: none, setPipe: none, setWing: none, selectedFor: () => null, select: none, }; const box: BoxControl = { adjustFor: () => ({ left: { ...DEFAULT_BOX_SIDE_ADJUST, ...(design?.box_adjust?.left ?? {}) }, right: { ...DEFAULT_BOX_SIDE_ADJUST, ...(design?.box_adjust?.right ?? {}) }, }), update: none, reset: none, setBody: none, setWing: none, selectedFor: () => null, select: none, }; const card = createCrossSectionCard( section, false, 1, none, intervalM, source.halfWidthM(), widthPx, plotHeightPx, source.designZ, undefined, rockBoundary(source.rockDefaultM), null, undefined, undefined, revetOffset, inletStructure, extraWalls, source.link, undefined, undefined, ford, box, ); // 그래프만(393-3) — 카드 머리 · 줌 단추 · 발(암 경계 · 요약) 걷음 · 벽 · 선 · 면적 고름 막음 card .querySelectorAll(":scope > header, :scope > footer, .b06-cross-card__zoom") .forEach((el) => el.remove()); card.addEventListener("click", (event) => event.stopPropagation(), true); return card; }