试着还原下墨迹mapbox合作的雷达图展示
条评论在四步走,墨迹天气雷达数据可视化指南这篇文章中,提到了用矢量瓦片代替传统传统栅格图像可视化方案,可以达到更流程的性能,更高清的数据展示,更灵活的样式表达。感觉挺有意思,同时也为了考察这么做的成本,就试着还原做了下。
从文章来看整个过程总结起来就是准备数据geojson
,切成pbf
或者mbtiles
在 mapbox 中展示。
背景
按惯例先解释下雷达数据。我之前通俗的把气象数据划分为了站点(散点)和格点两类,暂且不细说雷达数据到底属于哪类,但最终都可以通过比方说插值来得到一份格点数据。传统的栅格图像
可视化方案是基于格点数据利用matplotlib.pyplot.contourf这类工具,依据一定标准的图例,生成出来的一张等值面图,考虑到网络的传输,这种图片得体积小,分辨率就会下降,所以在缩放时候会失真,出现马赛克,矢量瓦片的出现就可以很自然的解决这个问题。
我会用降水格点数据来代替雷达数据进行了测试,二者数据格式内容上来说都相差不大,且都能用来反映未来降水的趋势。
开发
选用了 10 个时次的降水格点数据,格点大小为511*581
,经度范围为113.2, 119.4
,纬度范围为37.4, 42.7
。
生成 geojson
这一步其实有很多选择,文章里面也提到了一些,我都做了一些尝试,列一下尝试结果:
const contour = require("d3-contour").contours; |
const point = require("@turf/helpers").point; |
上面两种方式生成的结果,偶尔会出现的不同级别等值面重叠的情况,这样在前端渲染的时候,由于颜色通道的叠加,会导致重叠部分数据渲染错误的情况,不知道是我使用时候生成方法的弄错还是渲染方法弄错了,效果不太满意。
import matplotlib.pyplot as plt |
实践下来感觉这个方法生成的 geojson 效果会更好,我个人比较推荐使用。原理上就是先生成了传统等值面图片,把像素结果转换成了 geojson 数据。
合并 geojson(可选)
这一步很有趣,如果把每个时刻的降水数据做成单独的 geojson,在根据时序进行播放的时候就需要每次移除、加载图层,会有卡顿的效果,而看文章里面墨迹使用了 mapbox 的setFilter
功能,所以猜测是对 geojson 进行了合并。
在 QGIS 中打开了已经生成的 10 个 geojson 进行了合并,可以在属性表里面看到,每个图层的顺序是通过layer
字段进行区分的,后面会用上。
生成矢量瓦片
使用mapbox/tippecanoe这个官方工具就好了。如果在上面选择了合并 geojson,那么只需要对合并后的单个文件切瓦片就好了,不然就是对每个时刻的数据单独执行以下切瓦片的命令。
tippecanoe -e /Downloads/pbf --no-tile-compression -zg --drop-densest-as-needed -l pre merge.geojson |
-e 是生成目录
–no-tile-compression 是不对生成的 pbf 进行压缩,否则加载时候会报错
-zg –drop-densest-as-needed 是自动去判断瓦片的最大最小级别
-l 是手动指定图层名字
展示
- 在 leaflet 加载使用插件Leaflet.VectorGrid就好
const map = L.map("map", { |
- 在 mapbox 中加载直接定义一个自定义 source,并加载
const map = new mapboxgl.Map({ |
待优化
其实还有个工作没有尝试就是原文里面说的,对两个相邻间隔时间的数据做插值处理,以追求更加平滑的播放效果。个人感觉这个处理对于面向大众的场景比较实用,但在专业方面,有待使用更科学的方法进行处理。