GeoJSONcn
GeoJSONcn / 技术专栏 / 全国省市区县geojson数据下…

全国省市区县geojson数据下载后的几何瘦身:抽稀容差、小数位与传输体积实测

发布于 2026-09-14 · GeoJSONcn 技术团队 · 阅读约 12 分钟

打开一份下载来的区县边界文件,先看数值。湖南省浏阳市那份是 4.45 MB,32 个乡镇街道单元,合计 112,344 个顶点,坐标写到小数点后 15 位。相邻顶点的实际距离中位数是 18.6 米,最小的 3.1% 不到 0.5 米。

两组数字放一起,问题不在文件大小,而在精度分配。15 位小数在这个纬度上对应 0.01 微米,比 GPS 观测噪声小六个数量级;18.6 米点距意味着多数顶点连一个屏幕像素都占不到。全国省市区县geojson数据下载回来之后,几何层面通常就卡在这里:精度远超数据准确度,密度远超交付场景的分辨率。

三个动作各自能省多少

对同一份浏阳市文件做三种处理。抽稀用 Douglas-Peucker,容差 1e-4 度,本地纬度上约 11.1 米;小数位裁到六位,对应约 0.1 米量化误差。

处理方式文件体积顶点数相对原始gzip 后
原始文件4.45 MB112,344100%1,600 KB
仅裁到六位小数2.45 MB112,34455%684 KB
抽稀 + 裁到六位小数0.59 MB26,95313%181 KB
抽稀 + 裁到五位小数0.54 MB26,95312%约 165 KB

抽稀与裁位数是相乘不是相加:单做一项拿到五成左右,一起做拿到 13%。两者削掉的东西不同,小数位压的是每个坐标的长度,抽稀压的是坐标个数。裁位数对 gzip 后体积影响更直接——重复尾数去掉后,压缩字典命中率反而下降。

容差有一条收益曲线:2.2 米保留 60% 顶点,5.5 米保留 36%,11.1 米保留 24%,22.1 米保留 16%。从 2.2 米放宽到 11.1 米,顶点少了六成,外环总面积只从 4982.835 变到 4982.865 平方千米,相对偏差 0.0009%;再放宽到 22.1 米,面积偏差涨到 0.0015%。边际衰减很快,11 米上下是合适落点。

精度裁剪里最容易踩的两个坑

第一个坑是把坐标四舍五入当成无害操作。六位小数只有 0.05 米量级的量化误差,但数据一旦投影到 Web 墨卡托(EPSG:3857)再转回来,误差会被放大。实测新疆省级边界 10,503 个顶点,原始坐标转 3857 取整到米、再转回经纬度取六位小数,98.4% 的顶点数值变了,最大地面偏差 0.549 米。渲染上看不出来,可下游流程若拿两份文件做哈希比对,就会误报。

修法是在投影之前把精度定下来。反验很简单:定好精度的文件转 3857 取整到米、再转回来,得到的整数米坐标与直接转换完全一致——同一批 10,503 个顶点,不一致数是 0,两种网格双向唯一映射。第二个坑是拿抽稀后的几何去算面积、做空间分析。抽稀不是等比例缩放,对边界曲折的单元伤害更大:

单元面积抽稀后相对面积偏差
淮川街道6.31 km²0.0393%
金刚镇79.56 km²0.0266%
官桥镇87.6 km²0.0212%
大围山镇400.6 km²0.0101%

淮川街道 6.31 平方千米,相对偏差 0.0393%;大围山镇 400.6 平方千米,绝对偏差 40,397 平方米,相对偏差反而只有 0.0101%。单元越小、边界越碎,抽稀的相对影响越大,而面积口径逐级汇总上报,误差会随链条往下走。稳的做法是抽稀只用于展示与传输,面积与空间关系在未抽稀几何上算。 这套工序该写成一次性的生成步骤:

// 顺序:先抽稀,再定精度,最后才投影;顺序颠倒会引入漂移
function normalize(coords, tolDeg = 1e-4, decimals = 6) {
  const r = x => Number(x.toFixed(decimals));   // 六位小数 ≈ 0.1 m 量化误差
  const rnd = v => Array.isArray(v[0]) ? v.map(rnd) : v.map(n => r(n));
  return rnd(simplify(coords, tolDeg));          // 容差单位是度
}

压缩链路的位置关系

几何瘦身和传输压缩不是替代关系。同一份未裁剪的浏阳市文件在 CDN 上实测:原始 4.45 MB,gzip 后 1,600 KB,Brotli 后 1,524 KB。Brotli 比 gzip 只多省 4.7%,JSON 里重复的坐标尾数已被两种算法共同利用掉,文本压缩到这个比例基本见顶。几何侧做完再看,4.45 MB 变成 0.59 MB,再走 Brotli 推算约 170 KB,与 1.5 MB 相差一个数量级。

顺序上应先做几何侧、再开传输压缩:反过来,1.5 MB 会变成干扰项,看到它觉得能接受,就不再动几何了。

交付形态决定精度档位

对全国省市区县区划边界数据做批处理时,按层级定档比全局统一更划算。新疆省级 16 个要素 24,426 个顶点,523 KB;日喀则市 19 个要素 10,573 个顶点,229 KB;浏阳市区县层 32 个要素 112,344 个顶点,4,553 KB。省级一屏看全省,容差放到 20 米以上也不易察觉;区县层要下钻到乡镇街道,容差得收到 10 米以内;乡镇街道级若要支撑打印,六位小数加 5 米容差更稳。

村一级不同。全国村级geojson数据下载回来以后,单个村庄面积可能不到一平方千米,边界还夹着细碎飞地,容差一放大到 10 米,飞地形状直接消失。这一层建议只做小数位裁剪,抽稀交给渲染侧按 zoom 处理。 区划底图交给汇报场景时,这种权衡更直接。做 PPT 底图用单个省或省级下钻的市,区块形状要经得起放大看,11 米容差加六位小数基本够用;要按市、按区县单独取可编辑底图,可以到 地图 PPT 模板选购页 逐级下钻挑一份,先看预览再决定下载。

几何瘦身没有统一答案,只有分层答案:展示层求小求快,计算层求准求全,两套几何各自守住边界。GeoJSON下载环节的原始封装尽量保留不动,当作计算层的事实来源;面向浏览器的轻量版本单独生成,精度参数写进脚本而不是事后手改。判据很直接——瘦身后的文件放大到最大档仍看不出折线,就够用了。本文数据仅用于技术讨论,区划口径以国家有关部门发布的为准。