- 서버 snap_curve_stations ↔ TS snapCurveStations · gridIndices 지움 — 스냅 켬 = 끔과 같은 측점(20 m 그대로 + 「No.N+10 (MC)」) - 고르기 = 10 m · 측점 No. 둘 · load_station_snap_step = 10 만 · 옛 0.1 · 1 = 측점 No. - 시험 = 새 test_280_4_stations(거울 다섯 경우) · 224_2 · 344_3 · 366_3 · 390_4 · 390_5 · 407 고쳐 씀 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
125 lines
4.1 KiB
Python
125 lines
4.1 KiB
Python
"""PLAN 483-1(요구 280-4) — 스냅이 일반측점을 MC 로 옮기지 않음 · MC 특별측점 더함.
|
||
|
||
서버 `_station_layout`(`generate_sections`) ↔ TS `buildStations` 거울 — 분석 D 재현 1 다섯 경우
|
||
(BP–EP 200 m 직선 · 곡선 하나 · 측점 간격 20 m). 짝 = `helper_280_4_stations.cjs`.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import subprocess
|
||
import sys
|
||
import tempfile
|
||
from pathlib import Path
|
||
|
||
import numpy as np
|
||
import pytest
|
||
|
||
HERE = Path(__file__).resolve().parent
|
||
ROOT = HERE.parents[1]
|
||
if str(ROOT) not in sys.path:
|
||
sys.path.insert(0, str(ROOT))
|
||
|
||
from B05_Profile import B05_Profile_Engine_Sections_Core as core # noqa: E402
|
||
|
||
pytestmark = pytest.mark.skipif(
|
||
not (ROOT / "config" / "node_modules" / "typescript").is_dir(),
|
||
reason="프론트엔드 의존성 미설치",
|
||
)
|
||
|
||
LINE = [[0.0, 0.0], [200.0, 0.0]]
|
||
|
||
|
||
def _curve(bc: float, ec: float, radius: float = 30.0) -> list[dict]:
|
||
return [
|
||
{"start": [bc, 0.0], "apex": [(bc + ec) / 2, 3.0], "end": [ec, 0.0], "radius_m": radius}
|
||
]
|
||
|
||
|
||
CASES = {
|
||
"A_10m_긴호_MC50": {"curves": _curve(34.3, 65.7), "snap": True, "step": 10.0},
|
||
"B_10m_짧은호_MC50": {"curves": _curve(45.6, 54.4, 8.5), "snap": True, "step": 10.0},
|
||
"C_10m_MC60": {"curves": _curve(44.3, 75.7), "snap": True, "step": 10.0},
|
||
"D_측점No_MC47": {"curves": _curve(31.3, 62.7), "snap": True, "step": None},
|
||
"E_스냅끔_MC50": {"curves": _curve(34.3, 65.7), "snap": False, "step": None},
|
||
}
|
||
GRID = [float(v) for v in range(0, 201, 20)]
|
||
|
||
|
||
class _Flat:
|
||
def sample_xy(self, xy):
|
||
count = len(np.asarray(xy))
|
||
return np.zeros(count), np.ones(count, dtype=bool)
|
||
|
||
|
||
def _server(case: dict) -> list[dict]:
|
||
data = core.generate_sections(
|
||
[[x, y, 0.0] for x, y in LINE],
|
||
_Flat(),
|
||
core.SectionGenerationOptions(),
|
||
design_curves=case["curves"],
|
||
station_snap=case["snap"],
|
||
station_snap_step=case["step"],
|
||
)
|
||
return data["longitudinal"]["stations"]
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def ts() -> dict:
|
||
jobs = [{"line": LINE, **case} for case in CASES.values()]
|
||
with tempfile.TemporaryDirectory() as folder:
|
||
path = Path(folder) / "job.json"
|
||
path.write_text(json.dumps(jobs), encoding="utf-8")
|
||
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
|
||
["node", str(HERE / "helper_280_4_stations.cjs"), str(path)],
|
||
capture_output=True,
|
||
text=True,
|
||
encoding="utf-8",
|
||
timeout=60,
|
||
)
|
||
assert proc.returncode == 0, proc.stderr
|
||
return dict(zip(CASES, json.loads(proc.stdout), strict=True))
|
||
|
||
|
||
_KIND = {"bp": "end", "ep": "end", "regular": "grid", "curve": "curve"}
|
||
|
||
EXPECT_CURVE = {
|
||
"A_10m_긴호_MC50": 50.0,
|
||
"B_10m_짧은호_MC50": 50.0,
|
||
"C_10m_MC60": None,
|
||
"D_측점No_MC47": 47.0,
|
||
"E_스냅끔_MC50": 50.0,
|
||
}
|
||
|
||
|
||
@pytest.mark.parametrize("name", list(CASES))
|
||
def test_일반측점_그대로_MC_특별측점(name, ts):
|
||
server = _server(CASES[name])
|
||
regular = [s["chainage_m"] for s in server if s["kind"] in ("bp", "regular", "ep")]
|
||
assert regular == GRID # 20 m 일반측점 하나도 안 사라짐
|
||
curves = [s for s in server if s["kind"] == "curve"]
|
||
mc = EXPECT_CURVE[name]
|
||
if mc is None: # N+0 = 일반측점 위 MC → 특별측점 없음
|
||
assert curves == []
|
||
else:
|
||
assert [s["chainage_m"] for s in curves] == [mc]
|
||
assert curves[0]["label"].endswith(" (MC)")
|
||
# 거울 — 누가거리 · 종류
|
||
ours = ts[name]
|
||
assert [s["m"] for s in ours] == pytest.approx([s["chainage_m"] for s in server], abs=1e-6)
|
||
assert [s["kind"] for s in ours] == [_KIND[s["kind"]] for s in server]
|
||
|
||
|
||
def test_A_열쇠(ts):
|
||
keys = {s["key"]: s["m"] for s in ts["A_10m_긴호_MC50"]}
|
||
assert keys["grid:2"] == 40.0 and keys["curve:50.00"] == 50.0
|
||
for s in ts["A_10m_긴호_MC50"]:
|
||
if s["kind"] == "grid":
|
||
assert s["key"] == f"grid:{round(s['m'] / 20)}"
|
||
|
||
|
||
def test_스냅_켬_끔_같은_목록():
|
||
on = _server(CASES["A_10m_긴호_MC50"])
|
||
off = _server(CASES["E_스냅끔_MC50"])
|
||
assert on == off
|