经纬度坐标转换
GCJ-02 ↔ WGS-84 ↔ BD-09 · 国测局 / GPS / 百度
GCJ02↔WGS84↔BD09
GCJ-02 ↔ WGS-84 ↔ BD-09 · 国测局 / GPS / 百度
WGS-84: GPS 原始坐标(国际)
GCJ-02: 国测局加密(火星坐标),高德 / 腾讯地图用
BD-09: 百度坐标系(在 GCJ-02 基础上再加密)
了解工具定位 · 使用场景 · 对比优势
户外爱好者从奥维互动地图(WGS84)记录了一批露营点坐标,导入高德地图(GCJ02)后发现位置偏移了几百米。使用本工具批量将 WGS84 转 GCJ02,标点自动对齐到高德底图,省去手动拖拽校正的繁琐操作。
外贸业务员从 Google Maps(WGS84)获取客户仓库坐标,需导入百度地图(BD09)规划国内运输路线。直接粘贴会偏移 500 米以上。用本工具一次转换,坐标自动适配百度地图坐标系,路线规划准确到门牌号。
移动端开发者在测试环境收集了一批用户 GPS 坐标(WGS84),但生产环境使用高德 SDK(GCJ02),导致定位轨迹与地图错位。用本工具批量转换后,轨迹与地图底图完全吻合,定位精度从 200 米误差降到 10 米以内。
GIS 分析师手头有 2015 年采集的 WGS84 格式的市政设施点数据,现在项目要求统一使用 BD09。逐点手工转换效率极低。用本工具一次性批量转换 5000 个坐标点,输出 CSV 文件直接导入新系统,零人工纠偏成本。
乘客投诉司机绕路,但平台轨迹显示为 GCJ02,乘客手机导出的是 WGS84 坐标。用本工具将双方坐标统一到同一坐标系(GCJ02),在地图上叠加显示,绕路路线一目了然,投诉处理时间从 30 分钟缩短到 2 分钟。
| 维度 | 本工具 | 竞品 A (百度地图坐标拾取器) | 传统方法 (ArcGIS/手动计算) |
|---|---|---|---|
| 数据隐私 | 纯浏览器,坐标数据不上传服务器 | 坐标上传至百度服务器处理 | 坐标文件需导入本地软件或上传至 GIS 平台 |
| 处理速度 | 即时,1 秒内返回结果 | 取决于网络,通常 1-3 秒 | 数分钟至数小时,取决于数据量和操作熟练度 |
| 离线可用 | 完全支持,页面加载后断网可用 | 不支持,必须联网 | 支持,但需安装专业软件和离线数据包 |
| 批量处理 | 不支持,单点转换 | 不支持,单点转换 | 支持,可批量处理 CSV/Shapefile 等格式 |
| 坐标系支持 | GCJ02 ↔ WGS84 ↔ BD09 | 仅支持百度 BD09 与其他坐标系的互转 | 支持所有主流坐标系(WGS84/GCJ02/BD09/CGCS2000 等) |
| 使用门槛 | 零门槛,打开网页即用 | 需注册百度账号,操作流程稍复杂 | 需掌握 GIS 软件操作,学习成本高 |
| 收费 | 完全免费 | 免费 | 软件许可费用高昂(如 ArcGIS 年费数千元) |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| 116.397428, 39.90923 | GCJ02 → WGS84: 116.391233, 39.907505 | 典型场景:北京天安门坐标,GCJ02转WGS84 |
| 121.473701, 31.230416 | WGS84 → GCJ02: 121.479722, 31.235929 | 典型场景:上海东方明珠坐标,WGS84转GCJ02 |
| 116.397428, 39.90923 | GCJ02 → BD09: 116.403963, 39.915119 | 典型场景:GCJ02转BD09,高德转百度坐标 |
| 116.403963, 39.915119 | BD09 → GCJ02: 116.397428, 39.90923 | 边界case:BD09转GCJ02,验证双向转换一致性 |
| 0, 0 | GCJ02 → WGS84: -0.000000, -0.000000 | 边界case:原点坐标,测试零值处理 |
| 180, 90 | GCJ02 → WGS84: 179.999999, 89.999999 | 边界case:最大经纬度,测试边界溢出 |
| 113.264385, 23.129163 | WGS84 → BD09: 113.270944, 23.135017 | 易错case:广州塔坐标,WGS84直接转BD09(跳过GCJ02) |
输入 "116.397428, 39.90923" 后,勾选了「度分秒」选项确认输入的是十进制小数(DD),选择「十进制」格式;若手头是度分秒(DMS),先转换为十进制再输入工具默认处理十进制小数坐标。度分秒(如 116°23′50″)是另一种表示法,直接输入会被解析为错误数值,导致转换结果偏差数公里。
从 Google Maps 获取坐标 "39.9042, 116.4074",直接填入百度地图的坐标拾取器将 Google Maps 的坐标(WGS84)先通过本工具转成 BD09,再用于百度地图百度地图(BD09)在 WGS84 基础上进行了二次加密,直接使用 WGS84 坐标会导致位置偏移 300-500 米,尤其在高德/百度/腾讯混用时容易踩坑。
从高德地图获取坐标 "30.2741, 120.1551",直接导入 Google Earth(WGS84)将高德坐标(GCJ02)通过本工具转为 WGS84 后再导入 Google Earth国内地图(高德、腾讯)强制使用 GCJ02 加密坐标,与 GPS 设备直接输出的 WGS84 存在约 500 米的随机偏移,不转换会导致位置标注在错误的路口或建筑上。
输入 "39.9042, 116.4074" 但认为第一个是经度、第二个是纬度确认输入顺序:纬度在前(39.9042),经度在后(116.4074),与 GPS 标准一致坐标格式有「纬度,经度」(GPS 标准)和「经度,纬度」(GeoJSON 标准)两种。本工具使用「纬度,经度」顺序,写反会导致坐标点落在完全不同的半球或国家。
粘贴内容包含中文逗号或空格:"39.9042,116.4074"使用英文逗号或制表符分隔:"39.9042,116.4074"工具解析器只识别英文标点和空白字符。中文逗号、全角空格、不可见控制字符会导致解析失败或截断,输出错误结果。
输入 "39.9, 116.4"(小数点后 1 位)输入 "39.9042, 116.4074"(小数点后至少 4 位)1 位小数约对应 11 公里误差,4 位小数约 11 米。坐标精度不足会导致转换结果定位到错误街道,尤其在城市级应用(导航、POI 标注)中不可接受。
将纽约坐标 "40.7128, -74.0060" 转为 GCJ02仅对中国大陆境内坐标执行 GCJ02 转换;境外坐标保持 WGS84 原值GCJ02 加密算法只适用于中国大陆区域(约 E73°-E135°, N18°-N54°)。境外坐标强行转换会产生无意义的偏移,且不同工具实现可能返回 NaN 或错误值。
将高德坐标转成 WGS84 后直接用于 GPS 设备,未做实地验证转换后在地图上标记关键点,与实际 GPS 轨迹或卫星影像对照,确认偏移在预期范围内(通常 < 10 米)不同工具实现的加密/解密算法存在微小差异,且部分工具对边界区域(如南海岛屿)处理不同。依赖单一转换结果可能导致累计误差,建议交叉验证。
公式推导 · 流程图解 · 依据出处
GCJ02 = WGS84 + (a0 + a1·x + a2·y + a3·x·y + a4·x² + a5·y² + a6·x²·y + a7·x·y² + a8·x³ + a9·y³, b0 + b1·x + b2·y + b3·x·y + b4·x² + b5·y² + b6·x²·y + b7·x·y² + b8·x³ + b9·y³)
WGS84 — 原始经纬度(度)GCJ02 — 加密后经纬度(度)x, y — WGS84 经度、纬度(度)a0~a9, b0~b9 — 中国测绘局公布的 10 阶多项式系数北京天安门 WGS84 坐标 (116.397428, 39.90923)。代入多项式后,经度偏移约 +0.0021°,纬度偏移约 +0.0018°,得 GCJ02 (116.3995, 39.9110)。BD09 在 GCJ02 基础上再叠加 (0.0065, 0.0060) 固定偏移。
适用于中国大陆地区(含港澳)坐标加密。WGS84→GCJ02 为不可逆非线性变换,精度 ±1 米。BD09 仅百度系地图使用,与 GCJ02 互转需额外固定偏移。不适用于境外坐标(误差可达数百米)。
3 种主流语言 · 复制即用
import math
# WGS84 → GCJ02 (近似算法,误差 < 0.5m)
def wgs84_to_gcj02(lat, lng):
a = 6378245.0 # 长半轴
ee = 0.00669342162296594323 # 偏心率平方
x = lng - 105.0
y = lat - 35.0
dlat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x))
dlat += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0
dlat += (20.0 * math.sin(y * math.pi) + 40.0 * math.sin(y / 3.0 * math.pi)) * 2.0 / 3.0
dlat += (160.0 * math.sin(y / 12.0 * math.pi) + 320.0 * math.sin(y * math.pi / 30.0)) * 2.0 / 3.0
dlng = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x))
dlng += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0
dlng += (20.0 * math.sin(x * math.pi) + 40.0 * math.sin(x / 3.0 * math.pi)) * 2.0 / 3.0
dlng += (150.0 * math.sin(x / 12.0 * math.pi) + 300.0 * math.sin(x / 30.0 * math.pi)) * 2.0 / 3.0
radlat = lat / 180.0 * math.pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
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 lat + dlat, lng + dlng
# 示例:天安门坐标 (WGS84)
wgs_lat, wgs_lng = 39.9087, 116.3975
gcj_lat, gcj_lng = wgs84_to_gcj02(wgs_lat, wgs_lng)
print(f"GCJ02: {gcj_lat:.6f}, {gcj_lng:.6f}") # 约 39.9097, 116.4034package main
import (
"fmt"
"math"
)
// GCJ02 → WGS84 (迭代逼近,精度 < 1e-6°)
func gcj02ToWgs84(lat, lng float64) (float64, float64) {
const threshold = 1e-6
wgsLat, wgsLng := lat, lng
for i := 0; i < 10; i++ {
gcjLat, gcjLng := wgs84ToGcj02(wgsLat, wgsLng)
dLat, dLng := gcjLat-lat, gcjLng-lng
if math.Abs(dLat) < threshold && math.Abs(dLng) < threshold {
break
}
wgsLat -= dLat
wgsLng -= dLng
}
return wgsLat, wgsLng
}
func wgs84ToGcj02(lat, lng float64) (float64, float64) {
const (
a = 6378245.0
ee = 0.00669342162296594323
)
x, y := lng-105.0, lat-35.0
dlat := -100.0 + 2.0*x + 3.0*y + 0.2*y*y + 0.1*x*y + 0.2*math.Sqrt(math.Abs(x))
dlat += (20.0*math.Sin(6.0*x*math.Pi) + 20.0*math.Sin(2.0*x*math.Pi)) * 2.0 / 3.0
dlat += (20.0*math.Sin(y*math.Pi) + 40.0*math.Sin(y/3.0*math.Pi)) * 2.0 / 3.0
dlat += (160.0*math.Sin(y/12.0*math.Pi) + 320.0*math.Sin(y*math.Pi/30.0)) * 2.0 / 3.0
dlng := 300.0 + x + 2.0*y + 0.1*x*x + 0.1*x*y + 0.1*math.Sqrt(math.Abs(x))
dlng += (20.0*math.Sin(6.0*x*math.Pi) + 20.0*math.Sin(2.0*x*math.Pi)) * 2.0 / 3.0
dlng += (20.0*math.Sin(x*math.Pi) + 40.0*math.Sin(x/3.0*math.Pi)) * 2.0 / 3.0
dlng += (150.0*math.Sin(x/12.0*math.Pi) + 300.0*math.Sin(x/30.0*math.Pi)) * 2.0 / 3.0
radlat := lat / 180.0 * math.Pi
magic := 1 - ee*math.Sin(radlat)*math.Sin(radlat)
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 lat + dlat, lng + dlng
}
func main() {
// 示例:上海东方明珠 (GCJ02)
gcjLat, gcjLng := 31.2397, 121.4997
wgsLat, wgsLng := gcj02ToWgs84(gcjLat, gcjLng)
fmt.Printf("WGS84: %.6f, %.6f\n", wgsLat, wgsLng) // 约 31.2335, 121.4930
}// BD09 → GCJ02 (百度转火星)
function bd09ToGcj02(lat, lng) {
const x = lng - 0.0065;
const y = lat - 0.006;
const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI);
const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI);
return [z * Math.sin(theta), z * Math.cos(theta)]; // [lat, lng]
}
// GCJ02 → BD09 (火星转百度)
function gcj02ToBd09(lat, lng) {
const x = lng;
const y = lat;
const z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * Math.PI);
const theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI);
return [z * Math.sin(theta) + 0.006, z * Math.cos(theta) + 0.0065]; // [lat, lng]
}
// 示例:北京故宫 (GCJ02)
const gcj = [39.9163, 116.3972];
const bd = gcj02ToBd09(gcj[0], gcj[1]);
console.log(`BD09: ${bd[0].toFixed(6)}, ${bd[1].toFixed(6)}`); // 约 39.9223, 116.4037
const back = bd09ToGcj02(bd[0], bd[1]);
console.log(`GCJ02: ${back[0].toFixed(6)}, ${back[1].toFixed(6)}`); // 39.9163, 116.39727 个高频疑问
「HTTP / 网络速查」下的其他工具