- 좌측 패널 · 아래 단추 넷 · 종단도 · 구조물 배치 폼을 페이지에 한 번만 만듦(design_shared) — 두 보기가 같은 노드 - 보기는 가운데 위 칸만: 종단 보기 = 3D(design_view_profile) · 횡단 보기 = 횡단 카드(design_view_cross · 처음 보일 때 그림) - 옛 B05_Profile_UI_Page · B06_Section_UI_Page 삭제 · 한 벌이 받은 조작은 지금 보기로, 관 목록 · 횡단 재계산 알림은 두 보기 모두로 - 진행 단계 종단설계 · 횡단설계 두 칸이 보기를 따라 켜짐 · 누르면 주소만 바꿈 · 제목도 따라감(setTitle · setActiveStep) - [저장] · [확정] 한 벌 — 두 보기 몫을 모아 saveDesign 한 번 · 종단 보기 [확정] 켬(횡단 보기를 숨긴 채 세워 횡단 자료를 얻음) - [초기화] · 계획노선 편집은 같은 페이지라도 다시 세움(remountRoute) - 덧붙임: 방향키는 초점 있는 쪽만(조정창 ↔ 종단도 계획고) · 횡단 보기 계획고 편집에도 [3D 업데이트] 대기 표시 · 종단 보기 폼 관 옵션을 횡단 캐시에도 얹음 · 종단 보기에서 횡단 조정 칸 가림 - 나눔: Cross_View 756→658(_Cross_View_Frame) · Page_Structures_Panel 700→547(_Structures_Spec) · 옛 B05 Page 786 → design_view_profile 638(_Page_Latest · _Page_Stations) - 시험: test_design_view_parity 한 벌 기준(한 패널 · 보기 오가도 같은 노드) · page_single · profile_single · save_channels · save_recompute 등 옮긴 자리로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
68 lines
3.8 KiB
TypeScript
68 lines
3.8 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Page_Stations.ts
|
|
* 종단 보기 3D **측점 바** 목록 — 규칙 측점 + 구조물(비정규) 측점 · 계획고 높이 · 상단측.
|
|
* 종단 보기 본체(`design_view_profile`)가 700줄을 넘어 여기로 뗐다(계획서 24-3b).
|
|
* ========================================================================== */
|
|
|
|
import { dropStationsNear } from "./B05_Profile_Util_Station";
|
|
import { interpolateIrregularStations } from "./B05_Profile_UI_Page_Helpers";
|
|
import type { IrregularStation } from "./B05_Profile_UI_IrregularStations";
|
|
import type { SectionDetailResponse } from "../B06_Section/B06_Section_Api_Fetch";
|
|
|
|
export interface StationLinesInput {
|
|
detail: SectionDetailResponse;
|
|
irregular: IrregularStation[];
|
|
routePoints: ReadonlyArray<{ x: number; y: number; z?: number | null }>;
|
|
/** 편집 중 라이브 계획선 샘플(없으면 정본 계획선). */
|
|
liveSamples: ReadonlyArray<{ chainage_m: number; elevation_m: number }> | null;
|
|
/** [예상형상] 켜짐 — 측점 바를 계획고 위로 올린다. */
|
|
corridorVisible: boolean;
|
|
/** 상단측(측구 방향) 사용자 변경분 — 키는 누가거리 3자리. */
|
|
uphillOverrides: Map<string, "left" | "right">;
|
|
}
|
|
|
|
export function stationLinesOf(input: StationLinesInput) {
|
|
const { detail } = input;
|
|
// 확정 때 종단 정본에 병합해 둔 비정규 측점은 그리지 않는다. 화면의 정본은 사이드바 목록이고
|
|
// 관을 옮기면 그 목록만 따라오므로, 둘을 겹쳐 그리면 옮기기 전 자리가 그대로 남는다
|
|
// (2026-08-02 사용자 보고). 저장분은 진입 시 `restoreSections`가 목록으로 되살린다.
|
|
const regular = detail.longitudinal.stations.filter((station) => station.kind !== "irregular");
|
|
const injected = interpolateIrregularStations(
|
|
regular,
|
|
input.irregular,
|
|
detail.longitudinal.length_m,
|
|
// 중심 좌표는 노선 폴리라인 기준 — 3D 마커가 노선 위에 정확히 얹힌다(2026-08-19).
|
|
input.routePoints,
|
|
);
|
|
// 예상형상이 켜져 있으면 측점 바를 **계획고** 기준으로 올린다 — 원지반 위에
|
|
// 얹힌 예상형상에 묻혀 측점 기준선이 안 보이던 문제(2026-08-23 사용자 지시).
|
|
const designAt = (chainageM: number): number | null => {
|
|
if (!input.corridorVisible) return null;
|
|
// 편집 중에는 라이브 alignment 샘플이 정본보다 새것이다(2026-08-23 지적 ③).
|
|
const samples = input.liveSamples ?? detail.longitudinal.design_profiles?.[0]?.samples;
|
|
if (!samples?.length) return null;
|
|
let best = samples[0];
|
|
for (const sample of samples) {
|
|
if (Math.abs(sample.chainage_m - chainageM) < Math.abs(best.chainage_m - chainageM)) {
|
|
best = sample;
|
|
}
|
|
}
|
|
return best.elevation_m;
|
|
};
|
|
// 측점 바 양 끝 램프용 상단측: 사용자 변경분 → solve 자동 판정 순으로 적용.
|
|
// 구조물 측점과 0.1m 안에서 겹치는 규칙 측점은 지운다 — 3D 측점 띠도 종단 그래프와
|
|
// 같은 규칙을 써야 두 화면의 측점이 어긋나지 않는다(2026-09-06).
|
|
return [...dropStationsNear(regular, injected), ...injected].map((station) => {
|
|
const design = designAt(station.chainage_m);
|
|
return {
|
|
...station,
|
|
// 절토 구간에서는 계획고가 지반보다 **아래**다(2026-09-04 사용자 지적).
|
|
// max 로 잡으면 코리도가 절취해 내려간 노면을 두고 막대만 원지반에 떠 있다.
|
|
// 코리도가 켜져 있으면(designAt 이 값을 줌) 계획고를 그대로 쓴다.
|
|
center_z: design !== null && station.center_z !== null ? design : station.center_z,
|
|
uphill_side:
|
|
input.uphillOverrides.get(station.chainage_m.toFixed(3)) ?? station.uphill_side ?? null,
|
|
};
|
|
});
|
|
}
|