Three.js 地理坐标系:从经纬度到三维世界的坐标解码
"一切3D图形的壮美,如果不落于地理坐标系上,终究只是漂浮在虚空之中。"
引言:两个宇宙的对话
在三维可视化开发中,我们常常面临一个根本性的问题:Three.js 默认的笛卡尔坐标系(原点在 (0,0,0))对"北京天安门"或"纽约自由女神"一无所知。而真实世界的数据------无论是 GPS 轨迹、建筑轮廓还是城市三维模型------都以经纬度来定义位置。
如何让 Three.js 理解"东经 116.3913°,北纬 39.9075°"?答案就藏在坐标系之中。
本文将沿着"地球 → 数学面 → 平面 → 屏幕"这条路径,系统讲解 GIS 坐标系的核心概念,并重点解决 Three.js 开发中最关键的问题:如何将地理坐标转换为三维空间坐标。
一、从地球到平面:坐标系的"三级逼近"
地球是一个不规则的球体,表面有高山也有海沟,无法直接用数学公式描述。为了能用数学表达地球上的位置,科学家们设计了三级逼近体系:
1.1 大地水准面(第一级逼近)
大地水准面是地球的物理模型------假设海水完全静止时延伸至大陆下方的重力等位面。由于地球质量分布不均,大地水准面的形状是不规则的,无法用简单数学公式表达。
1.2 地球椭球体(第二级逼近)
为了能用数学表达,我们用一个规则的椭球体来逼近大地水准面。不同的国家和地区会选择不同的椭球体来最佳拟合本地地形。例如:
- WGS84 椭球体:长半轴 6378137 米,扁率 1/298.257223563
- CGCS2000 椭球体:我国现行坐标系采用的椭球体
1.3 基准面(第三级逼近)
确定了椭球体后,还需要将它定位到地球上的具体位置------这就是基准面的作用。基准面决定了椭球体与地球表面的相对位置关系。
根据原点位置,基准面分为两类:
| 类型 | 原点 | 代表坐标系 |
|---|---|---|
| 地心基准面 | 地球质心 | WGS84、CGCS2000 |
| 区域基准面 | 特定区域的大地原点 | 北京54、西安80 |
关键理解:同一个椭球体可以配合不同的基准面。就像同一件衣服穿在不同人身上------椭球体是"衣服",基准面决定了它"穿"在地球的哪个位置。
二、坐标系的两大阵营:地理 vs 投影
2.1 地理坐标系(Geographic Coordinate System)
本质 :三维球面坐标系,用角度(经纬度)表示位置。
组成:角度单位(度/分/秒)+ 本初子午线 + 基准面(含椭球体)。
经典案例------WGS84(EPSG:4326):
- 全球通用的 GPS 坐标系,原点为地球质心
- 坐标单位:十进制度(如 116.3913°, 39.9075°)
- Z轴指向 BIH 1984.0 定义的协议地极方向
特点 :适合存储 和交换数据,但不适合直接用于平面测量和 Web 展示。
2.2 投影坐标系(Projected Coordinate System)
本质 :二维平面坐标系,用线性单位(米、英尺)表示位置。
组成:地理坐标系 + 投影方法 + 线性单位。
为什么需要投影? 因为地图是平的,而地球是曲的。投影的本质是用数学方法将球面"摊平"到平面上------但任何投影都会带来变形(面积、角度、距离三者不可兼得)。
三大经典投影:
| 投影名称 | 特点 | 典型应用 |
|---|---|---|
| 墨卡托投影 | 等角,航线为直线,两极变形极大 | 航海图 |
| Web Mercator(EPSG:3857) | 墨卡托的"黑客版",将地球近似为正球体 | Google Maps、OpenStreetMap |
| 高斯-克吕格 | 等角横切椭圆柱投影,中央经线无变形 | 中国1:1万~1:50万地形图 |
💡 Web Mercator 的由来:Google 工程师为了简化计算,将地球近似为正球体(半径 = 椭球体长半轴),并将 Y 轴范围截断与 X 轴相同,形成正方形地图------这就是"懒惰工程师"的智慧。
三、Three.js 坐标转换实战:经纬度 → 笛卡尔坐标
3.1 核心问题
Three.js 使用右手笛卡尔坐标系:
- X 轴:右
- Y 轴:上
- Z 轴:前(相机默认朝向)
而地理数据是经纬度(角度)------需要翻译官。
3.2 转换方案一:Web Mercator 投影法(适合城市级场景)
这是最常用的方法。Web Mercator 将地球投影为平面,公式如下:
javascript
// 经纬度转 Web Mercator 坐标(单位:米)
function lngLatToMercator(lng, lat) {
const earthRad = 6378137.0; // 地球赤道半径(米)
const x = lng * Math.PI / 180 * earthRad;
const latRad = lat * Math.PI / 180;
const y = earthRad / 2 * Math.log((1 + Math.sin(latRad)) / (1 - Math.sin(latRad)));
return { x, y };
}
// 示例:北京天安门
const beijing = lngLatToMercator(116.3913, 39.9075);
// 输出:{ x: 12957495.23, y: 4840818.93 }
得到的 (x, y) 即为 Three.js 场景中可用的平面坐标(Z 轴可设高度)。
3.3 转换方案二:Mapbox 风格转换法(适合与地图 SDK 集成)
如果使用 Mapbox 作为底图,可利用其内置的 MercatorCoordinate 类:
javascript
// 经纬度转 Mapbox 世界坐标(范围 0-1)
const mercator = mapboxgl.MercatorCoordinate.fromLngLat(
{ lng: 116.3913, lat: 39.9075 },
0 // 海拔高度(米)
);
// 输出:{ x: 0.91576, y: 0.48563, z: 0 }
// 获取米到世界坐标单位的换算比例
const scale = mercator.meterInMercatorCoordinateUnits();
// 在 Three.js 中使用
cube.position.set(mercator.x, mercator.y, mercator.z);
cube.scale.set(scale, scale, scale); // 保证模型大小正确
⚠️ 注意:Web Mercator 在局部范围内精度很高,但跨区域(如从赤道到两极)会出现严重变形------因为球面无法完美摊平。
四、中国的"偏移坐标系":不得不说的坑
在国内做地图开发,坐标系还有一层特殊加密。
4.1 三类坐标的"三国演义"
| 名称 | 代码 | 说明 | 使用方 |
|---|---|---|---|
| WGS84 | 4326 | 真实 GPS 坐标,无偏移 | 国际服务、硬件设备 |
| GCJ-02 | - | 国测局加密,"火星坐标" | 高德、腾讯、Google 中国 |
| BD-09 | - | 百度二次加密 | 百度地图 |
4.2 为什么会有偏移?
出于国家安全考虑,国内所有导航电子地图必须使用加密坐标系统------将真实经纬度按非线性算法"偏移"一定距离。这就是为什么用 GPS 设备采集的点直接叠加在高德地图上会"飘"出几条街。
4.3 转换方案(coordtransform)
javascript
import coordtransform from 'coordtransform';
// WGS84 → GCJ-02
const gcj = coordtransform.wgs84togcj02(lng, lat);
// GCJ-02 → BD-09
const bd = coordtransform.gcj02tobd09(lng, lat);
// 反向转换同理
开发建议:
- 统一后端存储为 WGS84
- 前端根据底图类型动态转换
- 跨地图服务商时务必转换,否则数据对不上
五、坐标系选型速查表
| 使用场景 | 推荐坐标系 | 原因 |
|---|---|---|
| GPS 数据存储 | WGS84(EPSG:4326) | 国际标准,无偏移 |
| 国际地图底图 | Web Mercator(EPSG:3857) | 瓦片服务标准 |
| 中国官方测绘 | CGCS2000(EPSG:4490) | 法定坐标系 |
| 高德/腾讯地图 | GCJ-02 | 服务商原生支持 |
| 百度地图 | BD-09 | 百度专用 |
| 精确面积/长度测量 | 高斯-克吕格(当地中央经线) | 区域变形最小 |
六、常见问题 FAQ
Q1:为什么我的 GPS 点在中国地图上显示偏移? A:中国地图服务(高德、百度等)使用加密坐标系(GCJ-02/BD-09),而 GPS 输出的是 WGS84。需要先做坐标转换。
Q2:Three.js 场景中模型位置总是不对? A:检查是否将经纬度正确转换为了 Web Mercator 坐标。记住:Three.js 不认识经纬度,只认数字。
Q3:CGCS2000 和 WGS84 可以通用吗? A:对于一般工程测量(精度要求厘米级以下),两者差异可忽略;但高精度场景(如测绘)需要严格区分。
Q4:如何在 Three.js 中渲染全球范围的地理数据? A:需要使用地心坐标系(ECEF),配合球体模型和相机控制。Web Mercator 只适合局部区域。
结语
坐标系的本质,是用数学模型描述物理世界。从大地水准面到椭球体,从地理坐标系到投影坐标系,再到 Three.js 中的笛卡尔坐标------每一次转换,都是对地球的一次"翻译"。
理解这些概念,不仅是为了解决"点飘到哪里去了"的技术问题,更是为了在三维数字世界中,精准地锚定现实。
"图形的浪漫在于幻想,地图的浪漫在于现实。而当你让三维图形落地在真实世界,那是浪漫与理性最优雅的交融。"
相关资源:
- EPSG 代码查询:epsg.io
- coordtransform 库:npm/coordtransform
- Three.js 坐标轴辅助调试:AxesHelper