본문 바로가기
IT & 코딩

GeoHash 레벨 별 크기 (QGIS)

by 에일라거 2021. 5. 13.

GeoHash 는 총 8개의 레벨로 구성되어 있습니다. 1레벨은 전 지구적인 크기, 2레벨은 그거보다 조금 작고... 8레벨은 약 가로 세로 20m 정도의 사이즈를 가지고 있습니다.

 

이게 대체 어느 정도 단위 차이를 가지고 있는지, QGIS 에서 한번 확인해 볼께요

 

 


GeoHash란?

일전에 글을 썼지만, GeoHash는 특정 지역의 위치를 해쉬 함수를 통해 일정한 영문자 및 숫자로 바꿔주는 일입니다.

 

 

공간 데이터 이해하기 : GeoHash란?

해쉬의 정의를 찾아보면, 아래와 같다. 해시 함수는 임의의 길이를 갖는 임의의 데이터에 대해 고정된 길이의 데이터로 매핑하는 함수를 말한다. 이 뜻에 따라 geohash란, 공간 상의 좌표

guzene.tistory.com

위의 글에서, GeoHash란 결국 위경도 좌표라고 하는 엄청나게 정확한 값을 조금 부정확한 값으로 해상도를 떨어뜨리는 작업이라고 말씀드렸구요. 장점이라고 하면 이를 통해 데이터량을 대폭 줄일 수가 있고, 단점이라면 위치가 부정확해진다는 단점이 있겠죠?

 

오늘 글에서 확인할 것은 대체 얼마나 부정확해지는 것인가? 를 파이썬 코드와 QGIS를 통해 확인해보자는 것입니다.

 

 

 

 


GeoHash를 확인해주는 코드

아래의 파이썬 코드는 세가지를 수행해 줍니다.

 

1. 특정 위경도 좌표에 해당하는 GeoHash를 2~8레벨까지 구함

2. 각 레벨별 GeoHash에 해당하는 직사각형 꼭지점 좌표를 구함 (위경도 좌표계)

3. 위경도 좌표계로 구해진 직사각형의 꼭지점을 KATEC 좌표계로 변환

4. 변환된 좌표를 QGIS에서 읽을 수 있는 Polygon 으로 저장해 줌

 

결국 좌표를 하나 찍어서 넣으면, QGIS에서 불러올 수 있는 파일로 변환해 주는 코드입니다.

 

from pyproj import Proj, transform

# 2진수(문자열)을 10진수(숫자)로 변경
def bin2dec(b):
    ans = 0
    for i, bb in enumerate(b[::-1]):
        ans += int(bb)*(2**i)
    return ans

# wkt로 불러들이기 위한 POLYGON string을 만들어주는 함수
def make_polygon(lon, lat):
    return f'"POLYGON (({lon[0]} {lat[0]}, {lon[0]} {lat[1]}, {lon[1]} {lat[1]}, {lon[1]} {lat[0]}, {lon[0]} {lat[0]}))"'

# 변환하려는 위치 
pos = [126.978419, 37.566671] # 서울시청
# Hash 셋업
base32 = '0123456789bcdefghjkmnpqrstuvwxyz' # Base32 인코딩
pair = [[3,2],[5,5],[8,7],[10,10],[13,12],[15,15],[18,17],[20,20]] # 경/위도 (lon/lat) 순서

# 결과 저장용 리스트
polygons = []
hashes = []

# 해쉬 길이별 루프 (1은 너무 넓어서 제외)
for hash_len in range(2,9):
    lon_range=[-180,180] # 경도 범위
    lat_range=[-90,90] # 위도 범위
    bits = ''

    cnt = [0,0]
    for i in range(20):
        lat_avg = (lat_range[0]+lat_range[1])/2
        lon_avg = (lon_range[0]+lon_range[1])/2

        # 경도
        if cnt[0] < pair[hash_len-1][0]:
            if pos[0] >= lon_avg:
                bits = bits + '1'
                lon_range[0] = lon_avg
            else:
                bits = bits + '0'
                lon_range[1] = lon_avg
            cnt[0] += 1

        # 위도
        if cnt[1] < pair[hash_len-1][1]:
            if pos[1] >= lat_avg:
                bits = bits + '1'
                lat_range[0] = lat_avg
            else:
                bits = bits + '0'
                lat_range[1] = lat_avg
            cnt[1] += 1

    geohash = ''
    for i in range(len(bits)//5):
        geohash += base32[bin2dec(bits[5*i:5*i+5])]
    hashes.append(geohash)
    
    # 좌표계 변환 : WGS84 to KATECH
    # EPSG:4326
    WGS84 = {'proj':'latlong', 'datum':'WGS84', 'ellps':'WGS84',}

    # KATECH
    KATECH = {'proj':'tmerc', 'lat_0':'38N', 'lon_0':'128E', 'ellps':'bessel',
       'x_0':'400000', 'y_0':'600000', 'k':'0.9999', 'a':'6377397.155', 'b':'6356078.9628181886',
       'towgs84':'-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43', 'units':'m'}

    inProj = Proj(**WGS84)
    outProj = Proj(**KATECH)
    
    lat_KATECH = []
    lon_KATECH = []
    for i in range(2):
        x2, y2 = transform(inProj, outProj, lon_range[i], lat_range[i])
        lon_KATECH.append(x2)
        lat_KATECH.append(y2)
    
    # KATECH 좌표계로 변환된 경위도 범위를 폴리곤 양식의 스트링으로 변경
    polygons.append(make_polygon(lon_KATECH, lat_KATECH))

# 아래의 경로는 본인 컴퓨터에 맞게 수정하세요    
with open('../__files/hash_test.csv','w') as f:
f.write('hash,wkt\n')
for i, h in enumerate(hashes):
    f.write(f'{h},{polygons[i]}\n')

 

위 코드의 원본 파일은 아래에서 다운받으실 수 있어요

 

geohash_to_qgis.py
0.00MB

 

 

 

 

 


GeoHash 로 변환한 결과 시각화 (QGIS)

이제 위 코드 실행 결과를 QGIS에서 확인해 보겠습니다. 참고로 코드에도 적혀 있지만, 변환한 위치는 서울시청입니다.

 

1. GeoHash 레벨 2

GeoHash 레벨 2 : 한국과 일본에 걸쳐있는 서울 시청

무지막지하게 넓습니다. 레벨 1은 전 지구적 범위를 가진다고 (...) 말씀드렸었죠? ㅋㅋㅋ 

 

2. GeoHash 레벨 3

이제 대충 경기도만한 시청

레벨 3도 무지막지하죠? 그래도 이제 시청 크기가 한 경기도만하게 줄었습니다. 지금 사각형이 여러개 보이는데 가장 바깥의 사각형을 보시면 됩니다.

3. GeoHash 레벨 4

아 이정도 건물은 지을만 하겠어?

오 이제 시청이 한 서울만해 졌네요!! 이정도 건물은 뭐 자다가도 짓겠어

...

 

그나저나 한가지 발견하실 수가 있을텐데, 사각형의 모양이 가로로 길어졌다가 세로로 길어졌다가 합니다. 그건 GeoHash를 만드는 특성상 자릿수가 홀수가 됐다가 짝수가 됐다가 하기 때문이예요. 자세한 내용은 위 링크 (아래에 링크를 한번 더 두겠습니다) 의 글을 참조하시면 좋을 거 같습니다.

 

 

 

공간 데이터 이해하기 : GeoHash란?

해쉬의 정의를 찾아보면, 아래와 같다. 해시 함수는 임의의 길이를 갖는 임의의 데이터에 대해 고정된 길이의 데이터로 매핑하는 함수를 말한다. 이 뜻에 따라 geohash란, 공간 상의 좌표

guzene.tistory.com

 

 

 

 

4. GeoHash 레벨 5

점점 가까워지고 있어!!!

오... 이제 한 두세개 구 정도로 커버가 되네요?? 범위가 점점 좁혀들어가고 있습니다

 

5. GeoHash 레벨 6

뭐야 그래도 덕수궁보다 크잖아?

 

하.. 아직도 일개 시청이 덕수궁보다도 더 크네요. ㅋㅋㅋㅋㅋ 무슨 아방궁인가

 

6. GeoHash 레벨 7

시청 근처 어딘가 쯤

 

드디어! GeoHash 레벨 7쯤에 와서야 시청도 아니고 그냥 시청 근처 어딘가쯤이 되었습니다. 그러니까... 여기서 느낄 수 있는 건

 

1. GeoHash는 레벨 7인데도 이정도밖에 안되면.... 너무 해상도가 낮은 거 아닌가??

2. GPS 단위는 미친듯이 정확한 거구나

 

정도가 될 거 같습니다. 저 사각형 안에 GPS가 어디에 찍히는 그냥 저 사각형으로 다 표현이 되는 거예요. 굉장히 부정확하죠? 하지만 어떤 면에서는 이정도면 충분하다고 할 분야도 분명히 있긴 있을 겁니다. 그러니까 사용하는 것일 테구요.

 

7. GeoHash 레벨 8

아까 스포했잖아요 ㅠㅠ

 

사실 레벨 7에서 이미 다 보였죠... ㅋㅋ 이게 가장 정확한 사이즈입니다. 이정도 되면 이제 아 굳이 GPS 아니더라도 이정도 쓰면 되겠는데? 싶은 사이즈가 됐네요.

 

 

 


 

 

 

오늘은 GeoHash 의 단위를 실제 지도에 뿌려서 어림잡기 위한 코드를 공유해 드리고, 실제로 QGIS에 뿌려 보았을 때 어떤 형식으로 나타나는지까지 살펴보았습니다.

 

아! QGIS 에서 csv 를 불러 작업했는데, 이 내용은 아래의 별도 링크를 참조하시면 좋을 거 같아요.

 

 

 

공간 데이터의 이해 - QGIS를 써 보자

공간이란 무엇일까? 보통 3차원 공간이라는 얘기를 많이 하는걸로 봐서는, 우리가 딛는 땅, 하늘, 그리고 지하 이런 것들을 모두 공간이라고 하는 것일 테고, 그러면 공간 데이터라는 건, 공간에

guzene.tistory.com

 

 

오늘도 긴 글 읽어주셔서 감사하구요, 저는 다음에 더 알찬 글로 돌아오겠습니다.

댓글