- map_layer_list = 겹 스물셋 · 처음 값 · 페이지 표(d03 · b05 보일 겹 · 처음 켬 · 취향 열쇠 — A② · A⑨) - map_layer_specs = GL 겹 꼴 · 차례(D03 UI_MapGl 에서 옮김 · 선 겹 꼴은 LINE_LAYERS 한 벌) - map_layer_bar = 겹 단추 줄 · 켬끔 · 취향 · 그래픽 카드 단추 / map_legend = 범례 칸 · 조각 겹 범례 - map_forest_layers = D03_UI_ForestLayers 옮김(이름만) - D03 UI_Layers 683 → 639 줄 · UI_MapGl 423 → 115 줄 · UI_LayerDefs 는 캔버스 도움 + 옛 이름 다시 내놓음 - 시험 길 고침(553-4 · 581-2 · 584-1 · 584-3 · 606-1 · 615 · 622-2) — 옮긴 파일 자리 · 553-4 겹 목록은 622-2 때 낡은 것(국유림 임도 · 경제림 · 생태자연도 빠짐) 같이 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
99 lines
3.9 KiB
Python
99 lines
3.9 KiB
Python
"""등고선 줌별 벡터 조각(PLAN 615) — MVT 풀어 읽기(겹 `contour` · `h` · `k`) · 줌별 간격 ·
|
|
빈 조각(바다 · 국내 밖) = 빈 MVT · 처음만 만들고 둘째 = 파일 · 조각 번호 범위 · 화면 = 고정 벡터 소스.
|
|
|
|
./venv/Scripts/python.exe -m pytest resources/tester/test_615_contour_tiles.py -q
|
|
"""
|
|
|
|
import math
|
|
from pathlib import Path
|
|
|
|
import mapbox_vector_tile
|
|
import pytest
|
|
|
|
from B04_PreProcess.B04_PreProcess_Engine_MapSheet import sheet5k_center
|
|
from common_util import common_util_contour_tiles as ct
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
SHEET = "36901074" # 상주 용화 산지
|
|
|
|
needs_gpkg = pytest.mark.skipif(not ct.NATIONAL_GPKG.is_file(), reason="전국 등고선 파일 없음")
|
|
|
|
|
|
def _tile(lon: float, lat: float, z: int) -> tuple[int, int, int]:
|
|
n = 2**z
|
|
r = math.radians(lat)
|
|
y = (1 - math.log(math.tan(r) + 1 / math.cos(r)) / math.pi) / 2 * n
|
|
return z, int((lon + 180) / 360 * n), int(y)
|
|
|
|
|
|
def _features(data: bytes) -> list[dict]:
|
|
return mapbox_vector_tile.decode(data).get(ct.LAYER, {"features": []})["features"]
|
|
|
|
|
|
@needs_gpkg
|
|
@pytest.mark.parametrize("z", [12, 13, 14, 15])
|
|
def test_zoom_step_and_bold(z: int) -> None:
|
|
lat, lon = sheet5k_center(SHEET)
|
|
features = _features(ct.build_tile(*_tile(lon, lat, z)))
|
|
assert features, "산지 조각에 선이 있어야 함"
|
|
step, bold = ct.STEP_M[z], ct.BOLD_M[z]
|
|
levels = [f["properties"]["h"] for f in features]
|
|
assert len(levels) == len(set(levels)) # 높이 하나 = 지물 하나
|
|
for f in features:
|
|
h, k = f["properties"]["h"], f["properties"]["k"]
|
|
assert h % step == 0 or h % bold == 0
|
|
assert k == int(h % bold == 0)
|
|
assert f["geometry"]["type"] in ("LineString", "MultiLineString")
|
|
if z == 15:
|
|
assert any(h % 10 for h in levels) # 5 m 전부
|
|
if z == 14:
|
|
assert any(h % 25 == 0 and h % 10 for h in levels) # 10 m + 계곡선 25 m
|
|
|
|
|
|
def test_rules_dense_to_sparse() -> None:
|
|
zooms = range(ct.MIN_ZOOM, ct.MAX_ZOOM + 1)
|
|
steps = [ct.STEP_M[z] for z in zooms]
|
|
assert steps == sorted(steps, reverse=True) and steps[-1] == 5
|
|
assert all(ct.BOLD_M[z] % ct.STEP_M[z] == 0 or z == 14 for z in zooms)
|
|
|
|
|
|
def test_empty_tiles() -> None:
|
|
assert _features(ct.build_tile(*_tile(120.0, 30.0, 10))) == [] # 국내 밖
|
|
assert not ct.in_bounds(*_tile(120.0, 30.0, 10))
|
|
if ct.NATIONAL_GPKG.is_file():
|
|
assert _features(ct.build_tile(*_tile(131.0, 37.8, 13))) == [] # 동해 바다
|
|
|
|
|
|
def test_bad_tile_number() -> None:
|
|
for z, x, y in [(7, 0, 0), (16, 0, 0), (10, -1, 0), (10, 0, 1024)]:
|
|
with pytest.raises(KeyError):
|
|
ct.ensure_tile(z, x, y)
|
|
|
|
|
|
@needs_gpkg
|
|
def test_second_read_is_file(tmp_path, monkeypatch) -> None:
|
|
monkeypatch.setattr(ct, "TILES_ROOT", tmp_path)
|
|
lat, lon = sheet5k_center(SHEET)
|
|
z, x, y = _tile(lon, lat, 15)
|
|
first = ct.ensure_tile(z, x, y)
|
|
files = list(tmp_path.rglob("*.pbf"))
|
|
assert len(files) == 1 and files[0].parts[-3:] == (str(z), str(x), f"{y}.pbf")
|
|
assert files[0].parent.parent.parent.name.startswith(f"v{ct.RULE_VERSION}_")
|
|
assert not list(tmp_path.rglob("*.part")) and not list(tmp_path.rglob("*.lock"))
|
|
|
|
def boom(*_args):
|
|
raise AssertionError("둘째는 파일에서 읽어야 함")
|
|
|
|
monkeypatch.setattr(ct, "build_tile", boom)
|
|
assert ct.ensure_tile(z, x, y) == first
|
|
|
|
|
|
def test_screen_uses_fixed_vector_source() -> None:
|
|
gl = (ROOT / "ui_template" / "ui_template_gl_map.ts").read_text(encoding="utf-8")
|
|
assert "export function contourTileSource" in gl and '"vector"' in gl
|
|
assert "/plan/contour/{z}/{x}/{y}.pbf" in gl
|
|
base = (ROOT / "D03_PlanAnalysis" / "D03_PlanAnalysis_UI_MapGl.ts").read_text(encoding="utf-8")
|
|
assert "contour: contourTileSource(projectId)" in base
|
|
specs = (ROOT / "A00_Common" / "map" / "map_layer_specs.ts").read_text(encoding="utf-8")
|
|
assert specs.count('"source-layer": "contour"') == 3 # 624-2 GL 겹 꼴 = 공용
|