postgis mvt矢量切片 django drf mapboxgl
目录
0.前提
1.sql代码
2.django drf后端服务代码
3.具体的应用(整体代码)
[1] 静态的矢量切片可以采用 tippecanoe 生成,nginx代理,这种数据是不更新的;
[2] 动态的矢量切片,一般采用postgis生成。基本上矢量切片80%的厂商都采用postgis,确实好用!不谈商业的。
[3] postgis矢量切片使用到的函数:ST_AsMVT、ST_AsMVTGeom、ST_TileEnvelope、ST_Transform、ST_Intersects、ST_SRID。
[4] postgis api参考文档官网:Official Manual | PostGIS,有postgis3.0版本以上的,点击html,点击8. PostGIS Reference,即可查看矢量处理的函数。
[1] 获取表的字段名称:(zzz替换成传入的表名)【PS:不建议动态查询将1-2结合,不好】
select column_name from information_schema.columns where table_name='zzz';
[2] 动态获取矢量切片: (1.0.0)替换成传入的z,x,y参数,zzz替换成传入的表名,geom替换成geom几何对应的字段名称。
with mvtgeom as (
select ST_AsMVTGeom(ST_Transform(geom, 3857), ST_TileEnvelope(1,0,0)) as geom, gid
from
zzz,
(select ST_SRID(geom) as srid from zzz where geom is not null limit 1) a
where
ST_Intersects(geom, ST_Transform(ST_TileEnvelope(1,0,0), srid))
)
select ST_AsMVT(mvtgeom.*, 'zzz', 4096, 'geom') as mvt from mvtgeom;
基于APIView重写get函数,再注册到urls.py中
前端访问 ip/`table_name`/`z`/`x`/`y`,eg:http://127.0.0.1:8080/getmap/zzz/2/1/1 这样就可以接收矢量切片mvt了。
from django.db import connection
from rest_framework.views import APIView
from rest_framework.response import Response
class MapView(APIView):
def get(self, request, table, z, x, y):
print(table, z, x, y,)
table_name = table #'zzz'
# sql = f"""select json_build_object('type', 'FeatureCollection', 'name', '{table_name}', 'features', json_agg(ST_ASGeoJSON(t.*)::json)) from {table_name} AS t """
# 获取表的字段名称 列表
# sql = f"""select column_name from information_schema.columns where table_name='{table_name}'""" # where后面是string 不应被转成对象变量
# 获取表的字段名称 字符串
# sql = f"""select array_to_string(array(select column_name from information_schema.columns where table_name='{table_name}' and column_name != 'geom'), ',');"""
# 动态矢量切片mvt
geom_name = 'geom'
sql = f"""with mvtgeom as (
select ST_AsMVTGeom(ST_Transform({geom_name}, 3857), ST_TileEnvelope({z},{x},{y})) as geom, gid
from
{table_name},
(select ST_SRID({geom_name}) as srid from {table_name} where {geom_name} is not null limit 1) a
where
ST_Intersects({geom_name}, ST_Transform(ST_TileEnvelope({z},{x},{y}), srid))
)
select ST_AsMVT(mvtgeom.*, '{table_name}', 4096, 'geom') as mvt from mvtgeom;"""
print(sql)
with connection.cursor() as cursor:
cursor.execute(sql)
results = cursor.fetchall()
return Response(results)
TODO
会了postgis的pgsql生成mvt切片,那么就基本上完成90%。