def render(self, path, tile_x, tile_y, zoom): """ Render a single tile to a given filename. """ print 'Rendering %s' % (path) # Calculate pixel positions of bottom-left & top-right half_width = self.width / 2 half_height = self.height / 2 px0 = (tile_x * self.width, (tile_y + 1) * self.height) px1 = ((tile_x + 1) * self.width, tile_y * self.height) # Convert tile coords to LatLng ll0 = self.tile_projection.fromPixelToLL(px0, zoom) ll1 = self.tile_projection.fromPixelToLL(px1, zoom) # Convert LatLng to map coords c0 = self.map_projection.forward(mapnik.Coord(ll0[0], ll0[1])) c1 = self.map_projection.forward(mapnik.Coord(ll1[0], ll1[1])) # Create bounding box for the render bbox = mapnik.Box2d(c0.x, c0.y, c1.x, c1.y) self.mapnik_map.zoom_to_box(bbox) self.mapnik_map.buffer_size = self.buffer_size if self.filetype == 'svg': surface = cairo.SVGSurface(path, self.width, self.height) mapnik.render(self.mapnik_map, surface) surface.finish() else: image = mapnik.Image(self.width, self.height) mapnik.render(self.mapnik_map, image) image.save(path, self.filetype) if self.grid: if self.key: grid = mapnik.Grid(self.width, self.height) else: grid = mapnik.Grid(self.width, self.height, key=self.key) fields = [] if self.fields: fields.extend(self.fields) mapnik.render_layer(self.mapnik_map, grid, layer=0, fields=fields) # then encode the grid array as utf, resample to 1/4 the size, and dump features # this comes from https://github.com/springmeyer/gridsforkids/blob/master/generate_tiles.py # with little consideration grid_utf = grid.encode('utf', resolution=4, features=True) # client code uses jsonp, so fake by wrapping in grid() callback base, ext = os.path.splitext(path) grid_filename = '%s.grid.json' % base print 'Rendering %s' % (grid_path) with open(grid_path, 'wb') as f: f.write('grid(' + json.dumps(grid_utf) + ')')
def renderArea(self, width, height, srs, xmin, ymin, xmax, ymax, zoom): """ """ start_time = time() # # Mapnik can behave strangely when run in threads, so place a lock on the instance. # if global_mapnik_lock.acquire(): try: if self.mapnik is None: self.mapnik = get_mapnikMap(self.mapfile) logging.debug('TileStache.Mapnik.GridProvider.renderArea() %.3f to load %s', time() - start_time, self.mapfile) self.mapnik.width = width self.mapnik.height = height self.mapnik.zoom_to_box(Box2d(xmin, ymin, xmax, ymax)) if self.layer_id_key is not None: grids = [] for (index, fields) in self.layers: datasource = self.mapnik.layers[index].datasource fields = (type(fields) is list) and map(str, fields) or datasource.fields() grid = mapnik.Grid(width, height) mapnik.render_layer(self.mapnik, grid, layer=index, fields=fields) grid = grid.encode('utf', resolution=self.scale, features=True) for key in grid['data']: grid['data'][key][self.layer_id_key] = self.mapnik.layers[index].name grids.append(grid) # global_mapnik_lock.release() outgrid = reduce(merge_grids, grids) else: grid = mapnik.Grid(width, height) for (index, fields) in self.layers: datasource = self.mapnik.layers[index].datasource fields = (type(fields) is list) and map(str, fields) or datasource.fields() mapnik.render_layer(self.mapnik, grid, layer=index, fields=fields) # global_mapnik_lock.release() outgrid = grid.encode('utf', resolution=self.scale, features=True) except: self.mapnik = None raise finally: global_mapnik_lock.release() logging.debug('TileStache.Mapnik.GridProvider.renderArea() %dx%d at %d in %.3f from %s', width, height, self.scale, time() - start_time, self.mapfile) return SaveableResponse(outgrid, self.scale)
def test_line_rendering(): ds = mapnik.MemoryDatasource() context = mapnik.Context() context.push('Name') pixel_key = 1 f = mapnik.Feature(context,pixel_key) f['Name'] = str(pixel_key) f.add_geometries_from_wkt('LINESTRING (30 10, 10 30, 40 40)') ds.add_feature(f) s = mapnik.Style() r = mapnik.Rule() symb = mapnik.LineSymbolizer() r.symbols.append(symb) s.rules.append(r) lyr = mapnik.Layer('Places') lyr.datasource = ds lyr.styles.append('places_labels') width,height = 256,256 m = mapnik.Map(width,height) m.append_style('places_labels',s) m.layers.append(lyr) m.zoom_all() #mapnik.render_to_file(m,'test.png') grid = mapnik.Grid(m.width,m.height,key='__id__') mapnik.render_layer(m,grid,layer=0,fields=['Name']) utf1 = grid.encode() eq_(utf1,line_expected,show_grids('line',utf1,line_expected))
def test_render_grid3(): """ test using feature id""" width,height = 256,256 sym = mapnik.MarkersSymbolizer() sym.width = mapnik.Expression('10') sym.height = mapnik.Expression('10') m = create_grid_map(width,height,sym) ul_lonlat = mapnik.Coord(142.30,-38.20) lr_lonlat = mapnik.Coord(143.40,-38.80) m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat)) grid = mapnik.Grid(m.width,m.height,key='__id__') mapnik.render_layer(m,grid,layer=0,fields=['__id__','Name']) utf1 = grid.encode('utf',resolution=4) eq_(utf1,grid_feat_id3,show_grids('id-markers',utf1,grid_feat_id3)) # check a full view is the same as a full image grid_view = grid.view(0,0,width,height) # for kicks check at full res too utf3 = grid.encode('utf',resolution=1) utf4 = grid_view.encode('utf',resolution=1) eq_(utf3['grid'],utf4['grid']) eq_(utf3['keys'],utf4['keys']) eq_(utf3['data'],utf4['data']) eq_(resolve(utf4,0,0),None) # resolve some center points in the # resampled view utf5 = grid_view.encode('utf',resolution=4) eq_(resolve(utf5,25,10),{"Name": "North West","__id__": 3}) eq_(resolve(utf5,25,46),{"Name": "North East","__id__": 4}) eq_(resolve(utf5,38,10),{"Name": "South West","__id__": 2}) eq_(resolve(utf5,38,46),{"Name": "South East","__id__": 1})
def test_clearing_grid_data(): g = mapnik.Grid(256, 256) utf = g.encode() # make sure it equals itself eq_(g.encode(), utf) m = make_map() mapnik.render_layer(m, g, layer=0, fields=['__id__', 'Name']) eq_(g.encode() != utf, True) # clear grid, should now match original g.clear() eq_(g.encode(), utf)
def render_grid(self, bbox, grid_fields, layer, width=None, height=None): """ Render the specified grid with Mapnik """ width = width or self.tilesize height = height or self.tilesize self._prepare_rendering(bbox, width=width, height=height) grid = mapnik.Grid(width, height) mapnik.render_layer(self._mapnik, grid, layer=layer, fields=grid_fields) grid = grid.encode() return json.dumps(grid)
def test_point_symbolizer_grid(): width,height = 256,256 sym = mapnik.PointSymbolizer() sym.file = '../data/images/dummy.png' m = create_grid_map(width,height,sym) ul_lonlat = mapnik.Coord(142.30,-38.20) lr_lonlat = mapnik.Coord(143.40,-38.80) m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat)) grid = mapnik.Grid(m.width,m.height) mapnik.render_layer(m,grid,layer=0,fields=['Name']) utf1 = grid.encode() eq_(utf1,point_expected,show_grids('point-sym',utf1,point_expected))
def _renderGridinfo(self,x,y,z,l0,l1,tile_uris): for i in range(int(self.tile_countX)): for j in range(int(self.tile_countY)): pt0 = (x + self.tile_size*i, y + self.tile_size*(j+1)) pt1 = (x + self.tile_size*(i+1), y + self.tile_size*j) # Convert to LatLong (EPSG:4326) lt0 = self.tileproj.fromPixelToLL(pt0, z); lt1 = self.tileproj.fromPixelToLL(pt1, z); # Convert to map projection (e.g. mercator co-ords EPSG:900913) ct0 = self.prj.forward(mapnik.Coord(lt0[0],lt0[1])) ct1 = self.prj.forward(mapnik.Coord(lt1[0],lt1[1])) if self.gridMap: mi = 0 for country,_gridMap in self.gridMap.items(): if self.countries[country].intersects(mapnik.Box2d(l0[0],l0[1],l1[0],l1[1])): try: _gridMap.zoom_to_box(mapnik.Box2d(ct0.x,ct0.y, ct1.x,ct1.y)) _gridMap.resize(int(self.tile_size), int(self.tile_size)) _gridMap.buffer_size = 0 grid = mapnik.Grid(int(self.tile_size), int(self.tile_size)) mapnik.render_layer(_gridMap, grid, layer = 1, fields=['symbol_name','wiki']) mapnik.render_layer(_gridMap, grid, layer = 0, fields=['highway','grade','surface','smoothness','ref','int_ref','tracktype','name']) utfgrid = grid.encode('utf',resolution=4) for key1 in utfgrid['data']: for key2,val2 in utfgrid['data'][key1].items(): if val2 in (None,'no',''): del utfgrid['data'][key1][key2] gridname = tile_uris[i*self.tile_countY +j].replace(".jpg",".js") f = codecs.open(gridname + '.tmp','w','utf-8') f.write(json.dumps(utfgrid, ensure_ascii = False)) f.close() if mi > 0: os.system('gzip -f %s' % (gridname + '.tmp')) if os.path.getsize(gridname + '.tmp.gz') > os.path.getsize(gridname+'.gz'): os.remove(gridname + '.gz') os.rename(gridname + '.tmp.gz',gridname+'.gz') else: os.remove(gridname + '.tmp.gz') else: os.rename(gridname + '.tmp.gz',gridname+'.gz') except Exception as E: print E mi += 1
def test_render_grid2(): """ test old against new""" width,height = 256,256 m = create_grid_map(width,height) ul_lonlat = mapnik.Coord(142.30,-38.20) lr_lonlat = mapnik.Coord(143.40,-38.80) m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat)) # new method grid = mapnik.Grid(m.width,m.height,key='Name') mapnik.render_layer(m,grid,layer=0,fields=['Name']) utf1 = grid.encode('utf',resolution=4) eq_(utf1,grid_correct_new) # old method - to be removed utf2 = mapnik.render_grid(m,0,key='Name',resolution=4,fields=['Name']) eq_(utf2,grid_correct) # for complex polygons these will not be true eq_(len(utf2['grid']),len(utf1['grid'])) eq_(len(utf2['keys']),len(utf1['keys'])) eq_(len(utf2['data']),len(utf1['data'])) # check a full view is the same as a full image grid_view = grid.view(0,0,width,height) # for kicks check at full res too utf3 = grid.encode('utf',resolution=1) utf4 = grid_view.encode('utf',resolution=1) eq_(utf3['grid'],utf4['grid']) eq_(utf3['keys'],utf4['keys']) eq_(utf3['data'],utf4['data']) eq_(resolve(utf4,0,0),None) # resolve some center points in the # resampled view utf5 = grid_view.encode('utf',resolution=4) eq_(resolve(utf5,25,10),{"Name": "North West"}) eq_(resolve(utf5,25,46),{"Name": "North East"}) eq_(resolve(utf5,38,10),{"Name": "South West"}) eq_(resolve(utf5,38,46),{"Name": "South East"})
def renderTile(self, width, height, srs, coord): """ """ if self.mapnik is None: self.mapnik = mapnik.Map(0, 0) mapnik.load_map(self.mapnik, str(self.mapfile)) # buffer as fraction of tile size buffer = float(self.buffer) / 256 nw = self.layer.projection.coordinateLocation( coord.left(buffer).up(buffer)) se = self.layer.projection.coordinateLocation( coord.right(1 + buffer).down(1 + buffer)) ul = self.mercator.locationProj(nw) lr = self.mercator.locationProj(se) self.mapnik.width = width + 2 * self.buffer self.mapnik.height = height + 2 * self.buffer self.mapnik.zoom_to_box(mapnik.Box2d(ul.x, ul.y, lr.x, lr.y)) # create grid as same size as map/image grid = mapnik.Grid(width + 2 * self.buffer, height + 2 * self.buffer) # render a layer to that grid array mapnik.render_layer(self.mapnik, grid, layer=self.layer_index, fields=self.fields) # extract a gridview excluding the buffer grid_view = grid.view(self.buffer, self.buffer, width, height) # then encode the grid array as utf, resample to 1/scale the size, and dump features grid_utf = grid_view.encode('utf', resolution=self.scale, add_features=True) if self.wrapper is None: return SaveableResponse(json.dumps(grid_utf)) else: return SaveableResponse(self.wrapper + '(' + json.dumps(grid_utf) + ')')
def test_render_to_grid_multiple_times(): # create map with two layers m = mapnik.Map(256,256) s = mapnik.Style() r = mapnik.Rule() sym = mapnik.MarkersSymbolizer() sym.allow_overlap = True r.symbols.append(sym) s.rules.append(r) m.append_style('points',s) # NOTE: we use a csv datasource here # because the memorydatasource fails silently for # queries requesting fields that do not exist in the datasource ds1 = mapnik.Datasource(**{"type":"csv","inline":''' wkt,Name "POINT (143.10 -38.60)",South East'''}) lyr1 = mapnik.Layer('One') lyr1.datasource = ds1 lyr1.styles.append('points') m.layers.append(lyr1) ds2 = mapnik.Datasource(**{"type":"csv","inline":''' wkt,Value "POINT (142.48 -38.60)",South West'''}) lyr2 = mapnik.Layer('Two') lyr2.datasource = ds2 lyr2.styles.append('points') m.layers.append(lyr2) ul_lonlat = mapnik.Coord(142.30,-38.20) lr_lonlat = mapnik.Coord(143.40,-38.80) m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat)) grid = mapnik.Grid(m.width,m.height) mapnik.render_layer(m,grid,layer=0,fields=['Name']) # should throw right here since Name will be a property now on the `grid` object # and it is not found on the second layer mapnik.render_layer(m,grid,layer=1,fields=['Value']) grid.encode()
def __init__(self, tile_dir, xmlmap, q, printLock, maxZoom, fields=None, layer_id=None): self.tile_dir = tile_dir self.q = q self.render_size = 256 self.m = mapnik.Map(self.render_size, self.render_size) self.g = mapnik.Grid(self.render_size, self.render_size) self.printLock = printLock # Load style XML mapnik.load_map_from_string(self.m, xmlmap) # Obtain <Map> projection self.prj = mapnik.Projection(self.m.srs) # Projects between tile pixel co-ordinates and LatLong (EPSG:4326) self.tileproj = GoogleProjection(maxZoom + 1) self.layer_id = layer_id self.fields = fields or []
def gen_grid_for_id(pixel_key): ds = mapnik.MemoryDatasource() context = mapnik.Context() context.push('Name') f = mapnik.Feature(context,pixel_key) f['Name'] = str(pixel_key) f.add_geometries_from_wkt('POLYGON ((0 0, 0 256, 256 256, 256 0, 0 0))') ds.add_feature(f) s = mapnik.Style() r = mapnik.Rule() symb = mapnik.PolygonSymbolizer() r.symbols.append(symb) s.rules.append(r) lyr = mapnik.Layer('Places') lyr.datasource = ds lyr.styles.append('places_labels') width,height = 256,256 m = mapnik.Map(width,height) m.append_style('places_labels',s) m.layers.append(lyr) m.zoom_all() grid = mapnik.Grid(m.width,m.height,key='__id__') mapnik.render_layer(m,grid,layer=0,fields=['__id__','Name']) return grid
def renderArea(self, width, height, srs, xmin, ymin, xmax, ymax, zoom, auth): """ """ start_time = time() # # Mapnik can behave strangely when run in threads, so place a lock on the instance. # if global_mapnik_lock.acquire(): try: if self.mapnik is None: self.mapnik = get_mapnikMap(self.mapfile) logging.debug( 'TileStache.Mapnik.GridProvider.renderArea() %.3f to load %s', time() - start_time, self.mapfile) for la in self.mapnik.layers: query = """(SELECT * FROM {} WHERE {} IN ({}) ) AS {}""".format( self.table, self.auth_column, ', '.join(str(i) for i in auth), self.table) la.datasource = mapnik.PostGIS( host=str(self.host), geometry_field=str(self.geometry_field), key_field=str(self.key_field), user=str(self.user), password=str(self.password), dbname=str(self.dbname), table=query) self.mapnik.width = width self.mapnik.height = height self.mapnik.zoom_to_box(Box2d(xmin, ymin, xmax, ymax)) if self.layer_id_key is not None: grids = [] for (index, fields) in self.layers: datasource = self.mapnik.layers[index].datasource fields = (type(fields) is list) and map( str, fields) or datasource.fields() grid = mapnik.render_grid(self.mapnik, index, resolution=self.scale, fields=fields) for key in grid['data']: grid['data'][key][ self. layer_id_key] = self.mapnik.layers[index].name grids.append(grid) # global_mapnik_lock.release() outgrid = reduce(merge_grids, grids) else: grid = mapnik.Grid(width, height) for (index, fields) in self.layers: datasource = self.mapnik.layers[index].datasource fields = (type(fields) is list) and map( str, fields) or datasource.fields() mapnik.render_layer(self.mapnik, grid, layer=index, fields=fields) # global_mapnik_lock.release() outgrid = grid.encode('utf', resolution=self.scale, features=True) except: self.mapnik = None raise finally: global_mapnik_lock.release() logging.debug( 'TileStache.Mapnik.GridProvider.renderArea() %dx%d at %d in %.3f from %s', width, height, self.scale, time() - start_time, self.mapfile) return SaveableResponse(outgrid, self.scale)
def create_utfgrids(shppath, minzoom, maxzoom, outdir, fields=None, layernum=0): ds = ogr.Open(shppath) print print "WARNING:" print " This script assumes a polygon shapefile in spherical mercator projection." print " If any of these assumptions are not true, don't count on the results!" # TODO confirm polygons # TODO confirm mercator # TODO get layernum from command line layer = ds.GetLayer(layernum) bbox = layer.GetExtent() mercator = globalmaptiles.GlobalMercator() m = mapnik.Map(256,256) # Since grids are `rendered` they need a style s = mapnik.Style() r = mapnik.Rule() polygon_symbolizer = mapnik.PolygonSymbolizer(mapnik.Color('#f2eff9')) r.symbols.append(polygon_symbolizer) line_symbolizer = mapnik.LineSymbolizer(mapnik.Color('rgb(50%,50%,50%)'),0.1) r.symbols.append(line_symbolizer) s.rules.append(r) m.append_style('My Style',s) ds = mapnik.Shapefile(file=shppath) mlayer = mapnik.Layer('poly') mlayer.datasource = ds mlayer.styles.append('My Style') m.layers.append(mlayer) if fields is None: fields = mlayer.datasource.fields() for tz in range(minzoom, maxzoom+1): print " * Processing Zoom Level %s" % tz tminx, tminy = mercator.MetersToTile( bbox[0], bbox[2], tz) tmaxx, tmaxy = mercator.MetersToTile( bbox[1], bbox[3], tz) for ty in range(tminy, tmaxy+1): for tx in range(tminx, tmaxx+1): output = os.path.join(outdir, str(tz), str(tx)) if not os.path.exists(output): os.makedirs(output) # Use top origin tile scheme (like OSM or GMaps) # TODO support option for TMS bottom origin scheme (ie opt to not invert) ymax = 1 << tz; invert_ty = ymax - ty - 1; tilefilename = os.path.join(output, "%s.json" % invert_ty) # ty for TMS bottom origin tilebounds = mercator.TileBounds( tx, ty, tz) #print tilefilename, tilebounds box = mapnik.Box2d(*tilebounds) m.zoom_to_box(box) grid = mapnik.Grid(m.width,m.height) mapnik.render_layer(m,grid,layer=0,fields=fields) utfgrid = grid.encode('utf',resolution=4) with open(tilefilename, 'w') as file: file.write(json.dumps(utfgrid))
def render_grid(m, output, scale_factor): grid = mapnik.Grid(m.width, m.height) mapnik.render_layer(m, grid, layer=0) utf1 = grid.encode('utf', resolution=4) open(output,'wb').write(json.dumps(utf1, indent=1))
#!/usr/bin/env python # -*- coding: utf-8 -*- import mapnik try: import json except ImportError: import simplejson as json if __name__ == "__main__": m = mapnik.Map(256, 256) mapnik.load_map(m, 'stylesheet.xml') box = mapnik.Box2d(-140, 0, -50, 90) m.zoom_to_box(box) grid = mapnik.Grid(m.width, m.height) mapnik.render_layer(m, grid, layer=0, fields=['NAME_FORMA', 'POP_EST']) utfgrid = grid.encode('utf', resolution=4) print json.dumps(utfgrid)
composer = Utfgrid.Utfgrid() for mapfile in mapfiles: t0 = time.clock() t0_ = time.time() sys.stdout.write("\tRendering '%s'..." % (mapfile)) sys.stdout.flush() m = mapnik.Map(mtileSize,mtileSize) mapnik.load_map(m, "%s/~map-%s.xml" % (mappath,mapfile), True) m.buffer_size = 0 m.resize(mtileSize, mtileSize) m.zoom_to_box(bbox) for n,l in enumerate(m.layers): tmp = re.sub(r'((?:-layer|-priority|-grade|-class)[-]?[0-9]+)','',l.name) name = re.sub(r'((?:route)[-]?[0-9]+)','route',tmp) if name in gridinfo: grid = mapnik.Grid(mtileSize, mtileSize) mapnik.render_layer(m, grid, layer = n, fields = gridinfo[name]) utfgrid = grid.encode('utf',resolution=RESOLUTION) for key1 in utfgrid['data']: for key2,val2 in utfgrid['data'][key1].items(): if val2 in (None,'no',''): del utfgrid['data'][key1][key2] composer.addLayer(json.dumps(utfgrid, ensure_ascii = False)) sys.stdout.write("done. (%gs/%gs)\n" % (time.clock() - t0,time.time() - t0_)) sys.stdout.flush()