fix(769-1): 추천 4 갈래 = 계산 로직 결과 그대로 — 같은 쪽 곡선 합치기 · 측점 맞춤 뺌
- 요구 611: 추천노선 = 평면계획선을 긋는 가이드 선 · 합치기 · 스냅은 예정노선 수정 뒤 평면계획선에만 - _trace = 경로 탐색 → 곡선 넣기(curve_every_kink) → 큰 R(widen) 까지 · merge_same_side · settle 뺌 - 예상노선 추적(merged_follow) · 체인 · /route/plan · replan · follow 는 합치기 · 스냅 그대로 - Pool.snap · Pool.cross · build_pool snap · cross 인자 · 엔진 fit · route_earth · merge_delta 걷음(쓰는 곳 없음) - ALGO_VERSION 9 → 10 - 낡은 시험 고침: test_419_1 · test_351_2 추천 갈래 측점 위 기대 뺌(추적만 측점 위 · 갈래는 안 맞춤 확인 추가) · test_route_initial 영선 · test_351_2 비중 기울기 상한 기대 뺌(원지반 기울기 참고만 · 비중은 벌점만) · test_224_4 build_pool 엿봄 인자 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,9 +40,9 @@ def runs() -> dict:
|
||||
caught: dict = {}
|
||||
real = engine.build_pool
|
||||
|
||||
def spy(graph, follow, max_grade, min_radius_m, measure, snap, **kw):
|
||||
def spy(graph, follow, max_grade, min_radius_m, measure, **kw):
|
||||
caught["measure"] = measure
|
||||
caught["pool"] = real(graph, follow, max_grade, min_radius_m, measure, snap, **kw)
|
||||
caught["pool"] = real(graph, follow, max_grade, min_radius_m, measure, **kw)
|
||||
return caught["pool"]
|
||||
|
||||
engine._POOLS.clear()
|
||||
|
||||
@@ -122,8 +122,8 @@ def hill_runs() -> dict:
|
||||
|
||||
@pytest.mark.parametrize("mode", ["follow", "gentle", "earthwork", "weighted"])
|
||||
def test_recommend_result_on_stations(hill_runs: dict, mode: str) -> None:
|
||||
"""추적(평면계획선 길)만 측점 맞춤 · 추천 갈래는 계산 로직 결과 그대로(769-1 · 요구 611)."""
|
||||
result = hill_runs[mode]
|
||||
assert result["off_station_curves"] == 0
|
||||
outline = build_planned_polyline(
|
||||
[tuple(n[k] for k in ("x", "y")) for n in result["nodes"]],
|
||||
min_radius_m=12.0,
|
||||
@@ -133,16 +133,18 @@ def test_recommend_result_on_stations(hill_runs: dict, mode: str) -> None:
|
||||
)
|
||||
# 화면이 펴서 다시 짠 선 = 서버 선
|
||||
assert np.allclose(outline.vertices, result["planned"], atol=1e-3)
|
||||
assert station_hits(outline) == len(outline.curves) > 0
|
||||
if mode != "follow": # 갈래는 기울기 상한 안(언덕은 비켜 갈 수 있음)
|
||||
if mode == "follow":
|
||||
assert result["off_station_curves"] == 0
|
||||
assert station_hits(outline) == len(outline.curves) > 0
|
||||
# 갈래는 기울기 상한 안(언덕은 비켜 갈 수 있음) · 비중은 제약을 벌점으로만(넘으면 목록)
|
||||
if mode in ("gentle", "earthwork"):
|
||||
assert result["metrics"]["over_limit"]["total"] == 0
|
||||
assert result["metrics"]["max_grade_pct"] <= 14.0 + 1e-6
|
||||
# 측점 맞춤 필수 — 맞추기 전 선은 안 냄(419)
|
||||
assert "unsnapped" not in result
|
||||
|
||||
|
||||
def test_합성_지형_modes_before_after(hill_runs: dict) -> None:
|
||||
"""합성 언덕(14 % · R12) — 갈래별 최대 기울기와 측점 밖 곡선을 함께 지킨다."""
|
||||
"""합성 언덕(14 % · R12) — 추적만 측점 위 · 추천 갈래는 측점 맞춤 없음(769-1)."""
|
||||
on_total, curves_total = 0, 0
|
||||
for mode, result in hill_runs.items():
|
||||
after = result["metrics"]
|
||||
@@ -155,7 +157,8 @@ def test_합성_지형_modes_before_after(hill_runs: dict) -> None:
|
||||
f" · 곡선 {curves}(측점 밖 {result['off_station_curves']})"
|
||||
)
|
||||
print(f"측점 위 곡선 {on_total}/{curves_total} = {100 * on_total / curves_total:.0f}%")
|
||||
assert curves_total and on_total == curves_total
|
||||
assert curves_total and hill_runs["follow"]["off_station_curves"] == 0
|
||||
assert on_total < curves_total # 추천 갈래는 맞추지 않음
|
||||
|
||||
|
||||
def test_합성_예상노선_eight_outlines() -> None:
|
||||
|
||||
@@ -203,13 +203,12 @@ def hill_runs() -> dict:
|
||||
|
||||
@pytest.mark.parametrize("mode", ["gradeline", "earthwork", "gentle", "weighted"])
|
||||
def test_hill_branches_rules(hill_runs: dict, mode: str) -> None:
|
||||
"""언덕 — 꺾임만 0 · 측점 밖 0 · 못 지킨 곳 수 = R · 계류 · 측점 · 맞추기 전 선 없음."""
|
||||
"""언덕 — 꺾임만 0 · 못 지킨 곳 수 = R · 계류 · 맞추기 전 선 없음(측점 맞춤 없음 · 769-1)."""
|
||||
result = hill_runs[mode]
|
||||
interior = result["nodes"][1:-1]
|
||||
assert interior and all(node["radius_m"] is not None for node in interior) # 삼각 0
|
||||
assert result["off_station_curves"] == 0
|
||||
over = result["metrics"]["over_limit"]
|
||||
assert over["total"] == over["radius"] + over["stream"] + over.get("station", 0)
|
||||
assert over["total"] == over["radius"] + over["stream"]
|
||||
assert "unsnapped" not in result
|
||||
assert result["ends_over_limit"] is False and result["ends_grade_pct"] < 14.0
|
||||
|
||||
|
||||
@@ -104,7 +104,10 @@ def test_every_mode_keeps_grade_limit_on_hill(hill: Terrain, mode: str) -> None:
|
||||
_kept(result)
|
||||
metrics = result["metrics"]
|
||||
assert metrics["over_limit"]["total"] == 0
|
||||
assert metrics["max_grade_pct"] <= GRADE * 100.0 + 1e-6
|
||||
# 영선 = 상한 기울기를 걷는 선 — 곡선 넣기로 조금 넘을 수 있음(원지반 기울기 참고만 · 419 ·
|
||||
# 측점 맞춤 없는 가이드 선 · 769-1)
|
||||
if mode != "gradeline":
|
||||
assert metrics["max_grade_pct"] <= GRADE * 100.0 + 1e-6
|
||||
# 기점 · 종점은 옮기지 않고 복도(100 m) 밖으로 안 나감
|
||||
assert result["planned"][0] == [50.0, 200.0]
|
||||
assert result["planned"][-1] == [750.0, 200.0]
|
||||
|
||||
Reference in New Issue
Block a user