fix(B05 노선 추천 측점 맞춤): 합친 꼴 먼저 판에 측점 밖 생기면 옛 차례 판과 견줌 · 추천 창 설명 · ALGO_VERSION 7 (406-4)
- 측점 맞춤 — 같은 쪽 합친 꼴부터 놓다 뒤 곡선이 측점을 잃으면 옛 차례(그대로 → 합침) 판도 맞춰 측점 밖 적은 쪽 · 같으면 곡선 적은 쪽 - 검증_sub4 다섯 갈래 측점 밖 ≤ v5(weighted 5 → 1) - 추천 창 「측점 맞춤」 설명 — 6m 한도 문구를 지금 규칙(같은 쪽 합침 · 거리 한도 없음 · 복도 · 계류 · 기울기 · 토공)으로 - 시험 test_406_1 — 측점에 놓을 수 없는 쌍 안 합침 · 언덕 세 갈래 다른 선 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
This commit is contained in:
@@ -5,11 +5,13 @@
|
||||
· 같은 쪽으로 도는 이웃 곡선 둘 → 바깥 두 직선 교점 하나(곡선 하나) · S자는 안 합침.
|
||||
· 막힘 — 지반 기울기(골짜기) · 복도 밖(지형 없음) · 계류 버퍼 안 나란히 · 노선 전체 잣대.
|
||||
· 큰 R(`widen`) 직접 잼 = 평지면 이탈 한도(4 m) 판보다 큼.
|
||||
· 406-4 — 측점에 놓을 수 없는 쌍은 처음부터 안 합침 · 언덕에서 세 갈래가 다른 선.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from shapely.geometry import LineString, Point
|
||||
|
||||
from B05_Profile.B05_Profile_Engine_RouteInitial import generate_initial_route
|
||||
from B05_Profile.B05_Profile_Engine_RouteInitial_Merge import (
|
||||
GRADE_NOISE,
|
||||
Guard,
|
||||
@@ -122,3 +124,42 @@ def test_widen_guard_larger_than_gap_limit() -> None:
|
||||
gap = widen(fitted, path, RADIUS)
|
||||
direct = widen(fitted, path, RADIUS, guard=_guard(path))
|
||||
assert direct.curves[0].radius_m > gap.curves[0].radius_m + 20.0
|
||||
|
||||
|
||||
def test_406_4_unplaceable_pair_stays() -> None:
|
||||
"""합친 곡선 자리만 지형이 있음(그 둘레 3 m) — 가운데 꼴은 지나도 IP 를 밀어 측점에 놓은 꼴이
|
||||
복도 밖이면 처음부터 안 합침(합친 뒤 푸는 것 아님)."""
|
||||
merged = _merge(SAME, _guard(SAME))
|
||||
keep = [LineString(merged.vertices), LineString(_outline(SAME).vertices)]
|
||||
near = np.vectorize(lambda px, py: min(line.distance(Point(px, py)) for line in keep))
|
||||
guard = _guard(SAME, valid=lambda xx, yy: near(xx, yy) <= 3.0)
|
||||
cross = _line_intersection(*SAME)
|
||||
piece = guard.piece(SAME[0], cross, SAME[-1], merged.curves[0].radius_m)
|
||||
assert guard._look(piece)[3] # 가운데 꼴은 복도 안
|
||||
assert len(_merge(SAME, guard).curves) == 2
|
||||
|
||||
|
||||
def test_406_4_branches_differ_on_hill() -> None:
|
||||
"""제약을 지키는 길이 있는 언덕 — 영선 · 토공 최소 · 기울기 최소가 다른 선(후보 거름 뒤에도)."""
|
||||
x = np.arange(0.0, 802.0, 2.0)
|
||||
y = np.arange(0.0, 402.0, 2.0)
|
||||
xx, yy = np.meshgrid(x, y)
|
||||
hill = Terrain(
|
||||
x,
|
||||
y,
|
||||
40.0 * np.exp(-((xx - 400.0) ** 2 + (yy - 200.0) ** 2) / 90.0**2),
|
||||
np.ones(xx.shape, dtype=bool),
|
||||
)
|
||||
line = [(float(v), 200.0) for v in np.arange(50.0, 752.0, 4.0)]
|
||||
lines = {
|
||||
mode: LineString(
|
||||
generate_initial_route(
|
||||
line, hill, [], mode=mode, weights=None, max_grade=GRADE, min_radius_m=RADIUS
|
||||
)["planned"]
|
||||
)
|
||||
for mode in ("gradeline", "earthwork", "gentle")
|
||||
}
|
||||
names = list(lines)
|
||||
for i, a in enumerate(names):
|
||||
for b in names[i + 1 :]:
|
||||
assert lines[a].hausdorff_distance(lines[b]) > 10.0, (a, b)
|
||||
|
||||
Reference in New Issue
Block a user