Polyline decoder
This commit is contained in:
parent
2b084ee2ab
commit
4d04882c18
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
||||
.DS_Store
|
||||
*.pyc
|
||||
cartodb_services.egg-info/
|
||||
build/
|
||||
dist/
|
||||
|
@ -1,2 +1,3 @@
|
||||
from redis_tools import RedisConnection
|
||||
from coordinates import Coordinate
|
||||
from polyline import PolyLine
|
||||
|
@ -0,0 +1,51 @@
|
||||
from itertools import tee, izip
|
||||
from math import trunc
|
||||
|
||||
|
||||
class PolyLine:
|
||||
""" Polyline decoder https://developers.google.com/maps/documentation/utilities/polylinealgorithm?csw=1 """
|
||||
|
||||
def decode(self, data):
|
||||
coordinates = []
|
||||
chunks = self._extract_chunks(data)
|
||||
for chunk in chunks:
|
||||
coordinate = self._process_chunk(chunk)
|
||||
coordinate /= 1e5
|
||||
print coordinate
|
||||
if len(coordinates) > 1:
|
||||
# We have to sum the previous with the offset in this chunk
|
||||
coordinate += coordinates[-2]
|
||||
coordinates.append(round(coordinate, 5))
|
||||
|
||||
print coordinates
|
||||
|
||||
return zip(coordinates, coordinates[1:])[::2]
|
||||
|
||||
def _extract_chunks(self, data):
|
||||
chunks, chunk = [], []
|
||||
for character in data:
|
||||
byte = ord(character) - 63
|
||||
if byte & 0x20 > 0:
|
||||
byte &= 0x1F
|
||||
chunk.append(byte)
|
||||
else:
|
||||
chunk.append(byte)
|
||||
chunks.append(chunk)
|
||||
chunk = []
|
||||
|
||||
return chunks
|
||||
|
||||
def _process_chunk(self, chunk):
|
||||
coordinate = self._get_coordinate(chunk)
|
||||
# Check if the coordinate is negative
|
||||
if coordinate & 0x1:
|
||||
return ~(coordinate >> 1)
|
||||
else:
|
||||
return coordinate >> 1
|
||||
|
||||
def _get_coordinate(self, chunk):
|
||||
coordinate = 0
|
||||
for i, c in enumerate(chunk):
|
||||
coordinate |= c << (i * 5)
|
||||
|
||||
return coordinate
|
39
server/lib/python/cartodb_services/test/test_polyline.py
Normal file
39
server/lib/python/cartodb_services/test/test_polyline.py
Normal file
@ -0,0 +1,39 @@
|
||||
from cartodb_services.tools import PolyLine
|
||||
from unittest import TestCase
|
||||
|
||||
|
||||
class TestPolyline(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.polyline = PolyLine()
|
||||
|
||||
def test_should_decode_a_chunk_correctly(self):
|
||||
decoded_polyline = self.polyline.decode('`~oia@`~oia@')
|
||||
original_value = [(-179.98321, -179.98321)]
|
||||
|
||||
assert decoded_polyline == original_value
|
||||
|
||||
def test_should_decode_polyline_correctly(self):
|
||||
original_polyline_1 = [(38.5, -120.2),
|
||||
(40.7, -120.95),
|
||||
(43.252, -126.453)]
|
||||
decoded_polyline_1 = self.polyline.decode('_p~iF~ps|U_ulLnnqC_mqNvxq`@')
|
||||
|
||||
assert decoded_polyline_1 == original_polyline_1
|
||||
|
||||
original_polyline_2 = [(17.95783,-5.58105),
|
||||
(15.79225,2.90039),
|
||||
(7.60211,-10.76660)]
|
||||
decoded_polyline_2 = self.polyline.decode('mkrlBp`aa@z}eL_pwr@js~p@tilrA')
|
||||
|
||||
assert decoded_polyline_2 == original_polyline_2
|
||||
|
||||
original_polyline_3 = [(62.75473,-157.14844),
|
||||
(65.07213,169.80469) ,
|
||||
(48.92250,158.55469),
|
||||
(44.33957,-150.46875)]
|
||||
decoded_polyline_3 = self.polyline.decode('ax_~Jv`d~\wrcMa`qj}@dfqaBngtcAhb~Zncc}y@')
|
||||
|
||||
assert decoded_polyline_3 == original_polyline_3
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user