GGRS: Geoscience, GIS, & Remote Sensing

지구과학, GIS, 그리고 원격탐사 블로그입니다.

GeoPandas: GPX 좌표가 영역 내부에 있는지 체크하기

댓글 0

GIS

2021. 8. 24.

안녕하세요? 이번 글은 GeoPandas(지오판다스)를 기반으로 GPX 좌표가 영역 내부에 있는지 체크해 보도록 하겠습니다.

GeoPandas(지오판다스) 설치 방법은 다음 글을 참고하시기 바랍니다.

 

GeoPandas(지오판다스) 설치하기

안녕하세요? 이번 글은 Python으로 지리공간 데이터를 보다 쉽게 다룰 수 있는 오픈소스 프로젝트, 'GeoPandas(지오판다스)' 설치방법을 정리해 보겠습니다. pandas에서 사용하는 데이터 유형(DataFrame)

blog.daum.net

일단, 필요한 라이브러리들을 호출합니다.

# 라이브러리 호출
import gpxpy
import pandas as pd
import geopandas as gpd
import os
from glob import glob
import shapely.geometry
import geog
import numpy as np

GPX 파일을 GeoPandas DataFrame으로 변환하는 함수를 정의해 봅니다.

def gpx_to_geodataframe(gpx_file):
    data = []
    gpx = gpxpy.parse(open(gpx_file, 'r', encoding='utf-8'))
    for track_idx, track in enumerate(gpx.tracks):
        for seg_idx, segment in enumerate(track.segments):
            for point_idx, point in enumerate(segment.points):
                data.append([os.path.basename(gpx_file), # 파일 이름
                             point.longitude, # 포인트 경도
                             point.latitude]) # 포인트 위도
    df = pd.DataFrame(data, columns=['f_Name', 'p_Lon', 'p_Lat']).fillna(0)
    gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.p_Lon, df.p_Lat))
    
    return gdf

GPX 파일을 해당 함수에 적용해 봅니다. geometry 컬럼이 DataFrame과 GeoDataFrame의 차이를 보여줍니다. 

gdf = gpx_to_geodataframe('D:/GEODATA/done_100016.gpx')
gdf.head()

Google 지도(https://www.google.co.kr/maps/)에서 우리는 손쉽게 특정 좌표를 확인할 수 있습니다. 만약 위 GPX 파일이 북한산국립공원 백운대를 지나는지 체크하려면 어떻게 해야할까요?! QGIS와 같은 데스크탑 GIS 소프트웨어에서 직접 체크해볼 수 있겠지만, 이렇게 체크해야 하는 파일 개수가 상당히 많다면 다른 방식을 고려해봐야 할 것입니다. 여기서는 백운대 좌표에 500m 만큼 영역을 지정한 후, GPX 좌표가 이 영역과 중첩되는지 여부로 다수의 파일을 체크해보도록 하겠습니다.

Google 지도 정보를 기반으로 백운대 좌표를 정의합니다.

# 백운대 좌표: 126.9687452, 37.6591658
point = shapely.geometry.Point([126.9687452, 37.6591658])

원(circle) 영역을 지정할 건데요, 백운대 좌표로부터 500미터 반경을 10개의 점(0-360도 범위)으로 표현합니다.

num_points = 10 # 점 개수
radius = 500 # 반경, 미터(meters)
angles = np.linspace(0, 360, num_points)
circle = shapely.geometry.Polygon(geog.propagate(point, angles, radius))

위 코드 중 버퍼 기능은 geog(지오그) 라이브러리를 활용합니다.

 

geog

Numpy-based vectorized geospatial functions

pypi.org

 

GPX 좌표와 원 영역이 하나라도 중첩된다면, 아래 조건문은 True를 출력할 것입니다. 결과는 False였습니다. 

print("True") if len(gdf[gdf['geometry'].intersects(circle)==True]) > 0 else print("False")

이번에는 다수의 GPX 파일에 대해 백운대 영역 내부에 있는지 체크해 보겠습니다. GPX 파일은 1천개입니다!

gpx_files = glob(os.path.join('D:/GEODATA/', "*.gpx"))
len(gpx_files)

백운대 영역과 중첩되는 좌표를 가진 GPX 파일만 DataFrame으로 추출해 봅니다! 

df = pd.DataFrame(columns=['f_Name', '백운대'])
start_time = datetime.now() # 시작시간

for file_idx, gpx_file in enumerate(gpx_files):
    gdf = gpx_to_geodataframe(gpx_file)
    if len(gdf[gdf['geometry'].intersects(circle)==True]) > 0:
        df=df.append({'f_Name': os.path.basename(gpx_file), '백운대':'Y'} , ignore_index=True)
end_time = datetime.now() # 종료시간
print('처리시간: {}'.format(end_time - start_time)) # 처리시간

df.head()

아래와 같이 처리시간은 1분이며 5개 GPX 파일이 체크되었습니다. QGIS에서 한번 열어보겠습니다!

아래 지도에서 흰 점으로 표현된 위치가 백운대 좌표값입니다. 다음과 같은 방식으로 다수의 GPX 파일을 빠른 속도로 지리 정보 처리해볼 수 있겠습니다. 여기까지 GeoPandas(지오판다스)를 기반으로 GPX 좌표가 영역 내부에 있는지 체크해 보는 방법을 정리해 봤습니다.