Files
Aislo/resources/tester/test_115_10_loft_smooth.py
T
eomsangdonandClaude Opus 5.5 0880d2b316 feat(B05): 3D 제안 ③ 사면 모양 평활화 — 사면 격자(노선 1 m × 빗면 약 1 m · 꺾임은 격자선) · Taubin 면 평활화 · 비탈 끝 선 가우스(측점 고정) · 곡선 안쪽 포락선(엇갈린 사면 선은 먼 쪽이 만나는 선에서 멈춤) · 곡률 상한(115-10)
- 새 _Corridor_Loft_Toe.ts(비탈 끝 거리 고르기 · 측점 고정 · 포락선) · _Corridor_Loft_Grid.ts(Taubin)
- _Corridor_Loft.ts 행마다 점 둘 부채꼴 → 격자 · 설계 점 0.3 m 솎기 · 둘레는 지형에 닿은 비탈 끝만
- 사면 실오라기 67 → 1.5 % · 음영 단차 p90 5.6 → 0.02° · 측점 오차 그대로(226 · d22)
- test_115_10 새로 · test_115_8 직선 · 꼬임 단언을 격자 · 포락선에 맞춤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYJJRCfHfdCGNhmXTjQKV7
2026-10-09 10:23:35 +09:00

68 lines
2.4 KiB
Python

# -*- coding: utf-8 -*-
"""PLAN 115-10 — B05 3D 제안 ③ 사면 모양 평활화 검사.
도우미(helper_115_8_corridor_loft.cjs)를 함께 쓴다. 사면 격자(실오라기 없음) · 비탈 끝 선
꼬임 0(포락선) · Taubin 평활화(고정점 그대로 · 줄어들지 않음) · 측점 단면 = B06 · 이음 틈 0.
"""
import json
import os
import subprocess
import pytest
HERE = os.path.dirname(os.path.abspath(__file__))
@pytest.fixture(scope="module")
def results():
proc = subprocess.run(
["node", os.path.join(HERE, "helper_115_8_corridor_loft.cjs")],
capture_output=True,
text=True,
timeout=240,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_slope_grid_no_slivers(results):
# 직선 · 소단 — 사면 삼각형 가로세로비 10 넘는 것 0(행마다 점 둘 실오라기 부채꼴 없음)
for name in ("straight", "berm"):
aspect = results[name]["aspect"]
assert aspect["count"] > 1000 and aspect["over"] == 0, (name, aspect)
def test_curves_few_slivers(results):
# 곡선 안쪽(행이 모이는 자리) · 두 비탈이 만나는 골 둘레만 조금 — 1.5 % 밑
for name in ("curve", "bend", "hairpin"):
aspect = results[name]["aspect"]
assert aspect["over"] <= 0.015 * aspect["count"], (name, aspect)
def test_toe_line_no_self_crossing(results):
for name in ("curve", "bend", "hairpin"):
assert results[name]["toeCross"] == 0, name
# 급곡선(R 10 m) — 엇갈린 사면 선은 만나는 선(골)에서 멈춤
assert results["hairpin"]["stats"]["bowtie"] > 0
def test_no_gap_no_failed_constraint(results):
for name in ("straight", "flip", "curve", "bend", "hairpin", "berm"):
assert results[name]["gaps"] == 0, name
assert results[name]["stats"]["failed"] == 0, name
def test_fixed_edges_and_station_section(results):
r = results["straight"]
assert r["drapeErr"] < 1e-4 # 비탈 끝 = 지형 위(고정)
assert r["sectionErr"] < 1e-4 and r["offsetErr"] < 1e-4 # 측점 단면 · 비탈 끝 = B06
assert results["berm"]["sectionErr"] < 1e-4
def test_taubin_keeps_fixed_and_volume(results):
r = results["taubin"]
assert r["fixedMoved"] == 0 # 노견 끝 · 비탈 끝 · 꺾임 그대로
assert r["roughAfter"] < 0.5 * r["roughBefore"] # 잡음 반 넘게 줄어듦
assert r["meanShift"] < 0.01 # 평균 높이 안 꺼짐(Taubin)