feat(B05): 3D 코리도 구조물 개별 선택
- 구조물 솔리드에 부재키(key) 부여 — B06과 같은 이름(inlet·outlet·extra{i}·bextra{i}·own·basin·pipe)
- 구조물 메쉬에 신원표(userData) — 이름 규칙은 그대로 유지
- 신규 모듈 두 개 — 3D 클릭·강조(Viewer_Structure_Pick), 좌측 패널 연결·B06 넘김(Structure_Pick_Session)
- 좌측 패널·종단에서 고른 것도 3D가 따라오도록 선택 동기화에 포트 추가
- B06 진입 시 세션 넘김값으로 그 측점 카드 선택·스크롤 + 기슭막이 조정창 열기
- 저장 코리도 만료(BUILD_VERSION 90→91) — 옛 저장본엔 부재키가 없음
- 뷰어 700줄 여유 — 검증용 요약을 Viewer_Debug로 분리(동작 불변)
- 검증 수단 — __corridorScene에 camera·project 추가
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,8 @@ import {
|
||||
} from "./B06_Section_UI_Page_Persist";
|
||||
import { maxToeFitHalfWidth } from "./B06_Section_UI_Cross_Fit";
|
||||
import { readAlignmentDraft } from "../B05_Profile/B05_Profile_UI_Profile_Edit";
|
||||
import { consumeStructurePick } from "../B05_Profile/B05_Profile_UI_Structure_Pick_Session";
|
||||
import type { RevetKey } from "./B06_Section_UI_Cross_Culvert";
|
||||
import { type CrossDesignChange, createSectionView } from "./B06_Section_UI_Section_View";
|
||||
import { hasStaleDesigns } from "./B06_Section_UI_Section_Common";
|
||||
import { revetWallSpec } from "./B06_Section_UI_Cross_Culvert_Const";
|
||||
@@ -55,6 +57,9 @@ import { loadSectionDetail } from "./B06_Section_Section_Store";
|
||||
import { buildGroup, createSampleWidener, L } from "./B06_Section_UI_Page_Common";
|
||||
import "@util/common_util_mass_haul.css";
|
||||
|
||||
/** B05 3D가 넘긴 부재키 중 **기슭막이 조정창이 받는 것**(2026-09-04). 집수정·배관은 빠진다. */
|
||||
const REVET_KEYS = /^(inlet|outlet|own|extra\d+|bextra\d+)$/;
|
||||
|
||||
export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
const projectId = localStorage.getItem(CURRENT_PROJECT_ID_KEY);
|
||||
let currentRouteId: number | null = null;
|
||||
@@ -513,6 +518,27 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
confirmButton.disabled = sectionDetail === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* B05 3D에서 고른 구조물을 이어받는다(2026-09-04 사용자 확정) — 세션 한 칸에 남긴
|
||||
* `{ 측점, 부재키 }`로 그 측점 카드를 고르고, 기슭막이 부재면 조정창까지 연다.
|
||||
* 값은 읽는 즉시 지워지므로 진입 한 번만 따라간다.
|
||||
*/
|
||||
function restoreStructurePick(): void {
|
||||
const handoff = consumeStructurePick(projectId);
|
||||
if (!handoff) return;
|
||||
const target = sectionDetail?.cross_sections.find(
|
||||
(section) => Math.abs(section.chainage_m - handoff.at) < 0.01,
|
||||
);
|
||||
if (!target) return;
|
||||
// 카드가 다 선 뒤에 고른다 — 스크롤이 자리를 잡아야 한다.
|
||||
requestAnimationFrame(() => {
|
||||
sectionView.focusStation(target.station_id);
|
||||
if (!handoff.key || !REVET_KEYS.test(handoff.key)) return;
|
||||
stationControls.revetOffset.select(target.chainage_m, handoff.key as RevetKey);
|
||||
sectionView.refreshCard(target.chainage_m);
|
||||
});
|
||||
}
|
||||
|
||||
function renderSectionDetail(): void {
|
||||
if (sectionDetail) {
|
||||
showSectionView();
|
||||
@@ -527,6 +553,7 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
`${projectId ?? "-"}:${currentRouteId ?? "-"}`,
|
||||
context?.natural_spoil_min_ground_slope ?? undefined,
|
||||
);
|
||||
restoreStructurePick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user