def make_map(map_output, scale=20000, x_center=622000, y_center=6406000): "Make a map as a function of the scale" # Compute the scale page_size = int(PAGE_FORMAT[1]) f = math.sqrt(2)**PAGES[page_size] # increasing map_x and map_y lead to decreasing font and symbol size: not good map_x = int(f * 4600) # 4600 is the number of pixels for an A4 length # if 460: zoom = 13 map_y = int(map_x / math.sqrt(2)) m = Map(map_x, map_y) load_map(m, MAPNIK_FILE) # Bounding box (expressed in EPSG:3857, meters) delta_x = f * 0.295 * scale / math.cos(LATITUDE * 2 * math.pi / 360) delta_y = delta_x / math.sqrt(2) xmin = x_center - delta_x / 2 xmax = x_center + delta_x / 2 ymin = y_center - delta_y / 2 ymax = y_center + delta_y / 2 bbox = (Envelope(xmin, ymin, xmax, ymax)) m.zoom_to_box(bbox) print("Scale = " + str(m.scale())) render_to_file(m, map_output)
def loadXML(self, xmlfile=None, strict=False, xmlstring='', basepath=''): """Loads and stores a complete map definition in leiu of a set of layers. Stores an empty style of the same name, which is the only option for rendering. The map will be rendered as prescribed in the XML.""" config = ConfigParser.SafeConfigParser() map_wms_srs = None if self.configpath: config.readfp(open(self.configpath)) if config.has_option('map', 'wms_srs'): map_wms_srs = config.get('map', 'wms_srs') tmp_map = Map(0,0) if xmlfile: load_map(tmp_map, xmlfile, strict) elif xmlstring: load_map_from_string(tmp_map, xmlstring, strict, basepath) else: raise ServerConfigurationError("Mapnik configuration XML is not specified - 'xmlfile' and 'xmlstring' variables are empty.\ Please set one of this variables to load mapnik map object.") # parse map level attributes if tmp_map.background: self.map_attributes['bgcolor'] = tmp_map.background if tmp_map.buffer_size: self.map_attributes['buffer_size'] = tmp_map.buffer_size if xmlfile is None : # Map objects have no name, so just call it default. layer_name = 'default' else : # The layer name is the basename of the xml file or the # whole file name layer_name = xmlfile fname_match = re.match('([A-Za-z0-9_\-\.]+).xml', xmlfile) if fname_match is not None : layer_name = fname_match.group(1) else : layer_name = xmlfile style_name = layer_name style_obj = Style() # Make the map have attributes expected of layers tmp_map.name = layer_name map_p = common.Projection(tmp_map.srs) if map_wms_srs is None : tmp_map.wms_srs = map_p.epsgstring() else : tmp_map.wms_srs = map_wms_srs tmp_map.queryable = False # set map extent from config file. geog_coords = config.get('map','wms_extent').split(',') geog_box = Box2d(float(geog_coords[0]), float(geog_coords[1]), float(geog_coords[2]), float(geog_coords[3])) proj_box = geog_box.forward(map_p) tmp_map.zoom_to_box(proj_box) tmp_map.maximum_extent = proj_box self.register_style(style_name, style_obj) self.register_layer(tmp_map, style_name)
def _buildMap(self, params): if str(params['crs']) not in self.allowedepsgcodes: raise OGCException('Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS') if params['bbox'][0] >= params['bbox'][2]: raise OGCException("BBOX values don't make sense. minx is greater than maxx.") if params['bbox'][1] >= params['bbox'][3]: raise OGCException("BBOX values don't make sense. miny is greater than maxy.") if params.has_key('styles') and len(params['styles']) != len(params['layers']): raise OGCException('STYLES length does not match LAYERS length.') m = Map(params['width'], params['height'], '+init=%s' % params['crs']) if params.has_key('transparent') and params['transparent'] == 'FALSE': if params['bgcolor']: m.background = params['bgcolor'] else: m.background = Color(0, 0, 0, 0) maplayers = self.mapfactory.layers orderedmaplayers = self.mapfactory.ordered_layers mapstyles = self.mapfactory.styles mapaggregatestyles = self.mapfactory.aggregatestyles # a non WMS spec way of requesting all layers if params['layers'] and params['layers'][0] == '__all__': for layername in orderedmaplayers: layer = copy_layer(layername) reqstyle = layer.wmsdefaultstyle if reqstyle in mapaggregatestyles.keys(): for stylename in mapaggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) m.layers.append(layer) else: for layerindex, layername in enumerate(params['layers']): try: layer = copy_layer(maplayers[layername]) except KeyError: raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined') try: reqstyle = params['styles'][layerindex] except IndexError: reqstyle = '' if reqstyle and reqstyle not in layer.wmsextrastyles: raise OGCException('Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined') if not reqstyle: reqstyle = layer.wmsdefaultstyle if reqstyle in mapaggregatestyles.keys(): for stylename in mapaggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) else: raise ServerConfigurationError('Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) m.layers.append(layer) m.zoom_to_box(Box2d(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) return m
def tile_generator(zoom_lvl, tile_width, tile_height, style_sheet, target_storage_path): print('\n\t[+]Generating tiles in zoom level -- {}\n'.format(zoom_lvl)) tiles = get_tile_extent(zoom_lvl, (-180, +90), tile_width, tile_height, 360, 180) if (not tiles): return False for key, value in tiles.items(): map_obj = Map(tile_width, tile_height, '+proj=longlat +datum=WGS84 +no_defs ') if (not format_style_sheet(style_sheet, [ 'layer1', 'layer2', 'layer3', 'layer4', 'layer5', 'layer6' ], 'Parameter', ['name', 'extent'], '{}, {}, {}, {}'.format(*value), 'tmp.xml')): return False print('\t\t[+]Rendering tile {} - {} - {} ...'.format( zoom_lvl, *key.split(','))) load_map(map_obj, 'tmp.xml') # loads generated XML style sheet map_obj.zoom_to_box(Box2d(*value)) render_to_file( map_obj, join(target_storage_path, '{}_{}_{}.png'.format(zoom_lvl, *key.split(','))), 'png256') # removes temporary XML file, which was generated from template XML unlink('tmp.xml') return True
def GetMap(self, params): if params["bbox"][0] >= params["bbox"][2]: raise OGCException("BBOX values don't make sense. minx is greater than maxx.") if params["bbox"][1] >= params["bbox"][3]: raise OGCException("BBOX values don't make sense. miny is greater than maxy.") if params.has_key("styles") and len(params["styles"]) != len(params["layers"]): raise OGCException("STYLES length does not match LAYERS length.") m = Map(params["width"], params["height"]) if params.has_key("transparent") and params["transparent"] == "FALSE": m.background = params["bgcolor"] else: m.background = Color(0, 0, 0, 0) maplayers = self.mapfactory.layers mapstyles = self.mapfactory.styles for layername in params["layers"]: try: layer = maplayers[layername] except KeyError: raise OGCException('Layer "%s" not defined.' % layername, "LayerNotDefined") for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) else: raise ServerConfigurationError( 'Layer "%s" refers to non-existent style "%s".' % (layername, stylename) ) m.layers.append(layer) m.zoom_to_box(Envelope(params["bbox"][0], params["bbox"][1], params["bbox"][2], params["bbox"][3])) im = Image(params["width"], params["height"]) render(m, im) im = fromstring("RGBA", (params["width"], params["height"]), rawdata(im)) fh = StringIO() im.save(fh, PIL_TYPE_MAPPING[params["format"]], quality=100) fh.seek(0) return Response(params["format"], fh.read())
def _buildMap(self, params): if str(params['crs']) not in self.allowedepsgcodes: raise OGCException( 'Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS') if params['bbox'][0] >= params['bbox'][2]: raise OGCException( "BBOX values don't make sense. minx is greater than maxx.") if params['bbox'][1] >= params['bbox'][3]: raise OGCException( "BBOX values don't make sense. miny is greater than maxy.") if params.has_key('styles') and len(params['styles']) != len( params['layers']): raise OGCException('STYLES length does not match LAYERS length.') m = Map(params['width'], params['height'], '+init=%s' % params['crs']) if params.has_key('transparent') and params['transparent'] == 'FALSE': m.background = params['bgcolor'] else: m.background = Color(0, 0, 0, 0) maplayers = self.mapfactory.layers mapstyles = self.mapfactory.styles mapaggregatestyles = self.mapfactory.aggregatestyles for layerindex, layername in enumerate(params['layers']): try: layer = maplayers[layername] except KeyError: raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined') reqstyle = params['styles'][layerindex] if reqstyle and reqstyle not in layer.wmsextrastyles: raise OGCException( 'Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined') if not reqstyle: reqstyle = layer.wmsdefaultstyle if reqstyle in mapaggregatestyles.keys(): for stylename in mapaggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) else: raise ServerConfigurationError( 'Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) m.layers.append(layer) m.zoom_to_box( Envelope(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) return m
def __renderCountry__(myMap: mapnik.Map, bbox: mapnik._Box2d, target_file: str, imageType: str) -> bool: ''' Renders a certain country's map, for which BoundingBox is provided Generated image file will be stored in provided path. ''' target = False try: myMap.zoom_to_box(bbox) mapnik.render_to_file(myMap, target_file, imageType) target = True except Exception: target = False finally: return target
def GetMap(self, params): if params['bbox'][0] >= params['bbox'][2]: raise OGCException( "BBOX values don't make sense. minx is greater than maxx.") if params['bbox'][1] >= params['bbox'][3]: raise OGCException( "BBOX values don't make sense. miny is greater than maxy.") if params.has_key('styles') and len(params['styles']) != len( params['layers']): raise OGCException('STYLES length does not match LAYERS length.') m = Map(params['width'], params['height']) if params.has_key('transparent') and params['transparent'] == 'FALSE': m.background = params['bgcolor'] else: m.background = Color(0, 0, 0, 0) maplayers = self.mapfactory.layers mapstyles = self.mapfactory.styles for layername in params['layers']: try: layer = maplayers[layername] except KeyError: raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined') for stylename in layer.styles: if stylename in mapstyles.keys(): m.append_style(stylename, mapstyles[stylename]) else: raise ServerConfigurationError( 'Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) m.layers.append(layer) m.zoom_to_box( Envelope(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) im = Image(params['width'], params['height']) render(m, im) im = fromstring('RGBA', (params['width'], params['height']), rawdata(im)) fh = StringIO() im.save(fh, PIL_TYPE_MAPPING[params['format']], quality=100) fh.seek(0) return Response(params['format'], fh.read())
def __call__(self, layers, system): request = system['request'] # get image width and height width = 256 height = 256 # get image bbox z = int(request.matchdict['z']) x = int(request.matchdict['x']) y = int(request.matchdict['y']) step = max/(2**(int(z) - 1)) xmin = x*step-max ymin = max-y*step xmax = (x+1)*step-max ymax = max-(y+1)*step bbox = Box2d(xmin, ymax, xmax, ymin) m = Map(width, height) load_map(m, abspath_from_asset_spec('osmtm:views/map.xml')) for l in layers: m.layers.append(l) m.zoom_to_box(bbox) format = request.matchdict['format'] if format == 'png': im = Image(width, height) render(m, im, 1, 1) request.response_content_type = 'image/png' return im.tostring('png') elif format == 'json': grid = Grid(width, height) render_layer(m, grid, layer=0, fields=['id']) utfgrid = grid.encode('utf', resolution=4) return json.dumps(utfgrid)
def __call__(self, layers, system): request = system['request'] # get image width and height width = 256 height = 256 # get image bbox z = int(request.matchdict['z']) x = int(request.matchdict['x']) y = int(request.matchdict['y']) step = max / (2**(int(z) - 1)) xmin = x * step - max ymin = max - y * step xmax = (x + 1) * step - max ymax = max - (y + 1) * step bbox = Box2d(xmin, ymax, xmax, ymin) m = Map(width, height) load_map(m, abspath_from_asset_spec('osmtm:views/map.xml')) for l in layers: m.layers.append(l) m.zoom_to_box(bbox) format = request.matchdict['format'] if format == 'png': im = Image(width, height) render(m, im, 1, 1) request.response_content_type = 'image/png' return im.tostring('png') elif format == 'json': grid = Grid(width, height) render_layer(m, grid, layer=0, fields=['id']) utfgrid = grid.encode('utf', resolution=4) return json.dumps(utfgrid)
r.symbols.append(PolygonSymbolizer(Color('#f2eff9'))) r.symbols.append(LineSymbolizer(Color('rgb(50%,50%,50%)'), 0.1)) s.rules.append(r) m.append_style('My Style', s) lyr = Layer('france', proj4) import os shp = Shapefile(base='.', file='departement') lyr.datasource = shp #lyr.datasource = SQLite(base=os.getcwd(), file = sqlitedatabase, table = tablename, geometry_field = 'Geometry', key_field = 'ID_GEOFLA', extent = shp_extent, wkb_format = 'spatialite') lyr.styles.append('My Style') lyr.styles.append('Text') m.layers.append(lyr) m.zoom_to_box(lyr.envelope()) file_formats = { 'svg': cairo.SVGSurface, } for type_format in file_formats: print '// -- Rendering %s -----------------------------' % type_format file_open = open('%s.%s' % (map_output, type_format), 'w') surface = file_formats[type_format](file_open.name, m.width, m.height) render(m, surface) save_map(m, "tmp_map.xml") surface.finish()
class MapRenderer: """ Class for rendering maps through mapnik """ def __init__(self, content): """ With MapRenderer you can render an aktionskarten map in different file formats like pdf, svg or png. Internally it uses mapnik and cairo to archieve this. A valid style has to be defined through `MAPNIK_OSM_XML`. Normally this a carto derived `style.xml`. In this file your datasource is specified. This can be for instance a postgres+postgis database with imported osm data. :param content: dict of map content """ # Mapnik uses mercator as internal projection. Our data is encoded in # latlon. Therefor we need a transformer for coordindates from longlat # to mercator proj_merc = Projection('+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0\ +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m \ +nadgrids=@null +no_defs +over') proj_longlat = Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 \ +no_defs') transformer = ProjTransform(proj_longlat, proj_merc) # our maps should be printable on a DIN A4 page with 150dpi self._map = Map(1754, 1240) bbox = transformer.forward(Box2d(*content['bbox'])) self._map.zoom_to_box(bbox) self._map.buffer_size = 5 start = timer() # add osm data (background) load_map(self._map, current_app.config['MAPNIK_OSM_XML']) mid = timer() self._add_grid(content['grid']) self._add_features(content['features']) self._add_legend(content['name'], content['place'], content['datetime'], content['attributes']) end = timer() print("Map.init - OSM: ", mid - start) print("Map.init - Map: ", end - mid) print("Map.init - Total: ", end - start) def _add_legend(self, name, place, datetime, attributes): features = [] box = self._map.envelope() # add name, place and date point = Point((box.minx, box.maxy)) features.append(Feature(geometry=point, properties={ 'name': name, 'place': place, 'date': datetime#strftime('%d.%m.%Y %H:%M') })) # add properties if (attributes and len(attributes) > 0): cell_size = ((box.maxy - box.miny) / 11.) offset = cell_size / 3 x = box.minx + offset y = box.miny + offset for i, (k, v) in enumerate(attributes): point = Point((x, y+offset*i)) properties = {'key': k, 'value': v} features.append(Feature(geometry=point, properties=properties)) # add osm copyright properties = { 'type': 'copyright', 'text': 'Tiles © OpenStreetMap contributers, CC-BY-SA' } point = Point((box.maxx, box.miny)) features.append(Feature(geometry=point, properties=properties)) # render them collection = json.dumps(FeatureCollection(features)) xml_str = get_xml("styles/legend.xml").format(collection).encode() load_map_from_string(self._map, xml_str) def _add_features(self, features): # add all features (as features are rendered on top of each other in the # order we provide it to mapnik, make sure markers are on top) types = ['Polygon', 'LineString', 'Point'] getter = lambda x: types.index(x['geometry']['type']) entries = sorted([strip(f) for f in features], key=getter) collection = json.dumps(FeatureCollection(entries)) xml_str = get_xml("styles/features.xml").format(collection).encode() load_map_from_string(self._map, xml_str) def _add_grid(self, grid): xml_str = get_xml("styles/grid.xml").format(json.dumps(grid)).encode() load_map_from_string(self._map, xml_str) def render(self, mimetype='application/pdf', scale=1): """ Renders a map through mapnik and in cases uses cairo to export in different file types. By default as a single paged `pdf` but you can pick as well other mimetypes. Maps are rendered and returned as in-memory file :class:`io.ByteIO`. Depending on the bounding box of your map, this is a ressouce and time consuming process. For web applications you should outsource it for instance in a task queue. Through scale you can alter the size of the rendered output. Currently only `image/png` supports this parameter. Normally this is a value between 0 and 1. For instance for aktionskarten the following sizings are used: small 0.5 medium 0.75 large 1 :param mimetype: `image/svg+xml`, `image/png` or `image/pdf` :param scale: scale factor for sizing """ start = timer() # export is done as in-memory file f = BytesIO() # create corresponding surface for mimetype if mimetype == 'image/svg+xml': surface = cairo.SVGSurface(f, self._map.width, self._map.height) # limit svg version to at least 1.2 otherwise we end up with an # embedded image instead of vector data. See as well: # * github.com/mapnik/mapnik/pull/4029 # * github.com/mapnik/mapnik/issues/3749 surface.restrict_to_version(cairo.SVGVersion.VERSION_1_2) elif mimetype == 'image/png': surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self._map.width, self._map.height) else: surface = cairo.PDFSurface(f, self._map.width, self._map.height) # let mapnik render the actual map render(self._map, surface) # pngs can be in different sizes through a scaling factor if mimetype == 'image/png': if (scale != 1): # render first and then scale resulting image otherwise fonts # occurr in wrong sizes pattern = cairo.SurfacePattern(surface) scaler = cairo.Matrix() scaler.scale(1./scale, 1./scale) pattern.set_matrix(scaler) pattern.set_filter(cairo.FILTER_FAST) # apply scale and save as new image surface width = int(self._map.width * scale) height = int(self._map.height * scale) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) ctx = cairo.Context(surface) ctx.set_source(pattern) ctx.paint() surface.write_to_png(f) else: surface.finish() f.seek(0) end = timer() print("Map.render: ", end - start) return f
r.symbols.append(PolygonSymbolizer(Color('#f2eff9'))) r.symbols.append(LineSymbolizer(Color('rgb(50%,50%,50%)'), 0.1)) s.rules.append(r) m.append_style('My Style', s) lyr = Layer('france', proj4) import os shp = Shapefile(base='.',file='departement') lyr.datasource = shp #lyr.datasource = SQLite(base=os.getcwd(), file = sqlitedatabase, table = tablename, geometry_field = 'Geometry', key_field = 'ID_GEOFLA', extent = shp_extent, wkb_format = 'spatialite') lyr.styles.append('My Style') lyr.styles.append('Text') m.layers.append(lyr) m.zoom_to_box(lyr.envelope()) file_formats = {'svg': cairo.SVGSurface, } for type_format in file_formats: print '// -- Rendering %s -----------------------------' % type_format file_open = open('%s.%s' % (map_output, type_format), 'w') surface = file_formats[type_format](file_open.name, m.width, m.height) render(m, surface) save_map(m,"tmp_map.xml") surface.finish()
from mapnik import render, Image, Map, load_map, Projection, Coord, Envelope projection = Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 " "+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m " "+nadgrids=@null +no_defs +over") map = Map(600, 600) load_map(map, "simple.xml") bbox = Envelope(Coord(-20037508.34, -20037508.34), Coord(20037508.34, 20037508.34)) map.zoom_to_box(bbox) image = Image(600, 600) render(map, image) with open('test.png', 'w') as image_file: image_file.write(image.tostring('png'))
from mapnik import PolygonSymbolizer, LineSymbolizer, Rule, Style, Color, Layer, Shapefile, Map, Image, render rule = Rule() rule.symbols.append(PolygonSymbolizer(Color("grey"))) rule.symbols.append(LineSymbolizer(Color("black"), 0.1)) style = Style() style.rules.append(rule) layer = Layer("world") layer.datasource = Shapefile(file="coastlines/land") layer.styles.append("world") m = Map(800, 400) m.background = Color("white") m.append_style("world", style) m.layers.append(layer) m.zoom_to_box(layer.envelope()) image = Image(800, 400) render(m, image) with open("test.png", "w") as image_file: image_file.write(image.tostring("png"))
from mapnik import render, Image, Map, load_map, Projection, Coord, Envelope projection = Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 " "+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m " "+nadgrids=@null +no_defs +over") map = Map(600, 600) load_map(map, "simple.xml") bbox = Envelope(Coord(-179.999999975, -85.0511287776), Coord(179.999999975, 85.0511287776)) map.zoom_to_box(bbox.forward(projection)) image = Image(600, 600) render(map, image) with open('test.png', 'w') as image_file: image_file.write(image.tostring('png'))
logging.info("range: bottomleft(%s, %s), topright(%s, %s)" % (west, lat - lat_half, east, lat + lat_half)) return west, south, east, north if __name__ == "__main__": mapfile = "my_styles/mapnik2normal.xml" map_uri = "map.png" lat = 49.25 lon = 7.0 if len(sys.argv) == 2: zoom = int(sys.argv[1]) else: zoom = 13 imgx = 500 imgy = 400 ll = center_to_bbox(lat, lon, zoom, imgx, imgy) m = Map(imgx, imgy) load_map(m, mapfile) prj = Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m" " +nadgrids=@null +no_defs +over") c0 = prj.forward(Coord(ll[0], ll[1])) c1 = prj.forward(Coord(ll[2], ll[3])) bbox = Box2d(c0.x, c0.y, c1.x, c1.y) m.zoom_to_box(bbox) im = Image(imgx, imgy) render(m, im) view = im.view(0, 0, imgx, imgy) # x,y,width,height view.save(map_uri, 'png')
if __name__ == "__main__": mapfile = "my_styles/mapnik2normal.xml" map_uri = "map.png" lat = 49.25 lon = 7.0 if len(sys.argv) == 2: zoom = int(sys.argv[1]) else: zoom = 13 imgx = 500 imgy = 400 ll = center_to_bbox(lat, lon, zoom, imgx, imgy) m = Map(imgx, imgy) load_map(m, mapfile) prj = Projection( "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m" " +nadgrids=@null +no_defs +over") c0 = prj.forward(Coord(ll[0], ll[1])) c1 = prj.forward(Coord(ll[2], ll[3])) bbox = Box2d(c0.x, c0.y, c1.x, c1.y) m.zoom_to_box(bbox) im = Image(imgx, imgy) render(m, im) view = im.view(0, 0, imgx, imgy) # x,y,width,height view.save(map_uri, 'png')
from mapnik import render, Image, Map, load_map map = Map(600, 600) load_map(map, "simple.xml") map.zoom_to_box(map.layers[0].envelope()) image = Image(600, 600) render(map, image) with open('test.png', 'w') as f: f.write(image.tostring('png'))
def _render(value, system): request = system['request'] if not isinstance(value, tuple): value = (None, value) layer_name, collection = value if not hasattr(collection, 'features'): raise ValueError('renderer is not passed a feature collection') # get image width and height try: img_width = int(request.params.get('img_width', 256)) except: request.response_status = 400 return 'incorrect img_width' try: img_height = int(request.params.get('img_height', 256)) except: request.response_status = 400 return 'incorrect img_height' # get image format try: img_format = request.params.get( 'img_format', request.matchdict.get('format', 'png')) img_format = str(img_format) except: request.response_status = 400 return 'incorrect img_format' # get image bbox img_bbox = request.params.get('img_bbox', request.params.get('bbox')) if img_bbox: try: img_bbox = map(float, img_bbox.split(',')) except ValueError: request.response_status = 400 return 'incorrect img_bbox' img_bbox = Box2d(*img_bbox) m = Map(img_width, img_height) load_map(m, mapfile) if len(m.layers) == 0: raise ValueError('no layer in the mapnik map') # if no layer_name is provided then, by convention, use # the first layer in the mapnik map if layer_name is None: layer_name = m.layers[0].name layer = self._set_layer_in_map(m, layer_name) layer.datasource = self._create_datasource(collection) m.zoom_to_box(img_bbox or layer.envelope()) im = Image(img_width, img_height) render(m, im, 1, 1) # get the image format from the request request.response.content_type = 'image/%s' % img_format return im.tostring(img_format)
def _buildMap(self, params): if str(params['crs']) not in self.allowedepsgcodes: raise OGCException('Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS') if params['bbox'][0] >= params['bbox'][2]: raise OGCException("BBOX values don't make sense. minx is greater than maxx.") if params['bbox'][1] >= params['bbox'][3]: raise OGCException("BBOX values don't make sense. miny is greater than maxy.") # relax this for now to allow for a set of specific layers (meta layers even) # to be used without known their styles or putting the right # of commas... #if params.has_key('styles') and len(params['styles']) != len(params['layers']): # raise OGCException('STYLES length does not match LAYERS length.') m = Map(params['width'], params['height'], '+init=%s' % params['crs']) if params.has_key('transparent') and params['transparent'] in ('FALSE','False','false'): if params['bgcolor']: m.background = params['bgcolor'] elif not params.has_key('transparent') and self.mapfactory.map_attributes.get('bgcolor'): m.background = self.mapfactory.map_attributes['bgcolor'] else: m.background = Color(0, 0, 0, 0) if params.has_key('buffer_size'): if params['buffer_size']: m.buffer_size = params['buffer_size'] else: buffer_ = self.mapfactory.map_attributes.get('buffer_size') if buffer_: m.buffer_size = self.mapfactory.map_attributes['buffer_size'] # haiti spec tmp hack! show meta layers without having # to request huge string to avoid some client truncating it! if params['layers'] and params['layers'][0] in ('osm_haiti_overlay','osm_haiti_overlay_900913'): for layer_obj in self.mapfactory.ordered_layers: layer = copy_layer(layer_obj) if not hasattr(layer,'meta_style'): pass else: layer.styles.append(layer.meta_style) m.append_style(layer.meta_style, self.mapfactory.meta_styles[layer.meta_style]) m.layers.append(layer) # a non WMS spec way of requesting all layers # uses orderedlayers that preserves original ordering in XML mapfile elif params['layers'] and params['layers'][0] == '__all__': for layer_obj in self.mapfactory.ordered_layers: # if we don't copy the layer here we get # duplicate layers added to the map because the # layer is kept around and the styles "pile up"... layer = copy_layer(layer_obj) if hasattr(layer,'meta_style'): continue reqstyle = layer.wmsdefaultstyle if reqstyle in self.mapfactory.aggregatestyles.keys(): for stylename in self.mapfactory.aggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in self.mapfactory.styles.keys(): m.append_style(stylename, self.mapfactory.styles[stylename]) m.layers.append(layer) else: for layerindex, layername in enumerate(params['layers']): if layername in self.mapfactory.meta_layers: layer = copy_layer(self.mapfactory.meta_layers[layername]) layer.styles.append(layername) m.append_style(layername, self.mapfactory.meta_styles[layername]) else: try: # uses unordered dict of layers # order based on params['layers'] request which # should be originally informed by order of GetCaps response layer = copy_layer(self.mapfactory.layers[layername]) except KeyError: raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined') try: reqstyle = params['styles'][layerindex] except IndexError: reqstyle = '' if reqstyle and reqstyle not in layer.wmsextrastyles: raise OGCException('Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined') if not reqstyle: reqstyle = layer.wmsdefaultstyle if reqstyle in self.mapfactory.aggregatestyles.keys(): for stylename in self.mapfactory.aggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in self.mapfactory.styles.keys(): m.append_style(stylename, self.mapfactory.styles[stylename]) else: raise ServerConfigurationError('Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) m.layers.append(layer) m.zoom_to_box(Envelope(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) return m
def _buildMap(self, params): if str(params['crs']) not in self.allowedepsgcodes: raise OGCException( 'Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS') if params['bbox'][0] >= params['bbox'][2]: raise OGCException( "BBOX values don't make sense. minx is greater than maxx.") if params['bbox'][1] >= params['bbox'][3]: raise OGCException( "BBOX values don't make sense. miny is greater than maxy.") # relax this for now to allow for a set of specific layers (meta layers even) # to be used without known their styles or putting the right # of commas... #if params.has_key('styles') and len(params['styles']) != len(params['layers']): # raise OGCException('STYLES length does not match LAYERS length.') m = Map(params['width'], params['height'], '+init=%s' % params['crs']) transparent = params.get('transparent', '').lower() == 'true' # disable transparent on incompatible formats if transparent and params.get('format', '') == 'image/jpeg': transparent = False if transparent: # transparent has highest priority pass elif params.has_key('bgcolor'): # if not transparent use bgcolor in url m.background = params['bgcolor'] else: # if not bgcolor in url use map background if mapnik_version() >= 200000: bgcolor = self.mapfactory.map_attributes.get('bgcolor', None) else: bgcolor = self.mapfactory.map_attributes.get( 'background-color', None) if bgcolor: m.background = bgcolor else: # if not map background defined use white color m.background = Color(255, 255, 255, 255) if params.has_key('buffer_size'): if params['buffer_size']: m.buffer_size = params['buffer_size'] else: buffer_ = self.mapfactory.map_attributes.get('buffer_size') if buffer_: m.buffer_size = self.mapfactory.map_attributes['buffer_size'] # haiti spec tmp hack! show meta layers without having # to request huge string to avoid some client truncating it! if params['layers'] and params['layers'][0] in ( 'osm_haiti_overlay', 'osm_haiti_overlay_900913'): for layer_obj in self.mapfactory.ordered_layers: layer = copy_layer(layer_obj) if not hasattr(layer, 'meta_style'): pass else: layer.styles.append(layer.meta_style) m.append_style( layer.meta_style, self.mapfactory.meta_styles[layer.meta_style]) m.layers.append(layer) # a non WMS spec way of requesting all layers # uses orderedlayers that preserves original ordering in XML mapfile elif params['layers'] and params['layers'][0] == '__all__': for layer_obj in self.mapfactory.ordered_layers: # if we don't copy the layer here we get # duplicate layers added to the map because the # layer is kept around and the styles "pile up"... layer = copy_layer(layer_obj) if hasattr(layer, 'meta_style'): continue reqstyle = layer.wmsdefaultstyle if reqstyle in self.mapfactory.aggregatestyles.keys(): for stylename in self.mapfactory.aggregatestyles[reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in self.mapfactory.styles.keys(): m.append_style(stylename, self.mapfactory.styles[stylename]) m.layers.append(layer) else: for layerindex, layername in enumerate(params['layers']): if layername in self.mapfactory.meta_layers: layer = copy_layer(self.mapfactory.meta_layers[layername]) layer.styles.append(layername) m.append_style(layername, self.mapfactory.meta_styles[layername]) else: try: # uses unordered dict of layers # order based on params['layers'] request which # should be originally informed by order of GetCaps response layer = copy_layer(self.mapfactory.layers[layername]) except KeyError: raise OGCException( 'Layer "%s" not defined.' % layername, 'LayerNotDefined') try: reqstyle = params['styles'][layerindex] except IndexError: reqstyle = '' if len(layer.wmsextrastyles) > 1 and reqstyle == 'default': reqstyle = '' if reqstyle and reqstyle not in layer.wmsextrastyles: raise OGCException( 'Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined') if not reqstyle: reqstyle = layer.wmsdefaultstyle if reqstyle in self.mapfactory.aggregatestyles.keys(): for stylename in self.mapfactory.aggregatestyles[ reqstyle]: layer.styles.append(stylename) else: layer.styles.append(reqstyle) for stylename in layer.styles: if stylename in self.mapfactory.styles.keys(): m.append_style(stylename, self.mapfactory.styles[stylename]) else: raise ServerConfigurationError( 'Layer "%s" refers to non-existent style "%s".' % (layername, stylename)) m.layers.append(layer) m.zoom_to_box( Envelope(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3])) return m