百度地图墨卡托坐标转高德经纬度坐标(偏移小)

参考: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代码的相应地方,如下图所示:

然后点击运行,查看结果:
百度墨卡托坐标转成百度经纬度坐标后,在高德地图上展示情况

将百度坐标转换成高德地图坐标后在高德地图中的展示情况

百度地图原始数据

后面经过尝试、发现差距并不是特别大,已使用这种方法进行坐标转换


Flag Counter

发布了166 篇原创文章 · 获赞 118 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/asahinokawa/article/details/95072882