Ubuntu16.0.4 Flask+Postgis(ST_AsMVT) 矢量切片初体验

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yh0503/article/details/84377133

MVT

MVT(Mapbox Vector Tile):传送门

本文中用到的PostGIS函数

矢量切片后端服务(基于PostGIS+Flask )

以下代码仅供参考!

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import shutil
import math
import psycopg2
import psycopg2.pool

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')
Dbpool = psycopg2.pool.PersistentConnectionPool(
    1,
    100,
    dbname='osm',
    user='postgres',
    host='192.168.90.110',
    password='postgres',
    port='5432')


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
    conn = Dbpool.getconn()
    # cur = conn.cursor()
    if (conn):
        query = "SELECT ST_AsMVT(tile, 'polygons', 4096, 'geom') AS tile FROM ( SELECT w.gid , ST_AsMVTGeom(w.geom, Box2D(ST_MakeEnvelope(%s,%s,%s,%s, 4326)), 4096, 0, true) AS geom FROM gis_osm_buildings_a_free_1 w ) tile WHERE tile.geom IS NOT NULL" 
        cur = conn.cursor()
        cur.execute(query, (xmin, ymin, xmax, ymax))
        tile = str(cur.fetchone()[0])
        cur.close()
        Dbpool.putconn(conn)
    return tile


@app.route('/')
def index():
    return render_template('leaflet_map.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/x-protobuf"
    response.headers['Access-Control-Allow-Origin'] = "*"
    response.headers['Access-Control-Allow-Methods'] = "POST"
    response.headers['Access-Control-Allow-Headers'] = "x-requested-with,content-type"
    return response


if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=5000)

矢量切片前端展示(基于MapBox-GL.js )

以下代码仅供参考!

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Add a third party vector tile source</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='mapbox-gl.js'></script>
    <link href='mapbox-gl.css' rel='stylesheet' />
    <style>
        body {
            margin: 0;
            padding: 0;
        }
        
        #map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
        }
    </style>
</head>

<body>
    <div id='map'></div>
    <script>
        mapboxgl.accessToken = '去Mapbox官网注册账号,申请你自己的Token';
        var tileset = 'mapbox.streets';
        var map = new mapboxgl.Map({
            container: 'map',
			//北京
            zoom: 14,
            center: [116.3900, 39.9209],	
            style: 'mapbox://styles/mapbox/light-v9',
            hash: false
        });

        map.on('load', function loaded() {
          map.addSource('custom-go-vector-tile-source1', {
              type: 'vector',
              tiles: ['http://192.168.90.110:5000/tiles/{z}/{x}/{y}']
          });
         
         map.addLayer({
             "id": "custom-go-vector-tile-layer1",
              "type": "fill",
              "source": "custom-go-vector-tile-source1",
				"source-layer": "polygons",
              "paint": {
                  "fill-color": "#0000ff"
                  }
          });	  
        });
    </script>
</body>
</html>

效果图:
在这里插入图片描述

测试结果

算不上是测试结果吧,说说用户体验吧:
900w 点数据(QGIS按照渔网随机填充生成点数据),实时渲染感觉速度还行。
600w 简单面数据(上面的点数据构建的泰森多边形),实时渲染感觉速度也可以,10级以上无压力。
具体测试数据,可以参考下面参考链接文章里的结果,这块我暂时没有做详细的测试,这块待我回头测试补充一篇文章。

快显优化策略

  1. 数据库建空间索引(GIST),这个当然了也是必须的。
  2. 简化节点 使用ST_RemoveRepeatedPoints 和 ST_SnapToGrid等函数。
  3. 确定查询的范围,在SQL中使用A&B,求取查询范围和geom字段的交集,减少无效的请求范围。
  4. SQL性能调优(这块本人不擅长,就不多说了)。
  5. 聚合数据(这块个人觉得看你的需求是啥了,一些太小的图形可以考虑聚合或者抽稀)。
  6. 升级到最新版本的Postgis。
  7. PG数据库这块集群(基于XL集群)。
  8. 服务器端PLpgSQL编程,看GeoHey就是这种搞的呐。

参考资料

本文主要参考资料:

猜你喜欢

转载自blog.csdn.net/yh0503/article/details/84377133