美文网首页
【译】 矢量切片大小优化指南

【译】 矢量切片大小优化指南

作者: 异步GIS | 来源:发表于2022-12-12 14:14 被阅读0次

  在Observable Vector Tile Dissector 一文中,我评估了不同的矢量切片供应商提供的切片大小。文中提到的一些限制,其实是完全随机选择的,依据的是我丰富的经验积累……但如何才能真正减小切片大小?我将尝试优化自己的矢量切片并逐步解释。

  以下所有空间数据均基于 OpenStreetMap,投影为web 墨卡托 (EPSG:3857) ,并托管于PostGIS 数据库。

长话短说

  使用一些方法后,我们可以将给定矢量切片的大小减小到原始大小的 14%。


  这些“无损”的方法是:

  • 移除不使用的数据
  • 减小缓冲区
  • 合并要素
  • 压缩

现状

  选择两个不同缩放级别的切片,让我们观察一下它们的大小:

切片 14/8717/5683.mvt 10/544/355.mvt
大小 64 KiB (64984 Bytes) 352 KiB (359820 Bytes)
原始数据
渲染后

  数据本身已经根据缩放层级进行了删减,并且还概化 [1] 了(降低空间复杂性)低缩放级别的要素。还能搞点啥?

Identifier

   让我们看看切片里都有啥:

  我们看到许多存储为数字的 ID。z10这个层级大概有几千个。然而当前配图并没有用到 ID,因此我们可以从Layer Schema中删除对 osm_id/id 的所有引用:

  看看结果如何:


  数字类型的属性少了很多,切片大小也显著减小:

Tile 14/8717/5683.mvt 10/544/355.mvt
原始切片 64 KiB (64984 Bytes) 352 KiB (359820 Bytes)
移除Id 51 KiB (51966 Bytes) 278 KiB (283677 Bytes)
相对大小 80% 79%

  Nice!仅仅是删除Id————这个未使用的属性,大小就减少了约 20%!

  然而在某些情况下挂载ID字段是有意义的,例如需要根据ID从切片中提取数据(比如通过OnClick()事件)看哈这个Azure Maps

  Anyway,咱们再压榨点空间试试。

Tile Buffer

  最近我写过一篇关于切片缓冲区的文章。目前我缓冲大小为256。试着减小到64:

切片 14/8717/5683.mvt 10/544/355.mvt
原始数据
渲染后

  没有出现visual artefacts,但切片也没小多少。意料之中。

Tile 14/8717/5683.mvt 10/544/355.mvt
previous step 51 KiB (51966 Bytes) 278 KiB (283677 Bytes)
64 coordinate unit buffer 50 KiB (51114 Bytes) 276 KiB (282250 Bytes)
relative size 98% 99%

Merge

  看看缩放层级为10时的其他统计数据:


  可以发现:

  公路和铁路层占所有要素的 87%。
  这些要素中超过 95% 仅包含 2 个点。
  让我们随机选一条道路并检查一下数据库:

SELECT 
    ST_NPoints(geometry) as points, 
    geometry 
FROM import.roads_gen10 
where (geometry && ST_Transform(ST_MakeEnvelope(11.2500, 47.9899, 11.6016, 48.2247, 4326), 3857)) AND ref = 'St 2345' order by points DESC;
image.png

  将这条道路在 postgis 中编码为矢量切片:

SELECT
    length(ST_AsMVT(q, 'roads', 4096, 'geom')) as length
FROM
    (
    SELECT
        ST_AsMVTGeom(
            geometry,
            ST_Transform(ST_MakeEnvelope(11.2500, 47.9899, 11.6016, 48.2247, 4326), 3857), 
            4096, 
            1) AS geom
    FROM
        import.roads_gen10
    WHERE
        (geometry && ST_Transform(ST_MakeEnvelope(11.2500, 47.9899, 11.6016, 48.2247, 4326), 3857))
        AND ref = 'St 2345' ) AS q;

  看一下结果:

Name Value
length 1639

  这么说来。该切片中一条由 112 个单独的 LineString 组成的连续道路,编码为矢量瓦片后,占用了 1639 字节空间。而这112条LineString中,大部分(104条)都只有两个点。

  如果我们 使用ST_LineMerge() 将只有 两个个 点的 LINESTRING 合并为一个大的 MULTILINESTRING 会发生什么?

SELECT
    length(ST_AsMVT(q, 'roads', 4096, 'geom')) AS length
FROM
    (
    SELECT
        ST_AsMVTGeom(
            ST_LineMerge( ST_Collect(geometry) ),
            ST_Transform(ST_MakeEnvelope(11.2500, 47.9899, 11.6016, 48.2247, 4326), 3857), 
            4096, 
            0) AS geom
    FROM
        import.roads_gen10
    WHERE
        (geometry && ST_Transform(ST_MakeEnvelope(11.2500, 47.9899, 11.6016, 48.2247, 4326), 3857))
        AND ref = 'St 2345' ) as q;

  results in:

Name Value
length 398

  So,仅仅是合并 LINESTRINGs 我们就将这条路的大小减少了 75%。背后的原理是,每次绘制一条新的 LINESTRING ,必须先将cursor移动到该LineString的起点,才能开始绘制。如果新Linestring的起点与上一个LineString的终点相同,则可以省略。也许我会写另一篇文章来详细解释。在此之前,请参阅 Vector Tile 规范

  Anyway,在真实场景中试试:


  干得漂亮!现在我们的切片里的要素又少又大。我们也可以合并其他一些LineStrings,例如waterways图层。

  其实面图层也可以采用这种方法。我们还可以使用 ST_Union()函数 将切片内的所有建筑物多边形合并为一个大的MultiPolygon,而且效果不错,尤其是在低缩放级别的情况下:

Tile 14/8717/5683.mvt 10/544/355.mvt
上一步骤 50 KiB (51114 Bytes) 276 KiB (282250 Bytes)
合并要素后 31 KiB (31518 Bytes) 73 KiB (74081 Bytes)
相对大小 62% 26%

  要使用此功能,您需要指定一个新的属性 (geom_query) 并对所有的keys施加group by:

image.png

  请记住,这些合并操作代价不菲,有可能会减慢未缓存的访问。

GZIP

  在减小了数据编码为切片的大小后,我们可以使用压缩算法进一步减小大小。所有可用的浏览器都支持 GZIP,因此无需担心兼容性问题。


image.png
Tile 14/8717/5683.mvt 10/544/355.mvt
上一步骤 31 KiB (31518 Bytes) 73 KiB (74081 Bytes)
压缩后 22 KiB (22382 Bytes) 49 KiB (50061 Bytes)
相对大小 71% 68%

  这不仅有助于节省存储成本,还可以缩短最终用户的加载时间。

Summary

Tile 14/8717/5683.mvt 10/544/355.mvt
Orignal 64 KiB (64984 Bytes) 352 KiB (359820 Bytes)
移除Id 51 KiB (51966 Bytes) 278 KiB (283677 Bytes)
调整Buffer后 50 KiB (51114 Bytes) 276 KiB (282250 Bytes)
合并要素后 31 KiB (31518 Bytes) 73 KiB (74081 Bytes)
相对大小 48% 21%
gzip压缩后 22 KiB (22382 Bytes) 49 KiB (50061 Bytes)
相对大小 34% 14%

  渲染图显示出一些细微差异,主要原始是某些要素的排序发生了变化:

Tile 14/8717/5683.mvt 10/544/355.mvt
之前 64KiB 352KiB
之后 31KiB 73KiB

  通过分析矢量切片及其空间数据,我们能够将矢量切片减小到原始大小的 21%(算上压缩的话,14%),同时并没有降低视觉体验。这些方法适用于几乎所有矢量切片服务器。

  我期待更多关于如何进一步减小切片大小的想法。

參考

原文链接:Optimizing vector tile size(cyclemap.link)


  1. 译者注:generalize ,概化。是降低空间要素复杂度的一类计算。See 概化

相关文章

  • Postgis 矢量切片优化

    Postgis生成矢量切片主要使用以下两个方法 ST_AsMVTGeom | Synopsis geometry ...

  • 矢量切片解决方案

    1.矢量切片简介   矢量切片是由mapbox组织提出的一种新型矢量数据切片格式,它按照TMS切片规则对矢量数据进...

  • 基于 PostGIS 的矢量切片服务器

    基于 PostGIS 的矢量切片服务器 矢量切片简介 矢量切片是 MapBox 定义的一种开放的 矢量地图标准 ,...

  • geoserver矢量切片资料整理

    环境搭建 arcsde数据连接 矢量切片制作发布 矢量切片leaflet加载 矢量切片相关概念 相关参考资料: l...

  • Openlayers指南-矢量切片图层

    这里主要介绍矢量切片图层在Openlayers中的应用,这里以加载mapbox样式图层为例来说明矢量切片图层的使用...

  • qgis中加载矢量切片

    概述 qgis既可以做矢量切片,又可以加载矢量切片。本文以geoserver作矢量切片,并在QGIS中进行加载展示...

  • GeoServer矢量切片地址获取

    一、发布矢量切片 在geoserver中发布矢量切片步骤不多说,基本都能搜到,地址的获取取决于已经发布的矢量切片。...

  • 2018-03-07

    矢量切片的介绍以及geoserver发布矢量切片 https://www.cnblogs.com/escage/p...

  • 矢量切片

    参考:https://blog.csdn.net/qingyafan/article/details/533672...

  • 使用mapbox加载由geoserver发布的矢量切片

    使用geoserver发布矢量切片的过程可以参考我在csdn上写的这篇文章: 利用geoserver发布矢量切片服...

网友评论

      本文标题:【译】 矢量切片大小优化指南

      本文链接:https://www.haomeiwen.com/subject/iydfqdtx.html