diff --git a/googlemap.py b/googlemap.py index 840d2ac..65fd8e8 100644 --- a/googlemap.py +++ b/googlemap.py @@ -127,6 +127,11 @@ class MapGen(object): self.web_assets_hook(self) return + + def finalize(self): + if self.skipjs: + return + # since we will only discover PointsOfInterest in chunks that need to be # [re]rendered, POIs like signs in unchanged chunks will not be listed # in self.world.POI. To make sure we don't remove these from markers.js @@ -153,5 +158,3 @@ class MapGen(object): output.write(' // ]},\n') output.write('];') - if self.web_assets_hook: - self.web_assets_hook(self) diff --git a/overviewer.py b/overviewer.py index b2aa275..a161f22 100755 --- a/overviewer.py +++ b/overviewer.py @@ -186,7 +186,7 @@ def main(): q.append(qtree) #create the distributed render - r = rendernode.RenderNode(q) + r = rendernode.RenderNode(q, world=w) # write out the map and web assets m = googlemap.MapGen(q, skipjs=options.skipjs, web_assets_hook=options.web_assets_hook) @@ -195,6 +195,8 @@ def main(): # render the tiles! r.go(options.procs) + m.finalize() + def delete_all(worlddir, tiledir): # TODO should we delete tiledir here too? diff --git a/quadtree.py b/quadtree.py index 77fac8b..b64333a 100644 --- a/quadtree.py +++ b/quadtree.py @@ -333,7 +333,7 @@ class QuadtreeGen(object): - def render_worldtile(self, chunks, colstart, colend, rowstart, rowend, path): + def render_worldtile(self, chunks, colstart, colend, rowstart, rowend, path, poi_queue=None): """Renders just the specified chunks into a tile and save it. Unlike usual python conventions, rowend and colend are inclusive. Additionally, the chunks around the edges are half-way cut off (so that neighboring tiles @@ -442,7 +442,7 @@ class QuadtreeGen(object): # draw the chunk! # TODO POI queue - chunk.render_to_image((chunkx, chunky), tileimg, (xpos, ypos), self, False, None) + chunk.render_to_image((chunkx, chunky), tileimg, (xpos, ypos), self, False, poi_queue) # Save them tileimg.save(imgpath) diff --git a/rendernode.py b/rendernode.py index a3e12b1..43b175d 100644 --- a/rendernode.py +++ b/rendernode.py @@ -14,6 +14,7 @@ # with the Overviewer. If not, see . import multiprocessing +import Queue import itertools from itertools import cycle, islice import os @@ -76,7 +77,7 @@ def roundrobin(iterables): class RenderNode(object): - def __init__(self, quadtrees): + def __init__(self, quadtrees, world): """Distributes the rendering of a list of quadtrees.""" if not len(quadtrees) > 0: @@ -89,6 +90,13 @@ class RenderNode(object): q._render_index = i i += 1 + # queue for receiving interesting events from the renderer + # (like the discovery of signs! + self.poi_q = multiprocessing.Queue() + + self.world = world + + def print_statusline(self, complete, total, level, unconditional=False): if unconditional: pass @@ -151,6 +159,18 @@ class RenderNode(object): timestamp = timestamp2 count_to_remove = (1000//batch_size) if count_to_remove < len(results): + try: + while (1): + # an exception will break us out of this loop + item = self.poi_q.get(block=False) + if item[0] == "newpoi": + if item[1] not in self.world.POI: + #print "got an item from the queue!" + self.world.POI.append(item[1]) + elif item[0] == "removePOI": + self.world.persistentData['POI'] = filter(lambda x: x['chunk'] != item[1], self.world.persistentData['POI']) + except Queue.Empty: + pass while count_to_remove > 0: count_to_remove -= 1 complete += results.popleft().get() @@ -166,6 +186,18 @@ class RenderNode(object): while len(results) > 0: complete += results.popleft().get() self.print_statusline(complete, total, 1) + try: + while (1): + # an exception will break us out of this loop + item = self.poi_q.get(block=False) + if item[0] == "newpoi": + if item[1] not in self.world.POI: + #print "got an item from the queue!" + self.world.POI.append(item[1]) + elif item[0] == "removePOI": + self.world.persistentData['POI'] = filter(lambda x: x['chunk'] != item[1], self.world.persistentData['POI']) + except Queue.Empty: + pass self.print_statusline(complete, total, 1, True) @@ -230,10 +262,10 @@ class RenderNode(object): jobcount += 1 if jobcount >= batch_size: jobcount = 0 - yield pool.apply_async(func=render_worldtile_batch, args= [batch]) + yield pool.apply_async(func=render_worldtile_batch, args= [batch, self.poi_q]) batch = [] if jobcount > 0: - yield pool.apply_async(func=render_worldtile_batch, args= [batch]) + yield pool.apply_async(func=render_worldtile_batch, args= [batch, self.poi_q]) def _apply_render_inntertile(self, pool, zoom,batch_size): """Same as _apply_render_worltiles but for the inntertile routine. @@ -262,7 +294,7 @@ class RenderNode(object): yield pool.apply_async(func=render_innertile_batch, args= [batch]) @catch_keyboardinterrupt -def render_worldtile_batch(batch): +def render_worldtile_batch(batch, poi_queue): global child_rendernode rendernode = child_rendernode count = 0 @@ -282,7 +314,7 @@ def render_worldtile_batch(batch): tilechunks = quadtree.get_chunks_in_range(colstart, colend, rowstart,rowend) #logging.debug(" tilechunks: %r", tilechunks) - quadtree.render_worldtile(tilechunks,colstart, colend, rowstart, rowend, path) + quadtree.render_worldtile(tilechunks,colstart, colend, rowstart, rowend, path, poi_queue) return count @catch_keyboardinterrupt