Files
Aislo/source/grobal_contours/convert_to_gpkg.py
T
2026-07-05 14:05:22 +09:00

97 lines
4.4 KiB
Python

"""
국가 기본도 등고선 대용량 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()