- 도엽 병합본의 화면 표시용 사본 생성(B04_wf1_Surface_Engine_SheetView):
프로젝트 + 500m로 잘라내고 좌표를 소수 7자리로 줄여 등고선 37.3MB -> 0.97MB.
분석용 원본은 그대로 둔다(배수유역은 상류까지 넓은 범위가 필요).
- /geojson의 도엽 레이어를 파일 그대로 + ETag로 전송 — 매 요청 2.0초 재직렬화 제거(0.008초).
- /vworld-map도 ETag 전송으로 바꾸고, 프론트가 붙이던 `&_t=` 시간꼬리표 제거.
- 도엽 레이어를 브라우저 보관함 경유로 조회하고 준비화면에서 미리 담는다.
- 배경 지도 범위 = 라이다 범위 + 계획노선 범위 + 여유 300m(SURFACE_MAP_MARGIN_M).
- 도엽 기준 좌표 = 계획노선 시점·종점(없으면 라이다 중심). 같은 도엽이면 9매,
이웃 도엽에 걸치면 12매. 표본 프로젝트는 기존 9매와 동일(회귀 없음).
- 선정에서 빠진 도엽 zip 정리(prune_sheets) — 표본에서 30매 중 21매가 다른 지역 잔재.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- GET /surface/confirmed 추가: 확정 구성(모델·필터·표현·평활·등고선간격)과
지형 가장자리만 반환(수 KB, 0.02s). 진입 판정·준비화면·B05의 단일 출처.
- B05 진입이 받던 포인트클라우드 JSON 23.8MB 제거 — 실제로 쓰던 값은 bounds뿐.
- 준비 표식을 프로젝트 ID에서 확정 signature로 변경: B04에서 다시 확정하면
대시보드 복귀·새 브라우저·B그룹 단계 이동 어느 경로로 들어와도 최신본을 담는다.
- preloadSurfaceAssets가 평활 여부를 추측하던 부분 제거(확정 저장값 사용) —
추측이 어긋나면 같은 지형을 두 번 내려받았다.
- B04 진입 시 필터·표현·평활·등고선간격을 확정본 값으로 초기화(확정 없으면 기존 기본값).
- 모델 확정 직후 준비 표식과 B05 세션 캐시를 비워 옛 지형이 남지 않게 함.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- B11_Status_UI_Loading + 라우트 b11-loading: 공통 프로그레스 서클로 단계·진행률 표시,
끝나면 원래 가려던 화면으로 자동 이동
- goToWorkflowStage: 아직 준비하지 않은 프로젝트면 준비 화면 경유, 같은 프로젝트로
다시 들어오면 건너뜀(탭 단위 기억). 다른 프로젝트면 보관분 교체
- 선적재 범위: 확정 지표면 3D + 그 등고선만 (종단·횡단은 0.86MB·0.06초로 이미 즉시라 제외,
배수유역·포인트클라우드도 제외)
- 실패 시 자동 이동하지 않고 담당자 연락 안내 + [그래도 이동]/[대시보드로]
- B04 등고선 간격 시작값을 B05 저장값과 공유(B04 변경은 DB에 쓰지 않음)
- 새 문구는 ui_locales에 한국어·영어 등록
- 휠 위 = 축소로 반전, 커서 지점을 축으로 한 dolly를 공용 유틸에서 직접 처리
- 회전 중심을 작은 구로 표시(돌리는 동안만, 화면상 크기 일정, 항상 위에 그림)
- 등고선 렌더 비용 감소: 폴리라인을 주곡선·보조곡선 2덩어리로 병합(드로우콜 424 → 2),
라벨은 카메라가 움직였을 때만 재배치
- common_util_http_cache: 파일 mtime+크기 ETag, If-None-Match 일치 시 304
(preview·contour 적용, 파일이 바뀌면 자동 무효화)
- A00_Common/b_asset_cache: IndexedDB 보관함(키 = projectId|url, 값 = 바이트+ETag).
보관본 즉시 사용 후 백그라운드 재검증, 3D는 보관 바이트를 직접 파싱
- 프로젝트 전환 시 타 프로젝트 보관분 삭제, 대시보드→B그룹 이동 시 확정 모델의
3D 프리뷰·등고선(1.0m) 미리 받기(포인트클라우드 제외)
- 회전축을 커서가 가리키는 지형 표면 지점으로. 포인트클라우드는 카메라 거리의 1%를
클릭 허용 반경으로 주고, 못 맞히면 시선 수직 평면과 만나 커서 방향 지점을 쓴다
(화면 중앙으로 되돌아가지 않음)
- 수직 회전 부호 반전 (마우스를 내리면 내려다보는 방향)
- controls.mouseButtons.MIDDLE = PAN (전역 공통). 브라우저 자동 스크롤 차단
- B05 뷰셋 버튼 그룹을 좌상단으로 이동 (.b05-route__view-controls top 58px → 16px)
증상 두 가지
1. 재산정 버튼을 눌러도 프론트에 아무 안내가 없었다.
오버레이가 지도 자체 상태(.b04-map__status)에 문구를 썼는데,
loadLayers 가 같은 칸에 3곳에서 덮어써 즉시 지워졌다.
2. 페이지 접근 시 배수유역이 안 보였다.
응답 캐시 파일(00_watershed_response.json)이 아직 없어 자동 조회가
빈 손으로 끝나는데, 그 사실을 화면에 알리지 않아 이유를 알 수 없었다.
조치
- 배수유역 전용 상태 줄(.b04-map__watershed-status)을 컨트롤 영역에 따로 둔다.
지도 로딩 문구와 서로 덮어쓰지 않는다.
- 컨트롤에 배수유역 그룹을 만들어 재산정 버튼 + 갈래 토글 4종 + 상태 줄을 묶었다.
- 진행 상태를 버튼 라벨에도 반영: 배수유역 재산정 -> 분석 중… / 불러오는 중…
- 결과 문구에 출처와 소요를 붙인다: [저장분] ... / [재산정 28.4초] ...
- 저장분이 없으면 오류가 아니라 안내로 표시:
"저장된 배수유역 분석이 없습니다. [배수유역 재산정]을 누르세요."
- 실패하면 버튼 활성 상태를 되돌려 껐다 켠 것처럼 보이지 않게 했다.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1. 재산정하지 않는 한 저장분을 그대로 쓴다
GET /drainage/primary-region 이 기본으로 영구저장소의 응답 캐시를
그대로 돌려준다(0.0004s). refresh=true 일 때만 다시 계산한다.
저장 배열에서 응답을 재조립하지 않고 **응답 자체**를 남긴다 —
재조립하면 원본과 어긋날 여지가 생긴다.
버튼 이름 배수유역 -> 배수유역 재산정. 지도를 열면 저장분이 자동으로 뜬다.
2. B05용 평균 흐름 화살표 (build_flow_arrows)
셀 화살표는 1m 라 도면 배율에서 경향이 안 보인다. 겹치지 않는 10m 블록으로
나눠 방향을 원형 평균하고, 40m 간격으로 솎아낸다.
- 세류선 셀과 도로 셀은 뺀다. 그 자리는 확정된 물길/노면을 따르는 값이라
사면 경향을 왜곡한다.
- 산술평균이 아니라 원형 평균(0도와 359도의 평균은 180도가 아니다).
평균 벡터 길이가 방향 일치도이므로 0.7 미만이면 그 블록은 버린다.
- 블록 유효 셀이 절반 미만이면 건너뛴다(가장자리 조각 방지).
실데이터 377개, 간격 40m 균일, 블록당 평균 98셀, 적 278 / 청 99.
config: ARROW_BLOCK_M / ARROW_SPACING_M / ARROW_MIN_COVERAGE / ARROW_MIN_AGREEMENT
3. 갈래별 하이드/쇼 버튼 4종
1차 유역 / 2차 유역 / 유역 방향 / 평균 흐름.
평균 화살표는 B04 에도 올려 형태를 확인할 수 있게 했다.
4. B05 는 페이지 진입 즉시 유역도를 올린다
B04 결과를 읽기만 해 0.1초면 끝나므로 버튼을 기다릴 이유가 없다.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
화살표가 안 보이던 문제
1m 격자를 도엽 전체 배율로 보면 셀이 1~2px 다. 줌 상한이 8배라 셀이
화살표 최소 크기(7px)에 절대 못 미쳐 채움색만 보였다.
-> 셀마다 그리지 않고 화면상 약 22px 간격이 되도록 건너뛰며 표본만 그린다.
화살표 크기는 그 간격에 맞춰 커진다. 흐름장을 읽는 표준 방식이다.
-> 채움색 위에서도 읽히도록 흰 테두리를 한 겹 깔고 그 위에 그린다.
갈래별 토글 버튼 추가 (1차 유역 / 2차 유역 / 유역 방향)
GIS 버튼 줄에 배수유역 전체 토글 옆으로 붙는다. 전체 토글이 꺼져 있으면
갈래 설정과 무관하게 아무것도 그리지 않는다.
그리는 순서는 유역방향(격자/화살표) -> 1차 유역 -> 2차 유역/관.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
분석은 돌고 상태 문구도 나오는데 지도에는 아무것도 안 보였다.
원인: 프레임 함수 이름이 draw() 가 아니라 drawVectorLayer() 라
오버레이 draw 호출을 끼워 넣는 치환이 조용히 실패했다. 호출 자체가
소스에 없었다.
- drawVectorLayer() 안, GIS 레이어와 등고 라벨 뒤에 오버레이 draw 삽입.
격자/화살표가 등고선을 덮어야 읽히므로 맨 위에 얹는다.
- drawPrimaryRegion 이 drawGridCells 를 한 번 더 부르던 중복 제거
(draw 체인이 이미 먼저 호출한다).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
분석이 30초 걸리는데 B05는 일반 사용자 화면이다. 관리자 확인용 B04에서
한 번 돌려 저장하고, B05는 그 결과를 읽어 관 보충과 세부유역만 처리한다
(2026-07-31 사용자 지시).
노선 원천 변경
- B05 확정 경로 -> B03 업로드 계획 노선 파일(CSV). 분석이 노선 설계보다
먼저 끝나 있어야 하기 때문. 샘플 planned_route_sample_epsg5187.csv 로 검증.
- common_util_route_geometry.py 신설 — RouteVertex/StructureCandidate/누가거리
보간/세류 교차점/계획 노선 CSV 리더. B04와 B05가 같은 표현을 쓰도록 공용화.
열 이름은 대소문자·한글 표기를 함께 받는다(B03이 여러 형식 수용 예정).
B04 (관리자 확인용, 신규)
- Engine_Watershed_{Grid,Stream,Descent,Flow,Expand,Export} — B05에서 git mv
- Engine_Watershed_Analyze.py — 1~8단계 오케스트레이션
- Router_Watershed.py — GET /drainage/primary-region
- UI_Watershed.ts — 2D 지도 GIS 레이어 그룹에 "배수유역" 토글 추가.
격자/화살표/세류망/1차영역/2차유역/기본관을 겹쳐 그린다.
- 저장 위치 B05_wf2_Route/drainage -> B04_wf1_Surface/drainage
- 03_road_routing 단계 추가: B05가 세부유역을 나눌 최소 배열(셀->도로셀 귀속,
유하장, 강도, 도로셀 제원, 셀 표고) + 계획도로선/기본배관/2차유역 기하
B05 (일반 사용자용, 축소)
- Engine_Drainage_Basin.py — B04 산출물 로더 + 관 보충(9) + 측구 라우팅/세부유역(10,11)
- Engine_Drainage.py 는 관경 산정만 남기고 322 -> 27줄
- Router_Drainage.py 509 -> 142줄. POST /drainage/basins 만 남김
- 화살표·격자·강도 띠 렌더 제거. 계획도로선/기본배관/2차유역만 받는다
삭제
- _legacy_watershed/ 4파일 (능선 행진 방식 원본 보관본)
- Engine_Watershed_Basin.py (B04 Analyze + B05 Drainage_Basin 으로 분할)
- GET /drainage/candidates 와 propose_structure_stations (구방식 후보 제안)
E2E 검증 (실데이터)
B04 분석 28.2s -> 저장(geojson 11KB + npz 2.6MB)
B05 로드 + 세부 설계 0.11s <-- 30초가 0.1초로
면적 457,404m2 로 B04 2차 유역과 정확히 일치
관 편집 재산정 0.12s, 관 3개 -> 세부유역 3개, 면적 보존
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>