This commit is contained in:
Darafei Praliaskouski 2013-02-27 23:48:26 +03:00
parent 846615d644
commit c82f301853
12 changed files with 1643 additions and 1645 deletions

View file

@ -27,7 +27,7 @@ from render import RasterTile
svg = False
if svg:
import cairo
import cairo
style = MapCSS(1, 19) #zoom levels
@ -44,12 +44,12 @@ db = DataBackend()
res = RasterTile(w, h, z, db)
if svg:
file = open("test.svg", "wb")
res.surface = cairo.SVGSurface(file.name, w,h)
file = open("test.svg", "wb")
res.surface = cairo.SVGSurface(file.name, w,h)
res.update_surface(bbox, z, style)
if not svg:
res.surface.write_to_png("test.png")
res.surface.write_to_png("test.png")
else:
res.surface.finish()
res.surface.finish()

View file

@ -35,91 +35,91 @@ from gtk_widget import KothicWidget
try:
import psyco
psyco.full()
import psyco
psyco.full()
except ImportError:
pass
pass
# debug("Psyco import failed. Program may run slower. Ir you run it on i386 machine, please install Psyco to get best performance.")
class KothicApp:
def __init__(self):
self.width, self.height = 800, 480
self.center_coord = (27.6549791, 53.8698)
self.zoom = 17.
self.data_projection = "EPSG:4326"
self.data = DataBackend()
self.load_style()
self.request_d = (0,0)
self.window = gtk.Window()
def __init__(self):
self.width, self.height = 800, 480
self.center_coord = (27.6549791, 53.8698)
self.zoom = 17.
self.data_projection = "EPSG:4326"
self.data = DataBackend()
self.load_style()
self.window.set_size_request(self.width, self.height)
self.window.connect("destroy", gtk.main_quit)
self.window.set_title("Kothic renderer")
menu = gtk.MenuBar()
filemenu = gtk.Menu()
filem = gtk.MenuItem("File")
filem.set_submenu(filemenu)
i = gtk.MenuItem("Reload style")
i.connect("activate", self.load_style)
filemenu.append(i)
stylemenu = gtk.Menu()
stylem = gtk.MenuItem("Style")
stylem.set_submenu(stylemenu)
styles = [name for name in os.listdir("styles") if ".mapcss" in name]
for style in styles:
i = gtk.MenuItem(style)
i.StyleName = style
i.connect("activate", self.reload_style)
stylemenu.append(i)
i = gtk.MenuItem("Exit")
i.connect("activate", gtk.main_quit)
filemenu.append(i)
menu.append(filem)
menu.append(stylem)
vbox = gtk.VBox(False, 2)
vbox.pack_start(menu,False,False,0)
self.KothicWidget = KothicWidget(self.data, self.style)
self.KothicWidget.set_zoom(self.zoom)
self.KothicWidget.jump_to(self.center_coord)
vbox.pack_end(self.KothicWidget)
self.window.add(vbox)
def load_style(self):
self.style = Styling(0,25)
self.style.parse(open("styles/osmosnimki-maps.mapcss","r").read())
def reload_style(self,w):
self.style = Styling(0,25)
self.style.parse(open("styles/%s"%w.StyleName,"r").read())
self.KothicWidget.style_backend = self.style
self.KothicWidget.redraw()
self.request_d = (0,0)
self.window = gtk.Window()
def main(self):
self.window.show_all()
gtk.main()
exit()
self.window.set_size_request(self.width, self.height)
self.window.connect("destroy", gtk.main_quit)
self.window.set_title("Kothic renderer")
menu = gtk.MenuBar()
filemenu = gtk.Menu()
filem = gtk.MenuItem("File")
filem.set_submenu(filemenu)
i = gtk.MenuItem("Reload style")
i.connect("activate", self.load_style)
filemenu.append(i)
stylemenu = gtk.Menu()
stylem = gtk.MenuItem("Style")
stylem.set_submenu(stylemenu)
styles = [name for name in os.listdir("styles") if ".mapcss" in name]
for style in styles:
i = gtk.MenuItem(style)
i.StyleName = style
i.connect("activate", self.reload_style)
stylemenu.append(i)
i = gtk.MenuItem("Exit")
i.connect("activate", gtk.main_quit)
filemenu.append(i)
menu.append(filem)
menu.append(stylem)
vbox = gtk.VBox(False, 2)
vbox.pack_start(menu,False,False,0)
self.KothicWidget = KothicWidget(self.data, self.style)
self.KothicWidget.set_zoom(self.zoom)
self.KothicWidget.jump_to(self.center_coord)
vbox.pack_end(self.KothicWidget)
self.window.add(vbox)
def load_style(self):
self.style = Styling(0,25)
self.style.parse(open("styles/osmosnimki-maps.mapcss","r").read())
def reload_style(self,w):
self.style = Styling(0,25)
self.style.parse(open("styles/%s"%w.StyleName,"r").read())
self.KothicWidget.style_backend = self.style
self.KothicWidget.redraw()
def main(self):
self.window.show_all()
gtk.main()
exit()
if __name__ == "__main__":
gtk.gdk.threads_init()
kap = KothicApp()
kap.main()
gtk.gdk.threads_init()
kap = KothicApp()
kap.main()

View file

@ -32,256 +32,256 @@ import twms.bbox
from twms import projections
class KothicWidget(gtk.DrawingArea):
def __init__(self, data, style):
gtk.DrawingArea.__init__(self)
self.data_backend = data
self.style_backend = style
self.request_d = (0,0)
self.tiles = TileSource(data,style, callback=self.redraw)
self.dx = 0
self.dy = 0
self.drag_x = 0
self.drag_y = 0
self.drag = False
self.rastertile = None
self.f = True
self.width = 0
self.height = 0
self.max_zoom = 25
def __init__(self, data, style):
gtk.DrawingArea.__init__(self)
self.data_backend = data
self.style_backend = style
self.request_d = (0,0)
self.tiles = TileSource(data,style, callback=self.redraw)
self.dx = 0
self.dy = 0
self.drag_x = 0
self.drag_y = 0
self.drag = False
self.rastertile = None
self.f = True
self.width = 0
self.height = 0
self.max_zoom = 25
self.zoom = 0
self.center_coord = (0.0,0.0)
self.old_zoom = 1
self.old_center_coord = (0.0,0.1)
self.tilebox = [] # bbox of currently seen tiles
self.bbox = []
self.add_events(gtk.gdk.BUTTON1_MOTION_MASK)
self.add_events(gtk.gdk.POINTER_MOTION_MASK)
self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
self.add_events(gtk.gdk.SCROLL)
self.zoom = 0
self.center_coord = (0.0,0.0)
self.old_zoom = 1
self.old_center_coord = (0.0,0.1)
self.tilebox = [] # bbox of currently seen tiles
self.bbox = []
self.add_events(gtk.gdk.BUTTON1_MOTION_MASK)
self.add_events(gtk.gdk.POINTER_MOTION_MASK)
self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
self.add_events(gtk.gdk.SCROLL)
# self.window.add_events(gtk.gdk.BUTTON1_MOTION_MASK)
self.connect("expose_event",self.expose_ev)
self.connect("motion_notify_event",self.motion_ev)
self.connect("button_press_event",self.press_ev)
self.connect("button_release_event",self.release_ev)
self.connect("scroll_event",self.scroll_ev)
self.connect("expose_event",self.expose_ev)
self.connect("motion_notify_event",self.motion_ev)
self.connect("button_press_event",self.press_ev)
self.connect("button_release_event",self.release_ev)
self.connect("scroll_event",self.scroll_ev)
# self.surface = cairo.ImageSurfaceicreate(gtk.RGB24, self.width, self.height)
def set_zoom(self, zoom):
self.zoom = zoom
self.queue_draw()
def jump_to(self, lonlat):
self.center_coord = lonlat
self.queue_draw()
def zoom_to(self, bbox):
self.zoom = twms.bbox.zoom_for_bbox (bbox, (self.width,self.height), {"proj":"EPSG:3857","max_zoom":self.max_zoom})-1
print "Zoom:", self.zoom
self.center_coord = ((bbox[0]+bbox[2])/2,(bbox[1]+bbox[3])/2)
print self.center_coord
self.redraw()
def set_zoom(self, zoom):
self.zoom = zoom
self.queue_draw()
def jump_to(self, lonlat):
self.center_coord = lonlat
self.queue_draw()
def zoom_to(self, bbox):
self.zoom = twms.bbox.zoom_for_bbox (bbox, (self.width,self.height), {"proj":"EPSG:3857","max_zoom":self.max_zoom})-1
print "Zoom:", self.zoom
self.center_coord = ((bbox[0]+bbox[2])/2,(bbox[1]+bbox[3])/2)
print self.center_coord
self.redraw()
def motion_ev(self, widget, event):
if self.drag:
self.dx = event.x - self.drag_x
self.dy = event.y - self.drag_y
#if((abs(self.dx) > 3 or abs(self.dy) > 3) and self.f):
if True:
# x = event.x
# y = event.y
# lo1, la1, lo2, la2 = self.tilebox
# self.center_coord = projections.coords_by_tile(self.zoom,1.*x/self.width*(lo2-lo1)+lo1, la1+(1.*y/(self.height)*(la2-la1)),"EPSG:3857")
def motion_ev(self, widget, event):
if self.drag:
self.dx = event.x - self.drag_x
self.dy = event.y - self.drag_y
#if((abs(self.dx) > 3 or abs(self.dy) > 3) and self.f):
if True:
# x = event.x
# y = event.y
# lo1, la1, lo2, la2 = self.tilebox
# self.center_coord = projections.coords_by_tile(self.zoom,1.*x/self.width*(lo2-lo1)+lo1, la1+(1.*y/(self.height)*(la2-la1)),"EPSG:3857")
widget.queue_draw()
def press_ev(self, widget, event):
if event.button == 1:
#debug("Start drag")
self.drag = True
self.drag_x = event.x
self.drag_y = event.y
self.timer = Timer("Drag")
#elif event.button == 2:
#debug("Button2")
#elif event.button == 3:
#debug("Button3")
def release_ev(self, widget, event):
if event.button == 1:
#debug("Stop drag")
self.drag = False
self.timer.stop()
#debug("dd: %s,%s "%(self.dx, self.dy))
x = event.x
y = event.y
lo1, la1, lo2, la2 = projections.from4326(self.bbox, "EPSG:3857")
print lo1, la1, lo2, la2
#self.center_coord = projections.to4326((0.5*(self.width+self.dx)/self.width*(lo1-lo2)+lo2, la1+(0.5*(self.height+self.dy)/self.height*(la2-la1))),"EPSG:3857")
self.center_coord = projections.to4326((0.5*(self.width+2*self.dx)/self.width*(lo1-lo2)+lo2, la1+(0.5*(self.height+2*self.dy)/self.height*(la2-la1))),"EPSG:3857")
#self.rastertile.screen2lonlat(self.rastertile.w/2 - self.dx, self.rastertile.h/2 - self.dy);
self.dx = 0
self.dy = 0
self.redraw()
def scroll_ev(self, widget, event):
if event.direction == gtk.gdk.SCROLL_UP:
if self.zoom+0.5 <= self.max_zoom:
self.zoom += 0.5
#debug("Zoom in")
elif event.direction == gtk.gdk.SCROLL_DOWN:
if self.zoom >= 0: ## negative zooms are nonsense
self.zoom -= 0.5
# debug("Zoom out")
#self.redraw()
debug("new zoom: %s"%(self.zoom))
widget.queue_draw()
def press_ev(self, widget, event):
if event.button == 1:
#debug("Start drag")
self.drag = True
self.drag_x = event.x
self.drag_y = event.y
self.timer = Timer("Drag")
#elif event.button == 2:
#debug("Button2")
#elif event.button == 3:
#debug("Button3")
def release_ev(self, widget, event):
if event.button == 1:
#debug("Stop drag")
self.drag = False
self.timer.stop()
#debug("dd: %s,%s "%(self.dx, self.dy))
x = event.x
y = event.y
lo1, la1, lo2, la2 = projections.from4326(self.bbox, "EPSG:3857")
print lo1, la1, lo2, la2
#self.center_coord = projections.to4326((0.5*(self.width+self.dx)/self.width*(lo1-lo2)+lo2, la1+(0.5*(self.height+self.dy)/self.height*(la2-la1))),"EPSG:3857")
self.center_coord = projections.to4326((0.5*(self.width+2*self.dx)/self.width*(lo1-lo2)+lo2, la1+(0.5*(self.height+2*self.dy)/self.height*(la2-la1))),"EPSG:3857")
#self.rastertile.screen2lonlat(self.rastertile.w/2 - self.dx, self.rastertile.h/2 - self.dy);
self.dx = 0
self.dy = 0
self.redraw()
def scroll_ev(self, widget, event):
if event.direction == gtk.gdk.SCROLL_UP:
if self.zoom+0.5 <= self.max_zoom:
self.zoom += 0.5
#debug("Zoom in")
elif event.direction == gtk.gdk.SCROLL_DOWN:
if self.zoom >= 0: ## negative zooms are nonsense
self.zoom -= 0.5
# debug("Zoom out")
#self.redraw()
debug("new zoom: %s"%(self.zoom))
widget.queue_draw()
def redraw(self):
"""
Force screen redraw.
"""
#res = RasterTile(3*self.width, 3*self.height, self.zoom, self.data_backend)
#res.update_surface_by_center(self.center_coord, self.zoom, self.style_backend)
#self.rastertile = res
self.queue_draw()
def redraw(self):
"""
Force screen redraw.
"""
#res = RasterTile(3*self.width, 3*self.height, self.zoom, self.data_backend)
#res.update_surface_by_center(self.center_coord, self.zoom, self.style_backend)
#self.rastertile = res
self.queue_draw()
def expose_ev(self, widget, event):
if(widget.allocation.width != self.width or widget.allocation.height != self.height ):
#debug("Rrresize!")
self.width = widget.allocation.width
self.height = widget.allocation.height
def expose_ev(self, widget, event):
if(widget.allocation.width != self.width or widget.allocation.height != self.height ):
#debug("Rrresize!")
self.width = widget.allocation.width
self.height = widget.allocation.height
cr = widget.window.cairo_create()
if self.old_center_coord != self.center_coord or self.old_zoom != self.zoom:
#print "Recentered!"
xy = projections.from4326(self.center_coord,"EPSG:3857")
xy1 = projections.to4326((xy[0]-40075016.*(0.5**(self.zoom))/self.tiles.tilewidth*self.width, xy[1]-40075016.*(0.5**(self.zoom))/self.tiles.tileheight*self.height), "EPSG:3857")
xy2 = projections.to4326((xy[0]+40075016.*(0.5**(self.zoom))/self.tiles.tilewidth*self.width, xy[1]+40075016.*(0.5**(self.zoom))/self.tiles.tileheight*self.height), "EPSG:3857")
self.bbox = (xy1[0],xy1[1],xy2[0],xy2[1])
self.tilebox = projections.tile_by_bbox(self.bbox, self.zoom, "EPSG:3857")
self.old_center_coord = self.center_coord
self.old_zoom = self.zoom
from_tile_x, from_tile_y, to_tile_x, to_tile_y = self.tilebox
dx = 1.*(from_tile_x - int(from_tile_x))*self.tiles.tilewidth
dy = 1.*(from_tile_y - int(from_tile_y))*self.tiles.tileheight
print dx,dy
#print self.dx, self.dy
onscreen_tiles = set()
for x in range (int(from_tile_x), int(to_tile_x)+1):
for y in range (int(to_tile_y), int(from_tile_y)+1):
onscreen_tiles.add((self.zoom,x,y))
self.tiles.onscreen = onscreen_tiles
for z,x,y in onscreen_tiles:
tile = self.tiles[(self.zoom,x,y)]
#print dx+(x-from_tile_x)*self.tiles.tilewidth-self.width
#print dy+(y-from_tile_y)*self.tiles.tileheight-self.height
#cr.set_source_surface(tile, int(self.dx-dx+(x-int(from_tile_x))*self.tiles.tilewidth-self.width), int(self.dy-dy-(int(from_tile_y)-y)*self.tiles.tileheight+self.height))
cr.set_source_surface(tile, int(self.dx-dx+(x-int(from_tile_x))*self.tiles.tilewidth), int(self.dy-dy-(int(from_tile_y)-y)*self.tiles.tileheight+self.height))
cr.paint()
#cr.set_source_surface(self.rastertile.surface, self.dx-self.width + self.rastertile.offset_x, self.dy - self.height + self.rastertile.offset_y)
#self.comm[3].release()
cr = widget.window.cairo_create()
if self.old_center_coord != self.center_coord or self.old_zoom != self.zoom:
#print "Recentered!"
xy = projections.from4326(self.center_coord,"EPSG:3857")
xy1 = projections.to4326((xy[0]-40075016.*(0.5**(self.zoom))/self.tiles.tilewidth*self.width, xy[1]-40075016.*(0.5**(self.zoom))/self.tiles.tileheight*self.height), "EPSG:3857")
xy2 = projections.to4326((xy[0]+40075016.*(0.5**(self.zoom))/self.tiles.tilewidth*self.width, xy[1]+40075016.*(0.5**(self.zoom))/self.tiles.tileheight*self.height), "EPSG:3857")
self.bbox = (xy1[0],xy1[1],xy2[0],xy2[1])
self.tilebox = projections.tile_by_bbox(self.bbox, self.zoom, "EPSG:3857")
self.old_center_coord = self.center_coord
self.old_zoom = self.zoom
from_tile_x, from_tile_y, to_tile_x, to_tile_y = self.tilebox
dx = 1.*(from_tile_x - int(from_tile_x))*self.tiles.tilewidth
dy = 1.*(from_tile_y - int(from_tile_y))*self.tiles.tileheight
print dx,dy
#print self.dx, self.dy
onscreen_tiles = set()
for x in range (int(from_tile_x), int(to_tile_x)+1):
for y in range (int(to_tile_y), int(from_tile_y)+1):
onscreen_tiles.add((self.zoom,x,y))
self.tiles.onscreen = onscreen_tiles
for z,x,y in onscreen_tiles:
tile = self.tiles[(self.zoom,x,y)]
#print dx+(x-from_tile_x)*self.tiles.tilewidth-self.width
#print dy+(y-from_tile_y)*self.tiles.tileheight-self.height
#cr.set_source_surface(tile, int(self.dx-dx+(x-int(from_tile_x))*self.tiles.tilewidth-self.width), int(self.dy-dy-(int(from_tile_y)-y)*self.tiles.tileheight+self.height))
cr.set_source_surface(tile, int(self.dx-dx+(x-int(from_tile_x))*self.tiles.tilewidth), int(self.dy-dy-(int(from_tile_y)-y)*self.tiles.tileheight+self.height))
cr.paint()
#cr.set_source_surface(self.rastertile.surface, self.dx-self.width + self.rastertile.offset_x, self.dy - self.height + self.rastertile.offset_y)
#self.comm[3].release()
class TileSource:
def __init__(self,data,style, callback = lambda: None):
self.tiles = {}
self.tilewidth = 2048
self.tileheight = 2048
self.max_tiles = 32
self.data_backend = data
self.style_backend = style
self.callback = callback
self.onscreen = set()
self._singlethread = False
self._prerender = True
def __getitem__(self,(z,x,y),wait=False):
def __init__(self,data,style, callback = lambda: None):
self.tiles = {}
self.tilewidth = 2048
self.tileheight = 2048
self.max_tiles = 32
self.data_backend = data
self.style_backend = style
self.callback = callback
self.onscreen = set()
self._singlethread = False
self._prerender = True
def __getitem__(self,(z,x,y),wait=False):
try:
#if "surface" in self.tiles[(z,x,y)] and not wait:
# self._callback((z,x,y), True)
print "Tiles count:", len(self.tiles)
return self.tiles[(z,x,y)]["surface"]
except:
self.tiles[(z,x,y)] = {"tile": RasterTile(self.tilewidth, self.tileheight, z, self.data_backend)}
self.tiles[(z,x,y)]["start_time"] = datetime.datetime.now()
if self._singlethread:
self.tiles[(z,x,y)]["surface"] = self.tiles[(z,x,y)]["tile"].surface
self.tiles[(z,x,y)]["tile"].update_surface(projections.bbox_by_tile(z,x,y,"EPSG:3857"), z, self.style_backend, lambda p=False: self._callback((z,x,y),p))
del self.tiles[(z,x,y)]["tile"]
else:
self.tiles[(z,x,y)]["surface"] = self.tiles[(z,x,y)]["tile"].surface.create_similar(cairo.CONTENT_COLOR_ALPHA, self.tilewidth, self.tileheight)
self.tiles[(z,x,y)]["thread"] = threading.Thread(None, self.tiles[(z,x,y)]["tile"].update_surface,None, (projections.bbox_by_tile(z,x,y,"EPSG:3857"), z, self.style_backend, lambda p=False: self._callback((z,x,y),p)))
self.tiles[(z,x,y)]["thread"].start()
if wait:
self.tiles[(z,x,y)]["thread"].join()
return self.tiles[(z,x,y)]["surface"]
def _callback (self, (z,x,y),last):
#if last:
# print last, "dddddddddddddddddd"
if not self._singlethread:
if ((z,x,y) in self.onscreen or last) and "tile" in self.tiles[(z,x,y)]:
cr = cairo.Context(self.tiles[(z,x,y)]["surface"])
cr.set_source_surface(self.tiles[(z,x,y)]["tile"].surface,0,0)
cr.paint()
if last:
try:
del self.tiles[(z,x,y)]["thread"]
del self.tiles[(z,x,y)]["tile"]
except KeyError:
pass
self.tiles[(z,x,y)]["finish_time"] = datetime.datetime.now() - self.tiles[(z,x,y)]["start_time"]
gobject.idle_add(self.callback)
self.collect_grabage()
if last and self._prerender:
if (z,x,y) in self.onscreen:
a = self.__getitem__((z-1,x/2,y/2),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2,y*2),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2+1,y*2),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2,y*2+1),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2+1,y*2+1),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x+1,y),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x,y+1),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x-1,y),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x,y-1),True)
def collect_grabage (self):
if len(self.tiles)> self.max_tiles:
# let's kick out the fastest rendered tiles - it's easy to rerender those
# don't touch onscreen tiles
cand = set(self.tiles.keys())
cand.difference_update(self.onscreen)
cand = [i for i in cand if "finish_time" in self.tiles[i]]
cand.sort(lambda i,j: self.tiles[i]["finish_time"]<self.tiles[i]["finish_time"])
while cand:
if (len(self.tiles)> self.max_tiles):
c = cand.pop()
try:
print "Killed tile ", c, " - finished in ",str(self.tiles[c]["finish_time"]), ", ago:", str(datetime.datetime.now()-self.tiles[c]["start_time"])
del self.tiles[c]
except KeyError:
pass
else:
break
#if "surface" in self.tiles[(z,x,y)] and not wait:
# self._callback((z,x,y), True)
print "Tiles count:", len(self.tiles)
return self.tiles[(z,x,y)]["surface"]
except:
self.tiles[(z,x,y)] = {"tile": RasterTile(self.tilewidth, self.tileheight, z, self.data_backend)}
self.tiles[(z,x,y)]["start_time"] = datetime.datetime.now()
if self._singlethread:
self.tiles[(z,x,y)]["surface"] = self.tiles[(z,x,y)]["tile"].surface
self.tiles[(z,x,y)]["tile"].update_surface(projections.bbox_by_tile(z,x,y,"EPSG:3857"), z, self.style_backend, lambda p=False: self._callback((z,x,y),p))
del self.tiles[(z,x,y)]["tile"]
else:
self.tiles[(z,x,y)]["surface"] = self.tiles[(z,x,y)]["tile"].surface.create_similar(cairo.CONTENT_COLOR_ALPHA, self.tilewidth, self.tileheight)
self.tiles[(z,x,y)]["thread"] = threading.Thread(None, self.tiles[(z,x,y)]["tile"].update_surface,None, (projections.bbox_by_tile(z,x,y,"EPSG:3857"), z, self.style_backend, lambda p=False: self._callback((z,x,y),p)))
self.tiles[(z,x,y)]["thread"].start()
if wait:
self.tiles[(z,x,y)]["thread"].join()
return self.tiles[(z,x,y)]["surface"]
def _callback (self, (z,x,y),last):
#if last:
# print last, "dddddddddddddddddd"
if not self._singlethread:
if ((z,x,y) in self.onscreen or last) and "tile" in self.tiles[(z,x,y)]:
cr = cairo.Context(self.tiles[(z,x,y)]["surface"])
cr.set_source_surface(self.tiles[(z,x,y)]["tile"].surface,0,0)
cr.paint()
if last:
try:
del self.tiles[(z,x,y)]["thread"]
del self.tiles[(z,x,y)]["tile"]
except KeyError:
pass
self.tiles[(z,x,y)]["finish_time"] = datetime.datetime.now() - self.tiles[(z,x,y)]["start_time"]
gobject.idle_add(self.callback)
self.collect_grabage()
if last and self._prerender:
if (z,x,y) in self.onscreen:
a = self.__getitem__((z-1,x/2,y/2),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2,y*2),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2+1,y*2),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2,y*2+1),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z+1,x*2+1,y*2+1),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x+1,y),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x,y+1),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x-1,y),True)
if (z,x,y) in self.onscreen:
a = self.__getitem__((z,x,y-1),True)
def collect_grabage (self):
if len(self.tiles)> self.max_tiles:
# let's kick out the fastest rendered tiles - it's easy to rerender those
# don't touch onscreen tiles
cand = set(self.tiles.keys())
cand.difference_update(self.onscreen)
cand = [i for i in cand if "finish_time" in self.tiles[i]]
cand.sort(lambda i,j: self.tiles[i]["finish_time"]<self.tiles[i]["finish_time"])
while cand:
if (len(self.tiles)> self.max_tiles):
c = cand.pop()
try:
print "Killed tile ", c, " - finished in ",str(self.tiles[c]["finish_time"]), ", ago:", str(datetime.datetime.now()-self.tiles[c]["start_time"])
del self.tiles[c]
except KeyError:
pass
else:
break
if __name__ == "__main__":
gtk.gdk.threads_init()
kap = KothicApp()
kap.main()
gtk.gdk.threads_init()
kap = KothicApp()
kap.main()

View file

@ -11,189 +11,189 @@ reload(sys)
sys.setdefaultencoding("utf-8") # a hack to support UTF-8
try:
import psyco
psyco.full()
import psyco
psyco.full()
except ImportError:
pass
#print >>sys.stderr, "Psyco import failed. Program may run slower. If you run it on i386 machine, please install Psyco to get best performance."
pass
#print >>sys.stderr, "Psyco import failed. Program may run slower. If you run it on i386 machine, please install Psyco to get best performance."
def get_vectors(bbox, zoom, style, vec = "polygon"):
bbox_p = projections.from4326(bbox, "EPSG:3857")
geomcolumn = "way"
bbox_p = projections.from4326(bbox, "EPSG:3857")
geomcolumn = "way"
database = "dbname=gis user=gis"
pxtolerance = 1.8
intscalefactor = 10000
ignore_columns = set(["way_area", "osm_id", geomcolumn, "tags", "z_order"])
table = {"polygon":"planet_osm_polygon", "line":"planet_osm_line","point":"planet_osm_point", "coastline": "coastlines"}
database = "dbname=gis user=gis"
pxtolerance = 1.8
intscalefactor = 10000
ignore_columns = set(["way_area", "osm_id", geomcolumn, "tags", "z_order"])
table = {"polygon":"planet_osm_polygon", "line":"planet_osm_line","point":"planet_osm_point", "coastline": "coastlines"}
a = psycopg2.connect(database)
b = a.cursor()
if vec != "coastline":
b.execute("SELECT * FROM %s LIMIT 1;" % table[vec])
a = psycopg2.connect(database)
b = a.cursor()
if vec != "coastline":
b.execute("SELECT * FROM %s LIMIT 1;" % table[vec])
names = [q[0] for q in b.description]
for i in ignore_columns:
if i in names:
names.remove(i)
names = ",".join(['"'+i+'"' for i in names])
taghint = "*"
types = {"line":"line","polygon":"area", "point":"node"}
adp = ""
if "get_sql_hints" in dir(style):
sql_hint = style.get_sql_hints(types[vec], zoom)
adp = []
for tp in sql_hint:
add = []
for j in tp[0]:
if j not in names:
break
else:
add.append(tp[1])
if add:
add = " OR ".join(add)
add = "("+add+")"
adp.append(add)
adp = " OR ".join(adp)
if adp:
adp = adp.replace("&lt;", "<")
adp = adp.replace("&gt;", ">")
if vec == "polygon":
query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s,
ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_PointOnSurface(way)),%s,%s,%s,%s),0) as reprpoint, %s from
(select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s, %s from
(select ST_Union(way) as %s, %s from
(select ST_Buffer(way, %s) as %s, %s from
%s
where (%s)
and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
and way_area > %s
) p
group by %s
) p
where ST_Area(way) > %s
order by ST_Area(way)
) p
"""%(bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn,
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
names,
pixel_size_at_zoom(zoom, pxtolerance),pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn, names,
geomcolumn, names,
pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn, names,
table[vec],
adp,
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
(pixel_size_at_zoom(zoom, pxtolerance)**2)/pxtolerance,
names,
pixel_size_at_zoom(zoom, pxtolerance)**2
)
elif vec == "line":
query = """select ST_AsGeoJSON(ST_TransScale(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)),%s,%s,%s,%s),0) as %s, %s from
(select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_LineMerge(way),%s)))).geom as %s, %s from
(select ST_Union(way) as %s, %s from
%s
where (%s)
and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
group by %s
) p
) p
"""%(bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn, names,
pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn, names,
geomcolumn, names,
table[vec],
adp,
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
names,
)
elif vec == "point":
query = """select ST_AsGeoJSON(ST_TransScale(way,%s,%s,%s,%s),0) as %s, %s
from %s where
(%s)
and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
limit 10000
"""%(
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn, names,
table[vec],
adp,
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
)
elif vec == "coastline":
query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s, 'coastline' as "natural" from
(select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s from
(select ST_Union(way) as %s from
(select ST_Buffer(SetSRID(the_geom,900913), %s) as %s from
%s
where
SetSRID(the_geom,900913) && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
) p
) p
where ST_Area(way) > %s
) p
"""%(bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn,
pixel_size_at_zoom(zoom, pxtolerance),pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn,
geomcolumn,
pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn,
table[vec],
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
pixel_size_at_zoom(zoom, pxtolerance)**2
)
#print query
a = psycopg2.connect(database)
b = a.cursor()
b.execute(query)
names = [q[0] for q in b.description]
for i in ignore_columns:
if i in names:
names.remove(i)
names = ",".join(['"'+i+'"' for i in names])
ROWS_FETCHED = 0
polygons = []
taghint = "*"
types = {"line":"line","polygon":"area", "point":"node"}
adp = ""
if "get_sql_hints" in dir(style):
sql_hint = style.get_sql_hints(types[vec], zoom)
adp = []
for tp in sql_hint:
add = []
for j in tp[0]:
if j not in names:
break
else:
add.append(tp[1])
if add:
add = " OR ".join(add)
add = "("+add+")"
adp.append(add)
adp = " OR ".join(adp)
if adp:
adp = adp.replace("&lt;", "<")
adp = adp.replace("&gt;", ">")
if vec == "polygon":
query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s,
ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_PointOnSurface(way)),%s,%s,%s,%s),0) as reprpoint, %s from
(select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s, %s from
(select ST_Union(way) as %s, %s from
(select ST_Buffer(way, %s) as %s, %s from
%s
where (%s)
and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
and way_area > %s
) p
group by %s
) p
where ST_Area(way) > %s
order by ST_Area(way)
) p
"""%(bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn,
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
names,
pixel_size_at_zoom(zoom, pxtolerance),pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn, names,
geomcolumn, names,
pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn, names,
table[vec],
adp,
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
(pixel_size_at_zoom(zoom, pxtolerance)**2)/pxtolerance,
names,
pixel_size_at_zoom(zoom, pxtolerance)**2
)
elif vec == "line":
query = """select ST_AsGeoJSON(ST_TransScale(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)),%s,%s,%s,%s),0) as %s, %s from
(select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_LineMerge(way),%s)))).geom as %s, %s from
(select ST_Union(way) as %s, %s from
%s
where (%s)
and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
group by %s
) p
) p
"""%(bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn, names,
pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn, names,
geomcolumn, names,
table[vec],
adp,
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
names,
)
elif vec == "point":
query = """select ST_AsGeoJSON(ST_TransScale(way,%s,%s,%s,%s),0) as %s, %s
from %s where
(%s)
and way && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
limit 10000
"""%(
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn, names,
table[vec],
adp,
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
)
elif vec == "coastline":
query = """select ST_AsGeoJSON(ST_TransScale(ST_ForceRHR(ST_Intersection(way,SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913))),%s,%s,%s,%s),0) as %s, 'coastline' as "natural" from
(select (ST_Dump(ST_Multi(ST_SimplifyPreserveTopology(ST_Buffer(way,-%s),%s)))).geom as %s from
(select ST_Union(way) as %s from
(select ST_Buffer(SetSRID(the_geom,900913), %s) as %s from
%s
where
SetSRID(the_geom,900913) && SetSRID('BOX3D(%s %s,%s %s)'::box3d,900913)
) p
) p
where ST_Area(way) > %s
) p
"""%(bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
-bbox_p[0],-bbox_p[1],intscalefactor/(bbox_p[2]-bbox_p[0]),intscalefactor/(bbox_p[3]-bbox_p[1]),
geomcolumn,
pixel_size_at_zoom(zoom, pxtolerance),pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn,
geomcolumn,
pixel_size_at_zoom(zoom, pxtolerance),
geomcolumn,
table[vec],
bbox_p[0],bbox_p[1],bbox_p[2],bbox_p[3],
pixel_size_at_zoom(zoom, pxtolerance)**2
)
#print query
a = psycopg2.connect(database)
b = a.cursor()
b.execute(query)
names = [q[0] for q in b.description]
ROWS_FETCHED = 0
polygons = []
for row in b.fetchall():
ROWS_FETCHED += 1
geom = dict(map(None,names,row))
for t in geom.keys():
if not geom[t]:
del geom[t]
geojson = json.loads(geom[geomcolumn])
del geom[geomcolumn]
if geojson["type"] == "GeometryCollection":
continue
if "reprpoint" in geom:
geojson["reprpoint"] = json.loads(geom["reprpoint"])["coordinates"]
del geom["reprpoint"]
prop = {}
for k,v in geom.iteritems():
prop[k] = v
try:
if int(v) == float(v):
prop[k] = int(v)
else:
prop[k] = float(v)
if str(prop[k]) != v: # leading zeros etc.. should be saved
prop[k] = v
except:
pass
geojson["properties"] = prop
polygons.append(geojson)
return {"bbox": bbox, "granularity":intscalefactor, "features":polygons}
for row in b.fetchall():
ROWS_FETCHED += 1
geom = dict(map(None,names,row))
for t in geom.keys():
if not geom[t]:
del geom[t]
geojson = json.loads(geom[geomcolumn])
del geom[geomcolumn]
if geojson["type"] == "GeometryCollection":
continue
if "reprpoint" in geom:
geojson["reprpoint"] = json.loads(geom["reprpoint"])["coordinates"]
del geom["reprpoint"]
prop = {}
for k,v in geom.iteritems():
prop[k] = v
try:
if int(v) == float(v):
prop[k] = int(v)
else:
prop[k] = float(v)
if str(prop[k]) != v: # leading zeros etc.. should be saved
prop[k] = v
except:
pass
geojson["properties"] = prop
polygons.append(geojson)
return {"bbox": bbox, "granularity":intscalefactor, "features":polygons}
@ -203,19 +203,19 @@ print
form = cgi.FieldStorage()
if "z" not in form:
print "need z"
exit()
print "need z"
exit()
if "x" not in form:
print "need x"
exit()
print "need x"
exit()
if "y" not in form:
print "need y"
exit()
print "need y"
exit()
z = int(form["z"].value)
x = int(form["x"].value)
y = int(form["y"].value)
if z>22:
exit()
exit()
callback = "onKothicDataResponse"
bbox = projections.bbox_by_tile(z+1,x,y,"EPSG:3857")
@ -235,13 +235,12 @@ dir = "/var/www/vtile/%s/%s/"%(z,x)
file = "%s.js"%y
try:
if not os.path.exists(dir):
os.makedirs(dir)
if not os.path.exists(dir):
os.makedirs(dir)
except:
pass
pass
file = open(dir+file,"w")
file.write(aaaa)
file.flush()
file.close()

View file

@ -43,349 +43,349 @@ substyles = []
last_id = 0
def get_id(i = 0):
global last_id
last_id += i
return last_id
global last_id
last_id += i
return last_id
def zoom_to_scaledenom(z1,z2=False):
"""
Converts zoom level to mapnik's scaledenominator pair for EPSG:3857
"""
if not z2:
z2 = z1
s = 279541132.014
z1 = (s/(2**(z1-1))+s/(2**(z1-2)))/2
z2 = (s/(2**(z2-1))+s/(2**z2))/2
#return 100000000000000, 1
return z1, z2
"""
Converts zoom level to mapnik's scaledenominator pair for EPSG:3857
"""
if not z2:
z2 = z1
s = 279541132.014
z1 = (s/(2**(z1-1))+s/(2**(z1-2)))/2
z2 = (s/(2**(z2-1))+s/(2**z2))/2
#return 100000000000000, 1
return z1, z2
def pixel_size_at_zoom(z, l=1):
"""
Converts l pixels on tiles into length on zoom z
"""
return int(math.ceil(l* 20037508.342789244 / 256 * 2 / (2**z)))
"""
Converts l pixels on tiles into length on zoom z
"""
return int(math.ceil(l* 20037508.342789244 / 256 * 2 / (2**z)))
def xml_fontset(name, unicode=True):
if unicode:
unicode = '<Font face-name="unifont Medium" />'
return """
<FontSet name="%s">
<Font face-name="%s" />
%s
</FontSet>"""%(name, name, unicode)
if unicode:
unicode = '<Font face-name="unifont Medium" />'
return """
<FontSet name="%s">
<Font face-name="%s" />
%s
</FontSet>"""%(name, name, unicode)
def xml_pointsymbolizer(path="", width="", height="", opacity=1, overlap="false"):
if width:
width =' width="%s" '%width
if height:
height =' height="%s" '%height
return """
<PointSymbolizer file="%s" %s %s opacity="%s" allow-overlap="%s" />"""\
%(os.path.join(icons_path, path), width, height, opacity, overlap)
if width:
width =' width="%s" '%width
if height:
height =' height="%s" '%height
return """
<PointSymbolizer file="%s" %s %s opacity="%s" allow-overlap="%s" />"""\
%(os.path.join(icons_path, path), width, height, opacity, overlap)
def xml_linesymbolizer(color="#000000", width="1", opacity="1", linecap="butt", linejoin="round", dashes="", smooth=0, zoom=200):
color = nicecolor(color)
linecap = {"none":"butt",}.get(linecap.lower(), linecap)
color = nicecolor(color)
linecap = {"none":"butt",}.get(linecap.lower(), linecap)
if dashes:
dashes = 'stroke-dasharray="%s"'%(dashes)
else:
dashes = ""
if dashes:
dashes = 'stroke-dasharray="%s"'%(dashes)
else:
dashes = ""
if smooth:
smooth = 'smooth="%s"'%(smooth)
else:
smooth = ""
if smooth:
smooth = 'smooth="%s"'%(smooth)
else:
smooth = ""
rasterizer = ""
rasterizer = ""
# if float(width) < 4 and not dashes and zoom < 6:
# rasterizer = ' rasterizer="fast"'
return """
<LineSymbolizer %s %s stroke="%s" stroke-width="%s" stroke-opacity="%s" stroke-linejoin="%s" stroke-linecap="%s" %s/>"""%(rasterizer, smooth, color, float(width), float(opacity), linejoin, linecap, dashes)
return """
<LineSymbolizer %s %s stroke="%s" stroke-width="%s" stroke-opacity="%s" stroke-linejoin="%s" stroke-linecap="%s" %s/>"""%(rasterizer, smooth, color, float(width), float(opacity), linejoin, linecap, dashes)
def xml_polygonsymbolizer(color="#000000", opacity="1", smooth='0'):
color = nicecolor(color)
if smooth:
smooth = 'smooth="%s"'%(smooth)
else:
smooth = ""
return """
<PolygonSymbolizer fill="%s" fill-opacity="%s" gamma="0.73" %s />"""%(color, float(opacity), smooth)
color = nicecolor(color)
if smooth:
smooth = 'smooth="%s"'%(smooth)
else:
smooth = ""
return """
<PolygonSymbolizer fill="%s" fill-opacity="%s" gamma="0.73" %s />"""%(color, float(opacity), smooth)
def xml_polygonpatternsymbolizer(file=""):
return """
<PolygonPatternSymbolizer file="%s"/>"""%(os.path.join(icons_path,file))
return """
<PolygonPatternSymbolizer file="%s"/>"""%(os.path.join(icons_path,file))
def xml_linepatternsymbolizer(file=""):
return """
<LinePatternSymbolizer file="%s"/>"""%(os.path.join(icons_path,file))
return """
<LinePatternSymbolizer file="%s"/>"""%(os.path.join(icons_path,file))
def xml_textsymbolizer(
text="name",face="DejaVu Sans Book",size="10",color="#000000", halo_color="#ffffff", halo_radius="0", placement="line", offset="0", overlap="false", distance="26", wrap_width=256, align="center", opacity="1", pos="X", transform = "none", spacing="4096"):
color = nicecolor(color)
halo_color = nicecolor(halo_color)
pos = pos.replace("exact", "X").replace("any","S, E, X, N, W, NE, SE, NW, SW").split(",")
pos.extend([str(int(float(x)*text_scale)) for x in size.split(",")])
pos = ",".join(pos)
size = str(int(float(size.split(",")[0])*text_scale))
placement = {"center": "interior"}.get(placement.lower(), placement)
align = {"center": "middle"}.get(align.lower(), align)
dy = int(float(offset))
dx = 0
if align in ("right",'left'):
dx = dy
dy = 0
return """
<TextSymbolizer fontset-name="%s" size="%s" fill="%s" halo-fill= "%s" halo-radius="%s" placement="%s" dx="%s" dy="%s" max-char-angle-delta="17" allow-overlap="%s" wrap-width="%s" minimum-distance="%s" vertical-alignment="middle" horizontal-alignment="%s" opacity="%s" placement-type="simple" placements="%s" text-transform="%s" minimum-path-length="5" spacing="%s">[%s]</TextSymbolizer>
"""%(face,int(float(size)),color,halo_color,halo_radius,placement,dx,dy,overlap,wrap_width,distance,align,opacity,pos, transform, spacing,text)
color = nicecolor(color)
halo_color = nicecolor(halo_color)
pos = pos.replace("exact", "X").replace("any","S, E, X, N, W, NE, SE, NW, SW").split(",")
pos.extend([str(int(float(x)*text_scale)) for x in size.split(",")])
pos = ",".join(pos)
size = str(int(float(size.split(",")[0])*text_scale))
placement = {"center": "interior"}.get(placement.lower(), placement)
align = {"center": "middle"}.get(align.lower(), align)
dy = int(float(offset))
dx = 0
if align in ("right",'left'):
dx = dy
dy = 0
return """
<TextSymbolizer fontset-name="%s" size="%s" fill="%s" halo-fill= "%s" halo-radius="%s" placement="%s" dx="%s" dy="%s" max-char-angle-delta="17" allow-overlap="%s" wrap-width="%s" minimum-distance="%s" vertical-alignment="middle" horizontal-alignment="%s" opacity="%s" placement-type="simple" placements="%s" text-transform="%s" minimum-path-length="5" spacing="%s">[%s]</TextSymbolizer>
"""%(face,int(float(size)),color,halo_color,halo_radius,placement,dx,dy,overlap,wrap_width,distance,align,opacity,pos, transform, spacing,text)
def xml_shieldsymbolizer(path="", width="", height="",
text="name",face="DejaVu Sans Book",size="10",color="#000000", halo_color="#ffffff", halo_radius="0", placement="line", offset="0", overlap="false", distance="26", wrap_width=256, align="center", opacity="1", transform="none", unlock_image='true', spacing='500'):
color = nicecolor(color)
halo_color = nicecolor(halo_color)
placement = {"center": "point"}.get(placement.lower(), placement)
align = {"center": "middle"}.get(align.lower(), align)
size = size.split(",")[0]
if width:
width =' width="%s" '%width
if height:
height =' height="%s" '%height
return """
<ShieldSymbolizer file="%s%s" %s %s fontset-name="%s" size="%s" fill="%s" halo-fill= "%s" halo-radius="%s" placement="%s" dy="%s" allow-overlap="%s" wrap-width="%s" minimum-distance="%s" horizontal-alignment="%s" opacity="%s" text-transform="%s" unlock-image="%s" spacing="%s">[%s]</ShieldSymbolizer>
"""%(icons_path, \
path, width, height,face,int(float(size)*text_scale),color,halo_color,halo_radius,placement,offset,overlap,wrap_width,distance,align,opacity, transform, unlock_image, spacing,text )
color = nicecolor(color)
halo_color = nicecolor(halo_color)
placement = {"center": "point"}.get(placement.lower(), placement)
align = {"center": "middle"}.get(align.lower(), align)
size = size.split(",")[0]
if width:
width =' width="%s" '%width
if height:
height =' height="%s" '%height
return """
<ShieldSymbolizer file="%s%s" %s %s fontset-name="%s" size="%s" fill="%s" halo-fill= "%s" halo-radius="%s" placement="%s" dy="%s" allow-overlap="%s" wrap-width="%s" minimum-distance="%s" horizontal-alignment="%s" opacity="%s" text-transform="%s" unlock-image="%s" spacing="%s">[%s]</ShieldSymbolizer>
"""%(icons_path, \
path, width, height,face,int(float(size)*text_scale),color,halo_color,halo_radius,placement,offset,overlap,wrap_width,distance,align,opacity, transform, unlock_image, spacing,text )
def xml_filter(string):
return """
<Filter>%s</Filter>"""%string
return """
<Filter>%s</Filter>"""%string
def xml_scaledenominator(z1, z2=False):
zz1, zz2 = zoom_to_scaledenom(z1,z2)
return """
<MaxScaleDenominator>%s</MaxScaleDenominator>
<MinScaleDenominator>%s</MinScaleDenominator><!-- z%s-%s -->"""%(zz1,zz2,z1,z2)
zz1, zz2 = zoom_to_scaledenom(z1,z2)
return """
<MaxScaleDenominator>%s</MaxScaleDenominator>
<MinScaleDenominator>%s</MinScaleDenominator><!-- z%s-%s -->"""%(zz1,zz2,z1,z2)
def xml_start(bgcolor="transparent"):
if bgcolor != "transparent":
bgcolor = nicecolor(bgcolor)
return """<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<Map background-color="%s" srs="%s" minimum-version="0.7.1" buffer-size="512" maximum-extent="-20037508.342789244,-20037508.342780735,20037508.342789244,20037508.342780709" >
"""%(bgcolor, map_proj)
if bgcolor != "transparent":
bgcolor = nicecolor(bgcolor)
return """<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<Map background-color="%s" srs="%s" minimum-version="0.7.1" buffer-size="512" maximum-extent="-20037508.342789244,-20037508.342780735,20037508.342789244,20037508.342780709" >
"""%(bgcolor, map_proj)
def xml_end():
return """
</Map>"""
return """
</Map>"""
def xml_style_start():
global substyles
layer_id = get_id(1)
substyles.append(layer_id)
return """
<Style name="s%s">"""%(layer_id)
global substyles
layer_id = get_id(1)
substyles.append(layer_id)
return """
<Style name="s%s">"""%(layer_id)
def xml_style_end():
return """
</Style>"""
return """
</Style>"""
def xml_rule_start():
return """
<Rule>"""
return """
<Rule>"""
def xml_rule_end():
return """
</Rule>"""
return """
</Rule>"""
def xml_cleantopo(zoom, x_scale, demramp):
return """
<Style name="elevation1z%s">
<Rule>%s
<RasterSymbolizer mesh-size="1">
<RasterColorizer default-mode="linear" epsilon="0.001">
%s
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
return """
<Style name="elevation1z%s">
<Rule>%s
<RasterSymbolizer mesh-size="1">
<RasterColorizer default-mode="linear" epsilon="0.001">
%s
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
<Layer name="ele-raster1z%s">
<StyleName>elevation1z%s</StyleName>
<Datasource>
<Parameter name="file">%s</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
<Parameter name="srid">3857</Parameter>
</Datasource>
</Layer>
""" % (zoom, x_scale, demramp, zoom, zoom, cleantopo_dem_path)
<Layer name="ele-raster1z%s">
<StyleName>elevation1z%s</StyleName>
<Datasource>
<Parameter name="file">%s</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
<Parameter name="srid">3857</Parameter>
</Datasource>
</Layer>
""" % (zoom, x_scale, demramp, zoom, zoom, cleantopo_dem_path)
def xml_srtm(zoom, x_scale, demramp):
return """
<Style name="elevationz%s">
<Rule>%s
<RasterSymbolizer mesh-size="1">
<RasterColorizer default-mode="linear" epsilon="0.001">
%s
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
return """
<Style name="elevationz%s">
<Rule>%s
<RasterSymbolizer mesh-size="1">
<RasterColorizer default-mode="linear" epsilon="0.001">
%s
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
<Layer name="ele-rasterz%s">
<StyleName>elevationz%s</StyleName>
<Datasource>
<Parameter name="file">%s</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
<Parameter name="srid">3857</Parameter>
</Datasource>
</Layer>
""" % (zoom, x_scale, demramp, zoom, zoom, srtm_dem_path)
<Layer name="ele-rasterz%s">
<StyleName>elevationz%s</StyleName>
<Datasource>
<Parameter name="file">%s</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
<Parameter name="srid">3857</Parameter>
</Datasource>
</Layer>
""" % (zoom, x_scale, demramp, zoom, zoom, srtm_dem_path)
def xml_hillshade(zoom, x_scale):
hs_path = cleantopo_hs_path
if zoom>6:
hs_path = srtm_hs_path
return """
<Style name="hillshade%s">
<Rule>%s
<RasterSymbolizer opacity="0.3" mesh-size="1">
<RasterColorizer default-mode="linear">
<stop value="0" color="rgba(0,0,0,1)" />
<stop value="128" color="rgba(128,128,128,0.4)" />
<stop value="255" color="rgba(255,255,255,1)" />
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
hs_path = cleantopo_hs_path
if zoom>6:
hs_path = srtm_hs_path
return """
<Style name="hillshade%s">
<Rule>%s
<RasterSymbolizer opacity="0.3" mesh-size="1">
<RasterColorizer default-mode="linear">
<stop value="0" color="rgba(0,0,0,1)" />
<stop value="128" color="rgba(128,128,128,0.4)" />
<stop value="255" color="rgba(255,255,255,1)" />
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
<Layer name="ele-hsz%s">
<StyleName>hillshade%s</StyleName>
<Datasource>
<Parameter name="file">%s</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
<Parameter name="srid">3857</Parameter>
</Datasource>
</Layer>
""" % (zoom, x_scale, zoom, zoom, hs_path)
<Layer name="ele-hsz%s">
<StyleName>hillshade%s</StyleName>
<Datasource>
<Parameter name="file">%s</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
<Parameter name="srid">3857</Parameter>
</Datasource>
</Layer>
""" % (zoom, x_scale, zoom, zoom, hs_path)
def xml_hardcoded_arrows():
return """
<LineSymbolizer stroke="#6c70d5" stroke-width="1" stroke-linejoin="bevel" stroke-dasharray="0,12,10,152" />
<LineSymbolizer stroke="#6c70d5" stroke-width="2" stroke-linejoin="bevel" stroke-dasharray="0,12,9,153" />
<LineSymbolizer stroke="#6c70d5" stroke-width="3" stroke-linejoin="bevel" stroke-dasharray="0,18,2,154" />
<LineSymbolizer stroke="#6c70d5" stroke-width="4" stroke-linejoin="bevel" stroke-dasharray="0,18,1,155" />
"""
return """
<LineSymbolizer stroke="#6c70d5" stroke-width="1" stroke-linejoin="bevel" stroke-dasharray="0,12,10,152" />
<LineSymbolizer stroke="#6c70d5" stroke-width="2" stroke-linejoin="bevel" stroke-dasharray="0,12,9,153" />
<LineSymbolizer stroke="#6c70d5" stroke-width="3" stroke-linejoin="bevel" stroke-dasharray="0,18,2,154" />
<LineSymbolizer stroke="#6c70d5" stroke-width="4" stroke-linejoin="bevel" stroke-dasharray="0,18,1,155" />
"""
def xml_layer(type="postgis", geom="point", interesting_tags = "*", sql = "true", zoom=0 ):
layer_id = get_id(1)
global substyles
subs = "\n".join(["<StyleName>s%s</StyleName>"%i for i in substyles])
substyles = []
intersection_SQL = ""
if zoom < 5:
intersection_SQL = '<Parameter name="intersect_max_scale">1</Parameter>'
elif zoom > 16:
intersection_SQL = '<Parameter name="intersect_min_scale">500000000000</Parameter>'
if type == "postgis":
waystring = 'way'
if zoom < 10:
waystring = "ST_Simplify(way, %s) as way"%(pixel_size_at_zoom(zoom,0.6))
if zoom >= 5:
sql = 'way &amp;&amp; !bbox! and '+ sql
if geom == "polygon":
sql = 'way_area &gt; %s and '%(pixel_size_at_zoom(zoom,0.1)**2)+ sql
interesting_tags = list(interesting_tags)
if '"' not in "".join(interesting_tags) and "->" not in "".join(interesting_tags):
interesting_tags = "\", \"".join(interesting_tags)
interesting_tags = "\""+ interesting_tags+"\""
else:
interesting_tags = ", ".join(interesting_tags)
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="table">
( -- zoom %s
select %s, %s
from %s%s
where %s
) as k_layer
</Parameter>
%s
<Parameter name="type">postgis</Parameter>
<Parameter name="st_prefix">true</Parameter>
<Parameter name="user">%s</Parameter>
<Parameter name="dbname">%s</Parameter>
<Parameter name="srid">%s</Parameter>
<Parameter name="geometry_field">way</Parameter>
<Parameter name="geometry_table">%s%s</Parameter>
<Parameter name="estimate_extent">false</Parameter>
<Parameter name="extent">-20037508.342789244, -20037508.342780735, 20037508.342789244, 20037508.342780709</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, zoom, interesting_tags, waystring, table_prefix, geom, sql, intersection_SQL, db_user, db_name, db_srid, table_prefix, geom)
elif type == "postgis-process":
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="table">
( -- zoom %s
%s
) as k_layer
</Parameter>
%s
<Parameter name="type">postgis</Parameter>
<Parameter name="st_prefix">true</Parameter>
<Parameter name="user">%s</Parameter>
<Parameter name="dbname">%s</Parameter>
<Parameter name="srid">%s</Parameter>
<Parameter name="geometry_field">way</Parameter>
<Parameter name="geometry_table">%s%s</Parameter>
<Parameter name="estimate_extent">false</Parameter>
<Parameter name="extent">-20037508.342789244, -20037508.342780735, 20037508.342789244, 20037508.342780709</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, zoom, sql, intersection_SQL, db_user, db_name, db_srid, table_prefix, geom)
elif type == "coast":
if zoom < 9:
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">%sshoreline_300</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, world_bnd_path)
else:
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">%sprocessed_p</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, world_bnd_path)
layer_id = get_id(1)
global substyles
subs = "\n".join(["<StyleName>s%s</StyleName>"%i for i in substyles])
substyles = []
intersection_SQL = ""
if zoom < 5:
intersection_SQL = '<Parameter name="intersect_max_scale">1</Parameter>'
elif zoom > 16:
intersection_SQL = '<Parameter name="intersect_min_scale">500000000000</Parameter>'
if type == "postgis":
waystring = 'way'
if zoom < 10:
waystring = "ST_Simplify(way, %s) as way"%(pixel_size_at_zoom(zoom,0.6))
if zoom >= 5:
sql = 'way &amp;&amp; !bbox! and '+ sql
if geom == "polygon":
sql = 'way_area &gt; %s and '%(pixel_size_at_zoom(zoom,0.1)**2)+ sql
interesting_tags = list(interesting_tags)
if '"' not in "".join(interesting_tags) and "->" not in "".join(interesting_tags):
interesting_tags = "\", \"".join(interesting_tags)
interesting_tags = "\""+ interesting_tags+"\""
else:
interesting_tags = ", ".join(interesting_tags)
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="table">
( -- zoom %s
select %s, %s
from %s%s
where %s
) as k_layer
</Parameter>
%s
<Parameter name="type">postgis</Parameter>
<Parameter name="st_prefix">true</Parameter>
<Parameter name="user">%s</Parameter>
<Parameter name="dbname">%s</Parameter>
<Parameter name="srid">%s</Parameter>
<Parameter name="geometry_field">way</Parameter>
<Parameter name="geometry_table">%s%s</Parameter>
<Parameter name="estimate_extent">false</Parameter>
<Parameter name="extent">-20037508.342789244, -20037508.342780735, 20037508.342789244, 20037508.342780709</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, zoom, interesting_tags, waystring, table_prefix, geom, sql, intersection_SQL, db_user, db_name, db_srid, table_prefix, geom)
elif type == "postgis-process":
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="table">
( -- zoom %s
%s
) as k_layer
</Parameter>
%s
<Parameter name="type">postgis</Parameter>
<Parameter name="st_prefix">true</Parameter>
<Parameter name="user">%s</Parameter>
<Parameter name="dbname">%s</Parameter>
<Parameter name="srid">%s</Parameter>
<Parameter name="geometry_field">way</Parameter>
<Parameter name="geometry_table">%s%s</Parameter>
<Parameter name="estimate_extent">false</Parameter>
<Parameter name="extent">-20037508.342789244, -20037508.342780735, 20037508.342789244, 20037508.342780709</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, zoom, sql, intersection_SQL, db_user, db_name, db_srid, table_prefix, geom)
elif type == "coast":
if zoom < 9:
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">%sshoreline_300</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, world_bnd_path)
else:
return """
<Layer name="l%s" status="on" srs="%s">
%s
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">%sprocessed_p</Parameter>
</Datasource>
</Layer>"""%(layer_id, db_proj, subs, world_bnd_path)
def xml_nolayer():
global substyles
substyles = []
global substyles
substyles = []
def xml_nosubstyle():
global substyles
substyles = substyles[:-1]
global substyles
substyles = substyles[:-1]

View file

@ -24,8 +24,8 @@ from mapcss import MapCSS
langs = ['int_name', 'name:af', 'name:am', 'name:ar', 'name:be', 'name:bg', 'name:br', 'name:ca', 'name:cs', 'name:cy', 'name:de', 'name:el', 'name:en', 'name:eo', 'name:es', 'name:et', 'name:eu', 'name:fa', 'name:fi', 'name:fr', 'name:fur', 'name:fy', 'name:ga', 'name:gd', 'name:gsw', 'name:he', 'name:hi', 'name:hr', 'name:hsb', 'name:hu', 'name:hy', 'name:it', 'name:ja', 'name:ja_kana', 'name:ja_rm', 'name:ka', 'name:kk', 'name:kn', 'name:ko', 'name:ko_rm', 'name:ku', 'name:la', 'name:lb', 'name:lt', 'name:lv', 'name:mk', 'name:mn', 'name:nl', 'name:pl', 'name:pt', 'name:ro', 'name:ru', 'name:sk', 'name:sl', 'name:sq', 'name:sr', 'name:sv', 'name:th', 'name:tr', 'name:uk', 'name:vi', 'name:zh', 'name:zh_pinyin']
if len(sys.argv) < 2:
print "Usage: make_postgis_style.py [stylesheet] [additional_tag,tag2,tag3]"
exit()
print "Usage: make_postgis_style.py [stylesheet] [additional_tag,tag2,tag3]"
exit()
style = MapCSS(1, 19) #zoom levels
style.parse(open(sys.argv[1],"r").read())
@ -33,33 +33,33 @@ style.parse(open(sys.argv[1],"r").read())
dct = {}
if len(sys.argv) >= 3:
langs.extend(sys.argv[2].split(","))
dct = dict([(k,set([("node", "linear"), ('way', 'linear')])) for k in langs])
langs.extend(sys.argv[2].split(","))
dct = dict([(k,set([("node", "linear"), ('way', 'linear')])) for k in langs])
t = {"node":("node", "linear"), "line":("way", "linear"), "area":("way", "polygon")}
for a in t:
for tag in style.get_interesting_tags(type=a):
if tag not in dct:
dct[tag] = set()
dct[tag].add(t[a])
for tag in style.get_interesting_tags(type=a):
if tag not in dct:
dct[tag] = set()
dct[tag].add(t[a])
print """
# OsmType Tag DataType Flags"""
for t in ("z_order","way_area",":area"):
if t in dct:
del dct[t]
if t in dct:
del dct[t]
keys = dct.keys()
keys.sort()
for k in keys:
v = dct[k]
s = ",".join(set([i[0] for i in v]))
pol = "linear"
if "polygon" in set([i[1] for i in v]):
pol = "polygon"
print "%-10s %-20s %-13s %s"%(s, k, "text", pol)
v = dct[k]
s = ",".join(set([i[0] for i in v]))
pol = "linear"
if "polygon" in set([i[1] for i in v]):
pol = "polygon"
print "%-10s %-20s %-13s %s"%(s, k, "text", pol)
print """
node,way z_order int4 linear # This is calculated during import
way way_area real # This is calculated during import"""

View file

@ -23,13 +23,13 @@ from twms import projections
from style import Styling
reload(sys)
sys.setdefaultencoding("utf-8") # a hack to support UTF-8
sys.setdefaultencoding("utf-8") # a hack to support UTF-8
try:
import psyco
psyco.full()
import psyco
psyco.full()
except ImportError:
pass
pass
MAXZOOM = 16
TEMPORARY_FILE_PATH = 'temp_file.bin'
@ -41,179 +41,179 @@ style = Styling()
# elsif($k eq 'highway' and $v eq 'footway' or $v eq 'path' or $v eq 'track'){
def tilelist_by_geometry(way, start_zoom = 0, ispoly = False):
"""
Gives a number of (z,x,y) tile numbers that geometry crosses.
"""
ret = set([])
tiles_by_zooms = {} # zoom: set(tile,tile,tile...)
for t in xrange(0,MAXZOOM+1):
tiles_by_zooms[t] = set([])
for point in way:
tile = projections.tile_by_coords(point, MAXZOOM, proj)
tile = (MAXZOOM, int(tile[0]),int(tile[1]))
tiles_by_zooms[MAXZOOM].add(tile)
for t in xrange(MAXZOOM-1,start_zoom-1,-1):
for tt in tiles_by_zooms[t+1]:
tiles_by_zooms[t].add((t, int(tt[1]/2), int(tt[2]/2)))
for z in tiles_by_zooms.values():
ret.update(z)
return ret
"""
Gives a number of (z,x,y) tile numbers that geometry crosses.
"""
ret = set([])
tiles_by_zooms = {} # zoom: set(tile,tile,tile...)
for t in xrange(0,MAXZOOM+1):
tiles_by_zooms[t] = set([])
for point in way:
tile = projections.tile_by_coords(point, MAXZOOM, proj)
tile = (MAXZOOM, int(tile[0]),int(tile[1]))
tiles_by_zooms[MAXZOOM].add(tile)
for t in xrange(MAXZOOM-1,start_zoom-1,-1):
for tt in tiles_by_zooms[t+1]:
tiles_by_zooms[t].add((t, int(tt[1]/2), int(tt[2]/2)))
for z in tiles_by_zooms.values():
ret.update(z)
return ret
def pix_distance(a,b,z):
"""
Calculates onscreen distance between 2 points on given zoom.
"""
return 2**z*256*(((a[0]-b[0])/360.)**2+((a[1]-b[1])/180.)**2)**0.5
"""
Calculates onscreen distance between 2 points on given zoom.
"""
return 2**z*256*(((a[0]-b[0])/360.)**2+((a[1]-b[1])/180.)**2)**0.5
def sanitize(string):
string=string.replace(" ", "_")
string=string.replace(";", ",")
string=string.replace("=", "###")
return string
string=string.replace(" ", "_")
string=string.replace(";", ",")
string=string.replace("=", "###")
return string
print sanitize (" ;=")
def initDB(filename):
conn = sqlite3.connect(filename)
c = conn.cursor()
# create table
c.execute('''CREATE TABLE nodes (id integer, lat real, lon real)''')
# create index in the id column
# - this makes node id lookup MUCH faster
c.execute('''CREATE INDEX id_idx ON nodes(id)''')
return conn
conn = sqlite3.connect(filename)
c = conn.cursor()
# create table
c.execute('''CREATE TABLE nodes (id integer, lat real, lon real)''')
# create index in the id column
# - this makes node id lookup MUCH faster
c.execute('''CREATE INDEX id_idx ON nodes(id)''')
return conn
def storeNode(conn, id, lat, lon):
# conn.execute("INSERT INTO nodes VALUES ('%d', %f, %f)" % (id, lat, lon))
conn.execute("INSERT INTO nodes(id, lat, lon) values (?, ?, ?)", (id, lat, lon))
conn.execute("INSERT INTO nodes(id, lat, lon) values (?, ?, ?)", (id, lat, lon))
def getNode(conn, id):
# conn.execute("SELECT * FROM nodes WHERE id = '%s'" % id)
return conn.execute("SELECT lat, lon FROM nodes WHERE id = '%s'" % id).fetchone()
return conn.execute("SELECT lat, lon FROM nodes WHERE id = '%s'" % id).fetchone()
def main ():
DROPPED_POINTS = 0
WAYS_WRITTEN = 0
NODES_READ = 0
WAYS_READ = 0
tilefiles = {}
tilefiles_hist = []
#osm_infile = open("minsk.osm", "rb")
osm_infile = sys.stdin
DROPPED_POINTS = 0
WAYS_WRITTEN = 0
NODES_READ = 0
WAYS_READ = 0
tilefiles = {}
tilefiles_hist = []
#osm_infile = open("minsk.osm", "rb")
osm_infile = sys.stdin
# remove any stale temporary files
if os.path.exists(TEMPORARY_FILE_PATH):
os.remove(TEMPORARY_FILE_PATH)
conn = initDB(TEMPORARY_FILE_PATH)
# remove any stale temporary files
if os.path.exists(TEMPORARY_FILE_PATH):
os.remove(TEMPORARY_FILE_PATH)
conn = initDB(TEMPORARY_FILE_PATH)
# nodes = {}
curway = []
tags = {}
context = etree.iterparse(osm_infile)
for action, elem in context:
items = dict(elem.items())
if elem.tag == "node":
NODES_READ += 1
if NODES_READ % 10000 == 0:
print "Nodes read:", NODES_READ
print len(curway), len(tags), len(tilefiles), len(tilefiles_hist)
if NODES_READ % 100000 == 0:
conn.commit()
print "flushing to temporary storage"
curway = []
tags = {}
context = etree.iterparse(osm_infile)
for action, elem in context:
items = dict(elem.items())
if elem.tag == "node":
NODES_READ += 1
if NODES_READ % 10000 == 0:
print "Nodes read:", NODES_READ
print len(curway), len(tags), len(tilefiles), len(tilefiles_hist)
if NODES_READ % 100000 == 0:
conn.commit()
print "flushing to temporary storage"
# nodes[str(items["id"])] = (float(items["lon"]), float(items["lat"]))
storeNode(conn, int(items["id"]), float(items["lon"]), float(items["lat"]))
tags = {}
elif elem.tag == "nd":
result = getNode(conn, int(items["ref"]))
if result:
curway.append(result)
storeNode(conn, int(items["id"]), float(items["lon"]), float(items["lat"]))
tags = {}
elif elem.tag == "nd":
result = getNode(conn, int(items["ref"]))
if result:
curway.append(result)
# try:
# curway.append(nodes[str(items["ref"])])
# except KeyError:
# pass
elif elem.tag == "tag":
tags[sanitize(items["k"])] = sanitize(items["v"])
elif elem.tag == "way":
WAYS_READ += 1
if WAYS_READ % 1000 == 0:
print "Ways read:", WAYS_READ
mzoom = 1
#tags = style.filter_tags(tags)
if tags:
if True:#style.get_style("way", tags, True): # if way is stylized
towrite = ";".join(["%s=%s"%x for x in tags.iteritems()]) ### TODO: sanitize keys and values
#print towrite
way_simplified = {MAXZOOM: curway}
elif elem.tag == "tag":
tags[sanitize(items["k"])] = sanitize(items["v"])
elif elem.tag == "way":
WAYS_READ += 1
if WAYS_READ % 1000 == 0:
print "Ways read:", WAYS_READ
for zoom in xrange(MAXZOOM-1,-1,-1): ######## generalize a bit
# TODO: Douglas-Peucker
prev_point = curway[0]
way = [prev_point]
for point in way_simplified[zoom+1]:
if pix_distance(point, prev_point, zoom) > 1.5:
way.append(point)
prev_point = point
else:
DROPPED_POINTS += 1
mzoom = 1
#tags = style.filter_tags(tags)
if tags:
if True:#style.get_style("way", tags, True): # if way is stylized
towrite = ";".join(["%s=%s"%x for x in tags.iteritems()]) ### TODO: sanitize keys and values
#print towrite
way_simplified = {MAXZOOM: curway}
if len(way) == 1:
mzoom = zoom
#print zoom
break
if len(way) > 1:
way_simplified[zoom] = way
#print way
for tile in tilelist_by_geometry(curway, mzoom+1):
z, x, y = tile
path = "tiles/z%s/%s/x%s/%s/"%(z, x/1024, x, y/1024)
if tile not in tilefiles:
for zoom in xrange(MAXZOOM-1,-1,-1): ######## generalize a bit
# TODO: Douglas-Peucker
prev_point = curway[0]
way = [prev_point]
for point in way_simplified[zoom+1]:
if pix_distance(point, prev_point, zoom) > 1.5:
way.append(point)
prev_point = point
else:
DROPPED_POINTS += 1
if not os.path.exists(path):
os.makedirs(path)
tilefiles[tile] = open(path+"y"+str(y)+".vtile","wb")
tilefiles_hist.append(tile)
else:
if not tilefiles[tile]:
tilefiles[tile] = open(path+"y"+str(y)+".vtile","a")
tilefiles_hist.append(tile)
tilefiles_hist.remove(tile)
tilefiles_hist.append(tile)
print >>tilefiles[tile], "%s %s" % (towrite, items["id"]), " ".join([str(x[0])+" "+str(x[1]) for x in way_simplified[tile[0]]])
if len(tilefiles_hist) > 400:
print "Cleaned up tiles. Wrote by now:", len(tilefiles),"active:",len(tilefiles_hist)
for tile in tilefiles_hist[0:len(tilefiles_hist)-100]:
if len(way) == 1:
mzoom = zoom
#print zoom
break
if len(way) > 1:
way_simplified[zoom] = way
#print way
for tile in tilelist_by_geometry(curway, mzoom+1):
z, x, y = tile
path = "tiles/z%s/%s/x%s/%s/"%(z, x/1024, x, y/1024)
if tile not in tilefiles:
if not os.path.exists(path):
os.makedirs(path)
tilefiles[tile] = open(path+"y"+str(y)+".vtile","wb")
tilefiles_hist.append(tile)
else:
if not tilefiles[tile]:
tilefiles[tile] = open(path+"y"+str(y)+".vtile","a")
tilefiles_hist.append(tile)
tilefiles_hist.remove(tile)
tilefiles_hist.append(tile)
print >>tilefiles[tile], "%s %s" % (towrite, items["id"]), " ".join([str(x[0])+" "+str(x[1]) for x in way_simplified[tile[0]]])
if len(tilefiles_hist) > 400:
print "Cleaned up tiles. Wrote by now:", len(tilefiles),"active:",len(tilefiles_hist)
for tile in tilefiles_hist[0:len(tilefiles_hist)-100]:
tilefiles_hist.remove(tile)
tilefiles[tile].flush()
tilefiles[tile].close()
tilefiles[tile] = None
tilefiles_hist.remove(tile)
tilefiles[tile].flush()
tilefiles[tile].close()
tilefiles[tile] = None
#print >>corr, "%s %s %s %s %s %s"% (curway[0][0],curway[0][1],curway[1][0],curway[1][1], user, ts )
WAYS_WRITTEN += 1
if WAYS_WRITTEN % 10000 == 0:
print WAYS_WRITTEN
curway = []
tags = {}
elem.clear()
# extra insurance
del elem
#user = default_user
#ts = ""
print "Tiles generated:",len(tilefiles)
print "Nodes dropped when generalizing:", DROPPED_POINTS
#print >>corr, "%s %s %s %s %s %s"% (curway[0][0],curway[0][1],curway[1][0],curway[1][1], user, ts )
WAYS_WRITTEN += 1
if WAYS_WRITTEN % 10000 == 0:
print WAYS_WRITTEN
curway = []
tags = {}
elem.clear()
# extra insurance
del elem
#user = default_user
#ts = ""
print "Tiles generated:",len(tilefiles)
print "Nodes dropped when generalizing:", DROPPED_POINTS
# print "Nodes in memory:", len(nodes)
c = conn.cursor()
c.execute('SELECT * from nodes')
print "Nodes in memory:", len(c.fetchall())
c = conn.cursor()
c.execute('SELECT * from nodes')
print "Nodes in memory:", len(c.fetchall())
# report temporary file size
print "Temporary file size:", os.path.getsize(TEMPORARY_FILE_PATH)
# report temporary file size
print "Temporary file size:", os.path.getsize(TEMPORARY_FILE_PATH)
# remove temporary files
os.remove(TEMPORARY_FILE_PATH)
# remove temporary files
os.remove(TEMPORARY_FILE_PATH)
main()

View file

@ -23,7 +23,7 @@ This is a module to substitute debug.py in porduction mode.
debug = lambda st: None
class Timer:
def __init__(self, comment):
pass
def stop(self):
pass
def __init__(self, comment):
pass
def stop(self):
pass

File diff suppressed because it is too large Load diff

View file

@ -40,10 +40,10 @@ db = DataBackend()
try:
import psyco
psyco.full()
import psyco
psyco.full()
except ImportError:
pass
pass
OK = 200
ERROR = 500
@ -63,8 +63,8 @@ urls = (
'/(.*)', 'mainhandler'
)
class mainhandler:
def GET(self, crap):
return handler()
def GET(self, crap):
return handler()
@ -85,7 +85,7 @@ def twms_main(req):
height=0
req_bbox = ()
if data.get("bbox",data.get("BBOX",None)):
req_bbox = tuple(map(float,data.get("bbox",data.get("BBOX",req_bbox)).split(",")))
req_bbox = tuple(map(float,data.get("bbox",data.get("BBOX",req_bbox)).split(",")))
req_bbox = projections.to4326(req_bbox, srs)
@ -102,11 +102,10 @@ def twms_main(req):
image_content = StringIO.StringIO()
res.surface.write_to_png(image_content)
resp = image_content.getvalue()
return (OK, content_type, resp)

View file

@ -23,136 +23,136 @@ from debug import debug
from mapcss.webcolors.webcolors import whatever_to_cairo as colorparser
class Styling():
"""
Class used to choose the right way of rendering an object.
"""
def __init__(self, stylefile = None):
self.Selectors = {}
self.Selectors["way"] = []
self.Selectors["node"] = []
self.Selectors["relation"] = []
if not stylefile:
# self.Selectors["way"].append(StyleSelector( ( [ ( ("building",),(None) ) ] ),{"fill-color": "#00f"} ))
#if stylefile=="zzzz":
### using "builtin" styling
self.Selectors["way"].append(StyleSelector( ( [ ( ("area",),("yes") ) ] ),{"fill-color": "#ff0000"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),(None) ) ] ),{"width":1,"color":"#ff0000","text": "name", "text-position":"line","text-halo-radius":2,} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("barrier",),(None) ) ] ),{"casing-width":1,} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("residential", "tertiary", "living_street")) ] ),{"width": 3, "color":"#ffffff", "casing-width": 5, "z-index":10} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("service", "unclassified")) ] ),{"width": 2.5, "color":"#ccc", "casing-width": 4, "z-index":9} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("primary", "motorway", "trunk")) ] ),{"width": 4, "color":"#ff0", "casing-width": 6, "z-index":11} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("primary_link", "motorway_link", "trunk_link")) ] ),{"width": 3.5, "color":"#ff0", "casing-width": 6, "z-index":11} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("secondary", )) ] ),{"width": 4, "color":"orange", "casing-width": 6, "z-index":10} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("living_street",),("yes")) ] ),{"width": 2, "casing-width": 3, "z-index": 0} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse","natural"),("forest", "wood") ) ] ),{"fill-color": "#020"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse",),("industrial",) ) ] ),{"fill-color": "#855"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse",),("military",) ) ] ),{"fill-color": "pink"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("waterway","natural"),("riverbank", "water") ) ] ),{"fill-color": "#002"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("waterway","natural"),("river", "stream") ) ] ),{"color": "#002"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse","natural"),("grass",) ) ] ),{"fill-color": "#050",} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("footway","pedestrian","path" )) ] ),{"width":2.5, "color":"#655", "dashes": [3,1],"z-index":3} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("bridge",),("yes") ) ] ),{"casing-width":10} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("power",),("line",)) ] ),{"width": 1, "color":"#ccc",} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("building",),(None) ) ] ),{"fill-color": "#522","text": "addr:housenumber","text-halo-radius":2,"z-index":100} ))#"extrude":10,
self.stylefile = stylefile
self.useful_keys = set(["layer"])
for objtype in self.Selectors.values(): # getting useful keys
for selector in objtype:
#debug(selector)
for tag in selector.tags:
self.useful_keys.update(set(tag[0]))
if "text" in selector.style:
self.useful_keys.update(set((selector.style["text"],)))
debug(self.useful_keys)
def get_style(self, objtype, tags, nodata = False):
"""
objtype is "node", "way" or "relation"
tags - object tags
nodata - we won't render that now, don't need exact styling
Class used to choose the right way of rendering an object.
"""
resp = {}
for selector in self.Selectors[objtype]:
resp.update(selector.get_style(tags))
if nodata:
if resp:
return True
if not nodata and resp:
#debug((tags, tags.get("layer",0)), )
try:
resp["layer"] = int(tags.get("layer",0))*100+resp.get("z-index",0)+1000
except ValueError:
resp["layer"] = 1000000
if "text" in resp: # unpacking text
if resp["text"] in tags:
resp["text"] = tags[resp["text"]]
#debug("text: %s"%resp["text"])
else:
del resp["text"]
return resp
def filter_tags(self, tags):
"""
Returns only tags that are useful for rendering
"""
#resp = {}
#for k,v in tags.iteritems():
# if k in self.useful_keys:
# resp[k] = v
return tags
def __init__(self, stylefile = None):
self.Selectors = {}
self.Selectors["way"] = []
self.Selectors["node"] = []
self.Selectors["relation"] = []
if not stylefile:
# self.Selectors["way"].append(StyleSelector( ( [ ( ("building",),(None) ) ] ),{"fill-color": "#00f"} ))
#if stylefile=="zzzz":
### using "builtin" styling
self.Selectors["way"].append(StyleSelector( ( [ ( ("area",),("yes") ) ] ),{"fill-color": "#ff0000"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),(None) ) ] ),{"width":1,"color":"#ff0000","text": "name", "text-position":"line","text-halo-radius":2,} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("barrier",),(None) ) ] ),{"casing-width":1,} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("residential", "tertiary", "living_street")) ] ),{"width": 3, "color":"#ffffff", "casing-width": 5, "z-index":10} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("service", "unclassified")) ] ),{"width": 2.5, "color":"#ccc", "casing-width": 4, "z-index":9} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("primary", "motorway", "trunk")) ] ),{"width": 4, "color":"#ff0", "casing-width": 6, "z-index":11} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("primary_link", "motorway_link", "trunk_link")) ] ),{"width": 3.5, "color":"#ff0", "casing-width": 6, "z-index":11} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("secondary", )) ] ),{"width": 4, "color":"orange", "casing-width": 6, "z-index":10} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("living_street",),("yes")) ] ),{"width": 2, "casing-width": 3, "z-index": 0} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse","natural"),("forest", "wood") ) ] ),{"fill-color": "#020"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse",),("industrial",) ) ] ),{"fill-color": "#855"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse",),("military",) ) ] ),{"fill-color": "pink"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("waterway","natural"),("riverbank", "water") ) ] ),{"fill-color": "#002"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("waterway","natural"),("river", "stream") ) ] ),{"color": "#002"} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("landuse","natural"),("grass",) ) ] ),{"fill-color": "#050",} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("highway",),("footway","pedestrian","path" )) ] ),{"width":2.5, "color":"#655", "dashes": [3,1],"z-index":3} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("bridge",),("yes") ) ] ),{"casing-width":10} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("power",),("line",)) ] ),{"width": 1, "color":"#ccc",} ))
self.Selectors["way"].append(StyleSelector( ( [ ( ("building",),(None) ) ] ),{"fill-color": "#522","text": "addr:housenumber","text-halo-radius":2,"z-index":100} ))#"extrude":10,
self.stylefile = stylefile
self.useful_keys = set(["layer"])
for objtype in self.Selectors.values(): # getting useful keys
for selector in objtype:
#debug(selector)
for tag in selector.tags:
self.useful_keys.update(set(tag[0]))
if "text" in selector.style:
self.useful_keys.update(set((selector.style["text"],)))
debug(self.useful_keys)
def get_style(self, objtype, tags, nodata = False):
"""
objtype is "node", "way" or "relation"
tags - object tags
nodata - we won't render that now, don't need exact styling
"""
resp = {}
for selector in self.Selectors[objtype]:
resp.update(selector.get_style(tags))
if nodata:
if resp:
return True
if not nodata and resp:
#debug((tags, tags.get("layer",0)), )
try:
resp["layer"] = int(tags.get("layer",0))*100+resp.get("z-index",0)+1000
except ValueError:
resp["layer"] = 1000000
if "text" in resp: # unpacking text
if resp["text"] in tags:
resp["text"] = tags[resp["text"]]
#debug("text: %s"%resp["text"])
else:
del resp["text"]
return resp
def filter_tags(self, tags):
"""
Returns only tags that are useful for rendering
"""
#resp = {}
#for k,v in tags.iteritems():
# if k in self.useful_keys:
# resp[k] = v
return tags
class StyleSelector():
def __init__(self, tags, style):
"""
Selector that decides if that style is right for the object
tags - list of tags [(("key","key"..), ("value", "value"...)), (("key","key"..), ("value", "value"...))]
style - MapCSS rules to apply
"""
self.tags = tags
self.style = {}
for key in style:
keyz = key.lower()
if "color" in keyz:
self.style[keyz] = colorparser(style[key])
debug((colorparser(style[key]),style[key]))
else:
self.style[keyz] = style[key]
def get_style(self, tags):
"""
Get actual styling for object.
"""
styled = False
#debug(self.tags)
for k,v in self.tags:
for j in k:
if j in tags:
if v:
if tags[j] in v:
styled = True
else:
styled = True
if styled:
return self.style
return {}
def __init__(self, tags, style):
"""
Selector that decides if that style is right for the object
tags - list of tags [(("key","key"..), ("value", "value"...)), (("key","key"..), ("value", "value"...))]
style - MapCSS rules to apply
"""
self.tags = tags
self.style = {}
for key in style:
keyz = key.lower()
if "color" in keyz:
self.style[keyz] = colorparser(style[key])
debug((colorparser(style[key]),style[key]))
else:
self.style[keyz] = style[key]
def get_style(self, tags):
"""
Get actual styling for object.
"""
styled = False
#debug(self.tags)
for k,v in self.tags:
for j in k:
if j in tags:
if v:
if tags[j] in v:
styled = True
else:
styled = True
if styled:
return self.style
return {}
if __name__ == "__main__":
c = Styling()
print c.get_style("way", {"building":"yes"})
print c.get_style("way", {"highway":"residential"})
print c.get_style("way", {"highway":"road"})
print c.get_style("way", {"highway":"residential", "building": "yes"})
print c.get_style("way", {"highwadfgaay":"resifdgsdential", "builafgding": "yedfgs"})
print c.get_style("way", {"highwadfgaay":"resifdgsdential", "builafgding": "yedfgs"}, True)
print c.get_style("way", {"highway":"residential", "building": "yes"}, True)
print c.filter_tags({"highwadfgaay":"resifdgsdential", "builafgding": "yedfgs", "building": "residential"})
c = Styling()
print c.get_style("way", {"building":"yes"})
print c.get_style("way", {"highway":"residential"})
print c.get_style("way", {"highway":"road"})
print c.get_style("way", {"highway":"residential", "building": "yes"})
print c.get_style("way", {"highwadfgaay":"resifdgsdential", "builafgding": "yedfgs"})
print c.get_style("way", {"highwadfgaay":"resifdgsdential", "builafgding": "yedfgs"}, True)
print c.get_style("way", {"highway":"residential", "building": "yes"}, True)
print c.filter_tags({"highwadfgaay":"resifdgsdential", "builafgding": "yedfgs", "building": "residential"})

View file

@ -37,87 +37,87 @@ metatiles_in_progress = {}
renderlock = threading.Lock()
def kothic_fetcher (z, x, y, this_layer):
if "max_zoom" in this_layer:
if z >= this_layer["max_zoom"]:
return None
bbox = projections.bbox_by_tile(z,x,y,"EPSG:3857")
db = DataBackend(path="/home/kom/osm/kothic/src/tiles")
res = RasterTile(256, 256, 1, db, "EPSG:3857")
res.update_surface(bbox, z, style)
f = NamedTemporaryFile()
f.close()
res.surface.write_to_png(f.name)
del res
del db
im = Image.open(f.name)
os.unlink(f.name)
im = im.convert("RGBA")
if "max_zoom" in this_layer:
if z >= this_layer["max_zoom"]:
return None
bbox = projections.bbox_by_tile(z,x,y,"EPSG:3857")
db = DataBackend(path="/home/kom/osm/kothic/src/tiles")
res = RasterTile(256, 256, 1, db, "EPSG:3857")
res.update_surface(bbox, z, style)
f = NamedTemporaryFile()
f.close()
res.surface.write_to_png(f.name)
del res
del db
im = Image.open(f.name)
os.unlink(f.name)
im = im.convert("RGBA")
return im
return im
def kothic_metatile(z, x, y, this_layer):
print z, x, y
global metatiles_in_progress
if "max_zoom" in this_layer:
if z >= this_layer["max_zoom"]:
return None
if z<5:
return None
metatile_id = (z,int(x/8), int(y/8))
try:
metatiles_in_progress[metatile_id].join()
except KeyError:
metatiles_in_progress[metatile_id] = threading.Thread(None, gen_metatile, None, (metatile_id, this_layer))
metatiles_in_progress[metatile_id].start()
metatiles_in_progress[metatile_id].join()
except RuntimeError:
pass
local = config.tiles_cache + this_layer["prefix"] + "/z%s/%s/x%s/%s/y%s."%(z, x/1024, x, y/1024,y)
ext = this_layer["ext"]
if os.path.exists(local+ext): # First, look for tile in cache
print z, x, y
global metatiles_in_progress
if "max_zoom" in this_layer:
if z >= this_layer["max_zoom"]:
return None
if z<5:
return None
metatile_id = (z,int(x/8), int(y/8))
try:
im1 = Image.open(local+ext)
del metatiles_in_progress[metatile_id]
return im1
except IOError:
os.remove(local+ext)
metatiles_in_progress[metatile_id].join()
except KeyError:
metatiles_in_progress[metatile_id] = threading.Thread(None, gen_metatile, None, (metatile_id, this_layer))
metatiles_in_progress[metatile_id].start()
metatiles_in_progress[metatile_id].join()
except RuntimeError:
pass
local = config.tiles_cache + this_layer["prefix"] + "/z%s/%s/x%s/%s/y%s."%(z, x/1024, x, y/1024,y)
ext = this_layer["ext"]
if os.path.exists(local+ext): # First, look for tile in cache
try:
im1 = Image.open(local+ext)
del metatiles_in_progress[metatile_id]
return im1
except IOError:
os.remove(local+ext)
def gen_metatile(metatile_id, this_layer):
#renderlock.acquire()
z, x, y = metatile_id
z -= 3
wh = 2560
bb1 = projections.coords_by_tile(z, x-0.125, y-0.125, "EPSG:3857")
bb2 = projections.coords_by_tile(z, x+1.125, y+1.125, "EPSG:3857")
bbox = (bb1[0],bb2[1],bb2[0],bb1[1])
db = DataBackend()
res = RasterTile(wh, wh, 1, db, "EPSG:3857")
res.update_surface(bbox, z+3, style)
f = NamedTemporaryFile()
f.close()
res.surface.write_to_png(f.name)
del res
del db
im = Image.open(f.name)
os.unlink(f.name)
im = im.convert("RGBA")
x*=8
y*=8
z+=3
ext = this_layer["ext"]
for i in range(x,x+9):
for j in range(y,y+9):
local = config.tiles_cache + this_layer["prefix"] + "/z%s/%s/x%s/%s/y%s."%(z, i/1024, i, j/1024,j)
box = (256*(i-x+1),256*(j-y+1),256*(i-x+2),256*(j-y+2))
im1 = im.crop(box)
if not os.path.exists("/".join(local.split("/")[:-1])):
os.makedirs("/".join(local.split("/")[:-1]))
im1.save(local+ext)
del im1
#renderlock.release()
#renderlock.acquire()
z, x, y = metatile_id
z -= 3
wh = 2560
bb1 = projections.coords_by_tile(z, x-0.125, y-0.125, "EPSG:3857")
bb2 = projections.coords_by_tile(z, x+1.125, y+1.125, "EPSG:3857")
bbox = (bb1[0],bb2[1],bb2[0],bb1[1])
db = DataBackend()
res = RasterTile(wh, wh, 1, db, "EPSG:3857")
res.update_surface(bbox, z+3, style)
f = NamedTemporaryFile()
f.close()
res.surface.write_to_png(f.name)
del res
del db
im = Image.open(f.name)
os.unlink(f.name)
im = im.convert("RGBA")
x*=8
y*=8
z+=3
ext = this_layer["ext"]
for i in range(x,x+9):
for j in range(y,y+9):
local = config.tiles_cache + this_layer["prefix"] + "/z%s/%s/x%s/%s/y%s."%(z, i/1024, i, j/1024,j)
box = (256*(i-x+1),256*(j-y+1),256*(i-x+2),256*(j-y+2))
im1 = im.crop(box)
if not os.path.exists("/".join(local.split("/")[:-1])):
os.makedirs("/".join(local.split("/")[:-1]))
im1.save(local+ext)
del im1
#renderlock.release()