Created
January 12, 2023 18:28
-
-
Save sebastianknopf/d1d1819181240e17b6c16ba44f3d6c11 to your computer and use it in GitHub Desktop.
python script to fetch ZXY tiles from map servers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import requests | |
import math | |
import zipfile | |
from optparse import OptionParser | |
# map server constants | |
MAP_SERVER_ADDRESS = '[YourMapServer]' | |
MAP_SERVER_USERNAME = '' | |
MAP_SERVER_PASSWORD = '' | |
MAP_SERVER_STYLE = 'default' | |
MAP_SERVER_IMAGE_EXTENSION = 'jpg' | |
# create option parser object | |
opt_parser = OptionParser() | |
opt_parser.add_option('-z', dest='min_z', help='minimum zoom level value to render', type='int', default=4) | |
opt_parser.add_option('-Z', dest='max_z', help='maximum zoom level value to load', type='int', default=5) | |
opt_parser.add_option('-x', dest='min_x', help='minimum longitude value to load', type='float', default=5.5381) | |
opt_parser.add_option('-X', dest='max_x', help='maximum longitude value to load', type='float', default=15.3711) | |
opt_parser.add_option('-y', dest='min_y', help='minimum latitude value to load', type='float', default=47.2363) | |
opt_parser.add_option('-Y', dest='max_y', help='maximum latitude value to load', type='float', default=54.9549) | |
options, args = opt_parser.parse_args() | |
# conversion function | |
def longitude2tile(longitude, zoom): | |
tile = math.floor((longitude + 180) / 360 * math.pow(2, zoom)) | |
return tile | |
def latitude2tile(latitude, zoom): | |
tile = math.floor( | |
(1 - math.log(math.tan(latitude * math.pi / 180) + 1 / math.cos(latitude * math.pi / 180)) / math.pi) / 2 | |
* math.pow(2, zoom) | |
) | |
return tile | |
# zip a whole directory | |
def zipdir(path, ziph): | |
for root, dirs, files in os.walk(path): | |
for file in files: | |
ziph.write(os.path.join(root, file), | |
os.path.relpath(os.path.join(root, file), | |
os.path.join(path, '..'))) | |
# create output path for file | |
style_path = './output/{0}'.format(MAP_SERVER_STYLE) | |
if not os.path.exists(style_path): | |
os.makedirs(style_path) | |
# write info file | |
with open('./output/{0}/info.txt'.format(MAP_SERVER_STYLE), 'w') as file: | |
file.write(options.min_z) | |
file.write('\n') | |
file.write(options.max_z) | |
file.write('\n') | |
file.write() | |
file.write(MAP_SERVER_IMAGE_EXTENSION) | |
# download all tiles for given area | |
for z in range(options.min_z, options.max_z + 1): | |
min_x = longitude2tile(options.min_x, z) | |
max_x = longitude2tile(options.max_x, z) | |
delta_x = math.fabs(max_x - min_x) | |
min_y = min(latitude2tile(options.min_y, z), latitude2tile(options.max_y, z)) | |
max_y = max(latitude2tile(options.min_y, z), latitude2tile(options.max_y, z)) | |
delta_y = math.fabs(max_y - min_y) | |
print('loading {0} tiles of zoom level {1}'.format(delta_x * delta_y, z)) | |
for x in range(min_x, max_x + 1): | |
local = './output/{0}/{1}/{2}'.format(MAP_SERVER_STYLE, z, x) | |
if not os.path.exists(local): | |
os.makedirs(local) | |
for y in range(min_y, max_y + 1): | |
url = '{0}/styles/{1}/{2}/{3}/{4}.{5}'.format( | |
MAP_SERVER_ADDRESS, | |
MAP_SERVER_STYLE, z, x, y, | |
MAP_SERVER_IMAGE_EXTENSION | |
) | |
response = requests.get(url, auth=(MAP_SERVER_USERNAME, MAP_SERVER_PASSWORD)) | |
with open('{0}/{1}.{2}'.format(local, y, MAP_SERVER_IMAGE_EXTENSION), 'wb') as file: | |
file.write(response.content) | |
# generate zip archive of tile folder | |
with zipfile.ZipFile('{0}.zip'.format(MAP_SERVER_STYLE), 'w', zipfile.ZIP_DEFLATED) as zf: | |
zipdir('./output/{0}'.format(MAP_SERVER_STYLE), zf) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment