Hello,I've changed the generate_tiles and generate_image scripts to suit my needs and like to share them. The changes are:
- they can be called from the command line - generate_tiles can resume at a given tile - generate_image zoom levels work more like the slippy map zoom levels As a side effect, a dependency on optparse is added.
If anyone with svn access likes these changes, they can be added there. Otherwise, they just stay on the mailinglist for those interested.
Greetings, Steven
#!/usr/bin/python
#
# Generates a single large PNG image for a UK bounding box
# Tweak the lat/lon bounding box (ll) and image dimensions
# to get an image of arbitrary size.
#
# To use this script you must first have installed mapnik
# and imported a planet file into a Postgres DB using
# osm2pgsql.
#
# Note that mapnik renders data differently depending on
# the size of image. More detail appears as the image size
# increases but note that the text is rendered at a constant
# pixel size so will appear smaller on a large image.
from mapnik import *
from optparse import make_option,OptionParser
import sys, os
def render_image(ll, mapfile, map_uri="image.png", z=10):
prj = Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m [EMAIL PROTECTED] +no_defs +over")
c0 = prj.forward(Coord(ll[0],ll[1]))
c1 = prj.forward(Coord(ll[2],ll[3]))
yfactor = (c1.y - c0.y) / 78097
xfactor = (c1.x - c0.x) / (c1.y - c0.y)
imgy = int(yfactor * (2 ** (z - 1)))
imgx = int(imgy * xfactor)
m = Map(imgx,imgy)
load_map(m,mapfile)
bbox = Envelope(c0.x,c0.y,c1.x,c1.y)
m.zoom_to_box(bbox)
im = Image(imgx,imgy)
render(m, im)
view = im.view(0,0,imgx,imgy) # x,y,width,height
view.save(map_uri,'png')
return (imgx, imgy) # return size of generated image
if __name__ == "__main__":
try:
mapfile = os.environ['MAPNIK_MAP_FILE']
except KeyError:
mapfile = "osm.xml"
#---------------------------------------------------
# Change this to the bounding box you want
#
bbox = (-6.5, 49.5, 2.1, 59)
map_uri = "image.png"
zoom = 10
option_list = [
make_option("-b", "--bbox", type="float", nargs=4, dest="bbox", metavar="minLon minLat maxLon maxLat", help="Bounding box to render", default=bbox),
make_option("-u", "--map_uri", type="string", dest="map_uri", help="URI to save the image to", default=map_uri),
make_option("-z", "--zoom", type="int", dest="zoom", help="Zoom level to render", default=zoom),
]
parser = OptionParser(option_list=option_list)
(options, args) = parser.parse_args()
render_image(options.bbox, mapfile, options.map_uri, options.zoom)
#!/usr/bin/python
from math import pi,cos,sin,log,exp,atan
from subprocess import call
from optparse import make_option,OptionParser
import sys, os
DEG_TO_RAD = pi/180
RAD_TO_DEG = 180/pi
def minmax (a,b,c):
a = max(a,b)
a = min(a,c)
return a
class GoogleProjection:
def __init__(self,levels=18):
self.Bc = []
self.Cc = []
self.zc = []
self.Ac = []
c = 256
for d in range(0,levels):
e = c/2;
self.Bc.append(c/360.0)
self.Cc.append(c/(2 * pi))
self.zc.append((e,e))
self.Ac.append(c)
c *= 2
def fromLLtoPixel(self,ll,zoom):
d = self.zc[zoom]
e = round(d[0] + ll[0] * self.Bc[zoom])
f = minmax(sin(DEG_TO_RAD * ll[1]),-0.9999,0.9999)
g = round(d[1] + 0.5*log((1+f)/(1-f))*-self.Cc[zoom])
return (e,g)
def fromPixelToLL(self,px,zoom):
e = self.zc[zoom]
f = (px[0] - e[0])/self.Bc[zoom]
g = (px[1] - e[1])/-self.Cc[zoom]
h = RAD_TO_DEG * ( 2 * atan(exp(g)) - 0.5 * pi)
return (f,h)
from mapnik import *
def render_tiles(bbox, mapfile, tile_dir, minZoom=1,maxZoom=18, name="unknown", start=(0,0), quiet=False):
if not quiet:
print "render_tiles(",bbox, mapfile, tile_dir, minZoom,maxZoom, name, start,")"
if not os.path.isdir(tile_dir):
os.mkdir(tile_dir)
gprj = GoogleProjection(maxZoom+1)
m = Map(2 * 256,2 * 256)
load_map(m,mapfile)
prj = Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m [EMAIL PROTECTED] +no_defs +over")
ll0 = (bbox[0],bbox[3])
ll1 = (bbox[2],bbox[1])
for z in range(minZoom,maxZoom + 1):
px0 = gprj.fromLLtoPixel(ll0,z)
px1 = gprj.fromLLtoPixel(ll1,z)
# check if we have directories in place
zoom = "%s" % z
if not os.path.isdir(tile_dir + zoom):
os.mkdir(tile_dir + zoom)
for x in range(max(start[0],int(px0[0]/256.0)),int(px1[0]/256.0)+1):
# check if we have directories in place
str_x = "%s" % x
if not os.path.isdir(tile_dir + zoom + '/' + str_x):
os.mkdir(tile_dir + zoom + '/' + str_x)
for y in range(max(start[1],int(px0[1]/256.0)),int(px1[1]/256.0)+1):
p0 = gprj.fromPixelToLL((x * 256.0, (y+1) * 256.0),z)
p1 = gprj.fromPixelToLL(((x+1) * 256.0, y * 256.0),z)
# render a new tile and store it on filesystem
c0 = prj.forward(Coord(p0[0],p0[1]))
c1 = prj.forward(Coord(p1[0],p1[1]))
bbox = Envelope(c0.x,c0.y,c1.x,c1.y)
bbox.width(bbox.width() * 2)
bbox.height(bbox.height() * 2)
m.zoom_to_box(bbox)
str_y = "%s" % y
tile_uri = tile_dir + zoom + '/' + str_x + '/' + str_y + '.png'
exists= ""
if os.path.isfile(tile_uri):
exists= "exists"
else:
im = Image(512, 512)
render(m, im)
view = im.view(128,128,256,256) # x,y,width,height
view.save(tile_uri,'png')
command = "convert -colors 255 %s %s" % (tile_uri,tile_uri)
call(command, shell=True)
bytes=os.stat(tile_uri)[6]
empty= ''
if bytes == 137:
empty = " Empty Tile "
if not quiet:
print name,"[",minZoom,"-",maxZoom,"]: " ,z,x,y,"p:",p0,p1,exists, empty
start=(0,0) # reset start after first run
if __name__ == "__main__":
home = os.environ['HOME']
try:
mapfile = os.environ['MAPNIK_MAP_FILE']
except KeyError:
mapfile = home + "/svn.openstreetmap.org/applications/rendering/mapnik/osm-local.xml"
try:
tile_dir = os.environ['MAPNIK_TILE_DIR']
except KeyError:
tile_dir = home + "/osm/tiles/"
#-------------------------------------------------------------------------
#
# Change the following for different bounding boxes and zoom levels
#
# Start with an overview
# World
bbox = (-180.0,-90.0, 180.0,90.0)
zoom = (0,5)
start = (0,0)
name = "World"
option_list = [
make_option("-b", "--bbox", type="float", nargs=4, dest="bbox", metavar="minLon minLat maxLon maxLat", help="Bounding box to render", default=bbox),
make_option("-n", "--name", type="string", dest="name", default=name),
make_option("-q", "--quiet", action="store_true", dest="quiet", help="Do not print any progress information"),
make_option("-s", "--start", type="int", nargs=2, dest="start", metavar="tiledirnum tilenum", help="Tile to start rendering at", default=start),
make_option("-z", "--zoom", type="int", nargs=2, dest="zoom", metavar="minZoom maxZoom", help="Zoom levels to render", default=zoom),
]
parser = OptionParser(option_list=option_list)
(options, args) = parser.parse_args()
render_tiles(options.bbox, mapfile, tile_dir, options.zoom[0], options.zoom[1], options.name, options.start, options.quiet)
generate_tiles.sh
Description: Bourne shell script
_______________________________________________ dev mailing list [email protected] http://lists.openstreetmap.org/cgi-bin/mailman/listinfo/dev

