- logic 새 파일 9 — B06_Section_Cross_Culvert · _Culvert_Geom · _Culvert_Extra · _Culvert_Tiers · _Culvert_Types · _Culvert_Wire · _Box_Geom · _Ford_Geom · _Ford_Pavement - 그림 파일(UI_Cross_Culvert · _Culvert_Types · _Box · _Ford · _Ford_Pavement)은 받은 좌표로 그리기만 · 관 겹 꼭짓점(pipeShellCorners) · 물넘이 노면 끝 · 월류선 · 유출 성토선은 logic 으로 - 옛 순수 기하 6 파일(UI_Cross_Culvert_Geom · _Extra · _Tiers · _Wire · _Box_Geom · _Ford_Geom) 지움 · 부르는 쪽(B05 Corridor · Structure_Layouts · Route_Carry_Patch · Wall 등)은 import 줄만 - test_472_3 GEOMETRY_PULLS 자기 11 줄 + 더는 안 끌리는 Design_Surface 1 줄 걷음 - 시험 · helper 경로를 새 logic 파일로 — 옮긴 파일을 가리키던 낡은 경로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
176 lines
7.2 KiB
TypeScript
176 lines
7.2 KiB
TypeScript
/* =============================================================================
|
|
* 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, DesignProfile } 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/logic/B06_Section_Cross_Box_Geom";
|
|
import type { BoxControl } from "../B06_Section/B06_Section_UI_Cross_Box_Panel";
|
|
import {
|
|
culvertLinkFor,
|
|
type CulvertLink,
|
|
} from "../B06_Section/logic/B06_Section_Cross_Culvert_Wire";
|
|
import { fordAdjustOf } from "../B06_Section/logic/B06_Section_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;
|
|
return crossSourceOf(projectId, found, sections, detail.longitudinal.design_profiles, pane);
|
|
}
|
|
|
|
/** 단면 하나 → 판 재료(사본) — 이웃 단면 · 계획선은 연동 관 · 반폭 · 계획고 재료(종단 임시 횡단 창도 씀 · 505-3). */
|
|
export function crossSourceOf(
|
|
projectId: string,
|
|
found: CrossSection,
|
|
sections: readonly CrossSection[],
|
|
profiles: DesignProfile[] | undefined,
|
|
pane: string,
|
|
): RouteCrossSource {
|
|
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) — 카드 머리 · 줌 단추 · 발(암 경계 · 요약) 걷음 · 벽 · 선 · 면적 고름 막음
|
|
// 경고 칩(빈칸 · 기본값 · 사면 열림)만 그래프 오른쪽 위에 겹쳐 남김(505-3)
|
|
const chips = card.querySelectorAll(":scope > header .b06-cross-card__warning");
|
|
if (chips.length) {
|
|
const box = document.createElement("div");
|
|
box.className = "b05-cross-chips";
|
|
box.append(...chips);
|
|
card.append(box);
|
|
}
|
|
card
|
|
.querySelectorAll(":scope > header, :scope > footer, .b06-cross-card__zoom")
|
|
.forEach((el) => el.remove());
|
|
card.addEventListener("click", (event) => event.stopPropagation(), true);
|
|
return card;
|
|
}
|