tilestrata-postgismvt是一个用来从 PostGIS 数据库中检索出 mvt 格式矢量瓦片的插件。PostGIS 在 2.4.0 版本后支持了直接生成 mvt 数据,这让我们更方便的加工出矢量瓦片。
demo 项目可以参考tilestrata-sample-code
1. 基本要求
PostGIS 需要在2.4.0版本及以上
2. 安装
npm install tilestrata-postgismvt --save
|
在 ST_AsMVT 方法更新后 ,虽然作者更新了代码,但是 npm 包并不是最新的,建议用下面的方法安装最新版,或者直接去 Github 上下载
npm install --save https://github.com/Stezii/tilestrata-postgismvt
|
或者通过 package.json
"tilestrata-postgismvt": "github:Stezii/tilestrata-postgismvt"
|
3. 使用
前提:一个导入了 osm 数据的支持 PostGIS 2.4.0 的数据服务器
执行 mapbox 的脚本TileBBox.sql添加TileBBox
函数
3.1 普通模式
var tilestrata = require("tilestrata"); var postgismvt = require("tilestrata-postgismvt"); var headers = require("tilestrata-headers");
server = tilestrata();
server .layer("osm_mvt") .route("tile.mvt") .use( headers({ "Access-Control-Allow-Origin": "*" }) ) .use( postgismvt({ lyr: { table: "import.osm_buildings", geometry: "geometry", srid: 3857, minZoom: 3, maxZoom: 19, buffer: 10, fields: "name", resolution: 256 }, pgConfig: { host: "localhost", user: "gis", password: "gis", database: "gis", port: "6543" } }) );
server.listen(8080);
|
3.2 点云数据
如果是点要素,可以使用 cluster 模式,只要定义lry
中的mode
属性为cluster_fields、cluster或function
,注意的是需要同时定义type
为circle
server.layer('layer_name').route('tile.mvt') .use(postgismvt({ lyr: { ... mode: 'cluster' }, pgConfig: { ... }})) );
|
mode
和resolution
都支持是一个函数。通过这种方式可以手动指定一些缩放级别,用来控制精度
server.layer('layer_name').route('tile.mvt') .use(postgismvt({ lyr: { resolution: function(server, req) { if (req.z > 12) return 512; return 256; }, mode: function(server, req) { if (req.z > 15) return null; if (req.z > 13) return 'cluster_fields'; return 'cluster'; } }, pgConfig: { ... }})) );
|
4. 效果
demo 项目可以参考tilestrata-sample-code
5. 代码浅析
其实核心的方法就是用到了 PostGIS 的ST_AsMVT
和ST_AsMVTGeom
函数。mapbox 提供TileBBox.sql用来计算 zxy 位置的瓦片对应的 box 边界,再查询出其中的 geom,转换成 mvt 格式。
比如说 z=14,x=12917,y=6430
的瓦片对应的 sql 如下:
SELECT ST_AsMVT(q, 'osm_mvt', 256, 'geom') AS mvt FROM ( SELECT ST_AsMVTGeom( ST_Transform( import.osm_buildings.geometry, 3857), TileBBox(14, 12917, 6430, 3857), 256, 10, true ) geom ,name FROM import.osm_buildings WHERE ST_Intersects(TileBBox(14, 12917, 6430, 3857), import.osm_buildings.geometry) ) AS q
|
此外,fields
是可以用逗号分割传递多个想要的字段名的。