Files
Aislo/resources/tester/test_582_contour_lod.py
T
eomsangdonandClaude Opus 5.5 8793b4f6b2 feat(D03): 노선분석 바탕 MapLibre 전체 적용 — 겹 스물 · 등고 글 · 지명 GL · 처음 = 켬 · WebGL 못 쓰면 옛 캔버스 (PLAN 586-2 ①②③⑤ · 요구 448)
- GL 겹 스물: 위성 조각 · 음영 · 급경사 · 산사태위험(image) · 산림입지 · 보호구역 · 띠 · 물 면 · 건물(fill + 테두리)
  · 지적 · 등고선 · 도로 · 임도 짐작 · 올린 임도망도 · 세류 · 단층 · 지질구조선 · 0차곡 · 산사태취약 필지(line · 점선 px 그대로)
  · 산사태취약 점 · 지명 점(circle) — 색 · 굵기 · 투명도 · 차례 = 옛 캔버스 그대로
- 음영 = 위성 위 「곱하기 0.75」와 같은 셈의 검은 반투명 그림(밝기 g → 투명도 0.75·(1−g)) · 위성 끔 = 그대로
- 등고 수치 · 지명 = symbol(겹치면 뺌 · 등고 글은 선 따라) · 글꼴 = 화면 Noto Sans KR(OFL · 자체 보관)을 그 자리에서 그림
  (꼴에 글꼴 주소 없음 = 글꼴 조각 파일 없음 · 받기 전에 그 글자 글꼴 미리 받음)
- 카메라 주인 = D03 화면 view · 돌림 하나 — 휠 · 가운데 끌기 · 돌림 · 맞춤 · 단축키 모두 draw() → glCamera
- 처음 = GL(aislo:pref:d03.canvas = "1" 이면 옛 캔버스) · 겹 단추줄 끝 단추로 바꿈 · WebGL 못 열거나 잃음 = 저절로 옛 캔버스 + 알림
- GL 이면 캔버스 바탕 겹은 쉼(등고 주곡선 간격 셈만) · GL 이면 위성 한 장 그림 안 받음
- 산사태위험 그림도 경위도 귀퉁이(lonlat_corners 한 곳) · 묶음 꼴 표시 없는 합친 자료도 GL 이 받게 다시 쌈
- 캔버스 그리기 목록 = 새 D03_PlanAnalysis_UI_LayerPaint.ts(700줄 규칙) · 검증 창구 layers().gl = GL 겹별 그린 지물 수
- 잼(headless Edge 실 GPU · 검증_sub2_D · 겹 18 켬 = 자료 있는 겹 전부): 줌아웃 화면 간격 중앙 58.4 → 4.2 ms · 끊김 27 → 0/30
  · 끌기 62.5 → 4.2 ms · 끊김 37 → 0/40 · 마우스 4.2 ms 끊김 0 그대로 · 그은 선 대 GL 0.019 px(돌림 30° 0.019 · 확대 0.077)
- 시험: 캔버스 그리기를 옮긴 자리로 지킴 시험 넷 고침(581-2 · 582 · 584-1 · 584-3 — 그리기 차례 · 색 값이 LayerPaint 로)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 20:28:13 +09:00

92 lines
3.2 KiB
Python

# -*- coding: utf-8 -*-
"""582 등고선 줌 단계 색인 · 글 폭 기억 — 그림 그대로(D03 먼저).
- 색인 붙인 레이어 = 안 붙인 레이어와 그리기 명령(차례 · 좌표)이 똑같음 — 여러 줌 · 자리 ·
닫힌 고리 · 짧은 조각(색인 없음) · 간격 거름(25 m)
- 고른 단은 「무게 ≥ 허용 오차」 정점을 모두 담고 원래 차례 · 아주 확대하면 색인 없이 전부 훑음
- 다 줌아웃에서 훑는 정점이 줄어듦
- 글 폭 기억 = 같은 글 · 같은 자리 · 두 번째부터 재지 않음
- 색인 · 바탕 캔버스는 D03 만 켬(B04 · B05 는 안 부름)
Node 헬퍼(`helper_582_contour_lod.cjs`)가 진짜 TS 를 가짜 캔버스로 돌린다.
"""
import json
import os
import subprocess
from pathlib import Path
import pytest
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = Path(HERE).parents[1]
@pytest.fixture(scope="module")
def r():
proc = subprocess.run(
["node", os.path.join(HERE, "helper_582_contour_lod.cjs")],
capture_output=True,
text=True,
encoding="utf-8",
timeout=120,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_조각_갈래가_다_있음(r):
assert r["lodParts"] > 20
assert r["shortParts"] > 10
assert r["closedParts"] > 10
def test_색인으로_그린_명령이_지금과_같음(r):
assert len(r["cases"]) == 27
for case in r["cases"]:
assert case["same"], case
# 줌 · 자리마다 그린 정점 수가 실제로 달라짐(거름이 일함)
assert len({c["vertices"] for c in r["cases"]}) > 15
assert all(c["vertices"] > 0 for c in r["cases"] if c["scale"] <= 13)
def test_고른_단은_남는_정점을_모두_담음(r):
assert r["supersetOk"]
assert r["noLodFinest"]
def test_다_줌아웃_훑기가_줄어듦(r):
assert r["scannedRatio"] < 0.5
def test_글_폭_기억은_같은_글(r):
for case in r["cases"]:
assert case["labelsSame"], case
assert case["labelsRepeatSame"], case
assert case["labelMeasuredCached"] == 0
assert any(c["labelMeasuredPlain"] > 0 for c in r["cases"])
def _read(rel: str) -> str:
return (ROOT / rel).read_text(encoding="utf-8")
def test_D03_만_켬():
layers = _read("D03_PlanAnalysis/D03_PlanAnalysis_UI_Layers.ts")
assert "indexLayerLod(prepare(collection" in layers
# 581-1 합침 — 겹 모두 바탕 캔버스
paint = _read("D03_PlanAnalysis/D03_PlanAnalysis_UI_LayerPaint.ts") # 586-2 캔버스 그리기 따로
assert (
paint.count("base: true") == paint.count("draw: (context, map)") >= 12
) # 겹 모두 바탕(581 · 584 로 늘어남)
plan_map = _read("D03_PlanAnalysis/D03_PlanAnalysis_UI_Map.ts")
assert "requestAnimationFrame(flush)" in plan_map
assert "drawTop();" in plan_map
users = [
p.relative_to(ROOT).as_posix()
for folder in ("B04_PreProcess", "B05_Profile", "B06_Section", "A00_Common")
for p in (ROOT / folder).rglob("*.ts")
if "indexLayerLod(" in p.read_text(encoding="utf-8")
]
assert users == ["B04_PreProcess/logic/B04_PreProcess_UI_MapRender_Prepare.ts"]