feat(D03 겹): 노선분석 지도 단층 · 지질구조선 · 0차곡 겹 — 묶음 셋째 · 처음 끔 (PLAN 584-1 · 요구 443)
- 서버: 선 겹 = 브이월드 WFS lt_l_gimsfault · lt_l_gimslinea 받은 범위로 잘라 가닥 · 길이 · 덮으면 다시 안 받음 · 실패 = 502 · 새 선 겹은 LINE_KINDS 한 줄 - 서버: 0차곡 = 사업 DEM 2 m 솎음 D8 흐름누적(웅덩이 메움 · 평지 넘김 · numpy) · 위 집수 0.1~1 ha 칸 세선화 선 · 10 m 미만 토막 거름 · 파생 저장본(격자 지문 · 임계) · 임계 = 요청 min_m2 · max_m2 - 화면: 단추 셋(bolt · lineDashed · arrowsJoin 부품 상자에 더함) · 색 --draw-map-fault · lineament · zero-order · 범례 = 가닥 · km · 첫 셈 늦으면 알림 · 바탕 캔버스 - 선 긋기 · 그림 겹 놓기 · 그림 읽기를 LayerDefs 로 옮김(700줄 한도) - test_553_4: 겹 목록에 faults · lineaments · zeroOrder 더함(새 겹 · 기대 목록 갱신) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,9 @@
|
||||
- 산림입지도 = 브이월드 WFS `lt_c_fsdifrsts`(원자료 산림청 산림입지토양도 · PLAN 581-2) ·
|
||||
받은 범위로 잘라 토양형 코드 · 이름 · 넓이만 ·
|
||||
저장 = `processed/산림입지도_bounds.geojson` + 곁 열쇠
|
||||
- 선 겹 = 브이월드 WFS 단층 `lt_l_gimsfault` · 지질구조선 `lt_l_gimslinea`(PLAN 584-1) ·
|
||||
받은 범위로 잘라 가닥 · 길이만 · 저장 = `processed/<이름>_bounds.geojson` + 곁 열쇠
|
||||
- 0차곡 = `D03_PlanAnalysis_ZeroOrder`
|
||||
- 계류 100 m · 도로 300 m 띠 = 도엽 하천중심선(세류 뺌) · 도로중심선(미분류 · 소로 ·
|
||||
면리간도로 뺌) 합친 띠 · 받은 범위로 자름 · 파생 저장본(열쇠 = 두 파일 지문)
|
||||
|
||||
@@ -473,6 +476,67 @@ def ensure_soils(processed: Path, box: Box, epsg: int) -> dict[str, Any]:
|
||||
return {"path": path, "fetched": True}
|
||||
|
||||
|
||||
# ── 선 겹(단층 · 지질구조선) ─────────────────────────────
|
||||
|
||||
# 열쇠 → (이름, 브이월드 WFS 겹 이름) — 새 선 겹은 여기 한 줄(PLAN 584-1)
|
||||
LINE_KINDS: dict[str, tuple[str, str]] = {
|
||||
"faults": ("단층", "lt_l_gimsfault"),
|
||||
"lineaments": ("지질구조선", "lt_l_gimslinea"),
|
||||
}
|
||||
LINE_VERSION = 1
|
||||
|
||||
|
||||
def clip_lines(
|
||||
found: list[dict[str, Any]], box: Box, epsg: int
|
||||
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
|
||||
"""선 지물 → 받은 범위로 자른 선(길이 m · 원 속성 `legend`) + {가닥, 길이 m}."""
|
||||
from shapely.geometry import box as rect
|
||||
from shapely.geometry import mapping, shape
|
||||
from shapely.ops import transform
|
||||
|
||||
to_m, to_ll = _transforms(epsg)
|
||||
frame = rect(*box)
|
||||
features: list[dict[str, Any]] = []
|
||||
total = 0.0
|
||||
for feature in dedup_parcels(found):
|
||||
try:
|
||||
part = transform(to_m, shape(feature["geometry"])).intersection(frame)
|
||||
except (KeyError, TypeError, ValueError, AttributeError):
|
||||
continue
|
||||
if part.is_empty or part.length <= 0:
|
||||
continue
|
||||
total += part.length
|
||||
props = feature.get("properties") or {}
|
||||
features.append(
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": mapping(transform(to_ll, part)),
|
||||
"properties": {"legend": props.get("legend"), "length_m": round(part.length, 1)},
|
||||
}
|
||||
)
|
||||
return features, {"count": len(features), "length_m": round(total, 1)}
|
||||
|
||||
|
||||
def ensure_lines(processed: Path, box: Box, epsg: int, kind: str) -> dict[str, Any]:
|
||||
"""선 겹 — 열쇠 상자가 덮으면 그대로 · 아니면 범위 통째로 다시 받음 · 실패 = 오류."""
|
||||
label, typename = LINE_KINDS[kind]
|
||||
path, key_path = processed / f"{label}_bounds.geojson", processed / f"{label}_bounds.key.json"
|
||||
key = _read_json(key_path) or {}
|
||||
if path.is_file() and key.get("version") == LINE_VERSION and _covers(key.get("box"), box):
|
||||
return {"path": path, "fetched": False}
|
||||
got, failed = fetch_tile(box, epsg, 0, typename)
|
||||
if failed:
|
||||
raise RuntimeError(f"{label}을 받지 못했습니다 — 브이월드 WFS 실패")
|
||||
features, summary = clip_lines(got, box, epsg)
|
||||
processed.mkdir(parents=True, exist_ok=True)
|
||||
atomic_write_json(path, {"type": "FeatureCollection", "features": features, "summary": summary})
|
||||
atomic_write_json(
|
||||
key_path, {"version": LINE_VERSION, "box": [float(v) for v in box], "epsg": int(epsg)}
|
||||
)
|
||||
logger.info("D %s 받기: 선 %d · %.0f m", label, summary["count"], summary["length_m"])
|
||||
return {"path": path, "fetched": True}
|
||||
|
||||
|
||||
# ── 계류 · 도로 띠 ───────────────────────────────────────
|
||||
|
||||
BAND_KIND = "plan_band"
|
||||
|
||||
Reference in New Issue
Block a user