chore(docs): docs 폴더 git 추적 전환 · PLAN·OWNERS 최상위 이관

- `docs/` 를 .gitignore 에서 빼 git 추적 대상으로 전환 (위키·완료 이력·검증 기록)
- `docs/raw/PLAN.md` · `docs/raw/OWNERS.md` 를 저장소 최상위로 이동 후 .gitignore 에 등록
  — 창끼리 공유하되 저장소에는 안 올리는 장부
- 살아 있는 경로 참조 7개 파일 정정 (아카이브 107건은 그때 사실이라 그대로 둠)
- graphify 날짜별 산출물(`docs/wiki/graphify-out/20*/`) 제외 — `graphify update` 가 다시 만듦

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-09 18:19:07 +09:00
co-authored by Claude Opus 5
parent d7cb14f416
commit eb30b774f8
527 changed files with 43083 additions and 2 deletions
+54
View File
@@ -0,0 +1,54 @@
---
status: draft
page_id: B04_PreProcess
related_pages: ["[[B04_PreProcess/B04_backend]]", "[[B04_PreProcess/B04_frontend]]", "[[B04_PreProcess/B04_db]]", "[[B04_PreProcess/B04_dependencies]]", "[[architecture/project_map]]", "[[architecture/workflow_data_flow]]"]
last_updated: 2026-08-02
---
# B04_PreProcess — API
이 API는 [[B04_PreProcess/B04_frontend]]의 분석·확정 요청을 [[B04_PreProcess/B04_backend]]에 연결하고 [[workflow_state]] stage 1을 변경한다.
실제 라우터 prefix: `/api/projects` (`B04_PreProcess_Router.py`, `B04_PreProcess_Router_GIS.py`, `B04_PreProcess_Router_Contour.py`, `B04_PreProcess_Router_Basins.py`). 총 17개 엔드포인트.
## 엔드포인트
| 엔드포인트 | 위치 | 역할 |
|---|---|---|
| `POST /{project_id}/surface/analyze` | `B04_PreProcess_Router.py` | LAS 구조화+지면필터+모델생성 실행, DB 기록, WF1 stage 전이 |
| `GET /{project_id}/surface/models` | `B04_PreProcess_Router.py` | 생성된 지표면 모델 목록 |
| `POST /{project_id}/surface/confirm` | `B04_PreProcess_Router.py` | 사용자가 선택한 지표면 모델을 확정하고 WF1을 완료 처리 |
| `GET /{project_id}/surface/input-files` | `B04_PreProcess_Router.py` | 분석 대상 LAS/LAZ 입력파일 목록 |
| `GET /{project_id}/surface/point-cloud` | `B04_PreProcess_Router.py` | 3D 미리보기용 포인트클라우드 샘플 (지면 필터 `filter` 파라미터 적용) |
| `GET /{project_id}/surface/ground-stats` | `B04_PreProcess_Router.py` | 필터별 지면 포인트 통계 |
| `GET /{project_id}/surface/status` | `B04_PreProcess_Router.py` | WF1 분석 상태 조회 (workflow_state 우선, 레거시 폴백) |
| `GET /{project_id}/surface/models/{model_id}/preview` | `B04_PreProcess_Router.py` | 모델 미리보기 |
| `GET /{project_id}/surface/models/{model_id}/contour` | `B04_PreProcess_Router_Contour.py` | 등고선 생성/조회 (요청 간격 파일 부재 시 온디맨드 생성) |
| `GET /{project_id}/vworld-meta` | `B04_PreProcess_Router_GIS.py` | VWorld 배경지도 매핑 좌표 메타데이터 |
| `GET /{project_id}/vworld-map` | `B04_PreProcess_Router_GIS.py` | 배경 지도 레이어 PNG 이미지 |
| `GET /{project_id}/geojson` | `B04_PreProcess_Router_GIS.py` | 저장된 프로젝트의 특정 GeoJSON 레이어 데이터 |
| `GET /tiles/{project_id}/{layer}/{z}/{x}/{y}.pbf` | `B04_PreProcess_Router_GIS.py` | 프로젝트의 특정 레이어에 대한 정밀 벡터 타일(MVT) 조각 |
| `GET /{project_id}/drainage/primary-region` | `B04_PreProcess_Router_Watershed.py` | 배수유역 1차 해석 단계별 영구저장 및 응답 캐시 |
| `GET /{project_id}/drainage/road-inflow` | `B04_PreProcess_Router_Inflow.py` | 도로 유입 흐름 강도 1m 해상도 노출 및 기여 셀 외곽선 폴리곤 조회 |
| `GET /{project_id}/drainage/pipe-points` | `B04_PreProcess_Router_Basins.py` | 저장된 관 지점 및 세부유역 데이터 조회 (B04/B05 공용) |
| `POST /{project_id}/drainage/detail-basins` | `B04_PreProcess_Router_Basins.py` | 임시 관 매설 및 실시간 세부유역 분할 계산 (B04/B05 공용, 저장 안 함) |
| `PUT /{project_id}/drainage/pipe-points` | `B04_PreProcess_Router_Basins.py` | 관 매설 위치 확정 및 세부유역 구조 최종 영구 보존 (B04/B05 공용) |
| `DELETE /{project_id}/drainage/pipe-points` | `B04_PreProcess_Router_Basins.py` | 관 매설 저장분 및 세부유역 GeoJSON 물리적 디스크 삭제 및 자동배치 갱신 (B04/B05 공용) |
## 요청/응답 스키마 (Pydantic)
| 모델 | 위치 | 역할 |
|---|---|---|
| `SurfaceAnalyzeRequest` | `B04_PreProcess_Schema.py:16` | input_file_id, source_filters?, methods?, force. resolved_filters/methods로 화이트리스트 검증 |
| `SurfaceAnalyzeResponse` | `B04_PreProcess_Schema.py:97` | ground_summary, manifest_status, surface_model_ids |
| `SurfaceConfirmRequest` | `B04_PreProcess_Schema.py:45` | 확정할 surface_models.id |
| `SurfaceConfirmResponse` | `B04_PreProcess_Schema.py:52` | 지표면 모델 확정 결과 (status: success, confirmed: true) |
| `SurfaceModelSummary` / `SurfaceModelListResponse` | `B04_PreProcess_Schema.py:45,107` | 모델 요약/목록 |
| `SurfaceInputFileSummary` / `...ListResponse` | `B04_PreProcess_Schema.py:56,69` | 입력파일 요약/목록 |
| `SurfacePointCloudSampleResponse` | `B04_PreProcess_Schema.py:77` | 포인트클라우드 샘플(bounds/points/rgb) |
| `SurfaceGroundStatsResponse` | `B04_PreProcess_Schema.py:89` | 필터별 통계 |
- 공통 오류 포맷 `{"status":"error","message":...}` → [[schema_common]]
- 분석 파라미터 화이트리스트: `SURFACE_MODEL_SOURCE_FILTERS`+`ransac`, `SURFACE_MODEL_PRECOMPUTE` (config_system)
@@ -0,0 +1,100 @@
---
status: stable
page_id: B04_PreProcess
related_pages: ["[[B04_PreProcess/B04_frontend]]", "[[B04_PreProcess/B04_api]]", "[[B04_PreProcess/B04_db]]", "[[B04_PreProcess/B04_dependencies]]", "[[B03_FileInput/B03_backend]]", "[[B05_Profile/B05_backend]]", "[[las_free_sheet_surface]]", "[[concepts/drainage_watershed]]", "[[architecture/project_map]]", "[[architecture/workflow_data_flow]]"]
last_updated: 2026-08-30
source: ["docs/raw/plans/2026-08-17_plan_B04_등고선_추출_가속.md", "docs/raw/plans/2026-08-17_plan_B05_box_ui_recommendations.md", "docs/raw/verification/2026-08-17_verify_B04_등고선_추출_가속_교차검증.md", "docs/raw/plans/2026-08-30_plan_las_free_sheet_surface.md", "docs/raw/verification/2026-08-30_verify_las_free_sheet_surface.md"]
---
# B04_PreProcess — Backend
WF1 지표면 분석. LAS 구조화 → 지면 필터 → 지표면 5종 모델 생성 → 스무딩/등고선. 무거운 연산은 `asyncio.to_thread`로 실행. 또한 프로젝트 bounds 기준 1:5,000 수치지형도 도엽 3x3 자동 취득 및 등고선 하강 기반 배수유역 1차 해석 영구저장 캐싱을 전담. B04/B05 배수유역 설계 및 관 편집 데이터 소스(SSOT)가 B04로 단일화되어 관련 API 서빙을 전담합니다.
## 파일 구성 (오케스트레이터/저장소/라우터)
| 파일 | 위치 | 역할 |
|---|---|---|
| `B04_PreProcess_Router.py` | `B04_PreProcess_Router.py` | `/api/projects` 핵심 분석/모델/확정 엔드포인트 및 `GET /confirmed` (0.4KB 확정 지표면 요약, 0.018s 응답) (700줄 한계 규정 준수). |
| `B04_PreProcess_Router_GIS.py` | `B04_PreProcess_Router_GIS.py` | VWorld 이미지, GeoJSON, MVT 타일, 원청 계획선 좌표(`GET /planned-route`), 도엽 벡터 레이어 (raw byte direct 전송 + ETag 적용) 라우터. |
| `B04_PreProcess_Router_Contour.py` | `B04_PreProcess_Router_Contour.py` | 등고선 생성 및 캐시 다운로드 서빙 라우터 (700줄 한계 규정 준수). |
| `B04_PreProcess_Router_Watershed.py` | `B04_PreProcess_Router_Watershed.py` | `GET /{project_id}/drainage/primary-region` 배수유역 1차 해석 및 WAMIS 관측소 수급/지역 분기(본토 관측소 반경10km 최대지점, 제주 등우선) 라우터. |
| `B04_PreProcess_Router_Inflow.py` | `B04_PreProcess_Router_Inflow.py` | **[신설/2026-08-01]** `GET /{project_id}/drainage/road-inflow` 도로 유입 흐름 강도 1m 해상도 곡선, 유입 집중점 마커 및 기여 셀 외곽선 폴리곤 라우터 (700줄 한계 규정 준수). |
| `B04_PreProcess_Router_Basins.py` | `B04_PreProcess_Router_Basins.py` | **[신설/2026-08-01]** 관 매설 지점 및 세부유역 분할 연산 제어 라우터 (`GET/POST/PUT/DELETE /{project_id}/drainage/basins`). (B04/B05 배수 데이터 일원화 통합 라우터) |
| `B04_PreProcess_Schema.py` | `B04_PreProcess_Schema.py` | 요청/응답 Pydantic 검증 |
| `B04_PreProcess_Repository.py` | `B04_PreProcess_Repository.py` | processed_point_cloud/surface_models Raw SQL 및 DB 트랜잭션 헬퍼 |
| `B04_PreProcess_Engine.py` | `B04_PreProcess_Engine.py` | `run_surface_analysis()` 오케스트레이터, 노선 시/종점 기반 도엽 선정(`neighbors_for_points()`), 잔재 zip 정리(`prune_sheets()`) |
## 엔진 서브모듈
| 파일 | 역할 |
|---|---|
| `..._Engine_Structurize.py` | LAS/LAZ 구조화(structured.npz) 및 입력 정체성(파일명+크기+mtime) 캐시 가드 적용 |
| `..._Engine_Ground.py` | 지면 마스크 생성/요약(`build_ground_masks`, `summarize_masks`) |
| `..._Engine_Filter_Grid/CSF/PMF.py` | 지면 필터 3종 |
| `..._Engine_Pipeline.py` | `build_all_terrain_models()` 지표면 모델 파이프라인 + dtm 우선 빌드 + manifest |
| `..._Engine_ModelContext.py` | 모델 공통 컨텍스트/메시 유틸 |
| `..._Engine_ModelBuild.py` | TIN/DTM/NURBS/implicit/meshfree 생성 |
| `..._Engine_Smooth.py` | DTM/TIN 스무딩 |
| `..._Engine_Contour.py` | 저장 TIN faces·meshfree 단일 Delaunay를 공용 `rasterize_triangle_mesh()`로 직접 격자화. float32 UTM 축은 `searchsorted`로 처리하며 15유닛·스무딩을 유지한다. 2026-08-17 검증에서 등고선 27분 39초→77.6초, meshfree·dtm 완전 일치, TIN 정점 −0.03~−0.07%(화면 확인 후속). |
| `..._Engine_Watershed_Grid.py` | **[배수유역 하강]** 격자 규격, 1차 영역, 셀 마스크 |
| `..._Engine_Watershed_Stream.py` | **[배수유역 하강]** 세류망 노딩·도로 절단·상류 추출 |
| `..._Engine_Watershed_Descent.py` | **[배수유역 하강]** 등고선 하강 potential·방위(32방위) 산출 |
| `..._Engine_Watershed_Flow.py` | **[배수유역 하강]** 세류 burn, 사슬 추적 적/청 판정 |
| `..._Engine_Watershed_Analyze.py` | **[배수유역 하강]** ①~⑧ 배수유역 오케스트레이션 + 유입 집중점 `find_inflow_hotspots()` 산출 + 평균 화살표(10m ... 원형 평균) 백엔드 산출 |
## 주요 함수 (Router / Repository / Engine / Utility)
| 함수 | 위치 | 역할 |
|---|---|---|
| `get_road_inflow()` | `B04_PreProcess_Router_Inflow.py` | `GET /api/projects/{id}/drainage/road-inflow`: 도로 유입 흐름 강도 1m 해상도 노출 및 기여 셀 외곽선 폴리곤(`polygonize_labels`) 조회 |
| `find_inflow_hotspots()` | `B04_PreProcess_Engine_Watershed_Analyze.py` | 관 최소 간격(20m) 양 편측 제외 그리디 기반 유입 집중점 마커 위치 산출 |
| `get_planned_route()` | `B04_PreProcess_Router_GIS.py` | `GET /api/projects/{id}/planned-route`: 2D 배경 지도 표기용 B03 원청 계획노선 CSV 2D 좌표 추출 및 CRS 변환 API |
| `get_confirmed_surface()` | `B04_PreProcess_Router.py:372` | `GET /api/projects/{id}/surface/confirmed`: B05 수신량 절감을 위한 0.4KB 확정 지표면 요약 fast-path API |
| `get_drainage_basins()` | `B04_PreProcess_Router_Basins.py` | `GET /api/projects/{id}/drainage/basins`: 관 매설 정보(`pipe_points.json`) 및 세부유역(`04_detailed_basins.geojson`) 데이터 조회 API (B04/B05 공용) |
| `update_drainage_basins()` | `B04_PreProcess_Router_Basins.py` | `POST /api/projects/{id}/drainage/basins`: 관 매설 포인트 편집 및 임시 세부유역 분할 계산 API (`common_util_drainage_detail` 공용 엔진 연동, B04/B05 공용) |
| `confirm_drainage_basins()` | `B04_PreProcess_Router_Basins.py` | `PUT /api/projects/{id}/drainage/basins`: 세부 배수유역 구조 확정 및 `pipe_points.json`/`04_detailed_basins.geojson` 최종 영구보존 API (B04/B05 공용) |
| `delete_drainage_basins()` | `B04_PreProcess_Router_Basins.py` | **[신설/2026-08-02]** `DELETE /api/projects/{id}/drainage/basins`: 관 매설 저장분 및 세부유역 GeoJSON 물리적 디스크 삭제 및 자동배치 갱신 API (B04/B05 공용) |
| `_apply_recommendations()` | `B04_PreProcess_Router_Basins.py` | 자동 배치 관에 추천 관경·시설을 넣고 사용자 변경값·기존 옵션을 보호 |
| `analyze_surface()` | `B04_PreProcess_Router.py:88` | 분석 실행: start_stage → clear_confirmed_surface_models → to_thread(run_surface_analysis) → save_surface_analysis_to_db |
| `confirm_surface()` | `B04_PreProcess_Router.py:206` | 모델 수동 확정: 트랜잭션 내에서 기존 `CONFIRMED` 행들을 `COMPLETE`로 되돌리고, 선택된 모델을 `CONFIRMED`로 변경 후 `complete_stage` 호출 (SYSTEM_ADMIN 전용) |
| `confirm_surface_selection()` | `B04_PreProcess_Service.py:39` | 재사용 가능한 확정 서비스 헬퍼: CONFIRMED 처리, stage 1 params 스냅샷 저장 및 `complete_stage(1)` 수행 (API 및 자동 확정이 공유) |
| `get_surface_confirmation_params()` | `common_util_surface_confirmation.py:42` | 확정 params 스냅샷 조회: 스냅샷이 존재하면 이를 우선 사용하고, 없으면 config 기본값으로 폴백 조회 (B05 등 연동 경로 통합 경유) |
| `merge_surface_confirmation_params()` | `common_util_surface_confirmation.py:66` | 기존 stage 1 params에 확정 선택값 전체를 병합 저장 |
| `save_surface_analysis_to_db()` | `B04_PreProcess_Repository.py:336` | processed_point_cloud + surface_models INSERT (호출자 트랜잭션) |
| `delete_project_surface_models()` | `B04_PreProcess_Repository.py:321` | 재분석 시 이전 세대의 유령 모델 정보 누적 방지를 위해 기존 surface_models 삭제 |
| `get_wf1_analysis_status()` | `B04_PreProcess_Router.py:369` | 상태 조회(project_workflow_stages 우선, 폴백) |
| `_cache_contours_safely()` | `B04_PreProcess_Engine_Pipeline.py:111` | 등고선 캐시 오류 발생 시에도 모델 빌드 프로세스가 롤백되지 않도록 경고 로깅 처리 |
## 수치지형도 도엽 오버레이 아키텍처 (2026-07-26, 2026-08-01 S8 개편)
* **도엽 zip 영구보존 및 processed/map_sheets/**: VWorld를 통해 다운로드한 도엽 zip 원본 및 인덱스 메타(`map_sheets_index.json`)는 `{프로젝트 영구저장소}/B04_PreProcess/processed/map_sheets/` 경로에 보관하며, `prune_sheets()`를 통해 21개 비대상 잔재 zip을 자동 정리합니다.
* **노선 시/종점 기준 도엽 선정**: 기존 LAS 전체 bounds 기반 도엽 선정 대신 `neighbors_for_points()`를 구현하여 계획노선 시/종점 좌표 기반 도엽 합집합을 선정하여 불필요한 도엽 수집을 최소화합니다.
* **크롭 철회 및 raw byte 서빙**: 사용자 요청에 따라 도엽 잘라내기(크롭)를 철회하고 원본 등고선 전송을 유지하며, JSON 재직렬화 대신 raw byte direct 전송 및 ETag 304 응답 처리(`B04_PreProcess_Router_GIS.py`, 2.0s -> 0.006s)를 적용했습니다.
* **위성사진 범위 확대 (`SURFACE_MAP_MARGIN_TILES = 3`)**: 위성사진 타일 여유폭을 3타일로 확장하고 타임스탬프(`_t=`)를 제거하여 ETag/304 응답을 활성화했습니다.
* **VWorld 취득 자동화**: 검색 API(무로그인)와 다운로드 API(자격증명 `.env` `VWORLD_LOGIN_ID/PW` 활용 세션 로그인)를 파이썬 백엔드에서 오케스트레이션하여, 세션 만료 시에도 무인 구동하도록 재로그인 1회 재시도 정책을 포함합니다.
## 워크플로우 상태 전이 및 자동 확정
일반 역할(`role != "SYSTEM_ADMIN"`)인 경우 B03 분석이 끝난 시점에 백엔드에서 비동기 스레드 바깥(`B03_FileInput_Service_WF1.py`)에서 `confirm_surface_selection()`을 자동 호출하여 모델을 자동 확정하고 stage 1 `COMPLETE`를 격발합니다.
* **complete_stage(1) 호출 지점 일원화**: 기존 B03 라우터에서 분석 직후 stage 1 COMPLETE를 시키던 결함을 해결하고, 수동/자동 확정 서비스 내부로 일원화하였습니다.
* **스텝바 disabled 및 진입 가드**: 일반 사용자는 B04 페이지 진입이 차단되며(disabled 처리), URL 강제 진입 시 stage 1 완료 여부에 따라 B05 또는 B03으로 분기 리다이렉트됩니다.
* **uvicorn 로깅 부작용 완치**: status API 폴링에 따른 access_log 전면 차단 옵션(`access_log=False`)을 롤백하고, 일반 사용자 B04 진입 차단으로 인해 근본적인 로깅 비대화 문제가 해결되었습니다.
## ⚙️ 설정 및 환경 파일 정합성
* **.env**: uvicorn 자동 리로드로 인해 백그라운드 분석 스레드가 침묵 소멸하는 리스크 차단을 위해 `DEBUG=False`로 변경
* **config/config_system.py**:
* `SURFACE_CONFIRM_DEFAULT_FILTER="csf"`, `SURFACE_CONFIRM_DEFAULT_METHOD="dtm"` 등 자동 확정 기본값 설정 관리
* `SURFACE_MODEL_PRECOMPUTE` 순서에서 `dtm` 최우선 빌드되도록 조정
* 수치 정합성 기준치 old 버전 값(implicit/TIN/meshfree 등)으로 원복
* 기본 등고선 사전 캐시 간격을 1.0m로 유지하도록 `SURFACE_CONTOUR_INTERVAL_M=1.0` 설정
* **requirements.txt**: 현행 `scipy==1.18.0`. meshfree Delaunay 생성에는 사용하지만 등고선 격자 평가의 `find_simplex` 병목은 직접 삼각망 래스터화로 우회
## 📋 구현 예외 처리 검토 항목 (PLAN)
* **자동 확정 세션 분리**: 백그라운드 스레드 에러 방지를 위해 `confirm_surface` 트랜잭션을 로그인 세션 의존성 없이 DB 커넥션과 파라미터만 받는 독립 비동기 함수로 격리 설계.
* **등고선 간격 포맷 통일**: 부동소수점 오차로 인한 캐시 미인식 및 중복 연산 방지를 위해 등고선 간격은 API 및 파일 경로 조회 시 항상 소수점 1자리(예: `1.0`)로 포맷팅하여 통일.
## 2D/GIS 미표시 원인 분석 및 조치
* **PRJ 파일 부재로 인한 지도 다운로드 silent 스킵**: `B04_PreProcess_Engine_VWorld.py`의 `download_vworld_satellite_map`이 `.prj` 파일 부재 시 별도 예외 없이 즉시 `None`을 반환하여 위성 지도 및 메타데이터 생성이 무산됨.
* **좌표계 불일치(5186 ↔ 5187)로 인한 WFS API 빈 피처 반환**: `.prj` 파일이 없어 기본 투영을 `EPSG:5186`(중부원점)으로 가정하여 좌표 변환을 하였으나, 업로드 데이터의 실제 투영계는 `EPSG:5187`(동부원점)이었음. 이에 따라 BBOX 범위가 실제 범위에서 완전히 왜곡(바다 등)되어 브이월드 WFS API가 빈 GeoJSON 파일만 생성함.
* **검증 및 해결**: 수동 진단 스크립트(`scratch/test_vworld_download.py`)를 통해 정확한 PRJ 경로(`B03_FileInput/input/prj/result.prj`)와 정합 좌표계를 입력한 경우 위성 지도와 국가 GIS 벡터 데이터들이 모두 정상적으로 다운로드됨을 확인함.
@@ -0,0 +1,28 @@
---
type: page-frontend
status: stable
page_id: B04_PreProcess
related_pages: ["[[B04_PreProcess/B04_frontend]]", "[[B04_PreProcess/B04_drainage_compass_crs]]", "[[crs_metadata]]", "[[completed_2026-09-03_additional]]"]
last_updated: 2026-09-03
source: ["docs/raw/plans/2026-09-03_plan_completed_items_2.md"]
---
# B04 3D 방위·좌표계 최신 결정
## 3D 방위 위젯
| 항목 | 위치 | 역할 |
|---|---|---|
| `B04_PreProcess_UI_Compass.ts` | `B04_PreProcess/` | 카메라 방향과 앙각으로 경사 나침반 링·도북 화살·표고침 렌더링 |
| 방위 위젯 스타일 | B04 CSS | 84×84 링과 도북·표고 표시 제공 |
축 트라이어드 시안은 중간 검토안이며 최종 표기는 경사 나침반 링이다. 기본·상단·정면·측면 시점에서 링 납작함과 도북 방향을 확인했다.
## 작업 좌표계
| 항목 | 위치 | 역할 |
|---|---|---|
| 좌표계 일치 검사 | B03 입력 체인 | 라이다 PRJ와 노선·도엽 좌표계가 다르면 입력 단계에서 차단 |
| 도엽 재투영 | B04 도엽 서피스 체인 | 라이다가 없을 때 선택된 노선 좌표계로 도엽을 맞춤 |
이 결정은 [[B04_PreProcess/B04_drainage_compass_crs]]의 “지형 PRJ가 현재 주인” 기록보다 최신이다. 라이다가 있으면 라이다 PRJ를 우선하고, 없으면 노선 좌표계를 사용한다.
+37
View File
@@ -0,0 +1,37 @@
---
status: draft
page_id: B04_PreProcess
related_pages: ["[[B04_PreProcess/B04_backend]]", "[[B04_PreProcess/B04_api]]", "[[B04_PreProcess/B04_dependencies]]", "[[db_schema/files_surface]]", "[[architecture/project_map]]", "[[architecture/workflow_data_flow]]"]
last_updated: 2026-07-18
---
# B04_PreProcess — DB
이 페이지가 쓰는 테이블 (정의는 concepts에, 여기선 용도만).
## 쓰는 테이블
| 테이블 | 이 페이지의 용도 | 정의 |
|---|---|---|
| `processed_point_cloud` | 필터/변환된 포인트클라우드 저장(input_files 참조) | [[db_schema/files_surface]] |
| `surface_models` | TIN/DTM/NURBS/implicit/meshfree 모델 메타데이터 (status: PROCESSING, COMPLETE, CONFIRMED, FAILED) | [[db_schema/files_surface]] |
| `terrain_layers` | 등고선 등 파생 레이어 | [[db_schema/files_surface]] |
| `project_workflow_stages` | WF1(stage 1) 상태 전이·조회 | [[workflow_state]] |
| `input_files` | 분석 대상 LAS/LAZ 조회 | [[db_schema/files_surface]] |
| `projects` | (레거시 폴백) status 조회 | [[db_schema/projects]] |
## Repository 함수
| 함수 | 위치 | 역할 |
|---|---|---|
| `create_processed_point_cloud()` | `B04_PreProcess_Repository.py:28` | processed_point_cloud INSERT |
| `create_surface_model()` | `B04_PreProcess_Repository.py:92` | 모델별 메타데이터 저장 |
| `get_input_file()` | `B04_PreProcess_Repository.py:177` | 입력 LAS 단건 조회 |
| `clear_confirmed_surface_models()` | `B04_PreProcess_Repository.py:269` | 재분석 시 기존 CONFIRMED 모델들을 COMPLETE로 초기화 |
| `confirm_surface_model()` | `B04_PreProcess_Repository.py:282` | 지정된 모델을 CONFIRMED 상태로 업데이트하고 기존 확정 모델 초기화 |
| `delete_project_surface_models()` | `B04_PreProcess_Repository.py:321` | 재분석 시 이전 세대의 유령 모델 정보 누적 방지를 위해 기존 surface_models 삭제 |
## 참고
- `save_surface_analysis_to_db()`([[B04_PreProcess/B04_backend]])가 processed_point_cloud + surface_models를 한 트랜잭션으로 저장(호출자가 begin/commit)
- WF1 단계 판정 SSOT는 `project_workflow_stages`. `projects.status`는 레거시 폴백 경로에서만 참조 → [[workflow_state]]
@@ -0,0 +1,30 @@
---
status: stable
page_id: B04_PreProcess
related_pages: ["[[B04_PreProcess/B04_backend]]", "[[B04_PreProcess/B04_frontend]]", "[[dependencies]]", "[[architecture/project_map]]", "[[architecture/workflow_data_flow]]"]
last_updated: 2026-07-19
source: docs/raw/verification/2026-07-18_verify_crs_and_polling_log.md
---
# B04_PreProcess — Dependencies
이 페이지가 쓰는 외부 라이브러리 (공통 정의는 [[dependencies]]).
## 백엔드 (Python)
| 라이브러리 | 용도 |
|---|---|
| Laspy | laspy==2.7.0 (LAS/LAZ 구조화) |
| Whitebox / Rasterio | whitebox==2.3.6 / rasterio==1.5.0 (지면 필터·DEM 처리) |
| Trimesh | trimesh==4.12.2 (TIN/메시 모델) |
| Geopandas / Shapely | geopandas==1.1.4 / shapely==2.1.2 (GIS 벡터 연산) |
| NumPy | numpy==2.5.0 (배열 연산) |
| SciPy | scipy==1.18.0 (Delaunay 삼각망 생성 및 수치 보간) |
→ 공통 정의·버전 → [[dependencies]]
## 프론트엔드 (TypeScript)
| 라이브러리 | 위치 | 용도 |
|---|---|---|
| **three.js** | `B04_PreProcess_UI_Viewer.ts:1`, `..._TerrainViewer.ts` | WebGL 3D 뷰어(WebGLRenderer, OrbitControls, THREE.Points/Mesh) |
@@ -0,0 +1,40 @@
---
type: page-backend
status: stable
page_id: B04_PreProcess
related_pages: ["[[B04_PreProcess/B04_backend]]", "[[B04_PreProcess/B04_frontend]]", "[[drainage_watershed]]", "[[crs_metadata]]", "[[completed_2026-09-03]]"]
last_updated: 2026-09-03
source: ["docs/raw/plans/2026-09-03_plan_completed_items.md"]
---
# B04 세부유역·방위·좌표계
## 세부유역 형상 보존
| 항목 | 위치 | 역할 |
|---|---|---|
| `polygon_parts()` | `B04_PreProcess/B04_PreProcess_Engine_Watershed_Flow.py` | 유역의 분리 조각과 각 외곽·구멍 링을 보존 |
| `WatershedBasin.boundary_parts` | `common_util/common_util_drainage_detail.py` | 다중 조각 정본; `boundary_xy`·`boundary_rings`는 호환 파생값 |
| `polygon_rings_lonlat` | `B04_PreProcess/B04_PreProcess_Router_Basins.py` | API에 다중 링 좌표 제공 |
| `pointInRings()` | B04·B05 유역 캔버스 | even-odd 채움과 구멍을 고려한 선택 판정 |
| `assemble_basins()` | `common_util/common_util_drainage_detail.py` | 세부유역만 최소면적 0㎡, 단순화 허용오차 1m 적용 |
S자 실사례와 용화 자료에서 구멍·분리 조각을 유지하고 경계 없는 유역을 제거했다. 1차 전체 배수유역의 단일 외곽 규칙은 유지한다.
## 종단 높낮이 기반 배정
| 항목 | 위치 | 역할 |
|---|---|---|
| `assign_road_cells_to_pipes()` | `common_util/common_util_drainage_detail.py` | 관 사이 최고점을 분수령으로 삼아 좌우 관에 도로 셀 배정 |
미세 요철의 국소 저점 추적 대신 구간 마루를 사용한다. 관 없는 저점은 별도 시설로 만들지 않는다.
## 3D 방위와 좌표계
| 항목 | 위치 | 역할 |
|---|---|---|
| `B04_PreProcess_UI_Compass.ts` | `B04_PreProcess/` | 카메라 오프셋과 `x, 높이, -y` 규약으로 도북 회전각 산출 |
| `resolve_project_crs()` | `common_util/common_util_crs.py` | 노선 CRS·파일 라벨·지형 PRJ·DB EPSG·5186 순 폴백 창구 |
| 트림 실패 진단 | `common_util/common_util_route_geometry.py` | 노선과 지표면 bbox를 기록해 좌표계·측량범위 문제 구분 |
이 페이지 작성 당시 작업 좌표계는 지형 PRJ였으나, 이후 완료된 라이다 우선·입력 차단 결정은 [[B04_PreProcess/B04_compass_crs_2026_09]]을 따른다.
@@ -0,0 +1,87 @@
---
status: stable
page_id: B04_PreProcess
related_pages: ["[[B04_PreProcess/B04_backend]]", "[[B04_PreProcess/B04_api]]", "[[B04_PreProcess/B04_dependencies]]", "[[las_free_sheet_surface]]", "[[ui_templates]]", "[[concepts/drainage_watershed]]", "[[architecture/project_map]]", "[[architecture/workflow_data_flow]]"]
last_updated: 2026-08-30
source: ["docs/raw/verification/2026-07-19_verify_b04_gis_theme.md", "docs/raw/verification/2026-07-26_verify_도엽_오버레이.md", "docs/raw/verification/2026-07-28_verify_B04_Map_Performance.md", "docs/raw/verification/2026-08-01_verify_B04_B05_drainage_ui_improvements.md", "docs/raw/verification/2026-08-02_verify_B04_B05_drainage_unification.md", "docs/raw/verification/2026-07-17_verify_B04_contour.md", "docs/raw/verification/2026-07-17_verify_B04_Surface_Reorganization.md", "docs/raw/verification/2026-07-18_verify_b04_confirm_b05_rebuild.md"]
---
# B04_PreProcess — Frontend
WF1 지표면 분석 화면. **엔지니어링 레이아웃(상단 헤더 제거, 전체 화면 폭, 좌측 상세 옵션 패널 + 우측 메인 3D 뷰어 2열 배치(포인트클라우드 & 5종 지표면 모델 비교) + 양방향 카메라 동기화)** 및 하단 2D 배경 지도 인터페이스.
LAS 유무와 별개로 도엽등고 3D 서피스를 별도 컨테이너에서 비교하며, 6개 보간 방식과 확정 계약은 [[las_free_sheet_surface]]에서 관리한다.
## 파일 구조
| 파일 | 위치 | 역할 |
|---|---|---|
| `B04_PreProcess_UI_Page.ts` | `B04_PreProcess_UI_Page.ts:1-378` | 페이지 조립(`createWorkflowLayout` 사용) + 2열 뷰어 및 옵션 통합 제어, 모델 확정(Confirm) 및 초기화 |
| `B04_PreProcess_UI_Viewer.ts` | `B04_PreProcess_UI_Viewer.ts:1-346` | 포인트클라우드 3D 뷰어(three.js) 및 카메라 상태 브로드캐스트 |
| `B04_PreProcess_UI_TerrainViewer.ts` | `B04_PreProcess_UI_TerrainViewer.ts:1-647` | 지형 메시 3D 뷰어(three.js) 및 카메라 상태 동기화 수신, 표시 옵션 제공 |
| `B04_PreProcess_UI_Camera.ts` | `B04_PreProcess_UI_Camera.ts:1-43` | 3D 뷰어 공통 카메라 동기화, 축척 계산, 뷰 피팅 등 유틸리티 정의 |
| `B04_PreProcess_UI_MapViewer.ts` | `B04_PreProcess_UI_MapViewer.ts:1-423` | 하단 2D 지도 UI 및 이벤트 제어 (마우스 커서 줌 중심, 휠 드래그 브라우저 기본 간섭 차단, rAF 스로틀 렌더링 요청) |
| `B04_PreProcess_UI_MapRender.ts` | `B04_PreProcess_UI_MapRender.ts:1-359` | **[신설]** 하단 2D 지도 Canvas 렌더링 전용 엔진 (GeoJSON 0~1 정규화 사전 투영, 프레임당 1회 어파인 계수 재사용, bbox 뷰포트 컬링, Douglas-Peucker 오차 0.75px 연속 LOD 렌더링) |
| `B04_PreProcess_UI_MapOverlays.ts` | `B04_PreProcess_UI_MapOverlays.ts` | **[신설/2026-08-02]** 지도 위 오버레이 기하 도형(`drawFilledRing`, `drawRingBadge`, `drawUpstreamLines` 등) 렌더러 분리 모듈 (149줄, 700줄 제약 준수). |
| `B04_PreProcess_UI_Basins.ts` | `B04_PreProcess_UI_Basins.ts` | **[신설/2026-08-01]** 관 매설 지점 편집(스냅, 드래그, 추가/삭제, 우클릭 컨텍스트) 및 세부유역 분할 렌더러/이벤트 핸들러. (559줄) |
| `B04_PreProcess_UI_FlowRamp.ts` | `B04_PreProcess_UI_FlowRamp.ts` | **[신설/2026-08-01]** 도로 유입 흐름 강도 램프(FlowRamp) 공용 렌더링 및 범례(`createFlowLegend`) 렌더링 컴포넌트. |
| `B04_PreProcess_UI_FlowStrength.ts` | `B04_PreProcess_UI_FlowStrength.ts` | **[신설/2026-08-01]** 계획노선 1m 레인보우 흐름 강도 오버레이 및 유입 집중점 클릭 렌더러. |
| `B04_PreProcess_Api_Fetch.ts` | `B04_PreProcess_Api_Fetch.ts:1-224` | surface API 클라이언트 (지면 필터 쿼리 파라미터 연동, geojson layer 엔드포인트 연동) |
| `B04_PreProcess_UI_Style.css` | `B04_PreProcess_UI_Style.css` | 폼 그룹/모델 카드/2열 뷰어/2D 지도/관 매설 및 세부유역 관련 스타일 |
## ⚠️ 계획서와 실 코드 불일치 (3D 뷰어)
이전 wiki(계획서 기반)는 **"WebCAD 3D 뷰어 미구현"**으로 기재했으나,
실 코드에는 three.js(WebGL) 기반 뷰어가 **구현되어 있음**:
- `createSurfacePointCloudViewer` (`B04_PreProcess_UI_Viewer.ts:187` WebGLRenderer, OrbitControls, THREE.Points)
- `createSurfaceTerrainViewer` (`B04_PreProcess_UI_TerrainViewer.ts`)
- UI_Page에서 import·인스턴스화(`B04_PreProcess_UI_Page.ts:37,38,110,356`)
→ 규칙6, 실 코드 채택. dependencies도 three.js 반영 → [[B04_PreProcess/B04_dependencies]]
## 3D 뷰어 DOM 마운트 버그 수리
* **증상**: 3D 뷰어가 생성된 직후 DOM에 완전히 연결(`isConnected`)되기 전에 애니메이션 루프의 프레임이 실행되면서, 파괴 프로세스(`cancelAnimationFrame` 및 `dispose`)가 오동작하여 뷰어가 화면에서 영구적으로 사라지는 문제가 보고됨.
* **조치**: `hasConnected` 플래그를 신설하여 DOM에 1회 이상 정상적으로 마운트된 이후에만 `isConnected` 해제 시 소멸 로직이 격발하도록 뷰어 수명 주기를 제어하여 오류를 정상 복구함 (`B04_PreProcess_UI_Viewer.ts`, `_TerrainViewer.ts`).
## 3D 뷰어 테마 연동 및 가독성 개선
* **3D 뷰어 테마 연동**: `B04_PreProcess_UI_Camera.ts`에 추상화된 `bindSurfaceViewerTheme` 공통 유틸을 신설하여 뷰어(`Viewer.ts`, `TerrainViewer.ts`)가 개별적으로 테마 감지를 구현하지 않고 통일된 방식으로 배경 갱신을 동기화함. 다크 모드 시 `--color-surface-raised` 값을 computed style로 조회하여 Three.js `scene.background`에 적용하며, 로딩 전 상태에 대비해 안전한 다크 폴백(`0x251f38`)을 채택. `dispose` 시 MutationObserver 및 이벤트 리스너 리소스를 완벽히 제거함.
* **척도 가독성 확보**: `B04_PreProcess_UI_Style.css`에서 기존 하드코딩된 `--color-text` 계열 변수를 CSS 표준 토큰인 `--color-text-body`로 통합 매핑하고, 다크 모드 배경 및 복잡한 지형 메시 위에서 척도 식별이 수월하도록 `filter: drop-shadow(...)` 및 `text-shadow: 0 1px 2px var(--color-surface-raised)` 스타일 처리를 추가해 가독성을 확보함.
## 컴포넌트 & API 함수
| 함수 / API | 위치 | 역할 / 대응 API |
|---|---|---|
| `renderB04Surface()` | `_UI_Page.ts:95` | 페이지 조립 및 뷰어 로드 |
| `createSurfacePointCloudViewer()` | `_UI_Viewer.ts:187` | 포인트클라우드 three.js 뷰어 생성 |
| `createSurfaceTerrainViewer()` | `_UI_TerrainViewer.ts` | 지형 메시 three.js 뷰어 생성 |
| `createSurfaceMapViewer()` | `_UI_MapViewer.ts:44` | 2D 위성/지적 배경지도 뷰어 생성 |
| `initDrainageBasinsUI()` | `_UI_Basins.ts` | 관 매설 드래그/스냅/편집 및 세부유역 렌더링 |
| `confirmSurfaceModel()` | `_Api_Fetch.ts:139` | `POST /surface/confirm` (모델 확정) |
| `fetchDetailPipePoints()` | `_Api_Fetch.ts` | `GET /drainage/pipe-points` (관/세부유역 조회) |
| `computeDetailBasins()` | `_Api_Fetch.ts` | `POST /drainage/detail-basins` (유역분할 계산) |
| `saveDetailPipePoints()` | `_Api_Fetch.ts` | `PUT /drainage/pipe-points` (관/세부유역 확정) |
| `deleteDetailPipePoints()` | `_Api_Fetch.ts` | `DELETE /drainage/pipe-points` (관/세부유역 삭제) |
## 처리 흐름
1. 레이아웃 조립 후 프로젝트의 15개 지표면 모델 목록 및 입력파일 로드.
2. 좌측 패널에서 LAS 파일, 지면 필터, 표현 방식(dtm 등) 선택 및 3D 뷰어에 50만 샘플 렌더링.
3. 2열 뷰어 간 양방향 카메라 동기화(Orbit Target, Distance)로 시점 정합.
4. 모델 확정 시 ID를 백엔드로 보내 stage 1 확정하고 WF2 진입 권한 획득.
5. 초기화 시 입력값을 복원하고 `DELETE /drainage/pipe-points`로 관 매설 정보 물리 삭제.
6. 하단 2D 지도에서 6종 도엽 레이어(하천, 옹벽 등)를 위성사진 위에 탑뷰 정사 정합 렌더링.
## 3D 카메라 커서 피봇 & 2D 오버레이 UI 개선 (2026-08-01~02 일원화)
* **커서 피봇**: pointerdown 지점을 회전 축으로 삼고 줌 시 커서 지점 고정 dolly 처리.
* **조작 보정**: PAN(가운데 버튼 할당), 수직 회전 부호 반전, 뷰셋 버튼 그룹 좌상단 이동.
* **SSOT 일원화**: B05 사본 폴더를 폐지하고 B04의 `drainage/` 정본 경로로 연동 일원화.
* **2D 휠 줌 반전**: 당기면 확대, 밀면 축소로 줌 방향 통일.
* **가독성**: 2D 지도 우측 흐름램프 게이지 범례 신설, 2D 배관 라벨 흰 테두리 헤일로 입힘.
* **성능 최적화**: 등고선 LineSegments 2개로 드로우콜 병합, ETag/304 HTTP 및 IndexedDB asset 캐시 적용.
* **흐름 강도 분석**: 1m 간격 계획선 색상 오버레이 렌더링, 집중점 클릭 시 기여 셀 외곽선 실선 하이라이트.
## 의존성
- [[a00_app_shell_framework]] — `navigateTo`, `workflowSteps`
- `config_frontend.ts` — `API_BASE_URL`, `CURRENT_PROJECT_ID_KEY`, `ROUTES`
- [[ui_templates]] — `createWorkflowLayout`, `createProgressCircle`
- **three.js** (WebGL 3D 뷰어) → [[B04_PreProcess/B04_dependencies]]
- 백엔드 API → [[B04_PreProcess/B04_api]]
@@ -0,0 +1,22 @@
---
type: file-backend
status: draft
related_pages: ["[[architecture/project_map]]", "[[architecture/workflow_data_flow]]"]
page_id: B04_PreProcess
source_file: "B04_PreProcess/B04_PreProcess_Router.py"
last_updated: 2026-07-24
---
# B04_PreProcess_Router.py
포인트클라우드 기반 DTM/TIN/NURBS/implicit/meshfree 지표면 모델링 생성 연산 격발, 캐싱, 지표면 확정(confirm) API 라우터입니다.
## 🛠️ 주요 함수 목록
| 항목 | 위치(상대 경로) | 역할 |
|---|---|---|
| `generate_surface_models()` | `B04_PreProcess/B04_PreProcess_Router.py` | `POST /{project_id}/surface/generate` 5대 지표면 연산 격발 및 NPZ 캐싱 |
| `confirm_surface_model()` | `B04_PreProcess/B04_PreProcess_Router.py` | `POST /{project_id}/surface/confirm` 대표 지표면 확정 및 stage 1 COMPLETE 전이 |
## 🔗 연관 개념 및 의존성
- `B04_PreProcess_Engine.py` — 지표면 보간 엔진