GeoJSONcn
GeoJSONcn / 技术专栏 / 行政区划 GeoJSON 面积不…

行政区划 GeoJSON 面积不准?鞋带公式与测地面积的取舍实测

发布于 2026-08-29 · GeoJSONcn 技术团队 · 阅读约 10 分钟

整理全国省市区县区划边界数据下载回来的边界时,有个活比画图还烦人:你要给每个面算面积,好去核对数据对不对、或填进属性表。可同一个面,用鞋带公式算出来的"面积",和用球面测地线算出来的,往往差好几个百分数,高纬度差得更多。几乎所有「GeoJSON下载」教程都会跳过面积这一块,可偏偏它最容易被拿去直接下结论。这篇文章就讲清楚这两种算法差在哪、什么时候该用哪个,以及我拿真实区县数据踩过的几个坑。

两种算法的分歧根源

绝大多数人第一步用的是鞋带公式(shoelace / surveyor's formula):直接拿经纬度当成平面坐标用,算出来的单位是"平方度",再要转成平方千米还得乘一个和纬度有关的缩放系数。问题就出在这:地球是个椭球,经度 1 度在高纬和赤道的实际长度差了一倍不止。把一个内蒙古的旗和广东的区县用同一套平面系数换算,面积必然系统性偏大。

我拿 WGS84 边界的兰州附近一个区做了对比:鞋带平面算法约 3390 km²,用椭球测地面积算约 3308 km²,差了近 2.5%;同一条边界放到再北一点的地方,误差能冲到 5% 以上。所以做行政区划面积核对时,别拿鞋带当最终答案,它更适合用来快速测"相对大小"或判断环方向。

算法依赖高纬精度速度适用
平面鞋带 (shoelace)无偏差大(≥2%~5%)极快相对大小、环方向判正负
等距圆柱近似中纬度系数中快粗略估算
球面/椭球测地面积化算到固定坐标系的投影高稍慢面积核对、回填属性

一个能跑的测地面积脚本

要拿到和民政部口径接近的面积,实话说最稳的是把 WGS84 边界先投影到等积投影(比如中国的 Albers 或 Lambert 等积圆锥)再算平面面积,或者直接用库的测地面积函数。这里给一个用 Turf 的方案,它内部按椭球算,比手写鞋带靠谱:

import fs from 'node:fs';
import { area } from '@turf/turf';

const col = JSON.parse(fs.readFileSync('区县.geojson', 'utf8')).features;
const unitConv = 1; // Turf area() 返回平方米,除以 1e6 得平方千米
const rows = [];

for (const f of col) {
  const sqm = area(f);                       // 平方米
  const sqkm = sqm / 1e6;                    // 平方千米
  const cnPad = String(f.properties.adcode).padStart(6, '0');
  rows.push({ adcode: cnPad, name: f.properties.name, area_km2: Number(sqkm.toFixed(2)) });
}

console.table(rows.slice(0, 5));
fs.writeFileSync('area.csv', 'adcode,name,area_km2\n' +
  rows.map(r => `${r.adcode},${r.name},${r.area_km2}`).join('\n'));

跑出来的数字不要直接信,先和统计部门的"标准面积"横着比一把:行政区的权威面积网上都有,误差在 1%~2% 内基本说明边界和坐标没大问题;一旦出现某个县偏了几成,九成不是算法问题,而是数据本身的问题。

三个让面积"假得离谱"的坑

这几条是我真实踩过、并且能复现给别人的:

算完面积的落地姿势

面积字段算出来后,建议当作校验指标而非铁律:把每个面的面积和周边的乡镇「求和」对一下,看总和和市/省的面积差距,能快速发现漏了某个乡镇或飞地。这一点在做村级数据时特别有用——「全国村级geojson数据下载」回来的村级面经常缺碎片,村面积求和远小于乡镇面,一算就对上了。

我做这套校验时踩过一个很典型的过程:先把一个省所有区县面积加起来,和省级总面积对,差了 3% —— 排查半天发现是某个县底下少挂了一个飞地性质的镇,边界压根没进那份县级文件。所以说面积核对最大的价值不是"好看",是能把数据准备阶段的漏件揪出来。

怎么让面积进属性表又不臃肿

算完的面积,不要顺手给每个要素塞一个 area 字段当成多余负担。正确做法是:只在输出层补一列,且写明算法与单位,比如 area_km2(geodesic)。这样下游拿到手清楚知道口径,不会把平面近似值和测地值混着用。字段命名统一 ASCII、别用中文列名,BI 里做总量统计才不踩编码的坑。

整套面积计算就是一条 Node 脚本,配合 CI 或 cron 每天上限跑一次:上游更新边界,脚本自动重新算面积、重新核对、把对不上的面打标。比对时给一个阈值,比如单县面积偏离权威值超过 3% 就进人工复核队列,而不是直接改数据。这样既能自动发现坏数据,又不会误伤正常边界。

小结

一份行政区划 GeoJSON,面积算得准不准,往往决定后面的总量统计和价格核算靠不靠谱。我的建议很直接:平面鞋带用于快速判断、测地面积用于最终核对、面积求和用于发现漏件,三者配合才不会被个别坏数据带偏。预览边界免费,导出带 area_km2 属性、口径清晰的完整边界按次付费(¥1.99/次),适合先算一遍核对再交付给下游做总量统计。