"""B06 재생성 옵션 — 저장 옵션 · stage 2 파라미터 → 종단 계획선 기준 · 측점 생성 옵션. `B06_Section_Router.py` 에서 700줄 제한으로 분리(139-6). 라우터가 그대로 다시 씀. """ from __future__ import annotations from typing import Any from B05_Profile.B05_Profile_Engine_Grade import GradeDesignOptions, resolve_grade_options from B05_Profile.B05_Profile_Engine_Sections_Core import SectionGenerationOptions def _regeneration_grade_options(stage_params: dict[str, Any] | None) -> GradeDesignOptions | None: """재생성 시 종단 계획선 기준을 확정 당시 저장 파라미터(stage 2)로 재구성한다. grade_options 없이 재생성하면 종단 계획선(profile_alignment)이 통째로 소실돼 계획 횡단도선·유토곡선·테이블이 사라진다(2026-08-06 사용자 보고 — 옛 재계산 버튼 사고의 원인). B04 파일입력→B06 자동 계산 파이프라인이 쓰는 같은 엔진 경로를 재활용한다. """ if not stage_params: return None options = stage_params.get("options") or {} grade_class = options.get("grade_class") if not grade_class: return None stored = { key: stage_params.get(key) for key in ( "max_grade_pct", "min_vertical_radius_m", "min_tangent_length_m", "balance_segment_length_m", "start_elevation_offset_m", "end_elevation_offset_m", # 횡단배수 최소고 강제 스위치도 확정 당시 값을 따라야 한다 — 빠뜨리면 재생성이 # 기본(해제)으로 돌아가 켜 둔 계획선이 내려앉는다(2026-09-01). "enforce_pipe_clearance", ) if stage_params.get(key) is not None } # 설계속도는 B05가 저장해 둔 값을 그대로 따른다 — 없으면 종류별 기본(20). speed = options.get("design_speed_kph") return resolve_grade_options( str(grade_class), terrain_type=str(options.get("terrain_type") or "normal"), paved=bool(options.get("paved", False)), design_speed_kph=int(speed) if speed is not None else None, stored=stored, ) def _regeneration_options( stored_options: dict[str, Any] | None, stage_params: dict[str, Any] | None, cross_half_width_m: float, ) -> SectionGenerationOptions: """DB 저장 옵션(단일 소스) → stage 2 params → config 순으로 유지하고 반폭만 교체한다.""" defaults = SectionGenerationOptions() stored = stored_options or {} params = stage_params or {} def pick(key: str, default: float) -> float: return stored.get(key) or params.get(key) or default return SectionGenerationOptions( station_interval_m=pick("station_interval_m", defaults.station_interval_m), cross_half_width_m=cross_half_width_m, cross_sample_interval_m=pick("cross_sample_interval_m", defaults.cross_sample_interval_m), long_sample_interval_m=pick("long_sample_interval_m", defaults.long_sample_interval_m), include_endpoint=defaults.include_endpoint, )