fix(530-2): D 분석 지점 0.1 mm 반올림 — 노선 끝점 = 지점 · 연도 경계 정확히 맞물림 · 복도 300 m 실측 근거 주석

- 엔진 출력 자리수(4)로 지점을 맞춰 넣음 · 저장본 지점 대조 1 mm
- 실측(검증_sub3 근처 두 구간): 복도 100 · 200 · 300 m 못 지킨 곳 5 · 8 · 1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 19:47:30 +09:00
co-authored by Claude Opus 5.5
parent e250e0fde0
commit 83d38681df
3 changed files with 13 additions and 8 deletions
+7 -2
View File
@@ -60,8 +60,13 @@ def plan_criteria(road_type: str | None, design_speed_kph: int | None) -> dict[s
}
def _point(value: Any) -> tuple[float, float]:
"""엔진 출력 자리수(0.1 mm)로 — 노선 끝점 = 지점 그대로 · 연도 경계가 정확히 맞물림."""
return (round(float(value[0]), 4), round(float(value[1]), 4))
def _same_point(a: Any, b: Any) -> bool:
return abs(float(a[0]) - float(b[0])) < 1e-6 and abs(float(a[1]) - float(b[1])) < 1e-6
return abs(float(a[0]) - float(b[0])) < 1e-3 and abs(float(a[1]) - float(b[1])) < 1e-3
def read_segment(project_root: Path, seg: dict[str, Any]) -> dict[str, Any] | None:
@@ -91,7 +96,7 @@ def analyze_segment(
corridor_m: float = PLAN_CORRIDOR_M,
) -> dict[str, Any]:
"""연도 구간 하나 · 갈래 넷 — 입력 지문이 저장본과 같으면 그대로(`stored` True)."""
expected = [tuple(map(float, seg["start"])), tuple(map(float, seg["end"]))]
expected = [_point(seg["start"]), _point(seg["end"])]
inputs = {
"weights": None,
"max_grade": criteria["max_grade"],
+1 -1
View File
@@ -41,7 +41,7 @@ logger = logging.getLogger(__name__)
# 구간 표본 간격 — 도엽(≈2.8 × 2.3 km) 3×3 묶음이 끊기지 않게
SAMPLE_STEP_M = 1000.0
# 탐색 복도 반폭(D 만 · B 기본 100 m) — 실측(530-2): 노선이 복도 끝에 닿지 않는 폭
# 탐색 복도 반폭(D 만 · B 기본 100 m) — 실측(530-2): 100 · 200 m 는 못 지킨 곳 남음 · 300 m 0~1
PLAN_CORRIDOR_M = 300.0
# DEM 이 복도 밖으로 더 덮는 폭(복도 끝 칸 기울기 · 횡단 표본 ±20 m)
DEM_EXTRA_M = 50.0
+5 -5
View File
@@ -12,8 +12,8 @@ from D03_PlanAnalysis import D03_PlanAnalysis_Analyze as analyze
CRITERIA = {"max_grade": 0.14, "min_radius_m": 12.0, "design_speed": 20}
SEGMENTS = [
{"year": 2026, "start": (60.0, 200.0), "end": (560.0, 230.0)},
{"year": 2027, "start": (560.0, 230.0), "end": (1040.0, 160.0)},
{"year": 2026, "start": (60.0, 200.0), "end": (560.123456789, 230.987654321)},
{"year": 2027, "start": (560.123456789, 230.987654321), "end": (1040.0, 160.0)},
]
@@ -54,8 +54,8 @@ def test_boundary_chainage_and_line(run) -> None:
for route in result["routes"].values():
assert "error" not in route
# 시종점 그대로 — 연도 경계가 정확히 맞물림
assert route["planned"][0] == list(seg["start"])
assert route["planned"][-1] == list(seg["end"])
assert route["planned"][0] == result["start"] == pytest.approx(seg["start"], abs=1e-4)
assert route["planned"][-1] == result["end"] == pytest.approx(seg["end"], abs=1e-4)
assert results[0]["routes"]["gradeline"]["planned"][-1] == results[1]["start"]
rows = analyze.chain(results, {2026: "earthwork", 2027: None}, 1234.5)
@@ -70,7 +70,7 @@ def test_boundary_chainage_and_line(run) -> None:
first = results[0]["routes"]["earthwork"]["planned"]
second = results[1]["routes"]["gradeline"]["planned"]
assert len(line) == len(first) + len(second) - 1 # 경계점 한 번만(꺾인 채)
assert line[len(first) - 1] == list(SEGMENTS[0]["end"])
assert line[len(first) - 1] == results[0]["end"] == results[1]["start"]
def test_same_input_reads_store(run, monkeypatch) -> None: