- 구조물 솔리드에 부재키(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>
87 lines
3.9 KiB
TypeScript
87 lines
3.9 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Structure_Pick_Session.ts
|
|
* 3D에서 고른 구조물을 **좌측 「구조물 배치」 패널로 넘기고**, 그 선택을 세션 한 칸에
|
|
* 남겨 **B06 진입 때 같은 측점 카드가 열리게** 한다(2026-09-04 사용자 확정).
|
|
*
|
|
* B05·B06은 라우터가 따로 띄우는 화면이라 실시간 양방향이 아니다 — 조작 상태는 캐시
|
|
* 몫이라는 데이터 3층 규칙대로 sessionStorage에 남긴다. 값은 읽는 즉시 지운다(한 번만
|
|
* 따라간다 — 나중에 B06을 다시 열었을 때 옛 선택이 되살아나면 안 된다).
|
|
* ========================================================================== */
|
|
|
|
import type { StructurePick, StructurePickControls } from "./B05_Profile_UI_Viewer_Structure_Pick";
|
|
import type { StructuresSection } from "./B05_Profile_UI_Structures_Panel_Types";
|
|
import type { StructureInstance } from "./B05_Profile_Api_Structures";
|
|
|
|
/** B06으로 넘기는 선택 — B06이 쓰는 `{ 측점, 부재키 }` 한 쌍과 같은 모양이다. */
|
|
export interface StructurePickHandoff {
|
|
at: number;
|
|
key?: string;
|
|
}
|
|
|
|
const sessionKey = (projectId: string): string => `aislo:structure-pick:${projectId}`;
|
|
|
|
/** 세션에 남긴다(선택 해제면 지운다). */
|
|
export function rememberStructurePick(projectId: string | null, pick: StructurePick | null): void {
|
|
if (!projectId) return;
|
|
try {
|
|
if (!pick) {
|
|
window.sessionStorage.removeItem(sessionKey(projectId));
|
|
return;
|
|
}
|
|
const handoff: StructurePickHandoff = { at: pick.chainageM, key: pick.key };
|
|
window.sessionStorage.setItem(sessionKey(projectId), JSON.stringify(handoff));
|
|
} catch {
|
|
/* 세션 저장소가 막힌 환경 — 화면 선택만 살고 넘김은 포기한다. */
|
|
}
|
|
}
|
|
|
|
/** 세션에 남은 선택을 꺼내고 지운다. 없으면 null. */
|
|
export function consumeStructurePick(projectId: string | null): StructurePickHandoff | null {
|
|
if (!projectId) return null;
|
|
try {
|
|
const raw = window.sessionStorage.getItem(sessionKey(projectId));
|
|
if (!raw) return null;
|
|
window.sessionStorage.removeItem(sessionKey(projectId));
|
|
const value = JSON.parse(raw) as Partial<StructurePickHandoff>;
|
|
if (typeof value.at !== "number" || !Number.isFinite(value.at)) return null;
|
|
return { at: value.at, key: typeof value.key === "string" ? value.key : undefined };
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** 구간형 구조물이 그 누가거리를 덮는가(기준점형은 ±0.51m 안). */
|
|
function covers(entry: StructureInstance, chainageM: number): boolean {
|
|
const start = entry.start_m ?? entry.chainage_m;
|
|
const end = entry.end_m ?? entry.chainage_m;
|
|
if (start == null || end == null) return false;
|
|
return chainageM >= Math.min(start, end) - 0.51 && chainageM <= Math.max(start, end) + 0.51;
|
|
}
|
|
|
|
/**
|
|
* 3D 클릭 결과를 화면 전체에 적용한다.
|
|
*
|
|
* 배수관 세트(기슭막이·집수정·배관)는 `selectStation`(=기존 선택 동기화)이 좌측 폼·종단
|
|
* 그래프·3D 마커·유역도를 한 줄로 맞춘다. 그 줄에서 아무것도 안 잡히면 옛 정본 구조물로
|
|
* 보고 구조물 id로 연다.
|
|
*/
|
|
export function wireStructurePick(
|
|
controls: StructurePickControls,
|
|
projectId: string | null,
|
|
structures: StructuresSection,
|
|
/** 기존 선택 동기화(`selectStationOfPipe`) — 누가거리 하나로 전 화면을 맞춘다. */
|
|
selectStation: (chainageM: number | null) => void,
|
|
): void {
|
|
controls.onPick = (pick: StructurePick | null): void => {
|
|
rememberStructurePick(projectId, pick);
|
|
if (!pick) {
|
|
selectStation(null);
|
|
return;
|
|
}
|
|
selectStation(pick.chainageM);
|
|
if (structures.hasSelection()) return;
|
|
const hit = structures.getStructures().find((entry) => covers(entry, pick.chainageM));
|
|
structures.selectById(hit?.structure_id ?? null);
|
|
};
|
|
}
|