1. 程式人生 > >【轉】百度墨卡託轉百度經緯度【java版】

【轉】百度墨卡託轉百度經緯度【java版】

轉載自 滄海一粟世之塵埃 https://blog.csdn.net/qq_16664325/article/details/67639684

寫在前面:由於我的需求是在沒有網路的情況下分析出經緯度。所以我必須更深入的去解析原始碼。一開始我還天真的以為這個墨卡託就是人們常說的那個墨卡託,解析也就是常規的解析,後來那個地理位置偏到我自己都不知道是哪了。博主很懶,想找現成的程式碼,但是怎麼都找不到。手動笑哭。

上篇回顧

<script >
    var b = new BMap.MercatorProjection().pointToLngLat(new BMap.Pixel(12854318.52,4677433.40));
    g = [ b.lng, b.lat ];
    alert(g);
</script>
  • 1
  • 2
  • 3
  • 4
  • 5

pointToLngLat 這個函式網上是找不到原始碼的,只好自己動手豐衣足食了

關於獲取百度地圖API原始碼的方法

http://api.map.baidu.com/lbsapi/getpoint/index.html 答案還在這裡

<script >
    var b = new BMap.MercatorProjection().pointToLngLat(new BMap.Pixel(12854318.52,4677433.40));
    g = [ b.lng, b.lat ];
    alert(g);
</script>
  • 1
  • 2
  • 3
  • 4
  • 5

進入那個src:

(function(){ window.BMap_loadScriptTime = (new Date).getTime(); document.write('<script type="text/javascript" src="http://api.map.baidu.com/getscript?v=2.0&ak=E4805d16520de693a3fe707cdc96204&services=&t=20170324173232"></script>');})();
  • 1

再進入src:
也就5千行js程式碼吧,不得不吐槽一下,這是我看過最難懂的程式碼了,變數全是a、b、c、A、B、C函式全是fa、fb、fc總之就是不想讓你看懂的。手動再見。

原始碼分析:

很重要的程式碼(為了理解方便,只擷取核心程式碼)

C[x](T, {

            xu: 6370996.81,
            Sp: [1.289059486E7, 8362377.87, 5591021, 3481989.83, 1678043.12, 0],
            Hj: [75, 60, 45, 30, 15, 0],

            Au: [[1.410526172116255E-8, 8.98305509648872E-6, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 1.73379812E7], [ - 7.435856389565537E-9, 8.983055097726239E-6, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 1.026014486E7], [ - 3.030883460898826E-8, 8.98305509983578E-6, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37], [ - 1.981981304930552E-8, 8.983055099779535E-6, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06], [3.09191371068437E-9, 8.983055096812155E-6, 6.995724062E-5, 23.10934304144901, -2.3663490511E-4, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4], [2.890871144776878E-9, 8.983055095805407E-6, -3.068298E-8, 7.47137025468032, -3.53937994E-6, -0.02145144861037, -1.234426596E-5, 1.0322952773E-4, -3.23890364E-6, 826088.5]],

            Qp: [[ - 0.0015702102444, 111320.7020616939, 1704480524535203, -10338987376042340, 26112667856603880, -35149669176653700, 26595700718403920, -10725012454188240, 1800819912950474, 82.5], [8.277824516172526E-4, 111320.7020463578, 6.477955746671607E8, -4.082003173641316E9, 1.077490566351142E10, -1.517187553151559E10, 1.205306533862167E10, -5.124939663577472E9, 9.133119359512032E8, 67.5], [0.00337398766765, 111320.7020202162, 4481351.045890365, -2.339375119931662E7, 7.968221547186455E7, -1.159649932797253E8, 9.723671115602145E7, -4.366194633752821E7, 8477230.501135234, 52.5], [0.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245, 992013.7397791013, -1221952.21711287, 1340652.697009075, -620943.6990984312, 144416.9293806241, 37.5], [ - 3.441963504368392E-4, 111320.7020576856, 278.2353980772752, 2485758.690035394, 6070.750963243378, 54821.18345352118, 9540.606633304236, -2710.55326746645, 1405.483844121726, 22.5], [ - 3.218135878613132E-4, 111320.7020701615, 0.00369383431289, 823725.6402795718, 0.46104986909093, 2351.343141331292, 1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45]],
  •  

這裡C[x]其實可以理解為一種賦值函式,本次解析的重中之重是Sp和Au,後續分析會說明原因

new BMap 畫素物件

function S(a, b) {
    this.x = a || 0;
    this.y = b || 0;
    this.x = this.x;
    this.y = this.y
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

由於程式碼中有對映pointToLngLat 到 Al 下一步到Al

Al: function(a) {
    a = new K(a.x, a.y);
    return T.Ra(a) //下下個解析這玩意,這玩意超級重要!!!!!!
}
  • 1
  • 2
  • 3
  • 4

K函式構造座標

function K(a, b) {
    isNaN(a) && (a = hb(a), a = isNaN(a) ? 0 : a);
    Ha(a) && (a = fa(a));//這些是檢驗有效性的程式碼,並沒有太大的用處
    isNaN(b) && (b = hb(b), b = isNaN(b) ? 0 : b);
    Ha(b) && (b = fa(b));
    this.lng = a;
    this.lat = b
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

重頭戲Ra函式

Ra: function(a) {
    var b, c;
    b = new K(p.abs(a.lng), p.abs(a.lat));
    for (var d = 0; d < this.Sp[w]; d++) if (b.lat >=this.Sp[d]) {
        c = this.Au[d];
        break
    }
    a = this.Yr(a, c);
    return a = new K(a.lng.toFixed(6), a.lat.toFixed(6))
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

由之前我畫出來的重點可以得知百度地圖是把地球分成了6塊,每一塊有不同的‘加密’演算法!!!!!!!所以我一早上搞的那個墨卡託差點飛出地球了。Sp為百度把地球設定的分塊區間,Au為對應的加密方式。

又一個重頭戲Yr函式(‘解密’函式)

Yr: function(a, b) {
    if (a && b) {
        var c = b[0] + b[1] * p.abs(a.lng),
        d = p.abs(a.lat) / b[9],
        d = b[2] + b[3] * d + b[4] * d * d + b[5] * d * d * d + b[6] * d * d * d * d + b[7] * d * d * d * d * d + b[8] * d * d * d * d * d * d,
        c = c * (0 > a.lng ? -1 : 1),
        d = d * (0 > a.lat ? -1 : 1);
        return new K(c, d)
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 百度墨卡託轉BD-09座標系程式碼(各位大佬請笑納)
public static double[] Mercator2BD09(double lng,double lat) {
    double[] lnglat=new double[2];
    List<Double> c=null;
    lnglat[0]=Math.abs(lng);
    lnglat[1]=Math.abs(lat);

    for(int d=0;d<6;d++)
    {
        if(lnglat[1]>=Sp.get(d))
        {
            c = Au.get(d);
            break;
        }
    }
    lnglat = Yr(lnglat,c);
    return lnglat;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
public static double[] Yr(double[] lnglat,List<Double> b){
    if(b!=null){
        double c = b.get(0)+b.get(1)*Math.abs(lnglat[0]);
        double d = Math.abs(lnglat[1])/b.get(9);
        d = b.get(2)+b.get(3)*d+b.get(4)*d*d+b.get(5)*d*d*d+b.get(6)*d*d*d*d+b.get(7)*d*d*d*d*d+b.get(8)*d*d*d*d*d*d;
        BigDecimal bd=new BigDecimal(c*(0>lnglat[0]?-1:1));
        lnglat[0]=bd.setScale(6, BigDecimal.ROUND_UP).doubleValue();
        bd=new BigDecimal(d*(0>lnglat[1]?-1:1));
        lnglat[1]=bd.setScale(6, BigDecimal.ROUND_UP).doubleValue();
        return lnglat;
    }
    return null;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ok,今日就先到這裡,經過我測試,這個程式碼沒毛病。

--------------------- 本文來自 滄海一粟世之塵埃 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/qq_16664325/article/details/67639684?utm_source=copy