#!/usr/bin/env python
# BSD Licensed, Copyright (c) 2006-2010 TileCache Contributors
import sys, urllib, urllib2, time, os, math
import time
import httplib
try:
from optparse import OptionParser
except ImportError:
OptionParser = False
# setting this to True will exchange more useful error messages
# for privacy, hiding URLs and error messages.
HIDE_ALL = False
[docs]class WMS (object):
fields = ("bbox", "srs", "width", "height", "format", "layers", "styles")
defaultParams = {'version': '1.1.1', 'request': 'GetMap', 'service': 'WMS'}
__slots__ = ("base", "params", "client", "data", "response")
def __init__ (self, base, params, user=None, password=None):
self.base = base
if self.base[-1] not in "?&":
if "?" in self.base:
self.base += "&"
else:
self.base += "?"
self.params = {}
if user is not None and password is not None:
x = urllib2.HTTPPasswordMgrWithDefaultRealm()
x.add_password(None, base, user, password)
self.client = urllib2.build_opener()
auth = urllib2.HTTPBasicAuthHandler(x)
self.client = urllib2.build_opener(auth)
else:
self.client = urllib2.build_opener()
for key, val in self.defaultParams.items():
if self.base.lower().rfind("%s=" % key.lower()) == -1:
self.params[key] = val
for key in self.fields:
if params.has_key(key):
self.params[key] = params[key]
elif self.base.lower().rfind("%s=" % key.lower()) == -1:
self.params[key] = ""
[docs] def url (self):
return self.base + urllib.urlencode(self.params)
[docs] def fetch (self):
urlrequest = urllib2.Request(self.url())
# urlrequest.add_header("User-Agent",
# "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" )
response = None
while response is None:
try:
response = self.client.open(urlrequest)
data = response.read()
# check to make sure that we have an image...
msg = response.info()
if msg.has_key("Content-Type"):
ctype = msg['Content-Type']
if ctype[:5].lower() != 'image':
if HIDE_ALL:
raise Exception("Did not get image data back. (Adjust HIDE_ALL for more detail.)")
else:
raise Exception("Did not get image data back. \nURL: %s\nContent-Type Header: %s\nResponse: \n%s" % (self.url(), ctype, data))
except httplib.BadStatusLine:
response = None # try again
return data, response
[docs] def setBBox (self, box):
self.params["bbox"] = ",".join(map(str, box))
[docs]def seed (svc, layer, levels = (0, 5), bbox = None, padding = 0, force = False, reverse = False, delay = 0 ):
from Layer import Tile
try:
padding = int(padding)
except:
raise Exception('Your padding parameter is %s, but should be an integer' % padding)
if not bbox: bbox = layer.bbox
start = time.time()
total = 0
for z in range(*levels):
bottomleft = layer.getClosestCell(z, bbox[0:2])
topright = layer.getClosestCell(z, bbox[2:4])
# Why Are we printing to sys.stderr??? It's not an error.
# This causes a termination if run from cron or in background if shell is terminated
#print >>sys.stderr, "###### %s, %s" % (bottomleft, topright)
print "###### %s, %s" % (bottomleft, topright)
zcount = 0
metaSize = layer.getMetaSize(z)
ztiles = int(math.ceil(float(topright[1] - bottomleft[1]) / metaSize[0]) * math.ceil(float(topright[0] - bottomleft[0]) / metaSize[1]))
if reverse:
startX = topright[0] + metaSize[0] + (1 * padding)
endX = bottomleft[0] - (1 * padding)
stepX = -metaSize[0]
startY = topright[1] + metaSize[1] + (1 * padding)
endY = bottomleft[1] - (1 * padding)
stepY = -metaSize[1]
else:
startX = bottomleft[0] - (1 * padding)
endX = topright[0] + metaSize[0] + (1 * padding)
stepX = metaSize[0]
startY = bottomleft[1] - (1 * padding)
endY = topright[1] + metaSize[1] + (1 * padding)
stepY = metaSize[1]
for y in range(startY, endY, stepY):
for x in range(startX, endX, stepX):
tileStart = time.time()
tile = Tile(layer,x,y,z)
bounds = tile.bounds()
svc.renderTile(tile,force=force)
total += 1
zcount += 1
box = "(%.4f %.4f %.4f %.4f)" % bounds
print "%02d (%06d, %06d) = %s [%.4fs : %.3f/s] %s/%s" \
% (z,x,y, box, time.time() - tileStart, total / (time.time() - start + .0001), zcount, ztiles)
if delay:
time.sleep(delay)
[docs]def main ():
if not OptionParser:
raise Exception("TileCache seeding requires optparse/OptionParser. Your Python may be too old.\nSend email to the mailing list \n(http://openlayers.org/mailman/listinfo/tilecache) about this problem for help.")
usage = "usage: %prog <layer> [<zoom start> <zoom stop>]"
parser = OptionParser(usage=usage, version="%prog $Id: Client.py 406 2010-10-15 11:00:18Z crschmidt $")
parser.add_option("-f","--force", action="store_true", dest="force", default = False,
help="force recreation of tiles even if they are already in cache")
parser.add_option("-b","--bbox",action="store", type="string", dest="bbox", default = None,
help="restrict to specified bounding box")
parser.add_option("-c", "--config", action="store", type="string", dest="tilecacheconfig",
default=None, help="path to configuration file")
parser.add_option("-d","--delay",action="store", type="int", dest="delay", default = 0,
help="Delay time between requests.")
parser.add_option("-p","--padding",action="store", type="int", dest="padding", default = 0,
help="extra margin tiles to seed around target area. Defaults to 0 "+
"(some edge tiles might be missing). A value of 1 ensures all tiles "+
"will be created, but some tiles may be wholly outside your bbox")
parser.add_option("-r","--reverse", action="store_true", dest="reverse", default = False,
help="Reverse order of seeding tiles")
(options, args) = parser.parse_args()
if len(args)>3:
parser.error("Incorrect number of arguments. bbox and padding are now options (-b and -p)")
from Service import Service, cfgfiles
from Layer import Layer
cfgs = cfgfiles
if options.tilecacheconfig:
configFile = options.tilecacheconfig
print "Config file set to %s" % (configFile)
cfgs = cfgs + (configFile,)
svc = Service.load(*cfgs)
layer = svc.layers[args[0]]
if options.bbox:
bboxlist = map(float,options.bbox.split(","))
else:
bboxlist=None
if len(args)>1:
seed(svc, layer, map(int, args[1:3]), bboxlist , padding=options.padding, force = options.force, reverse = options.reverse, delay=options.delay)
else:
for line in sys.stdin.readlines():
lat, lon, delta = map(float, line.split(","))
bbox = (lon - delta, lat - delta, lon + delta, lat + delta)
print "===> %s <===" % (bbox,)
seed(svc, layer, (5, 17), bbox , force = options.force )
if __name__ == '__main__':
main()