# PLAN: B04 결함 수정 6건 + 확정 흐름 주의점 보완 (2026-07-17) ## 활성 작업: B04 결함 수정 6건 + 확정 흐름 주의점 보완 (2026-07-17) ### A. 지면 필터 미리보기가 원본 데이터를 표시 (핵심 결함) - **현상**: 지면 필터를 선택해도 필터링 후 데이터가 아닌 원본에서 50만 개를 샘플해 표시 - **원인 (확인됨)**: - `GET .../surface/point-cloud`가 `structured.npz`(지면 필터 **이전** 구조화 원본)를 고정 조회 — `B04_wf1_Surface_Router.py:332`. 필터 파라미터 자체가 없음 - 지면 필터 마스크는 분석 중 메모리에서만 생성·사용되고 **영구저장되지 않음** — `B04_wf1_Surface_Engine.py:77-85` (`build_ground_masks` → 모델 빌드에 전달 후 소멸) - **0_old 검증 프로그램의 방식 (준용)**: `create_ground_filter_cache`(`0_old/backend/app/analyzer.py:622-739`)가 분석 시 **필터링된 지면 포인트 자체를 브라우저 상한(0_old는 500만)으로 샘플해 `processed/ground-points.json`으로 영구저장**하고, `GET .../ground-points`(`0_old/backend/app/main.py:166-170`)가 캐시 파일을 그대로 서빙. 요청 시 재계산 없음 - **수정 방향 (0_old 패턴 준용)**: 1. Engine: 분석 시 필터별 지면 포인트 캐시를 `processed/ground_points_{filter}.npz`로 영구저장 — 50만 규칙(초과 시 랜덤 50만, 이하 전체) 적용된 미리보기 서빙용. 메타(원본 지면 포인트 수, 샘플 수, bounds) 포함 2. Router: point-cloud 엔드포인트에 `filter` 쿼리 파라미터 추가 — 지정 시 해당 캐시 파일 서빙, 미지정 시 기존 원본(structured) 동작 유지 3. Api_Fetch / UI_Page: 지면 필터 선택 변경 시 `filter` 파라미터로 재조회 → 뷰어 렌더 4. **기존 프로젝트**에는 캐시 파일이 없음 → filter 요청 시 파일 부재면 `structured.npz`로 해당 필터만 온디맨드 재계산 후 캐시 저장(백필) 5. 경로(B05)·등고선 등 백엔드 분석은 종전대로 전체 필터링 데이터 기준(미리보기 캐시와 무관) 유지 ### B. 등고선 간격 옵션 미작동 - **원인 (확인됨)**: 등고선은 분석 시 config 기본 간격(`contour_interval_meters`=5.0m) 파일만 사전 생성 — `B04_wf1_Surface_Engine_Pipeline.py:57-104`. contour 엔드포인트는 **파일 조회 전용**이라 다른 간격 요청 시 파일이 없고, 폴백 glob이 기존 5.0m 파일을 반환 — `B04_wf1_Surface_Router.py:655-662` → **간격 변경이 조용히 무시됨**. 프론트 전달(`interval` 파라미터)은 정상 — `B04_wf1_Surface_UI_TerrainViewer.ts:383-385` - **수정 방향**: 요청 간격의 파일이 없으면 저장된 모델 npz로 **온디맨드 등고선 생성 후 파일 캐시 저장**(기존 `Engine_Contour` 함수 재사용, `asyncio.to_thread`). 폴백 glob은 생성 실패 시에만 사용하거나 제거 ### C. 스무딩 옵션 동작 불명확 - **확인된 사실**: 프론트 연결은 정상(`smooth` 파라미터 전달 및 토글 시 재로드 — `UI_TerrainViewer.ts:326-329,568-570`). 스무딩은 **tin/dtm 전용**이며 `{stem}_smooth_preview.glb` 사전 생성 파일을 조회(`Router.py:567-570`). nurbs/implicit/meshfree는 토글해도 무동작이 현재 설계 - **수정 방향**: 1. 실행 검증: tin/dtm에서 `_smooth_preview.glb`·`contour_*_smooth_*.json` 파일 실존 및 토글 시 메시 교체 여부 확인, 파일 누락 시 Pipeline 생성 경로 수정 2. UX: 스무딩 미지원 기법(nurbs/implicit/meshfree) 선택 시 토글 비활성화(회색)로 "안 되는 게 아니라 해당 없음"을 명시 3. 등고선도 스무딩 상태와 간격을 함께 반영(B와 연동) ### D. 2D 지도 이미지 왜곡 (그룹 컨테이너에 맞춰 늘어남) - **원인 (확인됨)**: `.b04-map__image { object-fit: fill; width/height:100% }` — `B04_wf1_Surface_UI_Style.css:468-478`. VWorld 배경 이미지가 뷰포트(가변 폭 × 고정 560px)에 종횡비 무시로 강제 인장됨. 이전에 보고된 "살짝 대각선" 현상도 이 왜곡이 원인일 가능성 높음 - **수정 방향**: VWorld 요청 해상도를 뷰포트 실제 크기(종횡비)에 맞춰 요청하거나 `object-fit` 정합 처리 + canvas GeoJSON 오버레이 좌표 변환 동기화. 수정 후에도 대각선 느낌이 남으면 투영 좌표 변환 재점검 ### F. 두 3D 뷰어 카메라 동기화의 스케일 불일치 - **현상**: 포인트클라우드 미리보기 ↔ 지표면 표현 뷰어가 함께 움직이긴 하나 배율(스케일)이 서로 다름 - **원인 (확인됨)**: 카메라 상태를 비율로 주고받는데 **정규화 기준이 서로 다름** - Viewer: 데이터를 최대 span=180 고정 공간으로 스케일링(`UI_Viewer.ts:202`)하고 `distanceRatio = distance/180` 고정 기준(`UI_Viewer.ts:165-187`) - TerrainViewer: 실좌표 메시의 바운딩박스 span 기준 `distance/sceneSpan`(`UI_TerrainViewer.ts:270-296`) - 포인트클라우드 범위(현재는 원본이라 식생 포함 z-range 큼)와 지표면 메시 범위가 달라 같은 비율이 다른 배율로 나타남. A 수정 후에도 기준 데이터 범위가 완전히 같지 않으므로 잔존 - **수정 방향**: 카메라 상태를 **실세계 좌표(m) 기준 공통 프레임**으로 교환 — 각 뷰어가 자기 월드→씬 변환(Viewer: 180/span 배율+중심점, Terrain: sceneCenter)을 알고 있으므로, emit/apply 시 실좌표(중심 기준 오프셋 m, 거리 m)로 변환해 동기화. 축 방향 컨벤션(Viewer의 x/z/-y 스왑)도 함께 정합 ### G. 지표면 표현 뷰어가 컨테이너 전체를 사용하지 못함 - **원인 (확인됨)**: TerrainViewer 렌더 영역에 인라인 `height: 520px` 고정(`UI_TerrainViewer.ts:106`) — 포인트클라우드 뷰어(`.three-viewer` 560px, `UI_Style.css:355-360`)와 불일치하고, 2열 컨테이너 높이와 무관하게 고정됨 - **수정 방향**: 인라인 높이 제거, 두 뷰어 동일한 CSS 규칙(컨테이너 기준 100% 또는 공통 고정값)으로 통일. ResizeObserver 기반 리사이즈는 이미 구현되어 있어(`UI_TerrainViewer.ts:587-596`) CSS만 정리하면 추종함 ### E. 확정 흐름 주의점 보완 (2026-07-17 검증에서 발견) 1. `enableRouteStep`이 진행단계 버튼을 DOM 인덱스 `[2]` 하드코딩으로 탐색(`UI_Page.ts:186-188`) → 스텝 식별자/route 기반 탐색으로 변경 (스텝 순서 변경 시 무음 파손 방지) 2. 확정 토스트의 `{smoothing}` 값이 `"-"` 고정(`UI_Page.ts:304`) → 실제 스무딩 토글 상태 연결 3. B04 재진입 시(이미 확정 상태) WF2 스텝 활성화가 서버 workflowState 렌더에 의존 → 확정 → 새로고침 → 스텝 클릭 가능 여부 실행 검증, 불가하면 수정 4. 잔여 확인: 지면 필터 드롭다운의 `ransac` 제거(`UI_Page.ts:54` `SOURCE_FILTERS`) — 이전 계획 항목이나 현재 코드에 잔존 5. **확정 성공 시 B05로 자동 이동** (사용자 확정, 2026-07-17): 확정 토스트 표시 후 `goToWorkflowStage`로 WF2(B05) 페이지 자동 전환. 스텝 수동 클릭 대기 방식 폐기 — 단, `enableRouteStep`의 스텝 활성화 처리는 뒤로가기/재진입 대비 유지 ### 대상 파일 | 파일 | 작업 | |---|---| | `B04_wf1_Surface/B04_wf1_Surface_Engine.py` | 필터별 지면 포인트 캐시 영구저장 (A) | | `B04_wf1_Surface/B04_wf1_Surface_Router.py` | point-cloud `filter` 파라미터+캐시 서빙 (A), 등고선 온디맨드 생성 (B) | | `B04_wf1_Surface/B04_wf1_Surface_Api_Fetch.ts` | point-cloud filter 파라미터 전달 (A) | | `B04_wf1_Surface/B04_wf1_Surface_UI_Page.ts` | 필터 선택 → 재조회 연결 (A), E-1·2·4 | | `B04_wf1_Surface/B04_wf1_Surface_UI_Viewer.ts` | 카메라 상태 실좌표 변환 (F) | | `B04_wf1_Surface/B04_wf1_Surface_UI_TerrainViewer.ts` | 스무딩 토글 UX (C), 카메라 상태 실좌표 변환 (F), 인라인 높이 제거 (G) | | `B04_wf1_Surface/B04_wf1_Surface_UI_MapViewer.ts` | 이미지 종횡비 정합 (D) | | `B04_wf1_Surface/B04_wf1_Surface_UI_Style.css` | `object-fit` 수정 (D), 뷰어 높이 통일 (G) | | `B04_wf1_Surface/B04_wf1_Surface_Engine_Pipeline.py` | (조건부) 스무딩 프리뷰 생성 누락 시 수정 (C) | ### 구현 체크리스트 - [x] A-1. Engine: 분석 시 필터별 `processed/ground_points_{filter}.npz` 캐시 저장 (50만 규칙 + 메타) - [x] A-2. Router: point-cloud `filter` 파라미터 + 캐시 파일 서빙 - [x] A-3. Router: 캐시 파일 부재 시 온디맨드 재계산·백필 - [x] A-4. Api_Fetch/UI_Page: 필터 선택 → filter 파라미터 재조회·렌더 - [x] B-1. Router: 요청 간격 등고선 파일 부재 시 온디맨드 생성 + 캐시 저장 - [x] B-2. 폴백 glob 정리 (간격 무시 무음 동작 제거) - [x] C-1. tin/dtm 스무딩 프리뷰·등고선 파일 생성 여부 검증, 누락 시 Pipeline 수정 - [x] C-2. 스무딩 미지원 기법에서 토글 비활성화 - [x] D-1. VWorld 이미지 종횡비 정합 + canvas 오버레이 좌표 동기화 - [x] F-1. Viewer/TerrainViewer: 카메라 상태를 실세계 좌표(m) 공통 프레임으로 emit/apply 변환 (축 컨벤션 정합 포함) - [x] F-2. 동기화 배율 일치 실행 검증 (양쪽 축척바 값 비교) - [x] G-1. TerrainViewer 인라인 높이 제거, 두 뷰어 높이 통일 - [x] E-1. enableRouteStep 스텝 탐색 방식 개선 - [x] E-2. 확정 토스트 스무딩 값 연결 - [x] E-3. 확정 후 새로고침 시 WF2 스텝 활성화 실행 검증 - [x] E-4. `SOURCE_FILTERS`에서 `ransac` 제거 확인 - [x] E-5. 확정 성공 시 B05 자동 이동 (`goToWorkflowStage`) - [x] 700줄 제한 및 라우터 분리: `B04_wf1_Surface_Router.py`(643줄), `B04_wf1_Surface_Router_GIS.py`(175줄)로 분할하여 700줄 한계 준수 - [x] GIS/VWorld 라우터 복원: `B04_wf1_Surface_Router_GIS.py` 유실 복구 및 `main.py` 기동 실패(ImportError) 해결 ### 협의 완료 (2026-07-17 사용자 확정) - **확정 후 자동 이동**: 확정 성공 시 B05 자동 전환으로 확정 → E-5 반영 - **A-3 백필 방식**: 온디맨드 재계산 채택 — 기존 프로젝트(캐시 파일 없음)에서 필터 첫 선택 시 서버가 `structured.npz`로 해당 필터만 재계산해 캐시 생성 후 응답. 첫 선택에만 수 초 대기 발생, 이후 즉시 표시