feat(B05 노선 추천 엔진): 합치기 판정 = 바뀐 측점 횡단 차이 · 후보 줄 세움 = 노선 횡단 토공 · 균형 종단 위 5 개 (419-1)
- 420 cross_earthwork · cross_earthwork_delta 이음 — 합치기 멈춤 = 계획고 지반고 노선 횡단 +10 % - 토공 · 공사비 줄 세움 = 상한 누른 계획선 횡단(종단 켬) · 지반고 횡단(종단 끔) - 위 후보 수 3 → 5(검증_sub4 균형 종단 토공 최소 = 줄 세움 5 위) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
This commit is contained in:
@@ -24,6 +24,7 @@ from __future__ import annotations
|
||||
import copy
|
||||
import math
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
@@ -233,8 +234,13 @@ def _earth(metrics: dict[str, Any]) -> float:
|
||||
return metrics["cut_m3"] + metrics["fill_m3"]
|
||||
|
||||
|
||||
# (합치기 전 선, 합친 선, 바뀐 자리 누가거리(앞 선 기준 s0, s1)) → 노선 토공 차(㎥ · 횡단)
|
||||
EarthDelta = Callable[[PlannedPolyline, PlannedPolyline, tuple[float, float]], float]
|
||||
@dataclass
|
||||
class RouteEarth:
|
||||
"""합치기 멈춤 잣대 — 노선 토공(횡단 ㎥ · `..._CrossEarth`)과 바뀐 측점 횡단 차이."""
|
||||
|
||||
total: Callable[[PlannedPolyline], float]
|
||||
# (합치기 전 선, 합친 선, 바뀐 자리 누가거리(앞 선 기준 s0, s1)) → 노선 토공 차(㎥)
|
||||
delta: Callable[[PlannedPolyline, PlannedPolyline, tuple[float, float]], float]
|
||||
|
||||
|
||||
def merge_same_side(
|
||||
@@ -242,21 +248,23 @@ def merge_same_side(
|
||||
guard: Guard,
|
||||
min_radius_m: float,
|
||||
measure: Callable[[PlannedPolyline], dict[str, Any]],
|
||||
cross_earthwork_delta: EarthDelta | None = None,
|
||||
route_earth: RouteEarth | None = None,
|
||||
) -> Route:
|
||||
"""같은 쪽 이웃 꺾임 합치기를 되풀이한 선과 잰 값 · 합칠 것 없으면 받은 그대로.
|
||||
|
||||
멈춤 = 못 지킨 곳 수(R · 계류 · 원지반 기울기 뺌) 늘어남 · 노선 토공이 합치기 전 선의
|
||||
1 + `TOTAL_EARTH_TOL` 넘음. `cross_earthwork_delta` 주면 토공 = 바뀐 측점 횡단 차이 누적 ·
|
||||
없으면 노선 잣대 토공(`measure` 절 + 성)."""
|
||||
1 + `TOTAL_EARTH_TOL` 넘음. `route_earth` 주면 토공 = 횡단(합치기 전 선 전체 + 바뀐 측점 차이
|
||||
누적) · 없으면 노선 잣대 토공(`measure` 절 + 성 · 띠 가늠)."""
|
||||
outline, base = route
|
||||
if len(outline.curves) < 2:
|
||||
return route
|
||||
points, flags, radii = _flat(outline)
|
||||
points = [(round(x, 4), round(y, 4)) for x, y in points]
|
||||
current = route
|
||||
limit = _earth(base) * (1 + TOTAL_EARTH_TOL)
|
||||
earth = _earth(base) # 지금 선 토공 — 차이를 누적
|
||||
earth = (
|
||||
_earth(base) if route_earth is None else route_earth.total(outline)
|
||||
) # 지금 선 토공 — 차이를 누적
|
||||
limit = earth * (1 + TOTAL_EARTH_TOL)
|
||||
blocked: set[tuple[Xy, ...]] = set()
|
||||
while True:
|
||||
reference = _Reference(current[0].vertices)
|
||||
@@ -291,11 +299,11 @@ def merge_same_side(
|
||||
radii=trial_radii,
|
||||
)
|
||||
metrics = measure(line)
|
||||
if cross_earthwork_delta is None:
|
||||
if route_earth is None:
|
||||
total = _earth(metrics)
|
||||
else:
|
||||
window = sorted(reference.line.project(Point(xy)) for xy in (local[0], local[-1]))
|
||||
total = earth + cross_earthwork_delta(current[0], line, (window[0], window[1]))
|
||||
total = earth + route_earth.delta(current[0], line, (window[0], window[1]))
|
||||
if metrics["over_limit"]["total"] > base["over_limit"]["total"] or total > limit:
|
||||
blocked.add(tuple(points[k - 1 : k + 3]))
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user