fix(B05 노선 추천 [적용] 종단): 직선 기울기 누를 때 표고 반올림 여유 0.1 mm · 상한과 같은 균형 종단은 상한으로 (419-3)
- 검증_sub4 [적용] 뒤 종단 최대 14.47 % → 14.001 %(정본 0.1 mm 반올림 몫) → 14.0 %(넘음 표시 없음) - test_74 변화점 계획고 비교를 0.5 mm 허용차로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
This commit is contained in:
@@ -63,6 +63,8 @@ LAMBDA_STEPS = 14
|
||||
EXACT_STEPS = 6 # 고른 계획선의 실제 누가토량으로 λ 를 더 좁히는 횟수
|
||||
PIPE_SNAP_M = 5.0 # 관 자리가 노선에서 이 안이면 그 노선의 관으로 봄
|
||||
GRADE_EPS = 1e-6
|
||||
# [적용] 종단 꼭짓점 표고 반올림(0.1 mm) 두 끝 몫 — 직선 기울기 누를 때 남기는 여유(m · 419-3)
|
||||
ROUND_SLACK_M = 1e-4
|
||||
|
||||
|
||||
def _sample(
|
||||
@@ -251,10 +253,11 @@ def _reference(ground: np.ndarray, spans: np.ndarray, max_grade: float) -> np.nd
|
||||
|
||||
def _hold(s: np.ndarray, z: np.ndarray, limit: float) -> np.ndarray:
|
||||
"""변화점 사이 직선 기울기를 `limit` 안으로 — 시종점은 그대로 두고 앞으로 · 뒤로 누름(시종점
|
||||
사이가 상한 안이면 몇 번 안에 둘 다 맞음)."""
|
||||
사이가 상한 안이면 몇 번 안에 둘 다 맞음). 마디마다 `ROUND_SLACK_M` 남김 — 종단 정본이 표고를
|
||||
0.1 mm 로 반올림해도 상한 안(검증_sub4 14.001 %)."""
|
||||
z = z.copy()
|
||||
start, end = z[0], z[-1]
|
||||
rise = limit * np.diff(s)
|
||||
rise = np.maximum(limit * np.diff(s) - ROUND_SLACK_M, 0.0)
|
||||
for _ in range(4):
|
||||
z[0] = start
|
||||
for i in range(1, len(z)):
|
||||
@@ -278,7 +281,10 @@ def held_pass_through(
|
||||
from B05_Profile.B05_Profile_Engine_Grade_Alignment import build_curves, evaluate
|
||||
|
||||
stations_a, plan_a = np.asarray(stations, float), np.asarray(plan, float)
|
||||
limit = float(np.abs(np.diff(plan_a) / np.diff(stations_a)).max()) + GRADE_EPS
|
||||
limit = float(np.abs(np.diff(plan_a) / np.diff(stations_a)).max())
|
||||
# 계획고 1 mm 반올림(`plan_m`)으로 상한을 살짝 넘은 몫은 상한으로
|
||||
legal = policy.max_grade_pct / 100.0
|
||||
limit = legal if legal <= limit <= legal + 1e-4 else limit + GRADE_EPS
|
||||
target = np.interp(base_s, stations_a, plan_a)
|
||||
base_z = _hold(base_s, target, limit)
|
||||
for _ in range(12):
|
||||
|
||||
@@ -274,4 +274,5 @@ def test_419_3_applied_profile_holds_grade() -> None:
|
||||
assert steepest(pass_through(s, plan, policy)) > 0.15 # 옛 맞춤 = 상한 넘음(재현)
|
||||
held = held_pass_through(s, list(s), list(plan), policy)
|
||||
assert steepest(held) <= 0.14 + 1e-5
|
||||
assert steepest(np.round(held, 4)) <= 0.14 # 정본 0.1 mm 반올림 뒤도 상한 안
|
||||
assert held[0] == pytest.approx(plan[0]) and held[-1] == pytest.approx(plan[-1])
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from B05_Profile.B05_Profile_Router_Replan import RouteReplanRequest
|
||||
from B05_Profile.B05_Profile_Router_RouteInitial import _set_base_pvi
|
||||
from B06_Section.B06_Section_Router_Design import CARRY_INPUT_KEYS
|
||||
@@ -47,7 +49,8 @@ def test_변화점_계획고를_균형_종단으로(tmp_path: Path) -> None:
|
||||
p["elevation_m"]
|
||||
for p in json.loads(path.read_text("utf-8"))["profile_alignment"]["base_pvi"]
|
||||
]
|
||||
assert got == [10.0, 12.0, 13.0, 14.0] # 구조물 측점(30 m)은 직선 보간
|
||||
# 구조물 측점(30 m)은 직선 보간 · 상한 누를 때 반올림 여유 0.1 mm 몫(419-3)
|
||||
assert got == pytest.approx([10.0, 12.0, 13.0, 14.0], abs=5e-4)
|
||||
|
||||
|
||||
def test_확인_요청_기본은_끔() -> None:
|
||||
|
||||
Reference in New Issue
Block a user