139 lines
5.1 KiB
Python
139 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""509-6 배수유역도용 도엽 — 평면도와 따로 줄임(유역 + 여유).
|
||
|
||
- 범위 = 세부 유역(노선 교차 관으로 모이는 유역) ∪ 줌아웃 한계(노선 bbox 2 배) + 여유 300 m
|
||
- 평면도(route) 범위와 따로 저장(`_derived/sheet_drainage/`) · 유역이 없으면 사본 그대로
|
||
- 배수유역 계산 값 그대로 — 유역 · 관 파일 · 원본 도엽은 안 바뀜 · 배수유역 엔진은 이 사본을 안 읽음
|
||
|
||
임시 폴더 사업지(1 m = 0.00001 도) — 공유 storage · DB 안 씀.
|
||
"""
|
||
|
||
import hashlib
|
||
import json
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
from B04_PreProcess import B04_PreProcess_Engine_SheetClip as clip
|
||
from common_util.common_util_route_geometry import planned_route_working_path, write_route_csv
|
||
from config.config_system import DRAINAGE_CACHE_DIRNAME, DRAINAGE_DETAIL_FILENAME
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
META = {
|
||
"x_min": 0,
|
||
"y_min": 0,
|
||
"width_meters": 10000,
|
||
"height_meters": 10000,
|
||
"lon_min": 127.0,
|
||
"lon_max": 127.1,
|
||
"lat_min": 37.0,
|
||
"lat_max": 37.1,
|
||
}
|
||
|
||
|
||
def lonlat(x: float, y: float) -> list[float]:
|
||
return [127.0 + x * 1e-5, 37.0 + y * 1e-5]
|
||
|
||
|
||
@pytest.fixture()
|
||
def project(tmp_path: Path) -> tuple[Path, Path]:
|
||
processed = tmp_path / "B04_PreProcess" / "processed"
|
||
processed.mkdir(parents=True)
|
||
(processed / "vworld_satellite_meta.json").write_text(json.dumps(META), encoding="utf-8")
|
||
write_route_csv(
|
||
planned_route_working_path(tmp_path), [{"x": 5000, "y": 5000}, {"x": 5500, "y": 5200}]
|
||
)
|
||
ring = [lonlat(x, y) for x, y in [(4800, 5100), (6000, 5100), (6000, 6500), (4800, 6500)]]
|
||
basins = tmp_path / "B04_PreProcess" / DRAINAGE_CACHE_DIRNAME / DRAINAGE_DETAIL_FILENAME
|
||
basins.parent.mkdir(parents=True)
|
||
basins.write_text(
|
||
json.dumps(
|
||
{
|
||
"type": "FeatureCollection",
|
||
"features": [
|
||
{
|
||
"type": "Feature",
|
||
"properties": {"chainage_m": 100.0},
|
||
"geometry": {"type": "Polygon", "coordinates": [ring + [ring[0]]]},
|
||
}
|
||
],
|
||
}
|
||
),
|
||
encoding="utf-8",
|
||
)
|
||
source = processed / "도엽_등고선.display.geojson"
|
||
lines = [[lonlat(x, y) for x in range(0, 10001, 100)] for y in (4000, 4700, 5500, 6700, 7000)]
|
||
source.write_text(
|
||
json.dumps(
|
||
{
|
||
"type": "FeatureCollection",
|
||
"features": [
|
||
{
|
||
"type": "Feature",
|
||
"properties": {"등고수치": i},
|
||
"geometry": {"type": "LineString", "coordinates": c},
|
||
}
|
||
for i, c in enumerate(lines)
|
||
],
|
||
}
|
||
),
|
||
encoding="utf-8",
|
||
)
|
||
return tmp_path, source
|
||
|
||
|
||
def _digest(folder: Path) -> dict[str, str]:
|
||
return {
|
||
str(p.relative_to(folder)): hashlib.sha256(p.read_bytes()).hexdigest()
|
||
for p in sorted(folder.rglob("*"))
|
||
if p.is_file()
|
||
}
|
||
|
||
|
||
def test_범위는_유역_줌아웃_더하기_여유(project):
|
||
root, _ = project
|
||
# 줌아웃 4750~5750 · 4900~5300 ∪ 유역 4800~6000 · 5100~6500 → + 300 m
|
||
assert clip.clip_rect_m(root, "drainage", META) == (4450, 4600, 6300, 6800)
|
||
|
||
|
||
def test_평면도와_따로(project):
|
||
root, source = project
|
||
drainage = clip.clipped_sheet(root, source, "drainage")
|
||
route = clip.clipped_sheet(root, source, "route")
|
||
assert drainage.parent.name == "sheet_drainage" and route.parent.name == "sheet_route"
|
||
levels = [
|
||
f["properties"]["등고수치"]
|
||
for f in json.loads(drainage.read_text(encoding="utf-8"))["features"]
|
||
]
|
||
assert levels == [1, 2, 3] # y 4700 · 5500 · 6700 만 범위 안
|
||
route_levels = [
|
||
f["properties"]["등고수치"]
|
||
for f in json.loads(route.read_text(encoding="utf-8"))["features"]
|
||
]
|
||
assert route_levels == [1, 2] # 노선 띠 4400~5800
|
||
|
||
|
||
def test_유역이_없으면_사본_그대로(project):
|
||
root, source = project
|
||
(root / "B04_PreProcess" / DRAINAGE_CACHE_DIRNAME / DRAINAGE_DETAIL_FILENAME).unlink()
|
||
assert clip.clipped_sheet(root, source, "drainage") == source
|
||
|
||
|
||
def test_배수유역_값_그대로(project):
|
||
root, source = project
|
||
drainage_folder = root / "B04_PreProcess" / DRAINAGE_CACHE_DIRNAME
|
||
processed = root / "B04_PreProcess" / "processed"
|
||
before = (_digest(drainage_folder), _digest(processed))
|
||
clip.clipped_sheet(root, source, "drainage")
|
||
clip.clipped_sheet(root, source, "route")
|
||
assert (_digest(drainage_folder), _digest(processed)) == before
|
||
|
||
|
||
def test_배수유역_엔진은_잘린_사본을_안_읽음():
|
||
"""분석 · 관 자리 · 유역 계산 길에 SheetClip · `_derived/sheet_` 가 없음."""
|
||
for path in (ROOT / "B04_PreProcess").glob("B04_PreProcess_*Watershed*.py"):
|
||
text = path.read_text(encoding="utf-8")
|
||
assert "SheetClip" not in text and "sheet_route" not in text, path.name
|
||
basins = (ROOT / "B04_PreProcess" / "B04_PreProcess_Router_Basins.py").read_text("utf-8")
|
||
assert "SheetClip" not in basins
|