Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Script for request map tiles based on a BBOX, for seeding caches.
#!/usr/bin/env python
#
# Make requests to a tile server to seed the cache
# Created by Jesse Crocker, 6/30/2014
#
# This file is public-domain
#-------------------------------------------------------
from math import *
from optparse import OptionParser
import logging
import sys
import requests
# The following functions for handling tile coordiantes are from
# http://wiki.openstreetmap.org/index.php/Slippy_map_tilenames
#
# Written by Oliver White, 2007
def numTiles(z):
return(pow(2,z))
def sec(x):
return(1/cos(x))
def latlon2relativeXY(lat,lon):
x = (lon + 180) / 360
y = (1 - log(tan(radians(lat)) + sec(radians(lat))) / pi) / 2
return(x,y)
def latlon2xy(lat,lon,z):
n = numTiles(z)
x,y = latlon2relativeXY(lat,lon)
return(n*x, n*y)
def tileXY(lon, lat, z):
x,y = latlon2xy(lat,lon,z)
return(int(x),int(y))
if __name__ == "__main__":
usage = "usage: %prog http://tile.server/{x}/{y}/{z}.png"
parser = OptionParser(usage=usage,
description="Make requests to a tile server to fill cache, based on a bbox")
parser.add_option("-y", "--flip-y", action="store_true", dest="flip_y",
help="use TMS y origin, not OSM/google")
parser.add_option("-d", "--debug", action="store_true", dest="debug",
help="Turn on debug logging, prints every tile url")
parser.add_option("-q", "--quiet", action="store_true", dest="quiet")
parser.add_option("-D", "--dry-run", action="store_true", dest="dry_run",
help="Dry run, don't make http requests")
parser.add_option("-z", "--zoom", action="store", dest="zoom", default="0-10",
help="Zoom range to request, min-max inclusive")
parser.add_option("-b", "--bbox", action="store", dest="bbox", default="-180,-85,180,85",
help="Bounding box to request, in the format minLon,minLat,maxLon,maxLat")
parser.add_option("-p", "--progress", action="store_true", dest="progress",
help="Display progress indicators, prints a . every 100 requests, and a ! for every error")
(options, args) = parser.parse_args()
logging.basicConfig(level=logging.DEBUG if options.debug else
(logging.ERROR if options.quiet else logging.INFO))
#silence log messaages from requests
requests_logger = logging.getLogger('requests')
requests_logger.setLevel(logging.CRITICAL)
urllib3_logger = logging.getLogger('urllib3')
urllib3_logger.setLevel(logging.CRITICAL)
if len(args) == 0:
print "missing tile server url"
sys.exit(-1)
min_zoom, max_zoom = [int(d) for d in options.zoom.split("-")]
min_x, min_y, max_x, max_y = [float(d) for d in options.bbox.split(",")]
if min_zoom < 0 or max_zoom > 22:
logging.error("Zoom out of range")
sys.exit(-1)
if min_x < -180 or max_x > 180 or min_y < -85 or max_y > 85:
logging.error("bbox out of range")
sys.exit(-1)
#calculate the number of tiles before we start making requests
tile_count = 0
for z in range(min_zoom, max_zoom + 1, 1):
tile_min_x, tile_max_y = tileXY(min_x, min_y, z)
tile_max_x, tile_min_y = tileXY(max_x, max_y, z)
tile_count += (tile_max_x - tile_min_x) * (tile_max_y - tile_min_y)
logging.info("zoom %d - %d BBOX (%.5f, %.5f, %.5f, %.5f) %d tiles" %
(min_zoom, max_zoom, min_x, min_y, max_x, max_y, tile_count))
request_count = 0
error_count = 0
for z in range(min_zoom, max_zoom + 1, 1):
tile_min_x, tile_max_y = tileXY(min_x, min_y, z)
tile_max_x, tile_min_y = tileXY(max_x, max_y, z)
logging.debug("zoom:%d x:%d-%d, y:%d-%d" % (z, tile_min_x, tile_max_x, tile_min_y, tile_max_y))
for x in range(tile_min_x, tile_max_x + 1):
for y in range(tile_min_y, tile_max_y + 1):
if options.flip_y:
y = (2 ** z) - y - 1
for url in args:
url = url.replace("{x}", str(x))
url = url.replace("{y}", str(y))
url = url.replace("{z}", str(z))
logging.debug(url)
if not options.dry_run:
r = requests.get(url)
if r.status_code != 200:
error_count += 1
if options.progress:
sys.stdout.write('!')
sys.stdout.flush()
request_count += 1
if options.progress and request_count % 100 == 0:
sys.stdout.write('.')
sys.stdout.flush()
if options.progress:
sys.stdout.write("\n")
logging.info("%d requests, %d errors" % (request_count, error_count))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.