0

moved google map related code int googlemap.py (from quadtree.py)

basic support in googlemap.py for handling multiple QuadtreeGens
This commit is contained in:
Aaron Griffith
2011-03-20 21:23:26 -04:00
parent 329c7557f6
commit 0e87368a06
4 changed files with 162 additions and 95 deletions

View File

@@ -39,13 +39,16 @@ var signGroups = [
* path : string. Location of the rendered tiles. * path : string. Location of the rendered tiles.
* Optional: * Optional:
* base : string. Base of the url path for tile locations, useful for serving tiles from a different server than the js/html server. * base : string. Base of the url path for tile locations, useful for serving tiles from a different server than the js/html server.
*/
var mapTypeData=[ var mapTypeData=[
{'label': 'Unlit', 'path': 'tiles'}, {'label': 'Unlit', 'path': 'tiles'},
// {'label': 'Day', 'path': 'lighting/tiles'}, // {'label': 'Day', 'path': 'lighting/tiles'},
// {'label': 'Night', 'path': 'night/tiles'}, // {'label': 'Night', 'path': 'night/tiles'},
// {'label': 'Spawn', 'path': 'spawn/tiles', 'base': 'http://example.cdn.amazon.com/'} // {'label': 'Spawn', 'path': 'spawn/tiles', 'base': 'http://example.cdn.amazon.com/'}
]; ];
*/
var mapTypeData = {maptypedata};
// Please leave the following variables here: // Please leave the following variables here:
var markerCollection = {}; // holds groups of markers var markerCollection = {}; // holds groups of markers

12
gmap.py
View File

@@ -43,6 +43,7 @@ import optimizeimages
import composite import composite
import world import world
import quadtree import quadtree
import googlemap
helptext = """ helptext = """
%prog [OPTIONS] <World # / Name / Path to World> <tiles dest dir> %prog [OPTIONS] <World # / Name / Path to World> <tiles dest dir>
@@ -159,10 +160,15 @@ def main():
w = world.World(worlddir, useBiomeData=useBiomeData) w = world.World(worlddir, useBiomeData=useBiomeData)
w.go(options.procs) w.go(options.procs)
# Now generate the tiles # create the quadtrees
# TODO chunklist # TODO chunklist
q = quadtree.QuadtreeGen(w, destdir, depth=options.zoom, imgformat=imgformat, optimizeimg=optimizeimg, rendermode=options.rendermode, web_assets_hook=options.web_assets_hook) q = quadtree.QuadtreeGen(w, destdir, depth=options.zoom, imgformat=imgformat, optimizeimg=optimizeimg, rendermode=options.rendermode)
q.write_html(options.skipjs)
# write out the map and web assets
m = googlemap.MapGen([q,], skipjs=options.skipjs, web_assets_hook=options.web_assets_hook)
m.go(options.procs)
# render the tiles!
q.go(options.procs) q.go(options.procs)
def delete_all(worlddir, tiledir): def delete_all(worlddir, tiledir):

147
googlemap.py Normal file
View File

@@ -0,0 +1,147 @@
# This file is part of the Minecraft Overviewer.
#
# Minecraft Overviewer is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# Minecraft Overviewer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
import os
import os.path
import cPickle
import Image
import shutil
from time import strftime, gmtime
import json
import util
"""
This module has routines related to generating a Google Maps-based
interface out of a set of tiles.
"""
def mirror_dir(src, dst, entities=None):
'''copies all of the entities from src to dst'''
if not os.path.exists(dst):
os.mkdir(dst)
if entities and type(entities) != list: raise Exception("Expected a list, got a %r instead" % type(entities))
for entry in os.listdir(src):
if entities and entry not in entities: continue
if os.path.isdir(os.path.join(src,entry)):
mirror_dir(os.path.join(src, entry), os.path.join(dst, entry))
elif os.path.isfile(os.path.join(src,entry)):
try:
shutil.copy(os.path.join(src, entry), os.path.join(dst, entry))
except IOError:
# maybe permission problems?
os.chmod(os.path.join(src, entry), stat.S_IRUSR)
os.chmod(os.path.join(dst, entry), stat.S_IWUSR)
shutil.copy(os.path.join(src, entry), os.path.join(dst, entry))
# if this stills throws an error, let it propagate up
class MapGen(object):
def __init__(self, quadtrees, skipjs=False, web_assets_hook=None):
"""Generates a Google Maps interface for the given list of
quadtrees. All of the quadtrees must have the same destdir,
image format, and world."""
self.skipjs = skipjs
self.web_assets_hook = web_assets_hook
if not len(quadtrees) > 0:
raise ValueError("there must be at least one quadtree to work on")
self.destdir = quadtrees[0].destdir
self.imgformat = quadtrees[0].imgformat
self.world = quadtrees[0].world
self.p = quadtrees[0].p
for i in quadtrees:
if i.destdir != self.destdir or i.imgformat != self.imgformat or i.world != self.world:
raise ValueError("all the given quadtrees must have the same destdir")
self.quadtrees = quadtrees
def go(self, procs):
"""Writes out config.js, marker.js, and region.js
Copies web assets into the destdir"""
zoomlevel = self.p
imgformat = self.imgformat
configpath = os.path.join(util.get_program_path(), "config.js")
config = open(configpath, 'r').read()
config = config.replace(
"{maxzoom}", str(zoomlevel))
config = config.replace(
"{imgformat}", str(imgformat))
# create generated map type data, from given quadtrees
maptypedata = map(lambda q: {'label' : q.rendermode.capitalize(),
'path' : q.tiledir}, self.quadtrees)
config = config.replace("{maptypedata}", json.dumps(maptypedata))
with open(os.path.join(self.destdir, "config.js"), 'w') as output:
output.write(config)
# Write a blank image
for quadtree in self.quadtrees:
blank = Image.new("RGBA", (1,1))
tileDir = os.path.join(self.destdir, quadtree.tiledir)
if not os.path.exists(tileDir): os.mkdir(tileDir)
blank.save(os.path.join(tileDir, "blank."+self.imgformat))
# copy web assets into destdir:
mirror_dir(os.path.join(util.get_program_path(), "web_assets"), self.destdir)
# Add time in index.html
indexpath = os.path.join(self.destdir, "index.html")
index = open(indexpath, 'r').read()
index = index.replace(
"{time}", str(strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())))
with open(os.path.join(self.destdir, "index.html"), 'w') as output:
output.write(index)
if self.skipjs:
if self.web_assets_hook:
self.web_assets_hook(self)
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
# we need to merge self.world.POI with the persistant data in world.PersistentData
self.world.POI += filter(lambda x: x['type'] != 'spawn', self.world.persistentData['POI'])
# write out the default marker table
with open(os.path.join(self.destdir, "markers.js"), 'w') as output:
output.write("var markerData=%s" % json.dumps(self.world.POI))
# save persistent data
self.world.persistentData['POI'] = self.world.POI
with open(self.world.pickleFile,"wb") as f:
cPickle.dump(self.world.persistentData,f)
# write out the default (empty, but documented) region table
with open(os.path.join(self.destdir, "regions.js"), 'w') as output:
output.write('var regionData=[\n')
output.write(' // {"color": "#FFAA00", "opacity": 0.5, "closed": true, "path": [\n')
output.write(' // {"x": 0, "y": 0, "z": 0},\n')
output.write(' // {"x": 0, "y": 10, "z": 0},\n')
output.write(' // {"x": 0, "y": 0, "z": 10}\n')
output.write(' // ]},\n')
output.write('];')
if self.web_assets_hook:
self.web_assets_hook(self)

View File

@@ -42,26 +42,6 @@ This module has routines related to generating a quadtree of tiles
""" """
def mirror_dir(src, dst, entities=None):
'''copies all of the entities from src to dst'''
if not os.path.exists(dst):
os.mkdir(dst)
if entities and type(entities) != list: raise Exception("Expected a list, got a %r instead" % type(entities))
for entry in os.listdir(src):
if entities and entry not in entities: continue
if os.path.isdir(os.path.join(src,entry)):
mirror_dir(os.path.join(src, entry), os.path.join(dst, entry))
elif os.path.isfile(os.path.join(src,entry)):
try:
shutil.copy(os.path.join(src, entry), os.path.join(dst, entry))
except IOError:
# maybe permission problems?
os.chmod(os.path.join(src, entry), stat.S_IRUSR)
os.chmod(os.path.join(dst, entry), stat.S_IWUSR)
shutil.copy(os.path.join(src, entry), os.path.join(dst, entry))
# if this stills throws an error, let it propagate up
def iterate_base4(d): def iterate_base4(d):
"""Iterates over a base 4 number with d digits""" """Iterates over a base 4 number with d digits"""
return itertools.product(xrange(4), repeat=d) return itertools.product(xrange(4), repeat=d)
@@ -90,7 +70,7 @@ def pool_initializer(quadtree):
child_quadtree = quadtree child_quadtree = quadtree
class QuadtreeGen(object): class QuadtreeGen(object):
def __init__(self, worldobj, destdir, depth=None, tiledir="tiles", imgformat=None, optimizeimg=None, rendermode="normal", web_assets_hook=None): def __init__(self, worldobj, destdir, depth=None, tiledir="tiles", imgformat=None, optimizeimg=None, rendermode="normal"):
"""Generates a quadtree from the world given into the """Generates a quadtree from the world given into the
given dest directory given dest directory
@@ -103,11 +83,11 @@ class QuadtreeGen(object):
assert(imgformat) assert(imgformat)
self.imgformat = imgformat self.imgformat = imgformat
self.optimizeimg = optimizeimg self.optimizeimg = optimizeimg
self.web_assets_hook = web_assets_hook
self.lighting = rendermode in ("lighting", "night", "spawn") self.lighting = rendermode in ("lighting", "night", "spawn")
self.night = rendermode in ("night", "spawn") self.night = rendermode in ("night", "spawn")
self.spawn = rendermode in ("spawn",) self.spawn = rendermode in ("spawn",)
self.rendermode = rendermode
# Make the destination dir # Make the destination dir
if not os.path.exists(destdir): if not os.path.exists(destdir):
@@ -160,75 +140,6 @@ class QuadtreeGen(object):
return return
logging.info("{0}/{1} tiles complete on level {2}/{3}".format( logging.info("{0}/{1} tiles complete on level {2}/{3}".format(
complete, total, level, self.p)) complete, total, level, self.p))
def write_html(self, skipjs=False):
"""Writes out config.js, marker.js, and region.js
Copies web assets into the destdir"""
zoomlevel = self.p
imgformat = self.imgformat
configpath = os.path.join(util.get_program_path(), "config.js")
config = open(configpath, 'r').read()
config = config.replace(
"{maxzoom}", str(zoomlevel))
config = config.replace(
"{imgformat}", str(imgformat))
with open(os.path.join(self.destdir, "config.js"), 'w') as output:
output.write(config)
# Write a blank image
blank = Image.new("RGBA", (1,1))
tileDir = os.path.join(self.destdir, self.tiledir)
if not os.path.exists(tileDir): os.mkdir(tileDir)
blank.save(os.path.join(tileDir, "blank."+self.imgformat))
# copy web assets into destdir:
mirror_dir(os.path.join(util.get_program_path(), "web_assets"), self.destdir)
# Add time in index.html
indexpath = os.path.join(self.destdir, "index.html")
index = open(indexpath, 'r').read()
index = index.replace(
"{time}", str(strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())))
with open(os.path.join(self.destdir, "index.html"), 'w') as output:
output.write(index)
if skipjs:
if self.web_assets_hook:
self.web_assets_hook(self)
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
# we need to merge self.world.POI with the persistant data in world.PersistentData
self.world.POI += filter(lambda x: x['type'] != 'spawn', self.world.persistentData['POI'])
# write out the default marker table
with open(os.path.join(self.destdir, "markers.js"), 'w') as output:
output.write("var markerData=%s" % json.dumps(self.world.POI))
# save persistent data
self.world.persistentData['POI'] = self.world.POI
with open(self.world.pickleFile,"wb") as f:
cPickle.dump(self.world.persistentData,f)
# write out the default (empty, but documented) region table
with open(os.path.join(self.destdir, "regions.js"), 'w') as output:
output.write('var regionData=[\n')
output.write(' // {"color": "#FFAA00", "opacity": 0.5, "closed": true, "path": [\n')
output.write(' // {"x": 0, "y": 0, "z": 0},\n')
output.write(' // {"x": 0, "y": 10, "z": 0},\n')
output.write(' // {"x": 0, "y": 0, "z": 10}\n')
output.write(' // ]},\n')
output.write('];')
if self.web_assets_hook:
self.web_assets_hook(self)
def _get_cur_depth(self): def _get_cur_depth(self):
"""How deep is the quadtree currently in the destdir? This glances in """How deep is the quadtree currently in the destdir? This glances in