官方边界GeoJSON大多是CGCS2000?与WGS84差多少、要不要转
做「全国省市区县geojson数据下载」整理时,很多人拿到民政部或天地图来源的边界,第一反应就是问:这是不是 WGS84?要不要统一转成 WGS84 好叠到地图上?我最早也这么干,直到有一次把一个省的县界全量转了一遍,发现好几条边界在图上"整体飘"了几十厘米到一两米,怎么排查都找不出几何问题。后来才弄明白,很多官方来源的边界底层用的是2000 国家大地坐标系(CGCS2000),而它跟 WGS84 不是一回事。这篇把两者的差别、要不要转、以及转的时候踩过的坑讲清楚。
CGCS2000 和 WGS84 到底差在哪
先给结论:两者都是地心地固椭球坐标系,椭球参数极其接近——长半轴 CGCS2000 用 6378137.0 米、WGS84 也是 6378137.0 米,扁率一个是 1/298.257222101、一个是 1/298.257223563,差别在第七位小数以后。所以做「全国省市区县区划边界数据下载」日常叠图时,绝大多数场景不转问题也不大。
真正有差别的是参考框架的实现。WGS84 的参考框架坐落在 WGS84 基准,而 CGCS2000 是在历元 2000.0 的 ITRF97 框架上定义的。由于板块运动和点位测量精度的不同,同一地理点在不同框架下的坐标在特定区域会有一两米的系统差(国内主要反映在高纬度、高山地区最明显,沿海稍小)。对 Web 地图 6 小数位坐标(约 0.1 米分辨率)来说,这个量级基本无感。
| 项目 | WGS84 | CGCS2000 |
|---|---|---|
| 长半轴 | 6378137.0 m | 6378137.0 m |
| 扁率倒数 | 298.257223563 | 298.257222101 |
| 参考框架 | 自身基准 | ITRF97 (历元 2000.0) |
| 与对方差异 | — | 区域 0.1~2 m 级 |
| Web 叠图 | 通用 | 官方边界默认 |
一个 30 行脚本判断数据到底是 84 还是 2000
与其猜,不如自己用已知点的标准坐标做交叉验证。做法很简单:取省级边界上的每个区县质心,跟你手工从权威测绘源查到的"标准经纬度"对比,偏差稳定在 0.1~2 米级、且方向一致,基本就是 CGCS2000;如果和 WGS84 其它数据叠了正好重合,那才是真 84。这里给一段用 pyproj 的快速判别脚本:
from pyproj import Transformer
# 以某个县城官方标准坐标(lng,lat)为准
ref = (116.4074, 39.9045) # 北京中心参考点
t = Transformer.from_crs("EPSG:4490", "EPSG:4326", always_xy=True) # 4490=CGCS2000, 4326=WGS84
c = t.transform(*ref)
print(f"CGCS2000->WGS84 偏移: {ref[0]-c[0]:.6f}° , {ref[1]-c[1]:.6f}°")
什么时候"不用转"
三条硬经验,帮你省下大量无效转换:
- 只做 Web 地图展示、预览、分级设色、点面归属:CGCS2000 边界直接按 4326 喂 Leaflet/MapLibre 完全够用。我在本站预览里就是这么处理的,边界不留缝、不打架。
- 底图和边界来源一致:如果底图本身就是天地图类 CGCS2000 系,边界连转都不用转,直接对齐。
- 比例尺小、不量算极端高纬:1:100 万以下的全图,一两米的差肉眼根本看不出。
必须"正经转"的三种情况
反过来,以下场景不做七参数/框架转换会出事:
- 和国外 OSM/OpenStreetMap 系数据严格叠加、做高精度空间连接:OSM 是经典 WGS84,和 CGCS2000 官方边界直接 join,个别点位会边缘判定错位。
- 把边界送进工程测绘、国土、不动产系统:这些系统要求 CGCS2000 就地入库,绝不能随手标成 4326。
- 跨省拼带做面积/长度的高精度量算:坐标序统一 + 框架明确,量出来的数才有可追溯性。
需要转时,用 EPSG 编号最省事:CGCS2000 经纬度是 EPSG:4490,WGS84 经纬度是 EPSG:4326。pyproj 一行 transformer = Transformer.from_crs("EPSG:4490","EPSG:4326", always_xy=True) 就能批量转换,别去网上找那种手写五参数的旧公式,容易把参数抄错。做完转换,我还习惯顺手把几何写回一份带 crs: {"type":"name","properties":{"name":"EPSG:4326"}} 的 GeoJSON下载 文件,这样下游拿到手第一眼就知道坐标基准,不会再把 2000 当 84 用了。
四个常踩的坑
- 数据标的和实际不一致:很多下载源把 CGCS2000 直接标成 WGS84,以为"差不多"。做法是以权威参考点实测为准,别信标注。
- 投影参数混用:有人为了面积把 CGCS2000 当成 WGS84 去投 Albers,等于坐标系和投影参数打架,算出的面积和官方对不上。
- 高程系统混淆:CGCS2000 只管水平基准,高程是另一个体系。别指望转换能顺便把高程也对齐,那不是它的活。
- 批量转换没带
always_xy=True:会把经纬度喂反变成纬度经度,面跑到海里。转换完先抽几个质心目检。
落地建议
我的做法是:源数据统一按 CGCS2000 留档、带上 crs 标注,线上预览与下载默认给 4326 版本,两种 EPSG 编号明确写进下载页,让下游知道口径。举例来说,「全国村级geojson数据下载」回来的村级面,如果只顾拼接不管基准,几个村的边界和乡镇面对不上,排查起来一头雾水;我都是在拼片之前就把坐标系标注一次性核清楚,后面才不会再返工。这样预览免费、导出按次付费(¥1.99/次),用户拿到的每一份边界坐标基准都说得清,不会因为"84 还是 2000"对不上而在集成时踩坑。
一句话收尾:CGCS2000 与 WGS84 差异是"框架级"而非"坐标值级",Web 场景大胆直接用,高精度工程场景再批转,判别靠参考点实测,别靠标注。