把 EPSG:4479 当地理坐标用,点位数值到了七位数
天地图服务目录里写着 CGCS2000,选了 4479,拿到的却是 X/Y/Z 三个米值。
现象
请求参数写 TILEMATRIXSET=4490 时一切正常;
改成某个文档里提到的 4479 后,返回的坐标是
-2177350, 4389500, 4070300 这样的三个数,
前两个远超 ±180 / ±90,第三个也不是高程的合理量级。
把这三个数直接传进 Cesium.Cartesian3.fromDegrees(x, y, z),
相机飞到地球外面,屏幕只剩黑色。
原因
EPSG 码里同一基准往往有多个「坐标系」:
| EPSG | 名称 | 单位 | 典型数值 |
|---|---|---|---|
| 4490 | CGCS2000 地理 2D | 度 | 116.397, 39.909 |
| 4479 | CGCS2000 地心直角 | 米 | -2177350, 4389500, 4070300 |
| 4547 | CGCS2000 3 度带 111°E | 米 | 500000, 3800000 |
地心坐标是以地球质心为原点的 X/Y/Z,中国区域三个分量的绝对值都在
2.0e6~6.4e6 之间。它必须经过地心→地理的转换才能变成经纬度,
这一步不是简单的除以 111320。
排查过程
- 数一下有几个分量。三个分量且第三个不能当地理高度解释,就是地心坐标。
- 看绝对值量级:地心坐标必然小于 6378137 加高程,且三个分量都在百万级。
- 核对服务文档里的
TILEMATRIXSET或SRS参数,确认要的是 4490 而不是 4479。 - 用 proj4 从 4479 转到 4490,结果落在中国境内即可确认。
// 地心 -> 地理
proj4.defs('EPSG:4479',
'+proj=geocent +ellps=GRS80 +units=m +no_defs');
proj4.defs('EPSG:4490',
'+proj=longlat +ellps=GRS80 +no_defs');
proj4('EPSG:4479', 'EPSG:4490', [-2177350, 4389500, 4070300]);
// => [116.3974, 39.9092]
解决方案
接入时只用 4490。确实拿到地心坐标时,在进入渲染层之前做一次转换,
并显式声明 geocent,不要依赖库去猜。
// 三维场景下也可以直接用地心坐标构造笛卡尔点
// 注意:Cesium 的 Cartesian3 就是地心坐标,不需要 fromDegrees
const p = new Cesium.Cartesian3(-2177350, 4389500, 4070300);
viewer.camera.lookAt(p, new Cesium.Cartesian3(0, 0, 0));
// 若手上是经纬度,才用 fromDegrees
// Cesium.Cartesian3.fromDegrees(116.3974, 39.9092, 50)
fromDegrees 与 Cartesian3 的入参不是同一套东西。
前者接受度,后者接受米;混用不会报错,只会把相机送到错误位置。
验证
转换结果经度 116.3974、纬度 39.9092,落在北京; 地心坐标反算回经纬度后再正算,三个分量误差应小于 1 毫米。
const g = proj4('EPSG:4479', 'EPSG:4490', [-2177350, 4389500, 4070300]);
console.assert(Math.abs(g[0] - 116.3974) < 0.001, '经度不对');
console.assert(Math.abs(g[1] - 39.9092) < 0.001, '纬度不对');
适用版本
| 工具 / 服务 | 版本 | 说明 |
|---|---|---|
| 天地图 WMTS | 1.0.0 | CGCS2000 用 TILEMATRIXSET=4490 |
| proj4js | 2.9 及以上 | geocent 投影类型可用 |
| Cesium | 1.100 及以上 | Cartesian3 即地心坐标,单位为米 |
经纬志(2026)。《把 EPSG:4479 当地理坐标用,点位数值到了七位数》。https://www.jingweizhi.com/cookbook/tdt-4490-4479.html(访问日期 2026-11-03)。