Skip to content

Instantly share code, notes, and snippets.

@giohappy
Last active November 18, 2022 12:11
Show Gist options
  • Save giohappy/9b4768ce0dbf92d74b36e615cb12bfa4 to your computer and use it in GitHub Desktop.
Save giohappy/9b4768ce0dbf92d74b36e615cb12bfa4 to your computer and use it in GitHub Desktop.
OL + Flask + PostGIS for MVT rendering
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import shutil
import math
import psycopg2
from flask import Flask, render_template, make_response
app = Flask(__name__)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CACHE_DIR = os.path.join(BASE_DIR,'cache')
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
tilefolder = "{}/{}/{}".format(CACHE_DIR,z,x)
tilepath = "{}/{}.pbf".format(tilefolder,y)
if not os.path.exists(tilepath):
conn = psycopg2.connect('dbname=geo24 user=geo password=geo host=localhost')
cur = conn.cursor()
query = "SELECT ST_AsMVT(tile) FROM (SELECT id, name, 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 admin_areas) AS tile"
cur.execute(query,(xmin,ymin,xmax,ymax))
tile = str(cur.fetchone()[0])
if not os.path.exists(tilefolder):
os.makedirs(tilefolder)
with open(tilepath, 'wb') as f:
f.write(tile)
f.close()
cur.close()
conn.close()
else:
tile = open(tilepath, 'rb').read()
return tile
@app.route('/')
def index():
return render_template('index.html')
@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
@voledemar
Copy link

It seems we should cast to bytes instead str at the 35th row. cur.fetchone()[0] is a memoryview object that currently represents a byte sequence returned by ST_AsMVT.

@bennycheung
Copy link

Thanks for sharing the code! I have encountered this problem during interfacing with psycopg2. If you have any hint to resolve this?
psycopg2.ProgrammingError: function st_asmvt(record) does not exist
LINE 1: SELECT ST_AsMVT(tile) FROM (SELECT id, ST_AsMVTGeom(geometry...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.

@mortezaomidi
Copy link

@bennycheung You should update postgis version.

@bennycheung
Copy link

Thanks for the hint! greatly appreciated.

@bpositive
Copy link

It seems we should cast to bytes instead str at the 35th row. cur.fetchone()[0] is a memoryview object that currently represents a byte sequence returned by ST_AsMVT.

Yes, changing to bytes worked for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment