from __future__ import annotations import argparse import shutil import sys from pathlib import Path import numpy as np ROOT_DIR = Path(__file__).resolve().parents[1] if str(ROOT_DIR) not in sys.path: sys.path.insert(0, str(ROOT_DIR)) from config import TERRAIN_MODEL_CONFIG from utils.terrain_model_converter import build_all_terrain_models def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="TIN과 DTM 지표면 모델만 빠르게 재생성 및 스무딩을 테스트합니다.", ) parser.add_argument("--project-id", default="upload_sample", help="instance 하위 프로젝트 ID") return parser.parse_args() def clean_terrain_outputs(project_dir: Path) -> None: project_dir = project_dir.resolve() terrain_dir = (project_dir / "terrain_models").resolve() if terrain_dir.parent != project_dir: raise RuntimeError(f"삭제 대상이 프로젝트 폴더 밖입니다: {terrain_dir}") if terrain_dir.exists(): # dtm과 tin 관련 파일만 선별 삭제 for f in terrain_dir.glob("*"): if "tin" in f.name or "dtm" in f.name or f.name == "manifest.json": if f.is_file(): f.unlink() elif f.is_dir(): shutil.rmtree(f) print(f"[정리] {terrain_dir} 내 tin/dtm 관련 파일 정리 완료") def main() -> int: args = parse_args() project_dir = ROOT_DIR / "instance" / args.project_id structured_path = project_dir / "structured.npz" if not structured_path.exists(): raise FileNotFoundError( f"{structured_path}가 없습니다. run_filters_and_terrain_models.py를 먼저 실행하세요." ) masks: dict[str, np.ndarray] = {} for source_filter in TERRAIN_MODEL_CONFIG["source_filters"]: mask_path = project_dir / f"mask_{source_filter}.npy" if not mask_path.exists(): raise FileNotFoundError( f"{mask_path}가 없습니다. run_filters_and_terrain_models.py를 먼저 실행하세요." ) masks[source_filter] = np.load(mask_path, mmap_mode="r") print(f"[입력] 프로젝트={args.project_id}") print(f"[입력] 구조화={structured_path}") # 캐시 스킵 방지를 위해 기존 파일 삭제 부분 주석 처리 # clean_terrain_outputs(project_dir) # TIN과 DTM 방식만 실행하도록 임시 오버라이드 fast_config = TERRAIN_MODEL_CONFIG.copy() fast_config["precompute"] = ("tin", "dtm") print("[모델] TIN 및 DTM 조합(스무딩 포함) 계산 시작") with np.load(structured_path) as data: manifest = build_all_terrain_models( data, masks, project_dir / "terrain_models", fast_config, force=False, # force=False로 변경하여 이미 만들어진 파일은 연산을 스킵하게 함 ) print( f"[완료] 상태={manifest['status']} | 실패={manifest['failure_count']} | " f"{manifest['duration_seconds']:.2f}초" ) print(f"[결과] {project_dir / 'terrain_models'}") return 0 if manifest["failure_count"] == 0 else 1 if __name__ == "__main__": try: raise SystemExit(main()) except KeyboardInterrupt: print("\n[중단] 사용자가 실행을 중단했습니다.") raise SystemExit(130) except Exception as exc: print(f"\n[오류] {exc}", file=sys.stderr) raise SystemExit(1)