2022년 11월 24일 목요일

파이썬, OSGeo, QGIS를 이용한 SHP 레이어 생성 프로그램 개발, 속성 테이블 추가 및 엑셀 파일 생성하기

이 글은 파이썬, OSGeo, QGIS를 이용한 SHP 레이어 생성 프로그램 개발, 속성 테이블 추가 및 엑셀 파일 생성하는 방법을 간략히 보여준다.

공간정보 데이터를 분석하다보면, 가끔, 텍스트 같은 다른 데이터소스에 저장된 폴리곤 데이터를 SHP파일로 변환하고, 피처 속성 테이블을 생성한 후 엑셀로 출력하고 싶을 때가 있다. 이 글은 관련 개발 방법을 요약한다. 

개발 환경 준비
이 글의 내용을 따라하기 위해서는 다음과 같은 개발환경을 준비해야 한다. 
  • Ubuntu 리눅스, windows 개발환경
  • QGIS 설치
  • Python 및 사용 패키지 설치: pip install numpy, geopandas, osgeo
참고로, OSGEO는 공간정보 오픈소스 데이터 표준화, 라이브러리 및 개발 도구를 개발하는 전세계 민간 오픈소스 조직이다. 
OSGEO 소개(참고) 및 오픈소스 아키텍처

폴리곤 입력 데이터 준비
폴리곤 입력 데이터 input 은 다음과 같이 저장되어 있다고 가정한다. 

input = [[폴리곤 (x, y) 좌표들], [폴리곤 (x, y) 좌표들], ...]
예. [[(x, y), (x,y), ...], [(x, y), (x,y), ...], [...]]

이 데이터가 어떤 좌표계로 저장되어 있는 지 미리 알고 있어야 한다.

데이터 로딩 및 폴리곤 객체 생성
GIS 공간정보 데이터구조는 매우 다양하다. 폴리곤은 연결링 라인 자료 구조를 이용한다. 여기서는 관련 자료구조를 생성하기 위해 OSGEO 패키지를 사용한다. 상세 설명은 여기를 참고한다. 
OSGEO 패키지로 생성한 shape 형상들

다음과 같이, osgeo 패키지 등을 이용해, LinearRing 데이터 구조를 입력으로 부터 생성한다. 
import numpy as np
import geopandas as gpd
import osgeo.ogr as ogr
from osgeo import gdal, osr

def create_polygon(input):
shapes = []
for xy in input:
# 연결링 구조 라인 객체 생성
# 참고. 
line_string = ogr.Geometry(ogr.wkbLinearRing)
for p in xy:
    line_string.AddPoint(p[0], p[1])    
shapes.append(line_string)

    return shapes

SHP파일 출력
앞에서 LinearRing 자료구조로 정의된 폴리곤을  shp파일로 출력한다. 이를 위해 다음 과정을 실행해야 한다. 
  1. ESRI shp 파일 생성
  2. 좌표계 프로젝션 정의
  3. 레이어 생성
  4. shp 속성 필드 정의
  5. 레이어에 폴리곤 feature(형상) 객체 생성 및 추가
이를 구현하면 다음과 같다.

def save_shp(out_fname, shapes, projection_EPSG_ID = 25832):
    try:
        # shp 파일 생성
        driver = ogr.GetDriverByName("ESRI Shapefile")    # 드라이버 정의
        dataset_out = driver.CreateDataSource(out_fname)

        ref = osr.SpatialReference()
        ref.ImportFromEPSG(int(projection_EPSG_ID))

        # 레이어 생성
        layer = dataset_out.CreateLayer("data", ref, ogr.wkbPolygon)

        # shp 필드 정의 
        id_field = ogr.FieldDefn("id", ogr.OFTInteger)
        layer.CreateField(id_field)

        # 레이어에 피쳐 추가
        featureDefn = layer.GetLayerDefn()
        for index, s in enumerate(shapes):
            poly = ogr.Geometry(ogr.wkbPolygon) 
            poly.AddGeometry(s)

            feature = ogr.Feature(featureDefn)
            feature.SetGeometry(poly)
            feature.SetField("id", index)
            layer.CreateFeature(feature)

            feature = None
        dataset_out = None
    
    except BaseException as err:
        print(err)    

전체 처리 흐름은 다음과 같다.
def read_file():
input = []
# todo 
return input

def main():
input = read_file()
shapes = create_polygon(input)
save_shp('./output.shp', shapes)

전체 소스 코드는 다음 github 링크에서 다운로드할 수 있다.

QGIS 에서 속성 테이블 자동계산 및 추가 
생성된 output.shp 파일은 사용자가 생성한 피쳐들이 포함되어 있다. 여기서, 일부 속성 정보를 자동계산, 생성한다. 

shp 파일을 qgis 에 추가하면, 레이어가 생성된다. qgis 레이어 패널에서 레이어 선택 후 컨텍스트 메뉴의 Open Attribute Table 메뉴를 선택한다.
다이얼로그에서 Open field calculator (Ctrl+I) 메뉴를 선택한다.

Field calculator 다이얼로그에서 Output field name은 area, field type은 Decimal number (real) 을 선택하고, Search field에서 Geometry > $area 필드를 더블클릭한다. 그리고 OK 버튼을 클릭한다. 

참고로, 이외에, 필드에 대한 통계값, 배열 조작 연산, 색상 연산자, 컨디션, 데이터 유형 변환, 퍼지 함수, 기하 함수, 수학 등 매우 다양한 연산자를 이용해 해당 필드 값을 계산하는 프로그래밍이 가능하다.
필드 계산 프로그래밍 기능

다음과 같이 속성 테이블에 면적(area) 필드가 자동계산되어 생성된다. 만약, 해당 컬럼이 NULL로 출력된다면, 앞서 정의한 좌표계 프로젝션 유형이 값을 계산할 수 없는 경우이므로, 좌표계를 변경해 본다(여기 참고).

툴바의 Select Features 메뉴를 선택하고, 화면의 피쳐를 선택하면, 해당 속성들을 테이블에서 확인할 수 있다. 

레이어 객체의 컨텍스트 메뉴 > Export > Save features as 메뉴를 선택해 해당 결과를 엑셀, shp, kml, dxf, gml, geojson, sqlite 등 다양한 파일로 출력한다. 

다음은 출력된 엑셀파일, gml 파일이다. 


마무리
이 글에서 파이썬을 이용한 SHP 사용자 레이어, 피쳐 속성 테이블 추가, 계산 및 엑셀 출력하는 방법을 설명하였다. 앞서 다룬 OGR, qgis를 좀 더 깊게 이해하면 공간정보 데이터 처리를 자동화할 수 있는 다양한 기능을 개발할 수 있다.

레퍼런스

댓글 없음:

댓글 쓰기