WGS84、GCJ02、BD09 坐标系详解与转换指南
在地图开发、导航定位或地理数据整合时,开发者常遇到这样的问题:同一点位在不同地图上显示位置不一致。这往往不是 Bug,而是坐标系不统一导致的。本文系统梳理 WGS84、GCJ02、BD09 三大坐标系的关系与转换方法。
三大坐标系概述
- WGS84:世界大地坐标系(World Geodetic System 1984),国际通用的标准大地坐标系,GPS 芯片原始输出即为 WGS84 坐标。
- GCJ02:由国家测绘地理信息局制定,俗称"火星坐标系"。国内各类测绘地图(如高德、腾讯地图)均采用此坐标系。
- BD09:百度坐标系,在 GCJ02 基础上再次偏移加密得到,仅百度地图使用。
GCJ02 偏移原理
GCJ02 的本质是国家保密局对 WGS84 坐标进行非线性加密偏移。它并非简单平移,而是基于一组多项式公式,对经纬度分别施加与位置相关的偏移量,偏移幅度约 50-500 米。
由于偏移是非线性的,无法通过减去一个常量来还原,必须使用与加密过程对应的反算公式。
BD09 则在 GCJ02 基础上再叠加一次偏移,偏移量同样与位置相关。
转换算法
WGS84 → GCJ02
正向转换使用偏移公式,核心是计算经纬度方向的偏移量,关键参数为长半轴 a = 6378245.0 与偏心率平方 ee = 0.00669342162296594323:
function wgs84ToGcj02(lng, lat) {
const a = 6378245.0;
const ee = 0.00669342162296594323;
let dLat = transformLat(lng - 105.0, lat - 35.0);
let dLng = transformLng(lng - 105.0, lat - 35.0);
const radLat = (lat / 180.0) * Math.PI;
let magic = 1 - ee * Math.sin(radLat) ** 2;
const sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI);
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI);
return { lng: lng + dLng, lat: lat + dLat };
}GCJ02 → WGS84
由于偏移公式非线性,直接反解精度有限。实际中采用迭代反算:先做一次粗略反算,再将结果代入正向公式比较误差,反复修正直至收敛。相比一步反算,迭代法往返精度可达约 1e-7 量级,能很好地还原原始坐标。
境外坐标处理
对于中国境外的坐标,偏移公式本就不适用,因此需先做 outOfChina 判断:若经度小于 72.004 或大于 137.8347,或纬度小于 0.8293 或大于 55.8271,则判定为境外,原样返回不做转换。
实际应用场景
- 地图开发:将 GPS 采集的 WGS84 坐标转到 GCJ02 后,才能在国内地图上正确显示。
- 导航定位:车辆轨迹数据需与地图底图坐标系对齐,避免路线偏移。
- 数据整合:来自不同源(百度、高德、GPS)的数据须统一到同一坐标系后才能叠加分析。
提示:国内地图展示必须使用 GCJ02 或 BD09,否则会出现整体性偏移。
如需快速完成坐标转换,可使用 在线坐标转换工具,支持 WGS84、GCJ02、BD09 之间的相互转换。