본문 바로가기
:: Develop/Python

Polyline 변환에 대해 알아보고 패키지를 사용해보자.

by 메모밍 2019. 8. 2.

:: INTRO

  Google API를 쓰다보면 가끔 위도, 경도 (Latitude, Longitude)가 아닌 Polyline 이라는 알 수 없는 포멧으로 데이터를 주는 경우가 있다. 실제로 해당 데이터를 받아보면 이게 무엇을 의미하는지 정말 전혀 알아 볼 수 없다.

 

Response로 주어진 Polyline 

 

당장 구현을 해야하는데 이게 대체 무엇을 의미하는 건지 알 수 가 없어서 생존을 위해 열심히 찾아본 것들을 본 포스팅에서 간단히 정리 하려고 한다.

 


 

:: Polyline이 뭔데 ?

  Polyline은 일련의 좌표들을 '단일 문자열'로 저장 할 수 있게끔 해주는 손실 압축 알고리즘이다. 한 개 지점에 대한 위도, 경도가 아닌 여러 지점에 대한 위도 경도를 다뤄야 할 때는 [ (a,b), (c,d), (e,f) ] 등으로 자료를 다루어야 하는데, 이때 a,b,c,d,e,f 는 단순 정수가 아닌 소수점 형태로 이루어져 있다는 것을 감안하면 주고 받기 힘든 자료형태인데 이를 하나의 문자열로 주고 받을 수 있게끔 해주는 알고리즘 이라고 생각하면 된다.

 

  손실 압축 알고리즘인 이유는 초기값에서 변환할 때 일정 부분을 반올림 하게 되는 과정을 거치기에 초기 가리키던 정확한 위치 정보와 미세한 차이를 보이기 때문이다. 그럼 Polyline이 어떻게 변환 되는지를 한번 보자.

 

1) 초기 값 가져오기

-179.9832104 을 초기값으로 하자.

 

2) 소수값에서 1e5 = 10,000을 곱하고 소수 첫째 자리에서 반올림하기

-179.9832104 * 10,000 = -17998321.04

소수 첫째 자리에서 반올림하여 정수화 = -17998321

 

3)  10진수 값을 2진수로 변환하기, 이때 음수라면 2의 보수를 취할 것.

일단 17998321을 2진수로 변환하면

0000 0001   0001 0010   1010 0001   1111 0001 

여기서 기존의 값은 음수였기 때문에 반전 후 

1111 1110   1110 1101   0101 1110   0000 1110

2의 보수를 취하기위해 1를 더해주면

1111 1110   1110 1101   0101 1110   0000 1111 이 된다.

 

4) 해당 2진 값을 1비트 왼쪽으로 SHIFT 연산한다.

1111 1101   1101 1010   1011 1100   0001 1110

 

5) 원래 초기값이 음수라면 해당 값을 반전 한다.

0000 0010   0010 0101   0100 0011   1110 0001

 

6) 해당 값을 오른쪽을 기준으로 5비트씩 나눈다.

00001  00010  01010  10000  11111  00001

 

7) 해당 값을 역순으로 배치 한다.

00001 11111 10000 01010 00010 00001

 

8) 해당 값만이 아닌 다른 비트 청크가 따르는 경우라면 각각의 값을 0X20 = 100000(2) 값으로 OR 연산

00001 | 100000 = 100001

11111 | 100000 = 111111

.... 전부 다 변환 하면 

100001 111111 110000 101010 100010 000001

 

9) 각 자리 값을 10진수로 변환

33 63 48 42 34 1

 

10) 각 변환 값에 63을 더함

96 126 111 105 97 64

 

11) 해당 값을 ASCII 코드 값으로 변환

.`~ oia @

 

쯔안 ~ 이렇게하면 우리의 -179.9832104 값을 Polyline으로 변환하여 .`~ oia @ 이라는 값을 얻을 수 있다. 이걸 이제 모든 좌표에 대해 해주면 되는데, 사실 중요한건 원리도 원리인데 그래서 당장 구현을 어떻게 해야하는가 ? 이기에 바로 패키지를 사용해서 간단히 다뤄보도록 하자.

 


:: 패키지를 이용해 Polyline 다뤄보기

  다행히 우리의 파이썬에는 라이브러리가 존재한다. 감사합니다 오픈소스 .. 언젠가 저도 꼭 기여 할께요. 

간단히 pip를 이용해 라이브러리를 설치해주자.

 

pip install polyline

 

설치가 되었다면 먼저 위도,경도를 PolyLine으로 변경해보자.

 

import polyline as poly

# LatLon to Polyline
latlon = [(38.5, -120.2), (40.7, -120.9), (43.2, -126.4)]
toPoly = poly.encode(latlon, precision=5)
print(toPoly)

 

  이때 precision은 손실 압축 과정에서 어디까지 가지고 갈것인지에 대한 값으로 위 변환 예시중 2)번에 대한 파라미터 조정 값이다. 기본적으로 5로 설정 되어있다.

 

import polyline as poly

# LatLon to Polyline
latlon = [(38.5, -120.2), (40.7, -120.9), (43.2, -126.4)]
toPoly = poly.encode(latlon, precision=5)
print(toPoly)

# Polyline to LatLon
polyData = "_p~iF~ps|U_ulL~ugC_hgN~eq`@"
toLatLon = poly.decode(polyData)
print(toLatLon)

 

두개의 결과값을 찍어보면 아래와 같이 같은 값으로 잘 변환이 되고 있음을 확인 할 수 있다 !

 

댓글0