Skip to content

Instantly share code, notes, and snippets.

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
# Written by Oliver White, 2007
def numTiles(z):
def sec(x):
def latlon2relativeXY(lat,lon):
x = (lon + 180) / 360
y = (1 - log(tan(radians(lat)) + sec(radians(lat))) / pi) / 2
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)
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')
urllib3_logger = logging.getLogger('urllib3')
if len(args) == 0:
print "missing tile server url"
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")
if min_x < -180 or max_x > 180 or min_y < -85 or max_y > 85:
logging.error("bbox out of range")
#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)"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))
if not options.dry_run:
r = requests.get(url)
if r.status_code != 200:
error_count += 1
if options.progress:
request_count += 1
if options.progress and request_count % 100 == 0:
if options.progress:
sys.stdout.write("\n")"%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.