feat(배수유역): 347-2 「지금 노선으로 셈」 서버 길 · 347-3 관 자리 후보 · [확정] 다시 셈

- POST drainage/live — 몸통 = 차례 번호 + 노선 초안(RouteDraft · 노선 [확인]과 같은 폴리라인 규칙) + 관 목록 · 서버 단독 · 작업본(00_watershed_response · 격자 배열 · 관 지점)에 안 씀 · 세부 유역까지 메모리 격자로 한 요청
- 프로젝트별 마지막 차례 · 1차 영역 뒤 · 확장 회차마다 · 세부 유역 앞에서 바뀌었으면 그만둠(superseded · AnalysisStopped)
- build_detail 에 메모리 routing · 상류선 · 관 자리 후보 suggest_pipe_positions(간격 보충 규칙 · 흐름 세기 + 오목 · 기존 관에서 먼 곳 · 정수 m) · 응답 pipe_candidates
- PUT pipe-points ?recompute=true([확정]) = 낡았으면 배수유역부터 다시 셈 · [저장]은 낡음 달고 관만
- 시험 test_347_2_drainage_live(늦은 차례 그만둠 둘 · 엔진 회차 그만둠 · 메모리 격자 · 후보 · 확정 다시 셈) · 검증_sub3 실측 저장 노선 16.9 s · 초안 노선 11.5 s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
This commit is contained in:
2026-10-16 11:38:17 +09:00
co-authored by Claude Opus 5.5
parent c0ad3edc80
commit d5d6415966
7 changed files with 399 additions and 5 deletions
@@ -23,6 +23,7 @@ from __future__ import annotations
import logging
import math
import time
from collections.abc import Callable
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
@@ -31,7 +32,10 @@ import numpy as np
from shapely.geometry import LineString
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Descent import ContourDescent
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Expand import expand_by_red_boundary
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Expand import (
AnalysisStopped,
expand_by_red_boundary,
)
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Flow import (
FlowClassification,
RoadRaster,
@@ -154,6 +158,7 @@ def preview_stages(
contour_features: list[dict[str, Any]],
stream_features: list[dict[str, Any]],
descent_store: tuple[Path, str] | None = None,
should_stop: Callable[[], bool] | None = None,
) -> StagePreview | None:
"""지금까지 구현·검증된 단계를 순서대로 돌려 결과를 모은다.
@@ -176,6 +181,8 @@ def preview_stages(
marks.append(("1차 영역(resolve_primary_region)", time.perf_counter()))
if region is None:
return None
if should_stop is not None and should_stop():
raise AnalysisStopped
started = time.perf_counter()
floor = route_elevation_floor([vertex.z for vertex in vertices])
@@ -187,6 +194,7 @@ def preview_stages(
region.split.upstream,
floor,
descent_store=descent_store,
should_stop=should_stop,
)
if expansion is None:
logger.warning("배수유역: 등고선 하강 방향을 세우지 못해 흐름 판정을 건너뜁니다.")