From 2d07b990a4154b94fcbed75311e4ae82bbda051a Mon Sep 17 00:00:00 2001 From: umsangdon Date: Wed, 2 Sep 2026 11:41:41 +0900 Subject: [PATCH] =?UTF-8?q?feat(B05):=203D=20=ED=8F=89=EB=A9=B4=20?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=B9=98=EB=A5=BC=20=EC=B5=9C=EC=A2=85=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=EB=AC=BC=EC=97=90=EC=84=9C=20=EC=88=A8?= =?UTF-8?q?=EA=B8=B4=EB=8B=A4=20(=EB=94=94=EB=B2=84=EA=B9=85=EC=9A=A9?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=90=98=EC=BC=A4=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EA=B2=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 투영 커브(구조물 노랑·날개 주황·투영선 빨강·잘린 자리 라임 등)는 구조물이 어디를 지우고 어디를 다시 채우는지 눈으로 좇으려고 만든 표기라 설계 산출물이 아니다. 사용자 지시로 **기본은 숨김**. 다만 절취·패치 기하를 다시 볼 때 쓰므로 지우지 않고 묶음째 감춘다(2026-09-02 사용자: "나중에 디버깅을 위해 재사용 가능성 있음"). - `_Corridor_Mesh.ts` — 커브를 `corridor-plan-sketch` 묶음에 담고 `visible` 을 브라우저 스위치(`frd_debug_plan_curves`, 기본 꺼짐)로 정한다. - `_Profile_UI_Viewer.ts` — `__corridorPlanCurves(true|false)` 로 켜고 끈다. 선택은 브라우저에 남아 다음에 열 때도 유지된다. 인자 없이 부르면 지금 상태를 돌려준다. 검증(wdw · 3D 실측, 같은 화면에서 켜고 끄며 스케치 색 픽셀을 셈): 숨김(기본) — 주황 1 · 노랑 0 · 빨강 0 · 라임 0 켬 — 주황 89 · 노랑 260 · 빨강 6 · 라임 195 `__corridorPlanCurves()` 기본 false → true → false 왕복 확인. `tsc --noEmit` 통과, `pytest tmp/tests/ -q` 356 passed / 0 failed, prettier 정합. Co-Authored-By: Claude Opus 5 (1M context) --- B05_Profile/B05_Profile_UI_Corridor_Mesh.ts | 29 ++++++++++++++++++++- B05_Profile/B05_Profile_UI_Viewer.ts | 24 ++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/B05_Profile/B05_Profile_UI_Corridor_Mesh.ts b/B05_Profile/B05_Profile_UI_Corridor_Mesh.ts index ca4757d2..a6e39ba3 100644 --- a/B05_Profile/B05_Profile_UI_Corridor_Mesh.ts +++ b/B05_Profile/B05_Profile_UI_Corridor_Mesh.ts @@ -50,6 +50,26 @@ const PLAN_CURVE_COLORS: Record = { "cut-wall": 0x000000, }; +/** + * 평면 스케치(투영 커브) 묶음의 이름 — 뷰어가 이 이름으로 찾아 켜고 끈다. + * + * **최종 결과물에서는 숨긴다**(2026-09-02 사용자). 이 커브들은 구조물이 어디를 지우고 + * 어디를 다시 채우는지 눈으로 좇으려고 만든 것이라 설계 산출물이 아니다. 다만 절취·패치 + * 기하를 다시 들여다볼 때 쓸모가 있어 **지우지 않고 감춰만 둔다**. + */ +export const PLAN_CURVE_GROUP = "corridor-plan-sketch"; + +/** 평면 스케치를 켜 둔 브라우저인가 — 기본은 꺼짐. 디버깅용 스위치다. */ +export const PLAN_CURVE_FLAG = "frd_debug_plan_curves"; + +export function planCurvesVisible(): boolean { + try { + return window.localStorage.getItem(PLAN_CURVE_FLAG) === "1"; + } catch { + return false; // 저장소가 막힌 환경(사생활 보호 모드 등) — 꺼진 것으로 본다. + } +} + /** 유출측 파선 눈금(m) — 유입은 실선이다. */ const PLAN_DASH_M = { dashSize: 0.6, gapSize: 0.4 }; @@ -391,6 +411,13 @@ export function createCorridorGroup(build: CorridorBuildResult, bounds: ModelBou // 탑뷰 투영 커브(2026-08-26 사용자) — 구조물 세트마다 **그 세트 구조물 상단 +5m** // 평면에 눕힌 닫힌 고리다. 종류는 색(구조물 노랑 / 변형 성토선 분홍 / 원본 하늘), // 유입·유출은 실선·파선으로 나눈다. 표기 전용 — 서피스는 안 건드린다. + // + // **최종 결과물에서는 숨긴다**(2026-09-02 사용자). 지우지는 않는다 — 절취·패치 기하를 + // 다시 들여다볼 때 쓰므로 묶음째 감춰 두고 `__corridorPlanCurves(true)` 로 되켠다. + const planGroup = new THREE.Group(); + planGroup.name = PLAN_CURVE_GROUP; + planGroup.visible = planCurvesVisible(); + group.add(planGroup); (build.planCurves ?? []).forEach((curve) => { // 벽 자리 커브는 표시용이 아니다 — 벽 서피스로만 나간다(2026-08-27 사용자). if (curve.source === "cut-wall") return; @@ -417,7 +444,7 @@ export function createCorridorGroup(build: CorridorBuildResult, bounds: ModelBou if (dashed) line.computeLineDistances(); const station = curve.setChainageM.toFixed(2); line.name = `corridor-plan:${curve.source}:${curve.role}:${curve.side}:${station}:${index}`; - group.add(line); + planGroup.add(line); }); }); // 절취 측벽 — 리본과 분리된 **별도 서피스**(2026-08-27 사용자). 성토면과 같은 색·빗금이라 diff --git a/B05_Profile/B05_Profile_UI_Viewer.ts b/B05_Profile/B05_Profile_UI_Viewer.ts index 9024499f..6487cd91 100644 --- a/B05_Profile/B05_Profile_UI_Viewer.ts +++ b/B05_Profile/B05_Profile_UI_Viewer.ts @@ -16,7 +16,11 @@ import { } from "./B05_Profile_UI_Markers"; import { createOrthoCameraRig } from "./B05_Profile_UI_Viewer_Camera"; import type { CorridorBuildResult } from "./B05_Profile_UI_Corridor_Build"; -import { createCorridorGroup } from "./B05_Profile_UI_Corridor_Mesh"; +import { + createCorridorGroup, + PLAN_CURVE_FLAG, + PLAN_CURVE_GROUP, +} from "./B05_Profile_UI_Corridor_Mesh"; import { clipTerrain } from "./B05_Profile_UI_Corridor_Clip"; import { TerrainHeightIndex } from "./B05_Profile_UI_Corridor_Terrain"; import { buildPatchSkirts } from "./B05_Profile_UI_Corridor_Skirt"; @@ -671,6 +675,24 @@ export function createRouteViewer(): RouteViewer { corridorGroup = createCorridorGroup(build, bounds); scene.add(corridorGroup); } + // 평면 스케치 되켜기 — 최종 결과물에서는 숨기지만 절취·패치 기하를 다시 볼 때 쓴다 + // (2026-09-02 사용자: "나중에 디버깅을 위해 재사용 가능성 있음"). + // `__corridorPlanCurves(true)` 로 켜고 `(false)` 로 끈다. 선택은 이 브라우저에 남아 + // 다음에 열 때도 그대로다. 인자 없이 부르면 지금 상태를 돌려준다. + ( + window as unknown as { __corridorPlanCurves?: (on?: boolean) => boolean } + ).__corridorPlanCurves = (on?: boolean): boolean => { + const sketch = corridorGroup?.getObjectByName(PLAN_CURVE_GROUP); + if (on !== undefined) { + try { + window.localStorage.setItem(PLAN_CURVE_FLAG, on ? "1" : "0"); + } catch { + // 저장소가 막힌 환경 — 이번 화면에만 적용한다. + } + if (sketch) sketch.visible = on; + } + return sketch?.visible ?? false; + }; scheduleTerrainClip(); }