Polyline decoder

This commit is contained in:
Mario de Frutos 2016-03-01 23:05:24 +01:00
parent 2b084ee2ab
commit 4d04882c18
4 changed files with 95 additions and 1 deletions

3
.gitignore vendored
View File

@ -1,2 +1,5 @@
.DS_Store
*.pyc
cartodb_services.egg-info/
build/
dist/

View File

@ -1,2 +1,3 @@
from redis_tools import RedisConnection
from coordinates import Coordinate
from polyline import PolyLine

View File

@ -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

View 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