Merge remote-tracking branch 'origin/sub_laptop_6' into main_laptop_1

This commit is contained in:
2026-10-18 09:35:01 +09:00
9 changed files with 424 additions and 47 deletions
+10 -2
View File
@@ -553,14 +553,18 @@ def sample_structure_sections(
extra_stations: tuple[tuple[float, str], ...],
options: SectionGenerationOptions | None = None,
crs: str | None = None,
with_curves: bool = False,
) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
"""구조물 측점만 샘플링해 (측점 dict, 횡단 dict) 목록을 돌려준다 — 파일은 안 씀.
`with_curves` — 곡선 측점(`curve` · 252-2)도 같이(정본 쓰기 · 구조물이 MC 를 비우면
되살림 · 407-3).
격자 측점과 똑같은 접선·오프셋 샘플링을 거치되(`generate_sections` 재사용) 구조물 측점
(`irregular` · 격자 · 시종점에 얹힌 것 `grid` 포함)만 골라낸다. [저장] 때 정본 쓰기
(`generate_irregular_sections`)와 B06 미리 뜨기(`preview_structure_sections`)가 같은 길(273-2).
"""
if not extra_stations:
if not extra_stations and not with_curves:
return [], []
base = options or SectionGenerationOptions()
merged_options = SectionGenerationOptions(
@@ -587,6 +591,8 @@ def sample_structure_sections(
)
def structural(entry: dict[str, Any]) -> bool:
if with_curves and entry.get("kind") == "curve":
return True
return entry.get("kind") == "irregular" or bool(entry.get("structure"))
return (
@@ -606,7 +612,8 @@ def generate_irregular_sections(
options: SectionGenerationOptions | None = None,
crs: str | None = None,
) -> list[dict[str, Any]]:
"""구조물 측점만 샘플링해 **횡단 파일을 쓰고** 측점 dict 목록을 돌려준다(빈 목록 = 없음).
"""구조물 측점(곡선 측점 포함 · 407-3)만 샘플링해 **횡단 파일을 쓰고** 측점 dict 목록을
돌려준다(빈 목록 = 없음).
기존 종단 계획선·규칙 측점·횡단은 건드리지 않는다 — 받는 쪽이 목록 전체로 다시 맞춤(272).
각각 `cross_*.json`으로 저장한다. B06 상세 조회가 이 폴더를 glob하고 종단 파일의 stations로
@@ -621,6 +628,7 @@ def generate_irregular_sections(
extra_stations=extra_stations,
options=options,
crs=crs,
with_curves=True,
)
if not irregular_stations:
return []
+60 -25
View File
@@ -381,32 +381,17 @@ def _design_curve_widenings(
return radii, sides, widenings
def generate_sections(
polyline: np.ndarray | list[list[float]],
sampler: SurfaceElevationSampler,
options: SectionGenerationOptions | None = None,
*,
source_snapshot: dict[str, Any] | None = None,
crs: str | None = None,
design_curves: list[dict[str, Any]] | None = None,
station_snap: bool = False,
station_snap_step: float | None = None,
) -> dict[str, Any]:
"""확정 경로로 CAD 인계 가능한 종단·횡단 원시 데이터를 생성한다.
`station_snap` — 호 안 측점 하나를 곡선 중점으로 옮김(`snap_curve_stations` · 요구 224-2) ·
`station_snap_step` — 그 MC 측점 값 자릿수를 정하는 스냅 간격(390-5 · None = 측점 No.).
MC 에 측점이 없으면 곡선 측점(kind `curve` · `curve_stations` · 요구 252-2) 하나를 더함.
"""
options = options or SectionGenerationOptions()
options.validate()
points, route_chainage = _clean_polyline(np.asarray(polyline, dtype=np.float64))
def _station_layout(
points: np.ndarray,
route_chainage: np.ndarray,
options: SectionGenerationOptions,
design_curves: list[dict[str, Any]] | None,
station_snap: bool,
station_snap_step: float | None,
) -> tuple[np.ndarray, list, set[float], dict[float, str], set[float]]:
"""측점 자리 한 벌(지반 표본 없음) — (측점 누가거리 · 곡선 구간 · 격자 자리 · 구조물 측점 ·
곡선 측점). `generate_sections` · `planned_curve_stations`(B06 측점 맞춤 판정 · 407-3)가 같은 길."""
total = float(route_chainage[-1])
long_chainage = _chainages(total, options.long_sample_interval_m, True)
long_xy = _interpolate_xy(points, route_chainage, long_chainage)
long_z, long_valid = sampler.sample_xy(long_xy)
station_chainage = _chainages(total, options.station_interval_m, options.include_endpoint)
spans = _design_curve_spans(points, route_chainage, design_curves or [])
if station_snap:
@@ -440,6 +425,56 @@ def generate_sections(
curves = {round(value, 6) for value in curve_stations(station_chainage, spans, total, step)}
if curves:
station_chainage = np.unique(np.r_[station_chainage, np.array(sorted(curves))])
return station_chainage, spans, regular_rounded, extras, curves
def planned_curve_stations(
polyline: np.ndarray | list[list[float]],
options: SectionGenerationOptions | None = None,
*,
design_curves: list[dict[str, Any]] | None = None,
station_snap: bool = False,
station_snap_step: float | None = None,
) -> list[float]:
"""지금 노선 · 관 · 구조물(`options.extra_stations`)이 세울 곡선 측점 누가거리(오름차순) —
`generate_sections` 와 같은 값 · 표본은 안 뜸."""
options = options or SectionGenerationOptions()
points, route_chainage = _clean_polyline(np.asarray(polyline, dtype=np.float64))
layout = _station_layout(
points, route_chainage, options, design_curves, station_snap, station_snap_step
)
return sorted(layout[4])
def generate_sections(
polyline: np.ndarray | list[list[float]],
sampler: SurfaceElevationSampler,
options: SectionGenerationOptions | None = None,
*,
source_snapshot: dict[str, Any] | None = None,
crs: str | None = None,
design_curves: list[dict[str, Any]] | None = None,
station_snap: bool = False,
station_snap_step: float | None = None,
) -> dict[str, Any]:
"""확정 경로로 CAD 인계 가능한 종단·횡단 원시 데이터를 생성한다.
`station_snap` — 호 안 측점 하나를 곡선 중점으로 옮김(`snap_curve_stations` · 요구 224-2) ·
`station_snap_step` — 그 MC 측점 값 자릿수를 정하는 스냅 간격(390-5 · None = 측점 No.).
MC 에 측점이 없으면 곡선 측점(kind `curve` · `curve_stations` · 요구 252-2) 하나를 더함.
"""
options = options or SectionGenerationOptions()
options.validate()
points, route_chainage = _clean_polyline(np.asarray(polyline, dtype=np.float64))
total = float(route_chainage[-1])
long_chainage = _chainages(total, options.long_sample_interval_m, True)
long_xy = _interpolate_xy(points, route_chainage, long_chainage)
long_z, long_valid = sampler.sample_xy(long_xy)
station_chainage, spans, regular_rounded, extras, curves = _station_layout(
points, route_chainage, options, design_curves, station_snap, station_snap_step
)
station_xy = _interpolate_xy(points, route_chainage, station_chainage)
tangents = np.vstack(
[
+7 -4
View File
@@ -300,7 +300,8 @@ def _merge_irregular_into_longitudinal(
`irregular_stations` = 지금 관 · 구조물로 새로 뜬 구조물 측점 전부(격자와 같은 m 인 것은
`grid` 표시 · `generate_irregular_sections`). 옛 구조물 측점은 다 빼고(빈 목록이어도),
구조물이 떠난 격자 자리(`grid`)는 일반 측점으로 되돌리고, 새 목록의 격자 자리 측점은 그
격자 측점을 갈음한다(같은 m 측점 하나 · 구조물이 위). 표고 샘플은 손대지 않는다.
격자 측점을 갈음한다(같은 m 측점 하나 · 구조물이 위). 곡선 측점(`curve`)도 새 목록이 통째로
갈음(구조물이 MC 를 비우면 되살아남 · 407-3). 표고 샘플은 손대지 않는다.
B06 상세는 종단 파일의 stations 에 맞는 cross 파일만 노출하고 남은 파일을 지운다
(`prune_stale_cross_files`). 계획선은 사라진 구조물 측점 자리만 고친다(`_follow_moved_stations`
— 바뀌면 새 등급 요약을 돌려줌). 파일 기반이라 다시 맞춰도 중복이 생기지 않는다.
@@ -318,14 +319,16 @@ def _merge_irregular_into_longitudinal(
before = [
float(station.get("chainage_m", 0.0))
for station in stations
if station.get("kind") == "irregular"
if station.get("kind") in ("irregular", "curve")
]
fresh = {round(float(s.get("chainage_m", 0.0)), 6): s for s in irregular_stations}
kept: dict[float, dict[str, Any]] = {}
left: list[dict[str, Any]] = []
for station in stations:
if station.get("kind") == "irregular" and not station.get("grid"):
continue # 옛 구조물 측점 — 새 목록이 갈음
if station.get("kind") == "curve" or (
station.get("kind") == "irregular" and not station.get("grid")
):
continue # 옛 구조물 측점 · 곡선 측점(407-3) — 새 목록이 갈음
key = round(float(station.get("chainage_m", 0.0)), 6)
if key not in fresh and ("structure" in station or station.get("grid")):
# 구조물이 떠난 격자 · 시종점 자리 — 일반 측점으로(옛 판 「regular + 글」 포함)