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)
# note: requires mapnik SVN r822 or greater. # Example of reprojecting the extent for the netherlands in epsg:28992 to google mercator and then back to the original netherlands extent. import sys try: from mapnik import ProjTransform, Projection, Envelope except ImportError, E: sys.exit('Requires Mapnik SVN r822 or greater:\n%s' % E) # http://spatialreference.org/ref/epsg/28992/ # http://mapnik.dbsgeo.com/days/2009-01-25 amersfoort_extent = Envelope(13599.999985,306799.999985,277999.999985,619299.999985) amersfoort_proj = Projection('+init=epsg:28992') merc_proj = 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 +wktext +no_defs') transform = ProjTransform(amersfoort_proj,merc_proj) merc_extent = transform.forward(amersfoort_extent) if transform.backward(merc_extent).__repr__() == amersfoort_extent.__repr__(): print 'Transformation successful!' print 'Original Dutch Extent: %s' % amersfoort_extent print 'Merc Extent: %s' % merc_extent else: print 'Reprojection failure...'
def GET(self, tilename, epsg, z, x, y): global cached_maps sffx = 'png' epsg = int(epsg) z = int(z) x = int(x) y = int(y) if (z < 0 or z > 19): return '' cType = { "png":"image/png" } qs = web.input(r='',x='',q='') isCache = False if qs.r == '': isCache = True output = False tilep = Tilep() web.header("Access-Control-Allow-Origin", "*") atilename = tilename+'_'+str(epsg) dbfilet = tilep.getDb(atilename) if dbfilet: cont = lite.connect(dbfilet) curt = cont.cursor() if isCache and dbfilet: if (qs.q == '') : sql = "SELECT * from tiles WHERE z = ? AND x = ? AND y = ? AND sffx = ? AND (q is null or q = ?);" else : sql = "SELECT * from tiles WHERE z = ? AND x = ? AND y = ? AND sffx = ? AND q = ?;" curt.execute(sql,[z,x,y,sffx,qs.q]) rows = curt.fetchall() for row in rows: output = zlib.decompress(row[7]) if output: web.header("Content-Type", cType[sffx]) return output if not output: box = tilep.getBbox(z=z,x=x,y=y) geo_extent = Box2d(box[0],box[1],box[2],box[3]) geo_proj = Projection('+init=epsg:4326') merc_proj = Projection('+init=epsg:'+str(epsg)) transform = ProjTransform(geo_proj,merc_proj) merc_extent = transform.forward(geo_extent) mp = False if isCache and atilename in cached_maps : if qs.q in cached_maps[atilename]: mp = cached_maps[atilename][qs.q] if not mp: mp = mapnik.Map(256,256,'+init=epsg:'+str(epsg)) s = mapnik.Style() r = mapnik.Rule() r.symbols.append(mapnik.RasterSymbolizer()) s.rules.append(r) mp.append_style('RStyle',s) adir = os.path.dirname(os.path.realpath(__file__)) coni = lite.connect(adir+'/indeks.db') curi = coni.cursor() sql = "SELECT * FROM indeks WHERE name = ? AND epsg = ? AND ((maxx >= ? AND maxy >= ? AND minx <= ? AND miny <= ?) OR (minx <= ? AND miny <= ? AND maxx >= ? AND maxy >= ?))" if (qs.q != '') : try: qray = json.loads(qs.q) except ValueError: qray = False if isinstance(qray, list): qray[0]= 'filename' qc = str(tilep.getQuery(qray)) sql = sql+"AND "+qc curi.execute(sql,[tilename,epsg,str(merc_extent[0]),str(merc_extent[1]),str(merc_extent[2]),str(merc_extent[3]),str(merc_extent[0]),str(merc_extent[1]),str(merc_extent[2]),str(merc_extent[3])]) #ok sql = "SELECT * FROM indeks WHERE name = ? AND epsg = ?;" #ok curi.execute(sql,[tilename,epsg]) rows = curi.fetchall() n = 0 for row in rows: afilename = str(row[1]) ds = mapnik.Gdal(file=afilename) layer = mapnik.Layer('raster'+str(n),'+init=epsg:'+str(epsg)) layer.datasource = ds layer.styles.append('RStyle') mp.layers.append(layer) n = n+1 #xmlstr = mapnik.save_map_to_string(mp) #print xmlstr #mapnik.load_map_from_string(mp,xmlstr) if atilename not in cached_maps : cached_maps[atilename] = {} #cached_maps[atilename][qs.q] = mp mp.zoom_to_box(merc_extent) im = Image(mp.width,mp.height) mapnik.render(mp,im) output = im.tostring('png') if dbfilet: minx = box[0] miny = box[1] maxx = box[2] maxy = box[3] sql = "INSERT INTO tiles VALUES (?,?,?,?,?,?,?,?,?,?);" curt.execute(sql,[z,x,y,minx,miny,maxx,maxy,lite.Binary(zlib.compress(output)),sffx,qs.q]) cont.commit() curt.close() web.header("Content-Type", cType[sffx]) return output else: return ''
def transform(self, from_prj, to_prj): trans = ProjTransform(from_prj, to_prj) return trans.forward(self)
def main(argv): b = "-180,-90,180,90" i = "" o = "" l = "-1" try: opts, args = getopt.getopt(argv,"hb:i:o:l:",["bbox","inputXml","output","layerGrid"]) except getopt.GetoptError: print 'tilep.py -b <bbox> -i <inputXml> -o <output> -l <layerGrid>' sys.exit(2) for opt, arg in opts: if opt == '-h': print 'tilep.py -b <bbox> -i <inputXml> -o <output> -l <layerGrid>' sys.exit() elif opt in ("-b", "--bbox"): b = arg elif opt in ("-i", "--inputXml"): i = arg elif opt in ("-o", "--output"): o = arg elif opt in ("-l", "--layerGrid"): l = arg box = [] for s in b.split(",") : box.append(float(s)) geo_extent = Box2d(box[0],box[1],box[2],box[3]) geo_proj = Projection('+init=epsg:4326') merc_proj = Projection('+init=epsg:3857') transform = ProjTransform(geo_proj,merc_proj) merc_extent = transform.forward(geo_extent) mp = mapnik.Map(256,256) #sys.exit(i) if i.find('http') >= 0: xmlurl=urllib2.urlopen(i) xmlstr=xmlurl.read() #xmlstr = '<Map srs="+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 +wktext +no_defs"><Style name="Style1"><Rule><PolygonSymbolizer fill="#ffbf00" fill-opacity="0.5"/><LineSymbolizer stroke="#ff7b00" stroke-width="1" stroke-opacity="1" stroke-linejoin="bevel"/></Rule></Style><Layer name="Layer1" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs "><StyleName>Style1</StyleName><Datasource><Parameter name="type">postgis</Parameter><Parameter name="host">localhost</Parameter><Parameter name="dbname">webgisPEP</Parameter><Parameter name="username">iyo</Parameter><Parameter name="password">SAlamaH</Parameter><Parameter name="table">(SELECT * FROM sxz51_iyo_data_6) as layer1</Parameter><Parameter name="geometry_field">the_geom</Parameter><Parameter name="srid">EPSG:4326</Parameter><Parameter name="fields">gid,nama_kebun,sk</Parameter></Datasource></Layer></Map>' mapnik.load_map_from_string(mp,xmlstr) xmldoc = minidom.parseString(xmlstr) else: mapnik.load_map(mp, i) xmldoc = minidom.parse(i) mp.zoom_to_box(merc_extent) printed = 0 if o == 'png': im = Image(mp.width,mp.height) mapnik.render(mp,im) fd, path = tempfile.mkstemp() os.write(fd,im.tostring('png')) os.fsync(fd) print path elif o == 'json': printed = 1 else: image = o+".png" if not os.path.exists(os.path.dirname(image)): try: os.makedirs(os.path.dirname(image)) except: pass mapnik.render_to_file(mp, image) if l == '-1': print image #print ((time.time())-(t0))*1000 #sys.exit() lgrids = [] if l != '-1': for s in l.split(",") : lgrids.append(s) else: sys.exit() itemlist = xmldoc.getElementsByTagName('Layer') fields = [] resolution = 4 #Pixel resolution of output. printed = 0 for lysl in lgrids : lys = lysl.split(":") ly = int(lys[0]) lz = '' if (len(lys) == 2): lz = lys[1] dat = itemlist[ly].getElementsByTagName('Datasource')[0] par = dat.getElementsByTagName('Parameter') for s in par : dv = s.attributes['name'].value dck = False if (dv[6:] == '' or lz == ''): dck = True elif (dv[6:].isdigit() and lz.isdigit()): dck = (int(lz) >= int(dv[6:])) if dv[:6] == 'fields' and dck and fields == [] : text = s.childNodes[0].nodeValue.encode("utf-8") #print "fields "+text fields = text.split(",") #elif dv[:6] == 'fields': # ly = ly + 1 if dv == 'resolution': res = s.childNodes[0].nodeValue.encode("utf-8") #print "resolution "+res resolution = int(res) layer_index = ly #First layer on the map - index in m.layers key = "__id__" #Field used for the key in mapnik (should probably be unique) enfix = "" if ly > 0: enfix = "_"+str(ly) d = mapnik.render_grid(mp, layer_index, key, resolution, fields) #returns a dictionary d = "grid("+json.dumps(d)+")" if o == 'json' and printed == 0: print d printed = 1 elif o == 'png': printed = 1 else: print d f = open(o+enfix+".json",'wb') f.write(d) f.close()
def GET(self, tilename, z, x, y, sffx): z = int(z) x = int(x) y = int(y) if (z < 0 or z > 19): return '' cType = { "png":"image/png", "json":"text/plain" } qs = web.input(r='',x='',q='') isCache = False if qs.r == '': isCache = True output = False tilep = Tilep() web.header("Access-Control-Allow-Origin", "*") dbfilet = tilep.getDb(tilename) if dbfilet: cont = lite.connect(dbfilet) curt = cont.cursor() if isCache and dbfilet: if (qs.q == '') : sql = "SELECT * from tiles WHERE z = ? AND x = ? AND y = ? AND sffx = ? AND (q is null or q = ?);" else : sql = "SELECT * from tiles WHERE z = ? AND x = ? AND y = ? AND sffx = ? AND q = ?;" curt.execute(sql,[z,x,y,sffx,qs.q]) rows = curt.fetchall() for row in rows: output = zlib.decompress(row[7]) if output: web.header("Content-Type", cType[sffx]) return output if not output: isforce = True if qs.x == '': isforce = False xmlstr = tilep.getXml(tilename,isforce,qs.q) if not xmlstr: return '' else: box = tilep.getBbox(z=z,x=x,y=y) geo_extent = Box2d(box[0],box[1],box[2],box[3]) geo_proj = Projection('+init=epsg:4326') merc_proj = Projection('+init=epsg:3857') transform = ProjTransform(geo_proj,merc_proj) merc_extent = transform.forward(geo_extent) mp = mapnik.Map(256,256) mapnik.load_map_from_string(mp,xmlstr) mp.zoom_to_box(merc_extent) if sffx == 'png': im = Image(mp.width,mp.height) mapnik.render(mp,im) output = im.tostring('png') if dbfilet: minx = box[0] miny = box[1] maxx = box[2] maxy = box[3] sql = "INSERT INTO tiles VALUES (?,?,?,?,?,?,?,?,?,?);" curt.execute(sql,[z,x,y,minx,miny,maxx,maxy,lite.Binary(zlib.compress(output)),sffx,qs.q]) cont.commit() curt.close() #if zoomcache >= z : # mapnik.render_to_file(mp, str(afile)) web.header("Content-Type", cType[sffx]) return output elif sffx == 'json': xmldoc = minidom.parseString(xmlstr) itemlist = xmldoc.getElementsByTagName('Layer') nlay = len(itemlist) fields = [] resolution = 4 #Pixel resolution of output. li = 0 for ly in range(0, nlay): resolution = 4 dat = itemlist[ly].getElementsByTagName('Datasource')[0] par = dat.getElementsByTagName('Parameter') for s in par : dv = s.attributes['name'].value dck = False if (dv[6:] == ''): dck = True elif (dv[6:].isdigit()): dck = (z >= int(dv[6:])) if dv[:6] == 'fields' and dck and fields == [] : text = s.childNodes[0].nodeValue.encode("utf-8") fields = text.split(",") li = ly if dv == 'resolution': res = s.childNodes[0].nodeValue.encode("utf-8") resolution = int(res) layer_index = li #First layer on the map - index in m.layers key = "__id__" #Field used for the key in mapnik (should probably be unique) enfix = "" #if ly > 0: # enfix = "_"+str(ly) #return str(len(fields)) if len(fields) > 0: d = mapnik.render_grid(mp, layer_index, key, resolution, fields) #returns a dictionary output = "grid("+json.dumps(d)+")" else: output = '' if output != '': if dbfilet: minx = box[0] miny = box[1] maxx = box[2] maxy = box[3] sql = "INSERT INTO tiles VALUES (?,?,?,?,?,?,?,?,?,?);" curt.execute(sql,[z,x,y,minx,miny,maxx,maxy,lite.Binary(zlib.compress(output)),sffx,qs.q]) cont.commit() curt.close() #if zoomcache >= z : # f = open(afile,'wb') # f.write(output) # f.close() web.header("Content-Type", cType[sffx]) return output else: return ''
# it to within the web mercator 'square world' if necessary. # # Example usage: latlon2merc.py -180 -90 180 90 import sys from mapnik import Box2d, Coord, Projection, ProjTransform latlon = Projection('+proj=latlong +datum=WGS84') 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 +wktext +no_defs' ) max_4326 = 85.0511287798066 max_3785 = 20037508.3427892 transform = ProjTransform(latlon, merc) if len(sys.argv) == 3: ll = transform.forward(Coord(float(sys.argv[1]), float(sys.argv[2]))) if (ll.y > max_3785): print(' '.join([str(ll.x), str(max_3785)])) elif (ll.y < -max_3785): print(' '.join([str(ll.x), str(-max_3785)])) else: print(' '.join([str(ll.x), str(ll.y)])) elif len(sys.argv) == 5: minx, miny, maxx, maxy = (float(sys.argv[1]), float(sys.argv[2]), float(sys.argv[3]), float(sys.argv[4])) if (miny < -max_4326):
# note: requires mapnik SVN r822 or greater. # Example of reprojecting the extent for the netherlands in epsg:28992 to google mercator and then back to the original netherlands extent. import sys try: from mapnik import ProjTransform, Projection, Envelope except ImportError, E: sys.exit('Requires Mapnik SVN r822 or greater:\n%s' % E) # http://spatialreference.org/ref/epsg/28992/ # http://mapnik.dbsgeo.com/days/2009-01-25 amersfoort_extent = Envelope(13599.999985, 306799.999985, 277999.999985, 619299.999985) amersfoort_proj = Projection('+init=epsg:28992') merc_proj = 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 +wktext +no_defs' ) transform = ProjTransform(amersfoort_proj, merc_proj) merc_extent = transform.forward(amersfoort_extent) if transform.backward(merc_extent).__repr__() == amersfoort_extent.__repr__(): print 'Transformation successful!' print 'Original Dutch Extent: %s' % amersfoort_extent print 'Merc Extent: %s' % merc_extent else: print 'Reprojection failure...'
def transform(self,from_prj,to_prj): trans = ProjTransform(from_prj,to_prj) return trans.forward(self)
# Converts a latlon coordinate or bounding box to web mercator, moving/cropping # it to within the web mercator 'square world' if necessary. # # Example usage: latlon2merc.py -180 -90 180 90 import sys from mapnik import Box2d, Coord, Projection, ProjTransform latlon = Projection('+proj=latlong +datum=WGS84') 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 +wktext +no_defs') max_4326 = 85.0511287798066 max_3785 = 20037508.3427892 transform = ProjTransform(latlon, merc) if len(sys.argv) == 3: ll = transform.forward(Coord(float(sys.argv[1]), float(sys.argv[2]))) if (ll.y > max_3785): print(' '.join([str(ll.x), str(max_3785)])) elif (ll.y < -max_3785): print(' '.join([str(ll.x), str(-max_3785)])) else: print(' '.join([str(ll.x), str(ll.y)])) elif len(sys.argv) == 5: minx, miny, maxx, maxy = ( float(sys.argv[1]), float(sys.argv[2]), float(sys.argv[3]),
def main(argv): b = "-180,-90,180,90" i = "" o = "" l = "0" try: opts, args = getopt.getopt(argv,"hb:i:o:l:",["bbox","inputXml","output","layerGrid"]) except getopt.GetoptError: print 'tilep.py -b <bbox> -i <inputXml> -o <output> -l <layerGrid>' sys.exit(2) for opt, arg in opts: if opt == '-h': print 'tilep.py -b <bbox> -i <inputXml> -o <output> -l <layerGrid>' sys.exit() elif opt in ("-b", "--bbox"): b = arg elif opt in ("-i", "--inputXml"): i = arg elif opt in ("-o", "--output"): o = arg elif opt in ("-l", "--layerGrid"): l = arg if not os.path.exists(os.path.dirname(o+".png")): os.makedirs(os.path.dirname(o+".png")) box = [] for s in b.split(",") : box.append(float(s)) geo_extent = Box2d(box[0],box[1],box[2],box[3]) lgrids = [] for s in l.split(",") : lgrids.append(int(s)) geo_proj = Projection('+init=epsg:4326') merc_proj = Projection('+init=epsg:3857') transform = ProjTransform(geo_proj,merc_proj) merc_extent = transform.forward(geo_extent) image = o+".png" mp = mapnik.Map(256,256) mapnik.load_map(mp, i) mp.zoom_to_box(merc_extent) mapnik.render_to_file(mp, image) print "rendered image to '%s'" % image xmldoc = minidom.parse(i) itemlist = xmldoc.getElementsByTagName('Layer') for ly in lgrids : dat = itemlist[ly].getElementsByTagName('Datasource')[0] par = dat.getElementsByTagName('Parameter') for s in par : if s.attributes['name'].value == 'fields': text = s.childNodes[0].nodeValue.encode("utf-8") fields = text.split(",") layer_index = ly #First layer on the map - index in m.layers key = "__id__" #Field used for the key in mapnik (should probably be unique) resolution = 4 #Pixel resolution of output. enfix = "" if ly > 0: enfix = "_"+ly d = mapnik.render_grid(mp, layer_index, key, resolution, fields) #returns a dictionary d = "grid("+json.dumps(d)+")" f = open(o+enfix+".json",'wb') f.write(d) f.close()