Pyproj完成WGS84到CGCS2000转换

Python
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

用 Pyproj 完成 WGS84 到 CGCS2000 转换,直接创建 Transformer,源 CRS 用 EPSG:4326、目标用 EPSG:4490,并加上 always_xy=True,几行代码即可把经纬度批量转过去。两套坐标系椭球半长轴相同、扁率差异极小,默认转换接近恒等,数值上几乎不变;中国地区实际差异主要来自参考框架与历元,通常约 0.5~1 米。大多数 GIS 场景可直接使用,厘米级成果再考虑历元归算或七参数。

用 Transformer 做 WGS84→CGCS2000 地理坐标转换

本章只讲转换本身,假定你已装好可用的 Pyproj(截至 2026 年 11 月稳定版为 3.8.0,配套 PROJ 9.8.1)。地理 2D 转换推荐始终用 Transformer,而不是旧的 Proj 类。

WGS84到CGCS2000地理坐标转换示意
  1. 导入必要类:from pyproj import Transformer, CRS
  2. 创建转换器(推荐写法):transformer = Transformer.from_crs(“EPSG:4326”, “EPSG:4490”, always_xy=True)。也可以写数字 4326、4490。always_xy=True 强制按经度、纬度(x/y)顺序输入输出,避免 PROJ 6 以后默认 lat/lon 轴序带来的踩坑。
  3. 单点转换:lon_cgcs, lat_cgcs = transformer.transform(lon_wgs, lat_wgs)。结果与输入几乎相同。
  4. 批量转换:传入等长的经度列表、纬度列表即可,返回对应的两个数组。循环里反复创建 Transformer 会慢,务必把 transformer 对象缓存起来复用。
  5. 需要确认 CRS 定义时,可先打印 CRS.from_epsg(4490) 或查看 axis_info,确认轴名与单位。

地理 CRS 转完后若还要进高斯-克吕格投影,再新建一个 Transformer 即可,不要指望一次搞定所有带号。

为什么结果几乎不变?实际差多少

WGS84(EPSG:4326)与 CGCS2000(EPSG:4490)都采用近似 GRS80 的椭球:半长轴 a=6378137 m,扁率 1/f 分别为 298.257223563 与 298.257222101,差异引起的坐标变化约 0.1 mm 量级,可忽略。EPSG 数据库里两者之间通常也没有显式非空转换参数,因此 Pyproj/PROJ 默认走接近恒等的路径。

真正需要留意的是参考框架与历元:CGCS2000 大致对齐 ITRF97(历元 2000.0),而当前使用的 WGS84 实现对应不同 ITRF 与观测历元,再叠加板块运动,中国陆地及近海差异常见在 0.5~1 米,并随时间缓慢增大。米级、亚米级 GIS 制图、Web 地图叠加,直接等同完全够用;厘米级控制网、精密工程则必须引入历元归算、速度场(如 CPM-CGCS2000)或联测控制点求七参数。

想系统对比差异来源与处理思路,可先读本站CGCS2000与WGS84差多少?坐标转换怎么做?;坐标系历史与定义差异见一文读懂WGS 84、CGCS2000和西安80:三大地理坐标系辨析。

项目 WGS84(EPSG:4326) CGCS2000(EPSG:4490)
Datum World Geodetic System 1984 ensemble China 2000
椭球半长轴 a 6378137 m 6378137 m
扁率 1/f 298.257223563 298.257222101
默认轴序 纬度, 经度 纬度, 经度
典型适用 全球 GNSS / 国际数据 中国陆地及近海正式成果

需要 CGCS2000 高斯投影时怎么选带

很多业务最终要落在 CGCS2000 的 3° 带或 6° 带高斯-克吕格投影上(例如 EPSG:4544 对应 3° 带中央子午线 105°E)。选带步骤如下:

  1. 根据测区经度计算中央子午线:3° 带为 3×N,6° 带为 6×N−3(N 为带号)。
  2. 到 EPSG 注册表或本站资料核对对应代码(CGCS2000 3°/6° 带有一系列代码,如 4491–4501、4513+、4534+ 等),确认后用 Transformer.from_crs(“EPSG:4490”, “EPSG:xxxx”, always_xy=True) 完成“地理→投影”。
  3. 输入仍建议经度、纬度顺序;输出为东向、北向(米)。跨带数据要按带分别转换,不要硬塞进一个中央子午线。
  4. 批量处理时同样缓存 Transformer;若同时处理多个带,用字典按 EPSG 代码缓存多个实例。

投影带选错会导致整体偏移几十到几百公里,验收时务必用已知控制点或图廓坐标核对。

轴序、性能与验收注意点

  • 轴序:地理 CRS 在 PROJ 6+ 默认 lat/lon。不设 always_xy=True 时,容易把经度当成纬度传入,结果跑到两极附近。创建后可用 transformer.transform(120, 30) 自测,合理结果应仍接近 (120, 30)。
  • 性能:不要在循环里反复 from_crs。一个进程内同一对 CRS 只建一次 Transformer。
  • 3D / 高程:二维地理转换不含高程系统。需要椭球高时改用对应 3D CRS(例如 WGS84 的 EPSG:4979),并明确高程含义。
  • 验收标准:同一点转换前后经纬度差值通常小于 0.000001°(亚毫米级椭球差);若出现米级以上跳变,先查轴序和是否误用了投影 CRS。与控制点比对时,米级以内可认为框架差异正常,厘米级再上精密方法。
  • 正式测绘成果在中国必须使用 CGCS2000;对外交换或对接国际数据时再考虑 WGS84。其他软件(如 ArcGIS)的转换思路可参考本站坐标系转换:ArcGIS坐标系转换工具与GCJ02转WGS84,逻辑一致,只是接口不同。
CGCS2000高斯投影分带示意

常见问题

转换后坐标几乎完全一样,是不是程序写错了?

不是。椭球差异可忽略,EPSG 又无专用非空参数,Pyproj 默认接近恒等变换,数值不变是预期结果。真正的 0.5~1 米框架差异不会在这个简单 CRS 对里自动体现。

不写 always_xy=True 会出什么问题?

输入输出可能变成 lat/lon 顺序。你以为传的是 (经度, 纬度),实际被当成 (纬度, 经度),点会落到错误半球。养成习惯一律加 always_xy=True,或转换后立刻用已知点自检。

我需要厘米级精度,只靠 EPSG:4326→4490 够吗?

不够。必须补充历元归算、速度场模型或通过公共点求七参数(布尔莎模型),再自行构建 pipeline。简单 Transformer 只适合米级及以下要求的 GIS 应用。

批量转换很慢或提示 PROJ 数据相关错误怎么办?

先确认 Transformer 已缓存复用;再检查 pyproj 与系统 PROJ 数据目录是否一致(可用 pyproj.datadir.get_data_dir() 查看)。wheels 通常已够用地理转换,网格文件仅在涉及特定大地水准面时才需要单独下载。

总结:WGS84 到 CGCS2000 的地理转换用 Transformer.from_crs(4326, 4490, always_xy=True) 即可,结果近恒等属正常现象;差异与精密处理详见本站相关文章。建议日常流程固定“缓存 Transformer + 强制 always_xy + 控制点抽检”,投影阶段再按中央子午线正确选带,这样既稳又快。