百度地图墨卡托坐标转高德经纬度坐标(偏移小)
Posted asahii
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了百度地图墨卡托坐标转高德经纬度坐标(偏移小)相关的知识,希望对你有一定的参考价值。
基本上是网上常见的方法进行坐标系的转换,但是误差很大。发现之所以误差大是在于百度的墨卡托坐标转百度的经纬度时误差太大,后面找到一个方法,误差较小,基本吻合。
参考:http://www.site-digger.com/tools/mct2latlng.html
这里的转换是直接调用百度地图SDK中的API,通过对其中javascript源代码的执行跟踪,提取出其中的墨卡托坐标转百度经纬度坐标的代码如下:
Java版本:
@Data
public static class Point
private double lng, lat;
public Point(double lng, double lat)
this.lng = lng;
this.lat = lat;
@Override
public String toString()
return lng + "," + lat;
private static double xPi = 3.14159265358979324 * 3000.0 / 180.0;
// 以下参数来自百度地图的SDK
private static double[] MCBAND = 12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0;
private static double[][] MC2LL =
1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2,
-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86,
-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37,
-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06,
3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4,
2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5
;
/**
* 参考:http://www.site-digger.com/tools/mct2latlng.html
* 对上述链接中的操作,找到百度地图的SDK的源代码,然后转换成Java
*/
private static Point convertMC2LL(Point mp)
Point absPoint = new Point(abs(mp.getLng()), abs(mp.getLat()));
double[] paramArr = null;
for (int i = 0; i < MCBAND.length; i++)
if (absPoint.getLat() >= MCBAND[i])
paramArr = MC2LL[i];
break;
if (mp == null || paramArr == null)
throw new RuntimeException("转换出错");
double lng = paramArr[0] + paramArr[1] * abs(mp.getLng());
double tlat = abs(mp.getLat()) / paramArr[9];
double lat = paramArr[2]
+ paramArr[3] * tlat
+ paramArr[4] * tlat * tlat
+ paramArr[5] * tlat * tlat * tlat
+ paramArr[6] * tlat * tlat * tlat * tlat
+ paramArr[7] * tlat * tlat * tlat * tlat * tlat
+ paramArr[8] * tlat * tlat * tlat * tlat * tlat * tlat;
lng *= mp.getLng() < 0 ? -1 : 1;
lat *= mp.getLat() < 0 ? -1 : 1;
return new Point(lng, lat);
/**
* 百度经纬度坐标转高德经纬度坐标。网上很常见的一种方式。
*/
private static Point BD09ToGCJ02(Point bdp)
double x = bdp.getLng() - 0.0065, y = bdp.getLat() - 0.006;
double z = sqrt(x * x + y * y) - 0.00002 * sin(y * xPi);
double theta = atan2(y, x) - 0.000003 * cos(x * xPi);
return new Point(z * cos(theta), z * sin(theta));
Python版本:
xPi = 3.14159265358979324 * 3000.0 / 180.0
# 以下参数来自百度地图的SDK
MCBAND = [12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0]
MC2LL = [
[1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2],
[-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86],
[-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37],
[-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06],
[3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4],
[2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5]
]
# 百度经纬度坐标转高德经纬度坐标。网上很常见的一种方式。
def bd09togcj02(bd_lon, bd_lat):
"""
百度坐标系(BD-09)转火星坐标系(GCJ-02)
百度——>谷歌、高德
:param bd_lat:百度坐标纬度
:param bd_lon:百度坐标经度
:return:转换后的坐标列表形式
"""
x, y = bd_lon - 0.0065, bd_lat - 0.006
z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * xPi)
theta = math.atan2(y, x) - 0.000003 * math.cos(x * xPi)
return z * math.cos(theta), z * math.sin(theta)
# 参考:http://www.site-digger.com/tools/mct2latlng.html
# 对上述链接中的操作,找到百度地图的SDK的源代码,然后转换成Java
def convertMC2LL(ox, oy) :
x, y = abs(ox), abs(oy)
for i in range(0, len(MCBAND)) :
if y >= MCBAND[i] :
paramArr = MC2LL[i]
break
if paramArr == None:
raise Exception('转换坐标失败')
lng = paramArr[0] + paramArr[1] * abs(ox)
tlat = abs(oy) / paramArr[9]
lat = paramArr[2] + paramArr[3] * tlat + paramArr[4] * tlat * tlat + paramArr[5] * tlat * tlat * tlat + paramArr[6] * tlat * tlat * tlat * tlat + paramArr[7] * tlat * tlat * tlat * tlat * tlat + paramArr[8] * tlat * tlat * tlat * tlat * tlat * tlat
lng *= (-1 if ox < 0 else 1)
lat *= (-1 if oy < 0 else 1)
return lng, lat
效果展示:
// 测试代码
String kejiyuan = "12682891.3894,2559542.0538,12682896.5467,2559793.62794,12682844.7433,2560206.11494,12682734.4366,2561087.88431,12682681.159,2562074.67985,12682831.1964,2562218.1177,12683623.9092,2562188.56753,12683732.2141,2562243.30281,12683877.4858,2562398.46172,12683916.3509,2562839.59511,12683912.6528,2563051.56215,12683997.6458,2563129.82525,12684148.9608,2563136.64739,12684423.9572,2563249.60486,12684687.41,2563412.50587,12685216.0839,2563387.9877,12686427.857,2563282.11338,12687017.2378,2563194.53233,12687547.0621,2563146.47597,12687711.6126,2563191.93924,12688072.3621,2563098.80984,12688551.9725,2562924.51818,12688595.2954,2562866.34103,12688581.4473,2562769.94654,12688592.8397,2562733.23579,12689180.0331,2562464.27042,12689211.9588,2562420.55064,12689195.8798,2562314.3281,12689168.3537,2562313.76442,12688839.1722,2562275.22138,12688521.5892,2562344.85031,12688215.549,2562370.2208,12687875.1633,2562296.16518,12687304.0261,2562224.77222,12686776.2826,2562209.27294,12686464.1449,2562201.14685,12686253.3935,2562183.17902,12686147.8737,2562159.13696,12686097.5228,2562114.03074,12686174.2562,2560903.22104,12686144.5094,2560727.85702,12686162.7094,2560701.00483,12686702.0782,2560744.58401,12686715.7214,2560727.54607,12686694.5355,2560518.79091,12686469.0556,2560122.34138,12686281.1211,2559770.33875,12686231.908,2559542.23454,12686214.5986,2559162.03758,12686197.169,2559118.19258,12685318.8834,2559094.19446,12685143.0646,2559094.6559,12684986.7893,2559013.13744,12684889.126,2558895.30627,12684835.3891,2558858.28003,12684600.8812,2558847.14735,12684139.8292,2558854.49449,12683748.6599,2558894.79101,12683582.3085,2558936.30384,12683435.5368,2559030.43944,12683260.9697,2559068.85924,12682852.8989,2559166.22101,12682834.3698,2559181.22174,12682891.3894,2559542.0538";
String pss = kejiyuan;
String[] points = pss.split(",");
if (points.length % 2 == 0)
for (int i = 0; i < points.length; i += 2)
System.out.println(
"[" +
BD09ToGCJ02(convertMC2LL(
new Point(
Double.parseDouble(points[i]),
Double.parseDouble(points[i + 1])
)
))
+ "],"
);
打开高德地图多边形绘制DEMO示例,然后将上述代码的对应执行结果,以正确的形式粘贴到DEMO代码的相应地方:
然后点击运行,查看结果:
百度墨卡托坐标转成百度经纬度坐标后,在高德地图上展示情况
将百度坐标转换成高德地图坐标后在高德地图中的展示情况
百度地图原始数据
后面经过尝试、发现差距并不是特别大,已使用这种方法进行坐标转换
以上是关于百度地图墨卡托坐标转高德经纬度坐标(偏移小)的主要内容,如果未能解决你的问题,请参考以下文章