十一长假我贬低了一张地图

2026年10月8日

十一长假,一位老友说开始用workbuddy尝试做地图,虽然是第一次,但毕竟不用自己写代码。

美观和体验缺少的workbuddy尝试
美观和体验缺少的workbuddy尝试

我们都做空间信息这一行,只是专注的业务不一样。老友做软件,极海做数据监测。他十一没有假期,趁着短暂的休息用 WorkBuddy 做了一个交互地图,想练练自己驾驭 AI 的手感。

我看了不到一分钟。数据别扭,界面挤,手指一滑,菜单就跟地图打架。我跟了一句让人不舒服的话。大意是,workbuddy就是不行。

话出口我就知道有点伤人。他在练手。我在用成品的标准砸一份练习,虽然我贬低的是workbuddy。更难堪的是,我平时老跟别人说,自己做成一件小事,比仰着头看新工具重要。轮到别人真做成一件小事,我先挑刺。

既然嘴这么快,就得自己做一张。正好,假期一直在用 Muse 抓数据,我想试试 Muse 这种个人助理,能不能把一个地图应用从空目录扛到能打开,而且正好与workbuddy类似,都算是免费的吧。结果是:壳,它能写个大概;账,它算的糊弄。改到最后,我都有点火冒三丈了!按照目前大模型的智能水平,我甚至都开始骂Muse——你这个傻子。不得不在 GitHub 上建了仓库,把 Grok bot拉进来,又让它去叫 Opus 5.5,才有了一个我愿意挂上版本号的站点:map.kowa88.net。

站点今天我还在更新,但自己也不觉得它有多大意义。今天把这段体验写下来的,不是又多了一个好看的世界地图,是这几天把「画得出来」和「敢标日期」看的更透彻了一点。

无非是另一个球
无非是另一个球

会变色的山,不是新画的山

我是不想不浪费任何一次做地图时候的尝新机会。假期前,我看到一张图。Bert Spaan 的 Relief。Google Maps Mania 在 10 月给它起了个标题,Providing Global Relief。FlowingData 也写了。地形的渲染随着镜头的拉近拉远而变化。你把地图从荷兰拖到青藏高原,颜色会跟着变,低地的几米高差不会被珠峰压成一种蓝。

动态地形图
动态地形图

近一点看青藏高原
近一点看青藏高原

很多人第一眼会以为,这是一张画得更细的山影。不是。

传统山影瓦片是一张烤好的图片。颜色在服务器上就已经死了。全球用同一套色标,珠峰占住最深的那一档,华北平原、荷兰圩田只好挤在最浅的一档里。你放大,看到的还是那张烤死的图,只是像素变大。

这个山影的实践反过来。它用的是 Mapterhorn 的全球高程。瓦片里不存颜色,存每个格子的海拔。荷兰局部还换了更高分辨率的 AHN。浏览器拿到高度以后,按你当前视野临时上色,再算阴影。所以山是活的。数据没变,色带变了。

在这个网页上你可以在「当前视野」和「绝对高程」之间切换,锁住色带,反色,开等高线,把海底也铺上。GEBCO 那套海深一接,海沟和山峰才在同一张图里。这是 2026 年秋天一张值得看的地图。有了这个技术,就不必提前生产各个级别的瓦片,还可以切换任意色带。

借着这个机会,我在自己站点的「地形」页做的是它的一个收窄版。渲染那一下,Muse一次就写出来了。转到球体上,某些角度瓦片会消失,俯仰角也会乱,后面又补了几轮。虽然后面的bug不是Muse改的,但也算完成首次交付就顺利出功能了。

视域分位高程瓦片
视域分位高程瓦片

我把它叫做视域分位高程瓦片

先把名字放下,免得后文绕。

视域分位高程瓦片。

它不是一种新的文件格式。文件仍是高程编码栅格瓦片,业内叫 Terrarium。新的是用法:颜色不烘在瓦片里,而按当前视野的海拔分位,在浏览器里现算。

地图瓦片其实就三家邻居。

影像瓦片,像素是颜色。卫星图、烤好的山影,都算这一家。烤完就死。

矢量瓦片,里面是点、线、面。国界、铁路、港口,走这一家。OpenFreeMap 的底图就是它。

高程瓦片,像素是高度。Mapterhorn 发的是 512 像素的 webp,全球大约 30 米一格。一个像素的红、绿、蓝拼成米数:红 × 256 + 绿 + 蓝 / 256 − 32768。减掉 32768,是为了让海平面附近落在中间,深海和高山都能写下。

视域分位,是高程瓦片的一种活法。预渲染山影是把高程提前烤成影像瓦片。烤完,荷兰永远是那种绿。

我这次做的时候,有四件不能省的事。

第一,海和陆不是同一张表。Mapterhorn 的海里是 0 米,它不负责海底。所以陆地缩放到 8 级以上用 Mapterhorn,更小的比例尺和海底用 AWS 那套老 Terrarium,海深主要来自 GEBCO。欧洲海域放到 10 级以上,改用 EMODnet,大约 115 米,取不到就退回 AWS。海深贴上去之后,还得做低通和双三次插值,不然海底是一块一块的格子。

第二,阴影不能在瓦片边上断开。山影要看相邻格子的高差。每块瓦片向邻居借 1 个像素,接缝才连得上。加载慢的时候,先用上一层或下一层顶着,不能让屏幕空一块。

第三,颜色按视野拉,但不能被一座尖峰绑架。当前屏幕里的陆地海拔,取 0 到 99.5% 分位,再留 5% 余量。海洋取 1% 到 98%。数字会平滑,免得你一拖地图,颜色就跳。另外有一道刹车:陆地色带的顶端,不许超过这个海拔在全球绝对色标上该有的颜色。一座几百米的丘陵不该假装自己是雪山。

第四,手机和老浏览器会失败。浮点纹理、着色器,不是台台都有。失败了就退回 MapLibre 自带的山影。总览页用的是同一套机器的灰度模式,平地和海透明,只把阴影压在矢量底图上。没有这层退路,演示在别人手机上就是一块黑。

换个色带,看看海洋的细节
换个色带,看看海洋的细节

原创网站Relief 比我这页完整。它还有等高线、色带动画、探索按钮。我没有把别人的交互再做一遍。我要确认的是:这种活的高程,一个助手能不能一次放进可发布的页面。能。难的从不在这里。

一小时的壳,我在里面说的脏话

我后来跟自己说,一个展示性质的 GIS 应用,一小时可以搞定。这句话容易听成吹牛。拆细了看,一小时搞定的是壳,不是数据监测。

壳里至少有这些。

矢量瓦片负责底图和注记。点、线、面不在浏览器里现画全世界,只取你视野里的那几块。这是成熟技术。这次多出来的,就是上面那种视域分位高程瓦片。一个运几何,一个运高度。别混成一种。

边界有两种,别谈成一件事。一种是瓦片接缝,借 1 个像素就能补。一种是政区边界。我们用 Natural Earth 的陆地国界做示意,但咱们国家的边界主张要画对,另外还要做南海十段线,底图还有一层很小的过滤,在第一批矢量瓦片解析之前就放进去。晚了,MapLibre 会把已经加载的瓦片全部重新解析一遍,手机上就能感到卡。页上写明了:国界是示意,不作划界依据。软件做得到的是把线放对、把不该混的注记滤掉。软件做不到的是让一条示意线变成法律。

符号化是把数变成能看的差别。首都的点按人口分级,用的是 Natural Earth 的都市区估算,不是最新普查,所以不能在弹窗里装成统计局数字。集装箱港按 2024/2025年的标准箱分级。货物港按吨。两套口径并排时必须写清,吨和箱不能加在一起。晶圆厂分最难,想找全了不太可能,先分三档精度:厂址、园区、城市。点的样子可以一样,旁边的字不能一样。

全球晶圆厂分布,核实数据用了快一整天
全球晶圆厂分布,核实数据用了快一整天

截图不是按一下系统截屏。当前图层如果还在懒加载,截出来的图会少一块,标题上的数字也会空。所以先等这一页要用的数据到齐,再画进画布,导出 PNG。手机上走系统分享,让人存到相册。一张发不出去的地图,在微信里等于没有。

过滤和多设备更不起眼,也更要命。图层要能关。底图过滤要赶在瓦片前面。页面高度用整屏,避开浏览器那一条地址栏。顶部和底部让出刘海和横条。按钮的点击区域不能跟地图抢手指。老友的演示,就是拉胯在这里。我后来补上了,也不觉得光荣。只是不用成品标准去砸别人之前,自己得先被手机砸一次。

壳做完,站点能转,能换中英文,能导出。到这一步,它仍然只是一个展览。

真正的来回,发生在坐标和日期上

仓库比网站诚实。

10 月 6 日,线上第一次被完整收进 GitHub。之后三天,数据版本号从 20261005d 走到 20261008b。好看的地形没有再改原理。改的是点能不能放上去。

晶圆厂最典型。第一轮,Grok 调 Opus,把 176 处原先落在城市中心的点挪到厂址或园区,弹窗里留下来源链接。然后 Muse 上的 GLM 5.3 逐条核验,改了 146 条:128 条把精度往下降,18 条动了坐标。听起来很负责。Grok 对着来源再核了一遍,只采纳了 2 处降级,其余 126 处维持原来有出处的数。第四轮又把剩下的城市级点位往厂区推。冲电气八王子那 8 条产线,2013 年就关了,不画。

你看,模型不是不会改坐标。它太会改了。没有来源、没有版本、没有下一轮否决,一次「逐条核验」就是一次整齐的误伤。

别的层也是同样的脾气。世界遗产官方名录里有 3 处没有坐标,不画。热门景点本来想做,访客量没有基准年份,整层拿掉。4F 机场只写已查明的,并标明不是全球全集,证据还分了强弱。集装箱港和货物港的年份不一样,中国货物港用的是交通运输部 2025 年的数,有的境外港只能拿到上一财年,页上分开写。美军基地的整理日期和源头报告的年份不是同一年,就两个都留下,临时演习地点不收。

看这些总结的句子很无聊。无聊才是专业。

演示问的是:能不能跑。专业应用问的是:这条点准到厂还是准到城,年份是 2024 还是 2025,关了的还画不画,没有坐标的要不要编一个。AI 现在很擅长把看见的东西画上去。它不擅长决定什么时候该从地图上拿掉。

生成不掉的,是这本账

所以我才觉得 map.kowa88.net 这种网站,做成了也还浅。

它证明了一件已经不稀奇的事:矢量瓦片、动态高程、导出、手机适配,都可以在一个假期里被助手拼出来。拼出来的是一台观看仪器。读者打开它,能看见首都、铁路、港口、核电站,也能看见一座会随视野变色的山。然后呢。他不能问:这个品牌上个月在哪些县净增了店,哪些店是真的关了,不是网站抽风。

极海这些年做的是后一个问题。2025 年 4 月我们写过一个里程碑,品牌监测收录的连锁品牌超过 1.5 万个,在营门店超过 150 万家。数字还会变,变的方式比数字重要。小程序和官网来的门店,是每天在看的那一部分。当天没看见,不立刻写成关店,先标暂停营业。这种情况超过 30 天,才把最后一次看见的日期写成停业日期。补充来的、门店变化慢的品牌,按季度看,不跟每天更新的那些搅在一个口径里。

这和「2013 年关闭的产线不画」「没有基准年的热度不画」是同一条纪律。差别只是,地图展览可以做完就停。监测不能停。停一天,暂停和关店就会混。混一次,后面所有「净增」「撤退」「下沉」都是故事,不是账。

AI 把观看变得很便宜。测量没有一起变便宜。模型可以在一小时里写出着色器,也可以在十分钟里给你一份「全国门店分布」的自信回答。你要是不追问年份、坐标精度、没看见的那天怎么记账,那份回答比没有地图更危险。没有地图,人知道自己不知道。一份干净的错误地图,会让决策变得很果断。

缰绳比聊天窗口重要,账本比缰绳重要

这次也把助手的差别看清了。

Muse 能把地形渲染一次写出来,这点我不抹杀。它扛不住的是整条链:仓库、预览、数据版本、来源链接、下一轮把上一轮打回去。WorkBuddy 在这份假期作业里更不像一个能交付的环境。从数据到界面,尤其是手机上的手指,都还停在「生成了一个页面」。

Grok、Claude Code、pi 这一类强一些,不是因为聊天更会说。是因为它们肯把活拴在一个仓库里。推上去有预览,错了能撤回,模型不够用时可以再叫一个更强的去核对来源。大家管这个叫做 harness,缰绳。没有缰绳的助手,偶尔能写出惊人的一段着色器,然后在坐标表上悄悄发挥。

有缰绳也不够。缰绳保证过程留得下。留得下的东西若没有日期、精度和删除规则,仍然是一个更好看的展览。Opus 把厂址找回来,GLM 把一批点降级,Grok 再按来源否决大部分降级。这三步都发生了,站点才从「能打开」变成「我敢把口径写在图例里」。

回到假期那一幕。

老友想练的事是对的。AI 这东西,不亲手驾驭一次,永远停在传闻里。我用移动端体验去蛐蛐他,贬低的是成品,不是练习。这句贬低,傲慢,不合时宜。收回。

另一半不收回。空间信息这一行,如果接下来比的是谁先做出一个能转的地球,那会越来越热闹,也越来越不值钱。软件会被一小时生成。观看会被一小时生成。不会被生成掉的,是一本还在每天翻的账:看见了记一笔,没看见先别写成关店,超过期限再落日期,口径不同的数不许加总。

山可以随你的视野变色。店不会。店开关的那一天,不会因为你把地图拖到了一个好看的角度,就自己出现。

王昊

用地图思考人生

评论正在加载...
Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
分享