PostgreSQL ST_AsMVT to VectorTiles to Leaflet Layer

雨燕双飞 提交于 2021-01-28 19:21:02

问题


I'm trying to create vector tiles from a PostgreSQL database and serve them via flask to a Leaflet map. I've followed this medium.com article which got me nearly all the way.

However, when i open the page with the Leaflet map on it I get the following in the browser console:

index.js:191 Uncaught Error: Unimplemented type: 4 at Pbf.skip (index.js:191) at Pbf.readFields (index.js:41) at new VectorTile$1 (vectortile.js:8) at FileReader. (Leaflet.VectorGrid.Protobuf.js:124)

to create the tiles I use the below:

  def tile_ul(x, y, z):
    n = 2.0 ** z
    lon_deg = x / n * 360.0 - 180.0
    lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * y / n)))
    lat_deg = math.degrees(lat_rad)
    return  lon_deg,lat_deg

    def get_tile(z,x,y):
        xmin,ymin = tile_ul(x, y, z)
        xmax,ymax = tile_ul(x + 1, y + 1, z)
        tile = None
        query = """SELECT ST_AsMVT(tile) FROM (SELECT id, ST_AsMVTGeom(geom, ST_Makebox2d(ST_transform(ST_SetSrid(ST_MakePoint(%s,%s),4326),3857),ST_transform(ST_SetSrid(ST_MakePoint(%s,%s),4326),3857)), 4096, 0, false) AS geom FROM "TimeZone (LineGridExp)") AS tile"""
cursor = db.connection.cursor()
cursor.execute(query,(xmin,ymin,xmax,ymax))
tile = str(cursor.fetchone()[0])
cursor.close()
return tile

@app.route('/tiles')
@app.route('/tiles/<int:z>/<int:x>/<int:y>', methods=['GET'])
def tiles(z=0, x=0, y=0):
    tile = get_tile(z, x, y)
    response = make_response(tile)
    response.headers['Content-Type'] = "application/octet-stream"
    return response

To add tiles to leaflet i use:

var url = "http://localhost:5000/tiles/{z}/{x}/{y}"
var mapillaryLayer = L.vectorGrid.protobuf(url).addTo(mymap);

The python end receives GET from the client and doesn't throw any errors. However I'm not sure about the SQL query and detecting empty tiles or whether the query is simply wrong.

Any help would be greatly appreciated.

Tom


回答1:


It was all a matter of the query not returning data and also returning as Bytes and not str:

 def get_tile(z,x,y):
    xmin, ymin = tile_ul(x, y, z)
    xmax, ymax = tile_ul(x + 1, y + 1, z)
    query = """SELECT ST_AsMVT(tile) FROM (
               SELECT id, ST_AsMVTGeom(geom, ST_MakeEnvelope( %s, %s, %s, %s ,4326), 4096, 256, false ) geom 
               FROM reproject ) as tile"""
    cursor = db.connection.cursor()
    cursor.execute(query,(xmin,ymin,xmax,ymax))
    tile = bytes(cursor.fetchone()[0])
    cursor.close()
    return tile


来源:https://stackoverflow.com/questions/60765560/postgresql-st-asmvt-to-vectortiles-to-leaflet-layer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!