feat(B04): 등고선 보간 6종을 만들어 화면에서 비교하게 한다

문헌(ANUDEM Hutchinson 1988/89, DEM 보간 비교연구)은 지형에 따라 우열이
갈려 단일 최적해가 없다고 본다. 방식을 하나로 고르지 않고 전부 만들어 두고
사용자가 눈으로 비교해 정하도록 했다(2026-08-30 사용자 지시).

신규 B04_PreProcess_Engine_SheetMethods.py — 거리비례 / TPS(박판, 감쇠
최소곡률 LSMR) / 라플라스 / TIN 선형 / TIN 곡면(Clough-Tocher) / IDW.
방식마다 dtm_sheet_{key}.npz + 프리뷰를 만들어 surface_models에
source_filter=sheet_{key}로 등록하므로 기존 뷰어·등고선·프리뷰 경로가 그대로
돈다. 폐합 링 안쪽 처리는 방식과 무관하게 똑같이 적용한다.

화면: 도엽등고 3D 서피스 컨테이너에 방식 전환 버튼과 '라이다 겹쳐 보기'
토글(반투명 파랑)을 달았다. 라이다는 같은 좌표계라 같은 자리에 겹친다.

실측(c1bb453f, 6종 65s): 평탄 셀 TPS 0.003% / 거리비례 0.014% /
TIN 곡면 0.026% / 라플라스 0.235% / TIN 선형 10.4% / IDW 69.1%.
LAS 대비 노선 |dz| 평균은 2.59~3.00m로 방식 간 차이가 작다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-30 16:11:08 +09:00
co-authored by Claude Opus 5
parent 15ce46d54d
commit b2d707f91d
9 changed files with 607 additions and 185 deletions
+5 -6
View File
@@ -237,13 +237,13 @@ def run_surface_analysis(
# 3-4. 도엽등고선 3D 서피스 — LAS가 있어도 참고용으로 같이 만들어 영구저장한다
# (2026-08-30 사용자 확정). 실패해도 분석은 계속한다.
_report(94, "surface_model", "도엽등고선 3D 서피스 생성 중")
sheet_model: dict[str, Any] | None = None
sheet_models: list[dict[str, Any]] = []
try:
from B04_PreProcess.B04_PreProcess_Engine_SheetSurface import (
build_sheet_surface_from_route,
)
sheet_model = build_sheet_surface_from_route(project_root, processed_dir, models_dir)
sheet_models = build_sheet_surface_from_route(project_root, processed_dir, models_dir)
except Exception as exc:
logger.warning("도엽등고선 서피스 생성 실패: %s", exc)
@@ -258,7 +258,7 @@ def run_surface_analysis(
total_points,
ground_summary,
manifest,
sheet_model,
sheet_models,
total_started,
)
@@ -415,7 +415,7 @@ def _collect_analysis_result(
total_points: int,
ground_summary: dict[str, Any],
manifest: dict[str, Any],
sheet_model: dict[str, Any] | None,
sheet_models: list[dict[str, Any]],
total_started: float,
) -> dict[str, Any]:
"""manifest에서 모델 목록을 추려 분석 결과 dict를 조립한다."""
@@ -464,8 +464,7 @@ def _collect_analysis_result(
"layers": layers,
}
)
if sheet_model is not None:
models.append(sheet_model)
models.extend(sheet_models)
logger.info(
"B04 WF1 분석 완료: 모델 %d개, 총 %.1fs", len(models), time.monotonic() - total_started