How should I test tuples of floats for equality, when they are returned from encoded polylines?
Context:
I am using Google Directions API to find roads inside a region.
My application is expected to often return repeated road segments, but I would like to "clean" these segments. That is, I want to know when I already have a given segment.
Since each node in the road network is a geographical location represented by a tuple(float,float)
(a latitude/longitude pair), this means testing tuples of floats for equality.
On one hand, floats are well-known to be unreliable regarding equality comparison. On the other hand, when Google Directions API returns a given same location twice, it is always (by definition, I suppose) exactely the same, since it returns JSON containing encoded polylines).
UPDATE:
here is my current code for decoding the polyline returned from the Directions service (with comments added by me):
def decodePolyline(point_str):
coord_chunks = [[]]
for char in point_str:
value = ord(char) - 63
split_after = not (value & 0x20)
value &= 0x1F
coord_chunks[-1].append(value)
if split_after:
coord_chunks.append([])
del coord_chunks[-1]
coords = []
for coord_chunk in coord_chunks:
coord = 0
for i, chunk in enumerate(coord_chunk):
coord |= chunk << (i * 5)
print coord
if coord & 0x1:
coord = ~coord
coord >>= 1
## "shifting" an integer to float
coord /= 100000.0
coords.append(coord)
points = []
prev_x = 0
prev_y = 0
for i in xrange(0, len(coords) - 1, 2):
if coords[i] == 0 and coords[i + 1] == 0:
continue
prev_x += coords[i + 1]
prev_y += coords[i]
# further restricting decimal precision
points.append([round(prev_x, 6), round(prev_y, 6)])
return points
if __name__ == '__main__':
print decodePolyline('_p~iF~ps|U_ulLnnqC_mqNvxq`@')
UPDATE TWO:
This might be of interest, regarding possible API upgrades or replacements in similar applications:
MapQuest Platform Services use a slight variant of the Google Polyline Encoding Format. The MapQuest Platform Services variant of the algorithm allows for arbitrary precision of encoded data. The default precision for encoded data is 5 digits (as with the Google format), but MapQuest line data is often accurate to 6 digits of precision.
Note that the precision used during encoding must be the same as the precision used during decoding, or your data will decompress to values which are off by orders of magnitude from the input data!