feat(346-3): 노선 저장 서버 길 — 배수유역 뗌 · 관 지킴 · 측점 열쇠 이월 · 초기값은 추천 [적용] 때만
- POST /route/replan = 노선 저장 체인(B05_Profile_Route_Save) — 풀기 → 구조물 · 관 좌표 따라감 → 새 세류선 교차점 기본 관 · 옛 노선 밖 오목 지점 보충 → 종횡단 한 번 → 계획고 옮김(바뀐 구간만 새 지반) → 횡단 이월(측점 열쇠 grid · pipe · structure · end · CARRY 일곱 + 구조물 조정) → B06 확정 · 3D - 관 정본 안 지움 · 배수유역 체인에서 뗌(관 정본 새 노선 지문 → B04 분석 낡음) - 요청에 노선 초안(RouteDraft 모양 draft) · as_initial · 응답에 관 · 구조물 · 버린 횡단 수 · 초기값 여부 · 시간 - 초기값 = 자동설계 + 추천 [적용](as_initial)만 · 손 편집 저장은 안 바꿈 - 실패 = 노선 · 관 · 구조물 · 종횡단 파일 · 새 노선 행 · stage 2 params 되살림 - 시험 test_346_3_route_save · test_133_2 새 체인으로 · 시간 재기 도구 run_346_3_route_save_timing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
@@ -392,6 +392,53 @@ async def _ensure_initial_polyline(
|
||||
logger.exception("초기 계획노선 폴리라인 생성 실패(계속 진행): %s", project_id)
|
||||
|
||||
|
||||
def redesign_solve_request(
|
||||
params: dict[str, Any], selection: dict[str, Any], surface_model_id: int
|
||||
) -> Any:
|
||||
"""stage 2 params(사용자 저장분) + 새 확정 지표면 → as_planned 풀기 요청(노선 저장도 씀)."""
|
||||
from B05_Profile.B05_Profile_Schema import RouteSolveRequest
|
||||
|
||||
points = params.get("points") or {}
|
||||
options = params.get("options") or {}
|
||||
return RouteSolveRequest(
|
||||
filter_key=str(selection.get("source_filter") or params.get("filter_key")),
|
||||
method=str(selection.get("method") or params.get("method") or "dtm"),
|
||||
smooth=bool(selection.get("smooth", params.get("smooth", False))),
|
||||
surface_model_id=surface_model_id,
|
||||
# 사용자가 고친 계획노선을 **그대로** 쓴다 — 다시 풀면 탐색 제약(종단경사·
|
||||
# 최소곡선반지름·회피지역)에 걸려 체인이 통째로 멈춘다(2026-09-06 실측:
|
||||
# 「세그먼트 1 (BP → CP1) 경로 탐색 실패」로 종횡단만 옛 노선에 남았음).
|
||||
# PLAN 0-3 에서 자동탐색은 접기로 했고 노선은 사용자가 직접 고친다.
|
||||
algorithm="as_planned",
|
||||
bp=points["bp"],
|
||||
ep=points["ep"],
|
||||
cp=points.get("cp") or [],
|
||||
ap=points.get("ap") or [],
|
||||
fp=points.get("fp") or [],
|
||||
station_interval_m=params.get("station_interval_m"),
|
||||
cross_half_width_m=params.get("cross_half_width_m"),
|
||||
cross_sample_interval_m=params.get("cross_sample_interval_m"),
|
||||
long_sample_interval_m=params.get("long_sample_interval_m"),
|
||||
**{key: options.get(key) for key in ("grade_class",) if options.get(key)},
|
||||
paved=bool(options.get("paved", False)),
|
||||
terrain_type=str(options.get("terrain_type") or "special"),
|
||||
main_direction=str(options.get("main_direction") or "auto"),
|
||||
min_curve_radius_m=options.get("min_curve_radius_m"),
|
||||
max_uphill_grade=options.get("max_uphill_grade"),
|
||||
max_downhill_grade=options.get("max_downhill_grade"),
|
||||
min_uphill_grade=options.get("min_uphill_grade"),
|
||||
min_downhill_grade=options.get("min_downhill_grade"),
|
||||
weights=options.get("weights"),
|
||||
allow_avoid_pass_through=bool(options.get("allow_avoid_pass_through", False)),
|
||||
max_grade_pct=params.get("max_grade_pct"),
|
||||
min_vertical_radius_m=params.get("min_vertical_radius_m"),
|
||||
min_tangent_length_m=params.get("min_tangent_length_m"),
|
||||
balance_segment_length_m=params.get("balance_segment_length_m"),
|
||||
start_elevation_offset_m=params.get("start_elevation_offset_m"),
|
||||
end_elevation_offset_m=params.get("end_elevation_offset_m"),
|
||||
)
|
||||
|
||||
|
||||
async def run_redesign_chain(
|
||||
project_id: UUID,
|
||||
surface_model_id: int,
|
||||
@@ -421,7 +468,6 @@ async def run_redesign_chain(
|
||||
confirm_latest_route,
|
||||
solve_route_record,
|
||||
)
|
||||
from B05_Profile.B05_Profile_Schema import RouteSolveRequest
|
||||
from B06_Section.B06_Section_Repository import (
|
||||
get_cross_section_designs,
|
||||
get_latest_section_options,
|
||||
@@ -478,7 +524,6 @@ async def run_redesign_chain(
|
||||
)
|
||||
params = (stage2 or {}).get("params") or {}
|
||||
points = params.get("points") or {}
|
||||
options = params.get("options") or {}
|
||||
if not points.get("bp") or not points.get("ep"):
|
||||
logger.warning(
|
||||
"재확정 체인 중단(stage 2 params에 제어점 없음): project_id=%s", project_id
|
||||
@@ -488,43 +533,7 @@ async def run_redesign_chain(
|
||||
marks.append(("준비·사용자입력 회수", time.perf_counter()))
|
||||
|
||||
# 2) B05 재계산 — 지표면 관련 값만 새 확정 선택으로 교체, 나머지는 사용자 저장분.
|
||||
request = RouteSolveRequest(
|
||||
filter_key=str(selection.get("source_filter") or params.get("filter_key")),
|
||||
method=str(selection.get("method") or params.get("method") or "dtm"),
|
||||
smooth=bool(selection.get("smooth", params.get("smooth", False))),
|
||||
surface_model_id=surface_model_id,
|
||||
# 사용자가 고친 계획노선을 **그대로** 쓴다 — 다시 풀면 탐색 제약(종단경사·
|
||||
# 최소곡선반지름·회피지역)에 걸려 체인이 통째로 멈춘다(2026-09-06 실측:
|
||||
# 「세그먼트 1 (BP → CP1) 경로 탐색 실패」로 종횡단만 옛 노선에 남았음).
|
||||
# PLAN 0-3 에서 자동탐색은 접기로 했고 노선은 사용자가 직접 고친다.
|
||||
algorithm="as_planned",
|
||||
bp=points["bp"],
|
||||
ep=points["ep"],
|
||||
cp=points.get("cp") or [],
|
||||
ap=points.get("ap") or [],
|
||||
fp=points.get("fp") or [],
|
||||
station_interval_m=params.get("station_interval_m"),
|
||||
cross_half_width_m=params.get("cross_half_width_m"),
|
||||
cross_sample_interval_m=params.get("cross_sample_interval_m"),
|
||||
long_sample_interval_m=params.get("long_sample_interval_m"),
|
||||
**{key: options.get(key) for key in ("grade_class",) if options.get(key)},
|
||||
paved=bool(options.get("paved", False)),
|
||||
terrain_type=str(options.get("terrain_type") or "special"),
|
||||
main_direction=str(options.get("main_direction") or "auto"),
|
||||
min_curve_radius_m=options.get("min_curve_radius_m"),
|
||||
max_uphill_grade=options.get("max_uphill_grade"),
|
||||
max_downhill_grade=options.get("max_downhill_grade"),
|
||||
min_uphill_grade=options.get("min_uphill_grade"),
|
||||
min_downhill_grade=options.get("min_downhill_grade"),
|
||||
weights=options.get("weights"),
|
||||
allow_avoid_pass_through=bool(options.get("allow_avoid_pass_through", False)),
|
||||
max_grade_pct=params.get("max_grade_pct"),
|
||||
min_vertical_radius_m=params.get("min_vertical_radius_m"),
|
||||
min_tangent_length_m=params.get("min_tangent_length_m"),
|
||||
balance_segment_length_m=params.get("balance_segment_length_m"),
|
||||
start_elevation_offset_m=params.get("start_elevation_offset_m"),
|
||||
end_elevation_offset_m=params.get("end_elevation_offset_m"),
|
||||
)
|
||||
request = redesign_solve_request(params, selection, surface_model_id)
|
||||
# 종횡단은 관을 정한 뒤 한 번만 만든다(342-2) — 여기서 만들면 아래 4c 가 통째로 덮는 헛일.
|
||||
solve_result: Any = await solve_route_record(project_id, request, generate_sections=False)
|
||||
if isinstance(solve_result, JSONResponse):
|
||||
|
||||
Reference in New Issue
Block a user