pgsql+postgis 实时返回mvt(Mapbox Vector Tiles) 切片 【笔记】
xmin,ymin,xmax,ymax 为瓦片范围坐标,下面有x,y,z转换为瓦片空间范围方法。(下面适用墨卡托底图)
SELECT ST_AsMVT ( fmvt, 'pointLayer', 4096, 'geom' ) as "mvt" FROM (SELECT dwmc,
ST_AsMVTGeom (ST_Transform ( st_simplify (dgeom,${tolerance},true), 3395),
ST_Transform ( ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490 ), 3395 ), 4096, 64, TRUE) AS geom FROM "${geomtable}"
WHERE dgeom && ST_Transform (ST_Transform ( ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490), 3395), 4490) ${conds} ) AS fmvt
多个图层
select (
(
SELECT ST_AsMVT ( fmvt, 'pointLayer', 4096, 'geom' ) as "mvt" FROM (SELECT dwmc,ST_AsMVTGeom (ST_Transform ( st_simplify (dgeom,${tolerance},true), 3395),
ST_Transform ( ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490 ), 3395 ), 4096, 64, TRUE) AS geom FROM "${geomtable}"
WHERE dgeom && ST_Transform (ST_Transform ( ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490), 3395), 4490) ${conds} ) AS fmvt
)
||
( SELECT ST_AsMVT ( fmvt, 'pointLayer', 4096, 'geom' ) as "mvt" FROM (SELECT dwmc,
ST_AsMVTGeom (ST_Transform ( st_simplify (dgeom,${tolerance},true), 3395),
ST_Transform ( ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490 ), 3395 ), 4096, 64, TRUE) AS geom FROM "${geomtable2}"
WHERE dgeom && ST_Transform (ST_Transform ( ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490), 3395), 4490) ${conds} ) AS fmvt
)
) as mvt
(经纬度底图适用以下语句)
SELECT ST_AsMVT ( fmvt, 'mvt', 4096, 'geom' ) as "mvt" FROM (SELECT dwmc,
ST_AsMVTGeom ( st_simplify (dgeom,${tolerance},true),
ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490 ), 4096, 64, TRUE) AS geom FROM "${jbxxbm}"
WHERE dgeom && ST_MakeEnvelope ( ${xmin}, ${ymin}, ${xmax}, ${ymax}, 4490) ${conds} ) AS fmvt
xyz转换为瓦片空间范围方法:
下面为node 代码:
// 墨卡托
xyz2lonlat_w(x, y, z) {
const n = Math.pow(2, z);
const lon_min = (x / n) * 360.0 - 180.0;
const lat_rad = Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / n)));
const lat_min = (180 * lat_rad) / Math.PI;
const lon_max = ((x+1) / n) * 360.0 - 180.0;
const lat_rad_max = Math.atan(Math.sinh(Math.PI * (1 - (2 * (y+1)) / n)));
const lat_max = (180 * lat_rad_max) / Math.PI;
return { lon_min, lat_min,lon_max,lat_max };
}
// 经纬度
xyz2lonlat_c(x,y,z){
const n = Math.pow(2, z + 1);
const m = Math.pow(2, z);
const lon_min = (x / n) * 360.0 - 180.0;
const lat_min= 90 - y * (180 / m);
const lon_max = ((x +1)/ n) * 360.0 - 180.0;
const lat_max= 90 - (y+1) * (180 / m);
return { lon_min, lat_min,lon_max,lat_max };
}