-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathosm_shortlink.py
73 lines (60 loc) · 2.37 KB
/
osm_shortlink.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# osm_shortlink.py - MAximillian Dornseif 2013 - Public Domain
# see http://wiki.openstreetmap.org/wiki/Shortlink
# https://github.com/openstreetmap/openstreetmap-website/blob/master/lib/short_link.rb
# and makeShortCode in
# https://github.com/openstreetmap/openstreetmap-website/blob/master/app/assets/javascripts/application.js
# array of 64 chars to encode 6 bits. this is almost like base64 encoding, but
# the symbolic chars are different, as base64's + and / aren't very
# URL-friendly.
from __future__ import print_function
import math
import sys
if sys.version_info > (3,):
long = int
ARRAY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~'
def short_osm(lat, lon, zoom=16, marker=False):
"""Return a short link representing a location in OpenStreetmap.
Provide coordinates and optional zoom level. e.g.:
>>> short_osm(50.671530961990356, 6.09715461730957)
http://osm.org/go/0GAjIv8h
>>> short_osm(0, 0, 3)
http://osm.org/go/wAAA--
>>> short_osm(0, 0, 4)
http://osm.org/go/wAAA
"""
marker = '?m' if marker else ''
return 'http://osm.org/go/{0}{1}'.format(
_encode(lat, lon, zoom),
marker)
def _encode(lat, lon, z):
"""given a location and zoom, return a short string representing it."""
x = long((lon + 180.0) * 2**32 / 360.0)
y = long((lat + 090.0) * 2**32 / 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 _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
if __name__ == '__main__':
# testing
print(short_osm(50.671530961990356, 6.09715461730957))
print(short_osm(50.671530961990356, 6.09715461730957, 10))
print(short_osm(50.671530961990356, 6.09715461730957, 5))
print(short_osm(50.671530961990356, 6.09715461730957, 4))
print(short_osm(0, 0, 4))
print(short_osm(0, 0, 3))