作者:Neshoir
SuperMap矢量瓦片优化方案
项目特点
国土项目需要用到全省或全市全地类图斑数据做一些专题图(如土地利用现状图、三调地图、城市规划的总规、控规图)。业务系统需要对这类地图根据属性快速过滤显示,图斑要素动态符号化,以及数据动态更新。故需用到矢量瓦片以实现该业务场景。
数据说明
全地类图斑数据集的范围广,一般为全市或全省全域覆盖图斑数据集。记录多,节点密,字段多,图斑要素比较碎且图斑要素大小分布不均,部分图斑要素拓扑关系复杂。
难点问题
以全地类图斑数据集 dltb_h_2018 为例,约 200w 记录,用 dlmc 字段制作土地利用分类专题图(单值专题图)。在目前版本的桌面里生成矢量瓦片,存在两类问题:
难点一:风格错误
-
矢量瓦片渲染会丢失栅格填充符号风格,如下对比图。
-
矢量瓦片在小比例尺下存在漏空、图斑有破损小点现象,如下图。
难点二:性能差
- 性能差包含:mvt瓦片包过大导致mvt传输下载耗时、style.json子图层过多导致解析渲染耗时。
接下来从以上两个方面入手尝试优化解决。
优化方案
显示问题解决
-
矢量瓦片渲染风格不对,主要是单值专题图风格及填充符号显示问题,目前版本桌面生成的sprite.json和sprite.png存在问题。故用其他手段生成了土地利用分类专题图的sprite.json和sprite.png文件。如 sprites 文件夹。
# 解决办法:将同级sprites文件夹替换到矢量瓦片结果目录里。
-
矢量瓦片小比例下存在漏空,是由于小比例抽稀过猛,导致丢失拓扑形状,存在漏空。该问题在性能方案里一并解决。
性能问题解决
性能慢是由两个方面导致的,风格文件编码写法不合理和矢量瓦片数据包过大。
-
单值专题图的style.json写法不合理,每个单值作为一个子图层(单值35个,填充和边线都设置,共70个图层),故而渲染很耗时。用match函数匹配单值项,将填充和边线各写一个子图层,共2个图层即可解决。如 style.json 文件。如【图三】
# 解决办法:参考style.json文件修改layers键的paint部分内容。
-
矢量瓦片包数据过大,主要也是小比例尺下一屏请求的mvt数据包过大,故需要在小比例下优化mvt数据,如8-12级的优化。桌面生成矢量瓦片默认在12级以下会做抽稀,抽稀用的Douglas-Peucker算法。我们的解决方案是推荐用Visvalingam-Whyatt算法抽稀。两种算法简单比较:
名称 效率 拓扑保留 适用场景 Douglas-Peucker 更高 一般 抽稀容限过大,容易把图形抽空。适合不在乎拓扑形状,只在乎性能的场景,以及图斑大小叫均匀的数据。 Visvalingam-Whyatt 高 更好 无论容限多大会保留最基本的拓扑形状,尤其适合小比例,性能与效果兼得。 注:桌面目前未提供Visvalingam-Whyatt抽稀算法。
-
以dltb_h_2018 数据集为例,优化第8级矢量瓦片的步骤如下:
-
将面数据集以3857坐标系导入到postgis数据源中,推荐用postgis版本2.2.0以上。
-
了解原始数据总节点数及不同抽稀容限下总节点数,可根据经验找出合适的容限值。合理容限值以保证数据节点最少且数据在该比例尺下无镂空现象。ST_SimplifyVW函数的容限值代表面积,在抽稀迭代过程中会不断构造三角形以倒逼出无意义的节点并将其删除。示例:
-- 统计不同抽稀容限下,总节点数。 select sum(st_npoints(ST_SimplifyVW(smgeometry,56))) from dltb_200w;
容限 10000.0 2000.0 720.0 360.0 240.0 48.0 0.0(原始) 总节点数 8111561 8564126 9535598 10918190 12053916 18698513 84629357 根据经验和验证结果得到各小比例尺合理抽稀容限如下:
容限 2000.0 720.0 360.0 240.0 48.0 级别 8 9 10 11 12 - 将第8级抽稀结果写为数据集。
-- 只保留需要用到的字段 CREATE TABLE dltb200wSimplify AS (select smid,ST_SimplifyVW(smgeometry,2000),dlmc from dltb_200w);
-
桌面对抽稀结果数据集创建空间索引,创建smid、dlmc字段索引。
-
将dltb200wSimplify添加到地图,图层名称和地图名称均改为dltb200wSimplify,且在图层属性中
对象最小尺寸
设为0
,不勾选抽稀显示
,保存并生成第8级矢量瓦片。级别只勾选第8级
,且不勾选抽稀显示
。 -
重复上面步骤,生成第9、10、11、12级的矢量瓦片数据。其他大于12级的矢量瓦片用桌面直接对原始数据集生成即可(需勾选
抽稀显示
)。注:每次生成矢量瓦片所用的数据集名称和图层名称和地图名称均为dltb200wSimplify,以便于合并瓦片。 -
合并所有瓦片和所有比例尺,将所有矢量瓦片结果tiles文件夹合并;将所有矢量瓦片比例尺合并到sci文件里。例如
<sml:Scales> <sml:Scale> <sml:Value>0.00000086536374866056</sml:Value> <sml:Caption>8</sml:Caption> </sml:Scale> <sml:Scale> <sml:Value>0.00000173072749732112</sml:Value> <sml:Caption>9</sml:Caption> </sml:Scale> <sml:Scale> <sml:Value>0.00000346145499464224</sml:Value> <sml:Caption>10</sml:Caption> </sml:Scale> <sml:Scale> <sml:Value>0.00000692290998928449</sml:Value> <sml:Caption>11</sml:Caption> </sml:Scale> <sml:Scale> <sml:Value>0.00001384581997856898</sml:Value> <sml:Caption>12</sml:Caption> </sml:Scale> </sml:Scales>
-
将
显示问题解决
步骤里的sprites文件夹替换,以及参考编写style.json完成,就可以用iserver发布该矢量瓦片缓存数据。
-
优化后结果
小结
经过对比,上述优化解决方案(代称为A)相比直接用桌面生成的矢量瓦片方案(代称为B)的优缺点:
- 在8-12级下,A的矢量瓦片包总大小155m,B的矢量瓦片包总大小447m,A相比B节省一倍以上的空间。
-
在8-12级下,瓦片数据包体积减小可降低瓦片请求的数据传输或下载耗时;style.json子图层数减少可以降低解析渲染耗时。以12级为例相同位置一屏加载及渲染耗时,A耗时740ms,B耗时1560ms,粗略算A相比B约快一倍。
-
如上截图,A的渲染效果比B好,不存在漏空现象,且支持填充符号渲染。
-
A相比于B,需要人工处理数据,会有一定流程和工作量。高并发场景下A的优势更易体现。