전 세계 대륙 데이터 잘라서 kml 파일로 보관하기

임우열 (WooYeol Lim)·2022년 11월 21일
0

GIS

목록 보기
2/2
post-custom-banner

AOI(Area of Interest)는 GIS 분야에서 매일 들릴만큼 중요한 요소로 작용합니다. AOI를 저장하는 방식에 다양한 Polygon 저장 형태가 있지만 그 중에서도 xml기반의 kml파일로 저장하는 케이스를 보이고자 합니다.

다음의 과정을 위해서는 GeoServer와 지구 대륙 데이터가 필요합니다.

Intro

  • AOI를 관리하는 Polygon 데이터도 결국 Vector Data입니다. Vector Data를 잘게 자르고 미리 저장해놓아 데이터를 Zoom Level에 따라 제공해주는 방식을 Vector Tiling이라고 합니다. Tiling은 Vector/Raster 두 데이터 모두 존재하며 GeoServer는 Vector Tiling과 Raster Tiling을 모두 제공합니다.
  • TMS 프로토콜은 타일링 데이터를 요청할 때 X,Y,Z을 사용하여 데이터를 요청할 수 있는데 Z는 Zoom Level, X,Y는 조합이 가능한 정수이기에 지구 전체를 한 번씩 접근 할 수 있는 좋은 접근 방법으로 사용 될 수 있다.

다음 두 가지 요소를 사용하여 지구 전체 데이터 대한 AOI를 추출해보고자 한다

Solution

  • GeoJson 데이터를 추출 및 파싱 작업 후 kml 형식으로 저장
# Z = 17, Tile : 32,951,762,944
# Z = 8, Tile : 48311 / 125952 -> 
# Z = 7, Tile : 13237 / 31744 
# Z = 6, Tile : 3738 / 7936 -> 3797
# Z = 5, Tile : 1123 / 1984 -> 1163
# Z = 4, Tile : 361 / 512 -> 386 

Code

import requests
import simplekml
import os

# minx,miny,maxx,maxy, z = 0, 1, 511, 246, 8
# minx,miny,maxx,maxy, z = 0, 0, 255, 123, 7
# minx,miny,maxx,maxy, z = 0, 0, 127, 61, 6
# minx,miny,maxx,maxy, z = 0, 0, 63, 30, 5
minx,miny,maxx,maxy, z = 0, 0, 31, 15, 4

# For Small Data
# minx,miny,maxx,maxy, z = 0, 0, 5, 5, 4

WORKSPACE = ""
LAYER = ""
GEOSERVER_URL = ""
FILENAME = f"earth_{LAYER}_zoomLevel_{z}"
TMS_URL = f'http://{GEOSERVER_URL}/geoserver/gwc/service/tms/1.0.0/{WORKSPACE}:{LAYER}@EPSG:4326@geojson'

count, aoi = 0, 0
kml = simplekml.Kml()

# Style
sharedstyle = simplekml.Style()
sharedstyle.linestyle.color = "ff000ff"
sharedstyle.polystyle.fill = 0

f = kml.newfolder(name = FILENAME)
# 가능한 X,Y의 모든 조합
for x in range(minx, maxx + 1):
    for y in range(miny, maxy + 1):
        res = requests.get(TMS_URL + f'/{z}/{x}/{y}.geojson')
        resData = res.json()
        if "features" in resData and resData["features"]:
            count += 1
            for data in resData["features"]:
                if len(data['geometry']['coordinates']) == 1: data['geometry']['coordinates'] = [data['geometry']['coordinates']]
                for coors in data['geometry']['coordinates']:
                    for idx,coor in enumerate(coors):
                        # print(coor)
                        aoi += 1
                        try:
                            mminx=min(coor, key=lambda data : data[0])[0]
                            mmaxx=max(coor, key=lambda data : data[0])[0]
                            mminy=min(coor, key=lambda data : data[1])[1]
                            mmaxy=max(coor, key=lambda data : data[1])[1]
                            # print(f"mminx : {mminx} | mmaxx : {mmaxx}")
                            # print(f"mminy : {mminy} | mmaxy : {mmaxy}\n")
                            pol = f.newpolygon(name = data['id']+f"_{idx}")
                            pol.outerboundaryis = [ (mminx,mminy), (mminx,mmaxy),
                                                    (mmaxx,mmaxy), (mmaxx,mminy),
                                                    (mminx,mminy)]
                        except Exception as e:
                            print(e, coor)
                pol.style = sharedstyle
kml.save(os.getcwd() + '/' + FILENAME+".kml")
print(f"Count : {count} | Aoi Count : {count}")

Result

현재 Zoom level 8의 데이터로 대략 12만 여개의 대륙 타일 데이터를 생성해볼 수 있었지만 중간 중간 원인 모를 이유로 데이터가 누락된 것을 확인 할 수 있었다.

소스코드의 수정이 필요해보이지만 지구 대륙 데이터를 원하는 만큼 잘랐을 때 데이터 양이 너무 많기 때문에 사용하지 않기로 결정하였다.

post-custom-banner

0개의 댓글