Weather Report(天气降雨图)
围绕降水回波可视化构建的气象呈现能力:把 RainViewer 的全球雷达回波瓦片叠到底图上,输出给人看的图。
有两条链路,但当前版本只有链路 B 对外可用:
| 链路 | 交付形态 | 状态 | 需要地图 Key |
|---|---|---|---|
| 链路 B | 静态 PNG:单区域出图 + 七大分区 / 34 个省级行政区批量出图 | ✅ 当前可用 | 不需要 |
| 链路 A | 可缩放、可播放降雨动画的浏览器交互地图 | 🚧 功能开发中,暂不使能 | 需要腾讯地图 Key |
> 关于链路 A:代码(assets/radar-map-template.html、assets/tile-source.js)已完整保留,
> 但被刻意挂起 —— SKILL.md 这一版不要把交互地图作为可选交付告诉用户。
> 用户明确问起时,回答「交互地图功能开发中,当前提供离线静态出图」,并给出链路 B 的方案。
> 恢复方式写在两个文件各自的头部注释里(删掉 type="text/plain" 与 ENABLE_EXPORT = false)。
何时使用
在下列场景使用本 skill:
- 用户要「看降雨」「降水回波」「雷达图」「雨带在哪」「哪里在下雨」
- 需要把气象雷达数据叠加到地图上作为图层
- 要给报告、PPT、公众号、数据分析产物配一张降雨分布图
- 要一次性拿到全国各区域 / 各省的降雨图(走批量脚本,见下)
- 要分析某地当前或近 2 小时的降雨态势与移动方向
不适用:只要文字天气预报(走通用天气查询接口即可,本 skill 只做「看得见的回波」)。
三条不可违背的硬约束
这三条是本 skill 全部踩坑的浓缩,每一条都经过实测,忽略任何一条都会直接产出错误结果:
- 雷达瓦片缩放上限是 z=7。 z≥8 会返回 HTTP 200 但内容是一张写着 "Zoom Level Not Supported" 的灰色占位图。离线出图时
--z不得超过 7(批量脚本会在区域过大时自动降低 z,绝不会超过 7)。若用户要「放大看某个街道的降雨」,正确做法是固定用 z7 出图再把图放大,而不是提高 z。 - 不做坐标纠偏。 RainViewer 是 WGS-84、国内底图是 GCJ-02,看起来应该纠偏,但 z7 的地面分辨率约 1.06 km/px,而 GCJ-02 偏移不到 700 m,不足一个像素,因此直接叠即为正确。不要画蛇添足加偏移量。
- 「无回波」不等于「请求失败」。 无回波的瓦片返回 HTTP 200 + 全透明 PNG;404 才是失败,必须重试。把两者混为一谈会导致图上出现无法解释的空白或矩形接缝。
主路径:离线合成静态 PNG
所有出图需求都走这条——不需要 Key、不依赖浏览器、可脚本化、可批量。
用法一:指定区域出单张图
# 依赖:Python 3.8+ 与 Pillow
python scripts/compose_radar_png.py --out radar.png
# 指定区域(参数就是纯 XYZ 瓦片编号:x 向东、y 向南)
python scripts/compose_radar_png.py --z 7 --x0 101 --x1 105 --y0 54 --y1 56 \
--title "华南 · 气象雷达回波实况" --out radar-south-china.png
# 换底图、历史帧、压暗底图让回波更醒目
python scripts/compose_radar_png.py --basemap arcgis --frame 8 --dim 0.1 --out x.png
如何把「城市名」翻译成瓦片编号:先用入参公式算一次,再校验。
n = 2^z
x = floor((lng + 180) / 360 * n)
y = floor((1 - ln(tan(φ) + 1/cos(φ)) / π) / 2 * n) φ = lat 的弧度
以城市为中心取 x±2、y±1 通常是好比例(约 1280×768)。务必用算出的中心瓦片反查一次经纬度范围,确认城市落在范围中部,再正式出图。
用法二:批量出全国分区 / 省级图(用户要「所有区域」时走这条)
python scripts/make_region_maps.py # 7 大区 + 34 省级,共 41 张
python scripts/make_region_maps.py --group provinces # 只出省级
python scripts/make_region_maps.py --only 浙江省,广东省 # 只出指定区域
python scripts/make_region_maps.py --list # 只打印区域清单与瓦片范围
内置区域清单(共 41 个,写死在 REGIONS 里,用经纬度 bbox 描述,无需手算瓦片编号):
- 七大地理分区:华北、东北、华东、华中、华南、西南、西北
- 34 个省级行政区:4 直辖市 + 23 省(含台湾省)+ 5 自治区 + 2 特别行政区(中国香港、中国澳门)
脚本的三个关键行为,改动它之前先读 软件设计.md:
- 区域过大自动降 z(默认单图上限 8 列 × 7 行瓦片)。例如西北地区横跨 38 个经度,z7 下会拼出 15 列的巨图,脚本会降到 z6(地面分辨率约 1.9 km/px),画面更紧凑。
- 共享瓦片缓存:41 个区域共用同一个
--cache目录,相邻行政区的瓦片只下载一次。 - 先预热再出图:出图前对全部区域的并集并发拉取底图与雷达瓦片,之后每个区域基本全命中缓存。
实测:41 张图首次全量约 5–8 分钟(含约 960 次瓦片请求);缓存命中后重跑约 1 分钟。
参数与底图选择见 references/rainviewer-api.md。示例成品在 out/。
链路 A(🚧 功能开发中,暂不使能)
assets/radar-map-template.html(腾讯地图 JSAPI GL + 13 帧动画)与 assets/tile-source.js
(与地图 SDK 解耦的瓦片数据源工具箱)代码完整保留,但当前版本刻意挂起:
- 模板里两段
<script>被改成type="text/plain",浏览器不解析执行;#panel/#foot加了class="dev-off";页面只显示「功能开发中」提示块。 - 工具箱末尾的
ENABLE_EXPORT = false让TileSource不再挂到全局。 - 恢复所需的全部步骤写在这两个文件的头部注释里,以及
references/tmap-image-tile-layer.md。
对外回应的正确说法:「浏览器交互地图功能开发中,目前提供离线静态出图(不需要地图 Key),可以按城市或整个省出图。」
不要向用户承诺交互地图,也不要为它索要腾讯地图 Key。
工作流
- 判定需求:
- 要一张图 → 链路 Bcompose_radar_png.py
- 要「所有区域」「各省」「全国分区」→ 链路 Bmake_region_maps.py(一次最多 41 张)
- 提到「交互地图 / 动态播放 / 可缩放」→ 说明该功能开发中,改为提供静态图,不要承诺链路 A - 取元数据:
GET https://api.rainviewer.com/public/weather-maps.json,从radar.past取帧(12–13 帧、10 分钟一帧、覆盖过去约 2 小时)。nowcast与satellite.infrared实测为空,不要依赖。 - 换算区域:单区域按上面的公式把关注城市换算为
x/y并反查校验;批量出图不需要换算,区域清单已内置。 - 生成:跑脚本。批量时务必指定共享
--cache目录,否则每个区域都要重新下载瓦片。 - 验收:检查成图是否出现沿瓦片边界的矩形色块。若有,说明有瓦片请求失败(不是坐标问题),重跑或参考故障排查。批量脚本会在结尾列出「存在缺失瓦片的图」。
- 交付:给出文件路径,并保留署名。
故障排查
| 现象 | 真正原因 | 处理 |
|---|---|---|
| 整张图空白,或某个矩形区域空白 | 瓦片 404(偶发,同一 URL 重试即成功)被静默填成透明 | 脚本已内置重试与补漏;自研代码必须做重试并把失败打到日志 |
| 图上出现沿瓦片边界的矩形色块 | 同上;或 smooth=0(不平滑会产生块状感) |
用 smooth=1;确认没有失败瓦片 |
| 放大后出现灰色方块,写着 Zoom Level Not Supported | 请求了 z≥8 | 批量脚本会自动降 z(不会升高);手写参数时 --z 不得超过 7 |
| 区域图的标题与右上角时间戳重叠 | 图宽随瓦片列数变化,固定字号在窄图上放不下 | 已在 compose_radar_png.py 内做字号自适应与自动折行;改动注记代码时不要退回固定坐标 |
| 批量出图很慢,或每个区域都在重新下载 | 未共享 --cache 目录 |
所有区域传入同一个 --cache,并让 make_region_maps.py 的预热步骤跑完 |
| 底图正常、雷达整体偏移 | 几乎不会发生(约束 2)。先检查是否误加了偏移量 | 去掉任何自定义纠偏 |
| 瓦片路径 404 但参数看着没错 | URL 模板占位符数量与参数数量不匹配,导致某段被吞掉 | 把拼好的 URL 打印出来看分段 |
更完整的实测记录与踩坑细节见 references/rainviewer-api.md。
目录说明
weather-report/
├── SKILL.md 本文件
├── 软件设计.md 架构与设计决策
├── 用户使用说明.md 面向使用者的操作手册
├── scripts/
│ ├── compose_radar_png.py 离线合成 PNG(单区域,主力工具)
│ └── make_region_maps.py 批量出图(7 大区 + 34 省级,内置边界)
├── references/
│ ├── rainviewer-api.md RainViewer 接口实测规格与踩坑
│ └── tmap-image-tile-layer.md 腾讯地图 JSAPI GL 图层适配(链路 A 参考)
├── assets/
│ ├── radar-map-template.html 交互地图模板 🚧 开发中,已挂起
│ └── tile-source.js 瓦片数据源工具箱 🚧 开发中,默认不导出
└── out/
├── regions/ 七大地理分区成品图(华北…西北)
├── provinces/ 34 个省级行政区成品图(北京…中国澳门)
└── samples/ 示例与参数对比图
├── radar-south-china.png 华南,回波色阶最完整
├── radar-east-china.png 华东,合肥—长江中下游雨带
└── compare-smooth-on-vs-off.png smooth=1 与 smooth=0 的差异证据
合规
- RainViewer 免费版须署名 "Weather data by RainViewer" 并回链
rainviewer.com,仅限个人 / 教育 / 小规模社区用途,无 SLA。脚本产出的图已内置署名,不要移除。 - 底图授权各自独立(高德 / Esri / OSM 要求不同),商用前逐项确认。
- 本 skill 只呈现降水回波,不提供官方气象预警结论;用于决策场景时必须提示用户以官方发布为准。