在彩云天气 App 和 API 里可以获取到当前经纬度的气象预警信息,比如「大风蓝色预警」。 不同国家地区的预警发布规则不一样,在中国是按照行政区划层级来发布的,其中最小到县级行政区。 所以在实现中,需要将经纬度转换成行政区划层级信息,再查找相关的预警信息。 在过去几年中,这部分模块经历了多次重构和完善,在此分享下每个版本的实现方式。
彩云天气地理查询优化(1): 气象站数据查询
我们从一个实际业务场景的谈起:
如何找到离北京市海淀区 768 创意产业园最近的 K 个国家级观测站?
最简单的思路是完整遍历所有候选站点,然后计算每个站点和 768 的距离,按照距离从小到大,选最多前 K 个。 这个代码并不难写。但是问题是慢。
Protocol Buffers 生成 Python Typing
Protocol Buffers 生成的 Python 代码是一坨人类无法阅读的代码, 近日才发现 Google
增加了一个参数 --pyi_out=./xxx
就可以生成 Python 的 typing 了。
这个功能在官方文档里是一点没有提及。
tzfpy Rust 重写🎉
书接上文:
经过一个周末的各种折腾,终于用 Rust 实现了 tzf 的功能,代码在
ringsaturn/tzf-rs
。
又用了晚上跑了多次 CI 将 Python 移植也重写出来了
ringsaturn/tzfpy
。
tzfpy 只要安装 >= 0.11.0
版本的就是用纯 Rust 实现的,在这个版本号之前都是
Python+CGO 实现的。 API 参数和之前一样,没有变化,但是索引命中的时候只需要 3~4
微妙,之前 Python+Go 需要 16 微妙。 最慢的单次查询 300 多微妙,timezonefinder(用
C 实现的多边形算法版本) 最慢的时候会有 1000 多微妙。
tzf 预览图制作
上周花了点时间学习下 mbtiles
文件格式,顺手给 tzf 项目制作了一个
social preview media:
制作流程很简单:
- 安装 https://github.com/mapbox/tippecanoe
- 安装 https://github.com/mapbox/mbview
- 下载时区的 GeoJSON 文件
# 根据 GeoJSON 制作 .mbtiles 文件
tippecanoe -o timezone.mbtiles -l Timezons -z7 combined-with-oceans.fmt.json
mbview ./timezone.mbtiles
网页里调整合适的角度,截图,调整下图片的分辨率即可。
使用地图瓦片索引实现地理聚合
在处理大规模的散点数据时,有时候我们需要提供一个只读的查询 API 在地图上做可视化。 当数据量过大,比如百万这个量级,将数据一口气全部返回给前端在浏览器上处理是不太合适的。 应当在后端服务内完成一定聚合,将聚合后的搜索返回给前端。 这里介绍下在 Go 中如何使用 MongoDB + Tile 索引实现这件事。
用 GitHub Actions 部署 Hugo 网页
用 Go 编写 Python 扩展
tzfpy 是 tzf 的 Python
binding。 如果只是本地可用,Go 代码加上 CGO 扩展编译成 .so
文件就能用了。
不过要做成发布到 PyPI 上在其他地方能直接安装的 wheel 是有些曲折的,看 CI
失败的记录就挺明显的。
Python 中经纬度转时区新的选择
上回 说到在 Go 里弄出了一个
tzf
的库,可以非常快速得到经纬度所在的时区信息。
当时的想法是用 Rust 实现出来然后用 maturin 制作 Python 扩展。
经过一段时间的摸索发现 Rust 的坑有点大,于是 2022-07-23 转换了方向,在 Python
里调用 Go 编译出来的 .so
文件。 验证 demo 还算简单
ringsaturn/tzf#11
。
在 Go 中将经纬度转时区
- 2022-05-29 01:04 +0800 立了个年度 Flag:在 Go 里用多边形搜索实现经纬度转时区
- 2022-05-29 20:47 +0800 搞出来了 https://github.com/ringsaturn/tzf
基本数据处理流程:
挺想用 Rust 实现一遍,然后用 pyo3 封装下,看看能不能比 Numba 加速的 timezonefinder 更快。