Files
Aislo/docs/raw/plans/2026-08-01_plan_B04_detailed_basins.md
T
eomsangdonandClaude Opus 5 eb30b774f8 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>
2026-09-09 18:19:07 +09:00

19 KiB
Raw Blame History

B04 상세 배수유역 계산 (2026-08-01 착수)

목표: B04 하단 2D 지도에서 관 매설 지점(기본/자동보충/수동)을 편집하고, 계획노선 종단 Z에 따른 측구 흐름으로 관별 세부 배수유역을 나눈다. 결과는 모델 확정 시 영구저장한다.

A. 조사로 확정된 사실 (2026-08-01)

항목 결론
최대/최소 관 간격 이미 config에 있음 — DRAINAGE_PIPE_MAX_SPACING_M=300.0(config_system.py:280), DRAINAGE_PIPE_MIN_SPACING_M=20.0(config_system.py:282). 둘 다 os.getenv 지원 → 테스트 100m는 .env 한 줄로 처리, 코드 수정 불필요
세부유역 알고리즘 이미 B05에 전부 구현됨 — place_pipes()/_fill_gap()(등간격+slack 보충), assign_road_cells_to_pipes()(종단선 1차원 내리막 추적 + 사그는 최근접 관), assemble_basins()(담당 관 라벨 → polygonize_labels) 모두 B05_wf2_Route_Engine_Drainage_Basin.py(502줄)
스플릿 라인 별도로 긋지 않는다. 담당 관 라벨 경계가 곧 세부유역 경계 — 겹침/틈 원리적 부재, union = 2차 전체 유역
기본 관 _base_pipes()(B04_wf1_Surface_Engine_Watershed_Analyze.py:323) 세류 교차점, 최소간격 미만은 병합. 03_road_routing에 저장됨
유입 집중점 find_inflow_hotspots()(..._Analyze.py:356) 현행 유지. 구역번호 −1 = 기본 관 자리
종단 Z 현행 B04 = 원청 CSV z(common_util_route_geometry.read_planned_route_csv), B05 = route_points.z(B05 최적경로)
서피스 표고 샘플러 build_surface_sampler() / sample_xy() (B05_wf2_Route_Engine_Sections_Sampler.py:124,21) 재사용 가능
관 지점 영구저장 없음. B05는 chainages를 payload로만 받아 세션 휘발
⚠ 정합 결함 B05_prepare()(B05_wf2_Route_Router_Drainage.py:54)는 B05 최적경로 route_points 기준 vertices를 쓰는데, B04 산출물 road_chainage는 원청 CSV 노선 기준. 노선이 다르면 누가거리가 어긋남 → Z 소스 통일 작업에서 함께 정정

B. 설계 결정 (사용자 확정)

  1. 종단 Z 우선순위: ① longitudinal_sections.data.profile_alignment(B05 편집 계획고) → ② route_points.z(B05 DRAFT 경로) → ③ 확정 서피스 샘플링(build_surface_sampler) → ④ 원청 CSV z. 단 ①②는 B05 최적경로 XY 기준이므로 원청 CSV 노선과 동일 노선일 때만 채택(다르면 ③으로).
  2. 필터/서피스/스무딩 변경 시: Z만 다시 뽑아 세부유역만 재계산. 1차 격자 해석(30초)은 재실행하지 않는다.
  3. 관 지점 정본: B04_wf1_Surface/drainage/edits/pipe_points.json 단일 파일. chainage_m 기준 저장. B04·B05 공용(B05는 이 파일만 사본 안 만들고 원본 참조).
  4. 노선 변경 시: route_signature(원청 CSV 해시) 불일치 = 전량 리셋 후 기본+자동보충 재생성 → 상세유역까지 자동 실행(기존 "유역분석" 버튼 경로).
  5. 재계산 트리거: 편집은 프론트 메모리, "상세유역 분석" 버튼 클릭 시에만 서버 계산. 자동 재계산 없음(사용자가 속도 보고 추후 판단).
  6. 저장 시점: 기존 "모델 확정" 버튼에서 동시 커밋. 확정 전 이탈 시 저장된 값으로 복귀(임시저장 없음).
  7. 시·종점 관 배치 안 함, 마지막 관 하류 구간은 2차 유역 미포함이라 무시. 종단 상단부 관/단조경사 쏠림은 사용자가 수동 조절.
  8. 측구 방향(산측/계곡측) 무시.
  9. 표시 토글 2그룹: 유입 집중점 마커 / 관 매설 마커(기본·자동·수동)를 각각 hide-show 버튼으로 분리.
  10. B04는 관리자 트러블슈팅용, B05는 일반 사용자용. UI는 달라도 같은 이름 버튼은 같은 백엔드 호출 → 공용 엔진으로 승격해 보장.

C. 구현 체크리스트

C-1. 공용 엔진 승격 (선행)

  • common_util/common_util_drainage_detail.py 신설(517줄) — WatershedBasin, RoadRouting, read_road_routing, place_pipes, _fill_gap, _best_position, pipes_from_chainages, assign_road_cells_to_pipes, assemble_basins, estimate_pipe_diameter_mm, build_detail 이관
  • B05_wf2_Route_Engine_Drainage_Basin.py를 B05 사본 폴더만 정하는 어댑터(58줄)로 축소
  • common_util/common_util_route_profile.py 신설 — 종단 Z 해석기 resolve_route_profile(), 노선 동일성 판정 routes_match(), design_elevation_from_longitudinal()(B06에서 이관)
  • common_util/common_util_drainage_context.py 신설 — B04/B05 공용 입력 준비(노선·Z·좌표계). 계획에 없던 추가분: 두 화면이 같은 입력을 보게 하려면 준비 단계도 한 곳이어야 함
  • common_util/common_util_surface_sampler.py — B05_wf2_Route_Engine_Sections_Sampler.py 이동(B04도 써야 하므로 역방향 import 제거)
  • B05 _prepare() 노선 소스를 원청 CSV 기준으로 정정하고 Z만 해석기로 주입 (⚠ 정합 결함 해소)
  • B05_wf2_Route_Engine_Drainage.py 삭제 — 관경 stub이 공용 모듈로 옮겨져 빈 파일이 됨

C-2. B04 백엔드

  • common_util/common_util_drainage_pipes.py 신설 — pipe_points.json 로드/저장, route_signature 검사, 불일치 시 리셋. 계획의 B04 전용 저장소에서 변경: B05도 같은 파일을 봐야 "같은 버튼 = 같은 결과"가 성립
  • B04_wf1_Surface/B04_wf1_Surface_Router_Basins.py 신설 (225줄)
    • GET /{project_id}/drainage/pipe-points — 저장분 조회(없으면 기본+자동보충 생성해 반환)
    • POST /{project_id}/drainage/detail-basins — 편집 중 목록으로 세부유역 산정(저장 안 함)
    • PUT /{project_id}/drainage/pipe-points — 확정 시 관 지점 + 세부유역 커밋
  • 04_detailed_basins.geojson 저장 (세부유역 폴리곤 + 관 지점 피처)
  • config_system.py에 DRAINAGE_PIPE_POINTS_FILENAME, DRAINAGE_EDITS_DIRNAME, DRAINAGE_DETAIL_FILENAME 추가
  • main.py 라우터 등록

C-3. B04 프론트엔드

  • B04_wf1_Surface_UI_Basins.ts 신설(438줄) — 관 마커(기본/자동/수동 색 구분) 렌더·스냅·드래그·히트 판정, 세부유역 폴리곤 렌더, 우클릭 메뉴, "상세유역 분석" 버튼, 표시 토글 2그룹. 계획의 3개 파일을 1개로 통합: 셋 다 같은 관 목록 상태를 공유해 나누면 상태가 흩어짐
  • B04_wf1_Surface_UI_RouteSamples.ts 신설 — 계획선 1m 재표본·누가거리 역변환(흐름 강도 오버레이와 공용, 마커 어긋남 방지)
  • B04_wf1_Surface_UI_MapLayers.ts 신설 — 레이어 목록·기본값·색 분리(D-1 해소)
  • _UI_MapViewer.ts 수정 — 오버레이 배선, 우클릭/드래그 이벤트, commitDrainage() 노출
  • B04_wf1_Surface_Api_Fetch.ts 수정 — 신규 3개 엔드포인트 클라이언트
  • B04_wf1_Surface_UI_Page.ts 수정 — "모델 확정" 클릭 시 관 지점·세부유역 동시 커밋
  • locale 12종 / theme 토큰 2종(--map-pipe-auto, --map-pipe-user) / 우클릭 메뉴 CSS 추가
  • 테스트 간격값은 사용자가 config_system.py 기본값을 100m/5m로 직접 조정 (규제값 300m는 .env로 복원)

C-4. 마감

  • ruff format / prettier 실행, ruff check 통과, tsc --noEmit 통과, vite build 성공
  • 700줄 초과 파일 없음 (최대 _UI_MapViewer.ts 647줄)
  • 커밋 후 .claude/git-autopush.ps1 실행

D. 실행 검증 결과 (2026-08-01, 서버 기동 상태)

대상 프로젝트 acb9170b… (원청 노선 135정점 / 350.1m / EPSG 5187), 격자 1589×904, 도로 셀 1907.

확인 항목 결과
종단 Z 출처 route_points (B05 최적경로가 원청 노선과 일치 판정) — Z 528.40~544.66m
자동 생성 관 4개(기본 1 + 자동보충 3), 세부유역 4개
세부유역 경계 근거 03_road_routing.npz의 road_slot(1m 셀별 물 흐름 도달 도로 셀) 라벨 경계
관 추가/이동 후 유역 수가 따라 늘고,면적 합 457,404㎡ 불변 (경계 불변 조건 충족)
저장/재조회 edits/pipe_points.json + 04_detailed_basins.geojson 기록, 재조회 시 기본/자동/수동 표시 유지
초기화(points: []) 저장분 무시하고 기본 관 + 자동 보충으로 복귀
인증 세션 없으면 401

검증에 쓴 임시 산출물(테스트로 만든 pipe_points.json·04_detailed_basins.geojson)은 삭제해 원래 상태로 되돌렸습니다.

E. 사용자 확인 후 후속 조치 1차 (2026-08-01, 커밋 83f23aa)

사용자가 화면에서 직접 확인하고 지시한 5건. 전부 반영 완료.

번호 지시 처리
1 관 매설·세부유역 토글을 하나로(이름 "세부유역") 따로 끄면 관을 옮겨도 유역이 안 보여 판단 불가 — 단일 토글로 통합
2 남는 버튼을 "집중유역"으로, 노선 위 집중점 hide/show(기본 hide) 유입 집중점 마커를 흐름 강도 색칠에서 분리해markerButton으로 신설. 끄면 골라 둔 유입 외곽선도 함께 걷는다
3 세부유역에 서클 번호(시점→종점 오름차순) 폴리곤 면적 중심(ringCentroid)에 서클 숫자. 번호는 백엔드 basin.index(누가거리 순)를 그대로 사용
4·5 관 매설 추가·삭제 동작 안 함 원인: 메뉴 항목을 누를 때 pointerdown이 뷰포트로 전파돼 메뉴가 먼저 닫히면서 click이 발생하지 않음. 메뉴 안 이벤트를 지도 조작에서 제외

F. 사용자 확인 후 후속 조치 2차 (2026-08-01, 커밋 8c37f2f)

번호 지시 처리
1 B05식 유역 부분 활성화를 B04에도, 유역 클릭 선택 포함 selectedBasin 도입. 유역 폴리곤 클릭(pointInRing)·관 마커 클릭 모두 선택, 유역 밖 클릭 시 해제. 클릭 우선순위 세부유역 → 집중점 고정(B04 오버레이 다중 충돌 방지). 선택 유역 제원은 상태 줄 표기
2 B05 배배관 편집 버튼 삭제, 상시 드래그, 이동 시 자동 재계산 editMode 제거 → 마커 상시 드래그. 계획선 좌클릭 추가는 폐지(유역 선택과 충돌) → 우클릭 메뉴로 이동. createPipeEditor(onChange, onCommit)의 onCommit에서 추가·삭제·이동 완료 시 즉시 재산정
3 "자동 제안" → "초기화" localeB05_Drainage_Btn_Auto 문구 변경 + 툴팁 추가
6 B04의 노선 유입 면적 컬러 표시를 B05에도 백엔드가strength_profile(1m 구간별 유입 면적)을 B04·B05 같은 값으로 응답. 색띠·정규화·렌더러를 B04_wf1_Surface_UI_FlowRamp.ts로 공용화, B05에 토글 신설

신설/이동 파일

  • B04_wf1_Surface_UI_FlowRamp.ts — 색띠·로그 정규화·강도선 렌더러(B04·B05 공용)
  • ui_template_context_menu.ts — 지도 우클릭 메뉴 공용 부품(B04·B05 중복 제거)
  • B05_wf2_Route_UI_Drainage_Parts.ts — 레이어 상수·토글 팩토리·유역 목록 렌더·좌표 투영기
  • common_util_drainage_detail.build_strength_profile() 추가

700줄 규칙 유지: 부품 분리 전 B05 패널이 838줄까지 늘어 세 차례 분리(838 → 806 → 723 → 677).

G. 전체 유역 편집 기능 제거 (2026-08-01, 커밋 e994330)

사용자 결정: "전체 등고선을 분석하였으니 수정할 필요 없음. 편집기능 삭제."

배경: 외곽선을 손으로 옮겨도 안쪽 세부유역은 1m 셀 라벨로 만들어지므로 따라오지 않는다. 전체 외곽선과 세부유역 합이 어긋나 면적·관경의 근거가 깨지는 구조였다.

제거 대상 (557줄 삭제)

  • B05_wf2_Route_UI_Drainage_Boundary.ts(195줄) 파일 삭제
  • "유역선 편집" 버튼, 경로 확정 시 저장 여부 모달(saveBoundaryEditsIfWanted)
  • PUT /{project_id}/drainage/boundary 엔드포인트, saveDrainageBoundary() 클라이언트
  • boundary_overrides 로드·저장·재부착(apply_boundary_overrides, parse_overrides, resample_boundary, BoundaryOverride)
  • config DRAINAGE_BOUNDARY_OVERRIDE_FILENAME / _HANDLE_SPACING_M / _MATCH_RADIUS_M, locale 2종
  • 응답 필드 boundary_spacing_m / boundary_overrides / boundary_dropped

결과: B05_wf2_Route_Engine_Drainage_Store.py 245줄 → 55줄(B04 사본 동기화만 남김). 외곽선은 detail.basin_lonlat을 그대로 표시.

H. 실행 검증 결과 2차 (2026-08-01, 서버 기동 상태)

확인 항목 결과
B04GET /drainage/pipe-points 200 · 관 4개 · 유역 4개 · 강도 307점(최대 409,210㎡)
B05POST /drainage/basins 200 · 유역 4개 · 외곽선 122점 · 강도 307점 ·z_source=route_points
두 화면 강도 곡선 점 개수·값 동일(공용 엔진 산출)
boundary* 응답 필드 전부 제거 확인
PUT /drainage/boundary 404 (엔드포인트 제거됨)
품질 게이트 ruff check 통과 · tsc --noEmit 통과 · vite build 성공
700줄 규칙 배수유역 관련 파일 전부 통과(최대_UI_Drainage_Panel.ts 619줄)
커밋 내용
07c4a78 feat(B04): 상세 배수유역 계산 — 관 매설 지점 편집 + 세부유역 분할
83f23aa fix(B04): 우클릭 메뉴 동작 복구 + 배수유역 토글 정리, 세부유역 서클 번호
8c37f2f feat(B04/B05): 유역 선택 강조, B05 배관 상시 드래그·자동 재산정, 강도 색칠 공용화
e994330 refactor(B05): 유역 외곽선 편집 기능 제거

I. 남은 미결

  1. 관경 산정식(estimate_pipe_diameter_mm)은 여전히 stub — 100년 강우강도 수식이 오면 채운다. 지금은 화면에 "미정"으로 나온다.
  2. B05 화면은 아직 pipe_points.json을 읽지 않는다(B04에서 확정한 관이 B05에 자동 반영되지 않음). B05 배수유역 패널 연동은 후속 작업.
  3. 기존 프로젝트 저장소에 남은 boundary_overrides.json은 삭제하지 않았다 — 사용자 데이터라 임의로 지우지 않았고, 이제 아무도 읽지 않는 고아 파일이다. 정리 여부는 사용자 판단.
  4. ui_template_locale.ts가 1230줄로 700줄 규칙 위반(작업 시작 시점에 이미 1102줄). 이번 작업에서 locale 키를 추가해 더 늘었다 — 페이지별 분할 필요.
  5. 위키 반영(concepts/drainage_watershed.md, B04_*, B05_*)은 위키 관리자 몫 — 특히 B05_backend.md에 이미 삭제된 Engine_Drainage_Watershed/Trace/Assemble/Subdivide 항목과 Engine_Drainage_Basin(현재 58줄 어댑터) 설명이 낡았다. B05_wf2_Route_UI_Drainage_Panel(배관 편집 토글)·_Drainage_Pipes 명세도 실제와 다르다.

J. 이번 세션 커밋 목록