""" 국가 기본도 등고선 대용량 SHP 파일 세트를 고속 공간 인덱싱이 적용된 단일 GeoPackage(.gpkg)로 병합 변환하는 유틸리티. [사전 필수 패키지 설치] 실행 전 가상환경(venv) 터미널에서 다음 라이브러리를 설치해 주세요: pip install geopandas pyogrio """ import sys from pathlib import Path import time try: import geopandas as gpd # fiona 대신 현재 설치된 고속 pyogrio 엔진을 검증 및 사용합니다. import pyogrio except ImportError: print("[오류] 필수 라이브러리가 누락되었습니다.") print("터미널에 다음 명령어를 입력하여 설치해 주세요:") print(">>> pip install geopandas pyogrio") sys.exit(1) def convert_shp_to_gpkg(): current_dir = Path(__file__).resolve().parent shp_files = sorted(list(current_dir.glob("TN_CTRLN*.shp"))) if not shp_files: print(f"[경고] {current_dir} 경로에서 'TN_CTRLN'으로 시작하는 .shp 파일을 찾을 수 없습니다.") return gpkg_output_path = current_dir / "national_contours.gpkg" print(f"-> 총 {len(shp_files)}개의 등고선 SHP 파일이 감지되었습니다.") print(f"-> 변환 시작 (저장 경로: {gpkg_output_path})") start_time = time.time() # 첫 번째 파일 처리 (새 GeoPackage 파일 생성) first_shp = shp_files[0] print(f"\n[1/{len(shp_files)}] {first_shp.name} 읽는 중...") try: # GeoPandas를 이용해 shapefile 로드 (엔진으로 pyogrio 명시하여 고속 로드) gdf = gpd.read_file(first_shp, encoding="cp949", engine="pyogrio") # 속성 필드명 표준화 (소문자로 통일하고 cont_val / elev 필드가 있으면 elevation으로 통일) gdf.columns = [col.lower() for col in gdf.columns] for elev_col in ["cont_val", "elev_val", "elevation"]: if elev_col in gdf.columns: gdf["elevation"] = gdf[elev_col].astype(float) break # 필요한 필드만 최소한으로 남겨 용량 최소화 keep_cols = ["geometry", "elevation"] if "elevation" in gdf.columns else ["geometry"] gdf = gdf[keep_cols] # GeoPackage 파일로 쓰기 (고속 pyogrio 엔진 및 spatial_index 생성 활성화) print(" -> GeoPackage 초기 생성 및 쓰기 중...") gdf.to_file(gpkg_output_path, layer="contours", driver="GPKG", spatial_index=True, engine="pyogrio") print(f" -> 완료 (레코드 수: {len(gdf)}개)") except Exception as e: print(f" -> [에러] 첫 번째 파일 처리 중 오류 발생: {e}") return # 나머지 파일들을 루프를 돌며 기존 GeoPackage 레이어에 추가(Append) for idx, shp_path in enumerate(shp_files[1:], start=2): print(f"\n[{idx}/{len(shp_files)}] {shp_path.name} 읽는 중...") try: gdf_append = gpd.read_file(shp_path, encoding="cp949", engine="pyogrio") # 컬럼 표준화 gdf_append.columns = [col.lower() for col in gdf_append.columns] for elev_col in ["cont_val", "elev_val", "elevation"]: if elev_col in gdf_append.columns: gdf_append["elevation"] = gdf_append[elev_col].astype(float) break keep_cols = ["geometry", "elevation"] if "elevation" in gdf_append.columns else ["geometry"] gdf_append = gdf_append[keep_cols] # 기존 gpkg 파일에 이어쓰기 (append mode, pyogrio 엔진 사용) print(" -> GeoPackage에 데이터 이어붙이는 중...") gdf_append.to_file(gpkg_output_path, layer="contours", driver="GPKG", mode="a", spatial_index=True, engine="pyogrio") print(f" -> 완료 (레코드 수: {len(gdf_append)}개)") except Exception as e: print(f" -> [에러] {shp_path.name} 파일 처리 중 오류 발생: {e}. 계속 진행합니다.") continue end_time = time.time() elapsed = end_time - start_time print("\n==================================================") print(f"★ 모든 등고선 변환이 완료되었습니다! (소요시간: {elapsed:.2f}초)") print(f"★ 파일 위치: {gpkg_output_path}") print("==================================================") if __name__ == "__main__": convert_shp_to_gpkg()