fix(배수 공용): 369 전체 자동 — 새 자리 0.5 m 안 지금 관 = 같은 관(그 자리 · 속성 · id 이어받음)

- 노선 따라감으로 0.14 m 어긋난 세월교가 새 관(관경 기본값)으로 바뀌던 흠 · 화면 SAME_PIPE_M 과 같은 값
- 검증_sub5 실측(지금 노선 메모리 격자) — 관 11 · 이어받음 5(세월교 352 m 포함) · 최대 간격 99 m

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
This commit is contained in:
2026-10-17 12:06:20 +09:00
co-authored by Claude Opus 5.5
parent bb6f73c0b7
commit d816c7c647
2 changed files with 21 additions and 3 deletions
+18 -1
View File
@@ -26,7 +26,7 @@ from __future__ import annotations
import json
import logging
from dataclasses import dataclass, field
from dataclasses import dataclass, field, replace
from pathlib import Path
from typing import Any
@@ -66,6 +66,10 @@ _SCORE_WEIGHT_STRENGTH = 0.7
_SCORE_WEIGHT_SAG = 0.3
# 성토부(내리막)는 물이 노선 밖으로 빠지므로 관 위치로 덜 선호한다.
_SCORE_FILL_PENALTY = 0.5
# [자동 제안] 전체 자동(369) — 새 자리에서 이만큼(m) 안의 지금 관 = 같은 관(그 자리 그대로 ·
# 속성 이어받음). 화면 `SAME_PIPE_M`(제안 · 같은 유역)과 같은 값 — 노선 따라감으로 cm 어긋난
# 세월교도 같은 관.
SAME_PIPE_M = 0.5
@dataclass
@@ -201,6 +205,19 @@ def build_detail(
# 자동 관 자리 = 정수 m · 일반 측점 1 m 안이면 그 측점(234-1) — 확정본(위)은 단추로만
placed = place_pipes(vertices, base, routing.strength_curve, fill=auto is not None)
pipes = snap_candidates(placed, vertices)
if confirmed_chainages:
kept = pipes_from_chainages(vertices, confirmed_chainages)
pipes = [
replace(
min(
(k for k in kept if abs(k.chainage_m - pipe.chainage_m) <= SAME_PIPE_M),
key=lambda k: abs(k.chainage_m - pipe.chainage_m),
default=pipe,
),
reason=pipe.reason,
)
for pipe in pipes
]
candidates = suggest_pipe_positions(vertices, pipes, routing.strength_curve)
detail = DrainageDetail(
+3 -2
View File
@@ -56,7 +56,7 @@ def test_all_은_세류선_더하기_100m_보충_지금_목록_무시(tmp_path):
reasons = [p.reason for p in detail.pipes]
places = [p.chainage_m for p in detail.pipes]
assert reasons.count("stream") == 1 and reasons.count("spacing") == 2
assert 150.0 in places and 10.0 not in places
assert 150.02 in places and 10.0 not in places # 세류선 150 m 0.5 m 안의 지금 관 = 그 자리
gaps = np.diff([0.0, *places, 300.0])
assert gaps.max() <= 100.0 and not detail.pipe_candidates
@@ -78,7 +78,7 @@ def _build(tmp_path, monkeypatch, points, auto):
def test_all_같은_자리_관은_속성_id_유지_새_관은_기본값(tmp_path, monkeypatch):
kept = PipePoint(
chainage_m=150.03,
chainage_m=150.3, # 세류선 150 m 에서 0.3 m — 노선 따라감으로 어긋난 같은 관
source="user",
facility="ford_bridge",
options={"ford_width_m": 4.0},
@@ -88,6 +88,7 @@ def test_all_같은_자리_관은_속성_id_유지_새_관은_기본값(tmp_path
_, carried = _build(tmp_path, monkeypatch, [gone, kept], "all")
ford = [p for p in carried if p.id == "keep"]
assert len(ford) == 1 and ford[0].facility == "ford_bridge" and ford[0].source == "user"
assert ford[0].chainage_m == 150.3 # 그 자리 그대로
assert all(p.id != "gone" for p in carried)
fresh = [p for p in carried if p.id != "keep"]
assert len(fresh) == 2 and all(p.source == "spacing" for p in fresh)