From d816c7c647d331838efd8188496df33631514511 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 17 Oct 2026 12:06:20 +0900 Subject: [PATCH] =?UTF-8?q?fix(=EB=B0=B0=EC=88=98=20=EA=B3=B5=EC=9A=A9):?= =?UTF-8?q?=20369=20=EC=A0=84=EC=B2=B4=20=EC=9E=90=EB=8F=99=20=E2=80=94=20?= =?UTF-8?q?=EC=83=88=20=EC=9E=90=EB=A6=AC=200.5=20m=20=EC=95=88=20?= =?UTF-8?q?=EC=A7=80=EA=B8=88=20=EA=B4=80=20=3D=20=EA=B0=99=EC=9D=80=20?= =?UTF-8?q?=EA=B4=80(=EA=B7=B8=20=EC=9E=90=EB=A6=AC=20=C2=B7=20=EC=86=8D?= =?UTF-8?q?=EC=84=B1=20=C2=B7=20id=20=EC=9D=B4=EC=96=B4=EB=B0=9B=EC=9D=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 노선 따라감으로 0.14 m 어긋난 세월교가 새 관(관경 기본값)으로 바뀌던 흠 · 화면 SAME_PIPE_M 과 같은 값 - 검증_sub5 실측(지금 노선 메모리 격자) — 관 11 · 이어받음 5(세월교 352 m 포함) · 최대 간격 99 m Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn --- common_util/common_util_drainage_detail.py | 19 ++++++++++++++++++- resources/tester/test_369_drainage_auto.py | 5 +++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/common_util/common_util_drainage_detail.py b/common_util/common_util_drainage_detail.py index 0f3961ea0..ac93ca754 100644 --- a/common_util/common_util_drainage_detail.py +++ b/common_util/common_util_drainage_detail.py @@ -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( diff --git a/resources/tester/test_369_drainage_auto.py b/resources/tester/test_369_drainage_auto.py index 2022901a8..e342a71ea 100644 --- a/resources/tester/test_369_drainage_auto.py +++ b/resources/tester/test_369_drainage_auto.py @@ -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)