中国地图坐标转换器

GPS、高德/腾讯(火星坐标)、百度坐标在线互转,修正坐标放到国内地图上出现偏移的问题。

为什么 GPS 坐标放到国内地图上会偏移?

按照国家相关规定,中国大陆公开发布的地图需要对坐标做加密偏移处理,由此形成 GCJ-02 坐标系,也叫国测局坐标,俗称“火星坐标”。高德、腾讯以及 Apple 地图、Google 地图的中国大陆道路图都使用 GCJ-02;百度地图在 GCJ-02 的基础上又做了一次偏移,形成 BD-09。GPS 设备和手机原始定位给出的是 WGS84 坐标,如果直接放到这些地图上,标记通常会偏离几百米,到了百度地图上可能超过 1 公里。坐标纠偏的做法,就是把坐标转换成目标地图使用的坐标系。

如何修正中国地图坐标偏移

1

粘贴坐标

输入 GPS、高德/腾讯或百度地图提供的经纬度,每行一组即可批量处理。保留清晰的数字和分隔符,方便检查解析结果。

2

选择来源和目标

按坐标来源选择 GPS、高德/腾讯或百度,再选择要使用结果的地图。选项同时标明 WGS84、GCJ-02、BD-09,方便核对坐标系。

3

复制或打开地图验证

查看目标坐标系的结果,复制单项或全部坐标,也可以打开目标地图核对标记。位置不符时,先检查来源和经纬度顺序。

我应该选择哪种坐标?

GPS / WGS84

GPS 设备、Google Earth 和 OpenStreetMap 通常使用 WGS84,常作为全球经纬度数据的交换基准。天地图使用 CGCS2000;普通网页地图标点可近似看待,专业测绘仍应遵循数据规范。

火星坐标 / GCJ-02

高德、腾讯、Apple 地图(中国大陆)使用 GCJ-02。GPS 坐标直接用于这些地图时,标记可能与道路或建筑错位。请按实际来源和目标地图选择转换方向,不要仅凭数值相近作判断。

百度 / BD-09

百度地图使用 BD-09,与 GCJ-02 仍有差异。GPS 坐标用于百度时,通常经 WGS84、GCJ-02 转为 BD-09;百度坐标转到其他地图时则选择相应的反向转换。

常见地图和数据使用的坐标系

地图或数据来源坐标系
GPS 设备、手机原始定位、照片 EXIFWGS84
Google Earth、OpenStreetMapWGS84
Google 地图(中国大陆道路图)GCJ-02(卫星图为 WGS84,两层会错位)
Apple 地图(中国大陆)GCJ-02(地图数据由高德提供)
高德地图、腾讯地图GCJ-02(火星坐标)
百度地图BD-09(经纬度)/ BD-09MC(墨卡托米制)
天地图CGCS2000(网页标点可近似看作 WGS84)

Google 地图在中国为什么道路和卫星图对不上?

在中国大陆范围内,Google 地图的道路图使用 GCJ-02,卫星图使用 WGS84,所以切换到卫星图后,道路和建筑会错开几百米。用 Google 地图道路图采集的中国大陆坐标属于 GCJ-02,用于 GPS 设备或 OpenStreetMap 前,应选择 GCJ-02 转 WGS84;在卫星图上采集的点则按 WGS84 处理。

转换示例:三种坐标系相差多少

下表用本工具对三个示例点做转换,显示同一位置在三种坐标系下的数值(经度, 纬度),以及与 WGS84 原点的距离。

示例点WGS84(GPS)GCJ-02(高德/腾讯)BD-09(百度)相对 WGS84 的偏移
北京 天安门城楼116.391263, 39.907359116.397504, 39.908760116.403877, 39.915104GCJ-02 约 555 米;BD-09 约 1378 米
上海 东方明珠电视塔121.495260, 31.241946121.499709, 31.239947121.506320, 31.245587GCJ-02 约 478 米;BD-09 约 1127 米
广州 广州塔113.319148, 23.109015113.324558, 23.106404113.331100, 23.112168GCJ-02 约 625 米;BD-09 约 1272 米

常见转换场景

GPS 坐标转高德/腾讯地图 (WGS84 to GCJ-02)

GPS 点放到高德或腾讯地图后与底图错位时,通常需要转为 GCJ-02;请先确认来源是 GPS/WGS84。

GPS 坐标转百度地图 (WGS84 to BD-09)

百度地图使用 BD-09。选择 WGS84 到 BD-09,工具会处理经过 GCJ-02 的转换链路。

火星坐标转 GPS (GCJ-02 to WGS84)

将高德、腾讯地图上采集的点用于 GPS 或全球地图时,可近似反向转为 WGS84,适合日常标点和数据核对。

百度坐标转高德/腾讯 (BD-09 to GCJ-02)

将百度坐标用于高德或腾讯地图时,选择 BD-09 为来源、GCJ-02 为目标,并打开地图核对标记。

输入格式、坐标顺序与批量处理

每行输入一组十进制度经纬度,例如天安门城楼的 GPS 坐标 116.391263, 39.907359(经度在前);多组请换行。来源和目标代表坐标系,顺序选项决定经纬度谁在前。高德、腾讯接口常用经度在前,部分 GPS 数据则纬度在前;自动识别后也建议抽查原始值。结果可复制为目标值或全部坐标,并选择逗号、逗号加空格或 JSON 格式,便于粘贴到表格和脚本。

还没有坐标? 用经纬度坐标拾取器在地图上点选

适用范围与边界情况

GCJ-02 与 BD-09 主要用于中国地图产品。大陆以外位置通常无需这些偏移,工具会按粗略范围判断并提示;这不是行政区或测绘边界。港澳台和不同地图版本的规则可能不同,重要点位应核对来源设备或接口说明,并在目标地图验证。测绘及 GIS 数据还可能使用 CGCS2000、投影坐标或高程基准;本工具只转换经纬度,不替代专业基准转换。

精度与限制

本工具按常见公式转换,GCJ-02/BD-09 逆转 GPS 使用迭代近似。用上面的示例点做往返测试,GCJ-02 转回 WGS84 的算法误差约 1 厘米,BD-09 转回 WGS84 约 6 厘米。原始数据和地图底图本身也会带来误差;结果适合日常标点和数据检查,不保证与测绘成果重合。请勿用于工程测量、法律边界、安全导航或应急救援。

开发者代码片段:WGS84、GCJ-02、BD-09 互转

以下 JavaScript 和 Python 函数与本工具使用相同的公式,参数和返回值均为经度在前。

JavaScript
const PI = Math.PI;
const A = 6378245.0;
const EE = 0.00669342162296594323;
const X_PI = PI * 3000.0 / 180.0;

function outOfChina(lng, lat) {
  return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271;
}

function transformLat(x, y) {
  let ret = -100 + 2 * x + 3 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
  ret += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3;
  ret += (20 * Math.sin(y * PI) + 40 * Math.sin(y / 3 * PI)) * 2 / 3;
  ret += (160 * Math.sin(y / 12 * PI) + 320 * Math.sin(y * PI / 30)) * 2 / 3;
  return ret;
}

function transformLng(x, y) {
  let ret = 300 + x + 2 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
  ret += (20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2 / 3;
  ret += (20 * Math.sin(x * PI) + 40 * Math.sin(x / 3 * PI)) * 2 / 3;
  ret += (150 * Math.sin(x / 12 * PI) + 300 * Math.sin(x / 30 * PI)) * 2 / 3;
  return ret;
}

// WGS84 (GPS) -> GCJ-02 (Amap / Tencent)
function wgs84ToGcj02(lng, lat) {
  if (outOfChina(lng, lat)) return [lng, lat];
  const radLat = lat / 180 * PI;
  let magic = Math.sin(radLat);
  magic = 1 - EE * magic * magic;
  const sqrtMagic = Math.sqrt(magic);
  const dLat = transformLat(lng - 105, lat - 35) * 180 / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
  const dLng = transformLng(lng - 105, lat - 35) * 180 / (A / sqrtMagic * Math.cos(radLat) * PI);
  return [lng + dLng, lat + dLat];
}

// GCJ-02 -> WGS84, iterative approximation
function gcj02ToWgs84(lng, lat) {
  if (outOfChina(lng, lat)) return [lng, lat];
  let [wLng, wLat] = [lng, lat];
  for (let i = 0; i < 10; i++) {
    const [gLng, gLat] = wgs84ToGcj02(wLng, wLat);
    wLng -= gLng - lng;
    wLat -= gLat - lat;
  }
  return [wLng, wLat];
}

// GCJ-02 -> BD-09 (Baidu)
function gcj02ToBd09(lng, lat) {
  const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI);
  const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI);
  return [z * Math.cos(theta) + 0.0065, z * Math.sin(theta) + 0.006];
}

// BD-09 -> GCJ-02
function bd09ToGcj02(lng, lat) {
  const x = lng - 0.0065;
  const y = lat - 0.006;
  const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
  const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
  return [z * Math.cos(theta), z * Math.sin(theta)];
}
Python
import math

PI = math.pi
A = 6378245.0
EE = 0.00669342162296594323
X_PI = PI * 3000.0 / 180.0


def out_of_china(lng, lat):
    return lng < 72.004 or lng > 137.8347 or lat < 0.8293 or lat > 55.8271


def _transform_lat(x, y):
    ret = -100 + 2 * x + 3 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x))
    ret += (20 * math.sin(6 * x * PI) + 20 * math.sin(2 * x * PI)) * 2 / 3
    ret += (20 * math.sin(y * PI) + 40 * math.sin(y / 3 * PI)) * 2 / 3
    ret += (160 * math.sin(y / 12 * PI) + 320 * math.sin(y * PI / 30)) * 2 / 3
    return ret


def _transform_lng(x, y):
    ret = 300 + x + 2 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x))
    ret += (20 * math.sin(6 * x * PI) + 20 * math.sin(2 * x * PI)) * 2 / 3
    ret += (20 * math.sin(x * PI) + 40 * math.sin(x / 3 * PI)) * 2 / 3
    ret += (150 * math.sin(x / 12 * PI) + 300 * math.sin(x / 30 * PI)) * 2 / 3
    return ret


def wgs84_to_gcj02(lng, lat):
    """WGS84 (GPS) -> GCJ-02 (Amap / Tencent)"""
    if out_of_china(lng, lat):
        return lng, lat
    rad_lat = lat / 180 * PI
    magic = 1 - EE * math.sin(rad_lat) ** 2
    sqrt_magic = math.sqrt(magic)
    d_lat = _transform_lat(lng - 105, lat - 35) * 180 / ((A * (1 - EE)) / (magic * sqrt_magic) * PI)
    d_lng = _transform_lng(lng - 105, lat - 35) * 180 / (A / sqrt_magic * math.cos(rad_lat) * PI)
    return lng + d_lng, lat + d_lat


def gcj02_to_wgs84(lng, lat):
    """GCJ-02 -> WGS84, iterative approximation"""
    if out_of_china(lng, lat):
        return lng, lat
    w_lng, w_lat = lng, lat
    for _ in range(10):
        g_lng, g_lat = wgs84_to_gcj02(w_lng, w_lat)
        w_lng -= g_lng - lng
        w_lat -= g_lat - lat
    return w_lng, w_lat


def gcj02_to_bd09(lng, lat):
    """GCJ-02 -> BD-09 (Baidu)"""
    z = math.sqrt(lng * lng + lat * lat) + 0.00002 * math.sin(lat * X_PI)
    theta = math.atan2(lat, lng) + 0.000003 * math.cos(lng * X_PI)
    return z * math.cos(theta) + 0.0065, z * math.sin(theta) + 0.006


def bd09_to_gcj02(lng, lat):
    """BD-09 -> GCJ-02"""
    x, y = lng - 0.0065, lat - 0.006
    z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * X_PI)
    theta = math.atan2(y, x) - 0.000003 * math.cos(x * X_PI)
    return z * math.cos(theta), z * math.sin(theta)

常见问题

为什么 GPS 坐标在高德、百度地图上会偏移?⌄
高德、腾讯地图使用 GCJ-02(火星坐标),百度地图使用 BD-09,而 GPS 给出的是 WGS84。坐标系不同,同一组数字在国内地图上就会偏离几百米到 1 公里以上。把坐标转换为目标地图的坐标系即可修正。
什么是火星坐标?⌄
火星坐标是 GCJ-02 的俗称,也叫国测局坐标,是中国大陆公开地图按规定做加密偏移后使用的坐标系。高德、腾讯地图以及 Apple 地图、Google 地图的中国大陆道路图都使用它。
火星坐标转 GPS 的精度有多高?⌄
GCJ-02 转 WGS84 没有公开的精确逆公式,本工具使用迭代近似。示例点的往返算法误差约 1 厘米,BD-09 转 WGS84 约 6 厘米,足够日常标点使用,但不适用于测绘。
中国以外的坐标需要转换吗?⌄
通常不需要。本工具在粗略中国范围外会原样返回,并显示提示。
港澳台坐标应该怎么选?⌄
不同地图产品策略可能不同。建议按坐标来源和目标地图产品选择,并用“在地图中打开”验证。
什么是 BD-09MC?⌄
BD-09MC 是百度墨卡托米制坐标,数值通常为七八位数。本工具目前只支持 BD-09 经纬度坐标,检测到 BD-09MC 会给出提示。
可以一次转换多组坐标吗?⌄
可以。每行输入一组坐标,设置来源、目标和经纬度顺序后开始转换;结果可以按目标坐标或全部坐标系复制。
经纬度顺序会影响结果吗?⌄
会。请根据原始数据选择经度在前或纬度在前。自动识别能帮助判断常见情况,但坐标数值不典型时仍应核对来源。
这个工具免费吗?⌄
免费,无需注册。转换在浏览器中完成,坐标不会上传。