I’m hoping someone more knowledgeable in Python than I am can help me. As I mentioned I’m trying to find a sample Python implementation of a shortlink decode routing. The samples at Shortlink - OpenStreetMap Wiki only have decode routines for Java, Perl and JS, so I used some of the new online code translators to convert those decode routines into Python and tried them out, but none of them seem to work correctly. The funny thing is that all three of the routines converted from different languages gave me the exact wrong results. Here’s the code I’m using:
ARRAY = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~’
import math
def _encode(lat, lon, z):
“”“given a location and zoom, return a short string representing it.”“”
x = int((lon + 180.0) * 232 / 360.0)
y = int((lat + 90.0) * 232 / 180.0)
code = _interleave(x, y)
str = ‘’
# add eight to the zoom level, which approximates an accuracy of
# one pixel in a tile.
for i in range(int(math.ceil((z + 8) / 3.0))):
digit = (code >> (56 - 6 * i)) & 0x3f;
str += ARRAY[digit]
# append characters onto the end of the string to represent
# partial zoom levels (characters themselves have a granularity
# of 3 zoom levels).
for i in range((z + 8) % 3):
str += “-”
return str
def decode(sc):
char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~"
x = 0
y = 0
i = 0
z = -8
for i in range(len(sc)):
ch = sc[i]
digit = char_array.index(ch)
if digit == -1:
break
# distribute 6 bits into x and y
x <<= 3
y <<= 3
for j in range(-2, 1):
x |= 0 if (digit & (1 << (2 * -j + 1))) == 0 else (1 << -j)
y |= 0 if (digit & (1 << (2 * -j))) == 0 else (1 << -j)
z += 3
x = x * 2 ** (2 - 3 * i) * 90 - 180
y = y * 2 ** (2 - 3 * i) * 45 - 90
# adjust z
if i < len(sc) and sc[i] == “-”:
z -= 2
if i + 1 < len(sc) and sc[i + 1] == “-”:
z += 1
return (y, x, z)
def _interleave(x, y):
“”“combine 2 32 bit integers to a 64 bit integer”“”
c = 0
for i in range(31, 0, -1):
c = (c << 1) | ((x >> i) & 1)
c = (c << 1) | ((y >> i) & 1)
return c
encoded = _encode(50.671530961990356, 6.09715461730957, 16)
print(encoded)
decoded = _decode(encoded)
print(decoded)
And here’s the results:
python decode_short.py
0GAjIv8h
[1035.3722476959229, 1308.7772369384766, 16]
(Sorry for the formatting - I can’t find a code block option in the forum interface)
Obviously the lat/long coordinates decoded are not the same as the ones encoded, but I’m not smart enough with Python to figure out where the error is happening.
Can anyone help? I’ll keep working on it but any hints/tips would be welcome.
Thanks
John