Files
Aislo/resources/tester/test_route_polyline_apex_roundtrip.py
eomsangdonandClaude Opus 5 0ef32b5279 chore(tester): 시험을 resources/tester/ 로 옮김 — 창끼리 건너가게
⚠ **뿌리** — `tmp/` 는 창 사이에 안 건너감(실측 확인: 상대 창이 놓은 `tmp/_sync_probe.txt`
가 시간을 두고 두 번 봐도 안 보임). 그래서 **정본(등록부 스키마)만 건너가고 그것을 읽는
시험은 안 건너가** 오늘 두 번, 같은 시험이 **연 창은 통과·받은 창은 실패**가 됐음.

- `tmp/tests/*` 를 `resources/tester/` 로 **복사**(127 파일). 내용은 **한 줄도 안 고침**
- `tmp/tests` 는 **남겨 둠** — 되돌릴 자리(사용자 지시)
- 실행: `./venv/Scripts/python.exe -m pytest resources/tester/ -q`
  옮기기 전과 **같은 수**: 617 통과 / 22 건너뜀 / 실패 0

⇒ 이제 시험·예외·까닭이 **정본과 함께** 움직임. 오늘 세운 「예외는 정본 스키마에」와 짝임.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 17:12:30 +09:00

82 lines
3.6 KiB
Python

"""묶인 곡선을 **교각점 하나로 갈아 끼워도 같은 선**이 나오는지.
왜 (2026-09-07 실측) — 서버는 처음 만들 때 이어진 꺾임을 한 곡선으로 묶고, 그 곡선의
교각점은 앞뒤 직선을 늘려 만나는 자리라 원본 꺾임점 중 어느 것도 아니다. 그런데 편집은
「꺾임점 하나 = 곡선 하나」로 표현되므로, 묶인 채로 두면 한 번만 손대도 묶음이 흩어지고
**맞춰 둔 반지름이 전부 법정 하한으로 되돌아간다**(R 12~199m → 전부 12m).
그래서 화면이 모달을 열 때 묶인 구간을 그 **교각점 하나**로 갈아 끼운다. 이 시험은 그렇게
갈아 끼운 목록을 서버에 되넣었을 때 **원래와 같은 선**이 나오는지를 지킨다.
"""
import math
from common_util.common_util_route_polyline import build_planned_polyline
MIN_RADIUS = 12.0
def _arc_route(radius_m: float) -> list[tuple[float, float]]:
points = [(float(x), 0.0) for x in range(-150, 0, 3)]
for degree in range(0, 91, 3):
angle = math.radians(degree)
points.append((radius_m * math.sin(angle), radius_m - radius_m * math.cos(angle)))
points += [(radius_m, radius_m + y) for y in range(3, 150, 3)]
return points
def _flatten(result):
"""화면이 하는 것과 같은 갈아 끼우기 — 묶인 구간을 교각점 하나로."""
replaced = {curve.node_first: curve for curve in result.curves}
dropped = {
index
for curve in result.curves
for index in range(curve.node_first + 1, curve.node_last + 1)
}
nodes: list[tuple[float, float]] = []
radii: list[float | None] = []
for index, node in enumerate(result.nodes):
if index in dropped:
continue
curve = replaced.get(index)
nodes.append(curve.apex if curve else (node.x, node.y))
radii.append(curve.radius_m if curve else None)
return nodes, radii
def test_교각점으로_갈아_끼워도_같은_선():
for radius in (25.0, 40.0, 80.0):
first = build_planned_polyline(_arc_route(radius), min_radius_m=MIN_RADIUS)
nodes, radii = _flatten(first)
again = build_planned_polyline(
nodes,
min_radius_m=MIN_RADIUS,
simplify=False,
curve_flags=[True] * len(nodes),
radii=radii,
)
assert again.curve_count == first.curve_count, f"R {radius}m 곡선 수가 달라짐"
fitted = [c.radius_m for c in first.curves]
kept = [c.radius_m for c in again.curves]
for one, other in zip(fitted, kept, strict=True):
assert math.isclose(one, other, rel_tol=1e-6), f"R {one:.2f}{other:.2f}"
# 선 자체도 거의 같아야 한다 — 정점 수와 양 끝이 맞고 최대 어긋남이 1mm 안.
assert len(again.vertices) == len(first.vertices)
worst = max(math.dist(a, b) for a, b in zip(first.vertices, again.vertices, strict=True))
assert worst < 1e-3, f"선이 {worst:.4f}m 어긋남"
def test_갈아_끼우지_않으면_반지름이_눌린다():
"""왜 갈아 끼워야 하는지 못박는다 — 원본 노드를 그대로 되넣으면 하한으로 눌린다."""
first = build_planned_polyline(_arc_route(40.0), min_radius_m=MIN_RADIUS)
raw = [(node.x, node.y) for node in first.nodes]
again = build_planned_polyline(
raw,
min_radius_m=MIN_RADIUS,
simplify=False,
curve_flags=[True] * len(raw),
radii=[None] * len(raw),
)
assert max(c.radius_m for c in first.curves) > 30.0
assert max(c.radius_m for c in again.curves) <= MIN_RADIUS + 1e-6