zoukankan      html  css  js  c++  java
  • 各大地理坐标系互转

    支持互转坐标

    支持坐标类型:
    	WGS84           WGS84坐标系[大地坐标系]
    	GCJ02           火星坐标系
    	BD09            百度坐标系
    	BD09MC          百度墨卡托坐标系
    	Mercator        普通墨卡托坐标系坐标系
    

    项目

    其他版本在开发中,莫急,到时会更新此文档

    缘由

    上篇博客说了下商圈数据获取,但是我们获取到商圈数据是BD09MC,这就无语了,我们需要将其转成WGS84GCJ02 才可以下一步处理,但是直接调百度接口有限额还有性能问题,直接看百度的Web SDK 查看实现逻辑,然后转后端实现

    名词解释

    坐标系统:用于定位的系统,就跟二维笛卡尔坐标系统一样,一个点使用(x,y),就能确定该点在笛卡尔坐标系统中的唯一位置。这里讲的坐标系统,相对于笛卡尔坐标系统,要复杂许多,但作用却都是一样,主要用于定位,也就是精确地定位地表上的一点。
    地理坐标系统:WGS84就是一种地理坐标系统。地理坐标坐标是对地球进行简单几何建模,比如将地球看成一个球体或者类球体,然后再将地表上点投影到该球面上形成的坐标就是地理坐标系统。WGS84就是定义了如何将地球抽象成球体或者类球体的规则。或者简单地来说,WGS84就是一堆参数,用于建立球体或者类球体,来近似地球。
    投影坐标系统:由于地球是一个球状,所以一般将其某个区域投影在平面上,形成的坐标系称为投影坐标系。

    墨卡托投影:世界地图并不是世界的真实样貌!甚至误差非常大

    简称解释

    WGS84(大地坐标系) :统为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系,Google Earth和中国外的Google Map使用,另外,目前基本上所有定位空间位置的设备都使用这种坐标系统,例如手机的GPS系统。
    GCJ02(国测局坐标系):又称火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
    BD09(百度经纬度坐标)):为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标。

    BD09mc(百度墨卡托平面坐标):百度墨卡托米制坐标

    反查源码

    1. 算法实现
      参考:百度拾取坐标系统 中的JS源码 版本: 081 更新时间: 20210122
    <script type="text/javascript" src="Js/public.js?20200211"></script>
    
    1. 前端

      <label class="pointLabel" for="pointLabel"><input type="checkbox" onfocus="this.blur()" id="pointLabel">坐标反查</label>
      

      可以看到class 是pointLabel,在反查时肯定会检测checkbox 是否被勾选

    2. 查看public.js

      1. pointLabel 哪里使用了

        function beginsearch(b, a) {
            var c = filtQuery(Fe.G("localvalue").value);
            // 处理特殊城市
            if (isInArray(c)) {
                trickCity(c);
                return;
            }
        
            if (!c || c == "请输入关键字进行搜索") {
                return
            }
            if (Fe.G("pointLabel").checked) {
                searchByPoint(c)  // 这里被调用
            } else {
                if (!a) {
                    b.setLocation(map)
                }
                b.search(c)
            }
        }
        
      2. 然后搜searchByPoint函数的调用

         var f = projection.pointToLngLat(new BMap.Pixel(d[0], d[1]));
        

        可以看到调用pointToLngLat来返解析墨卡托坐标

        那么projection 是哪里初始化的?

      3. projection

        function initMap() {
            window.map = new BMap.Map("MapHolder", {enableMapClick: false});
            window.projection = new BMap.MercatorProjection(); // 这里初始化的
          	...
        }
        

        可以看到MercatorProjection 的含义就是墨卡托投影

      4. 查看BMap的定义

        js 文件:

        <script type="text/javascript" src="https://api.map.baidu.com/getscript?v=2.0&amp;ak=E4805d16520de693a3fe707cdc962045&amp;services=&amp;t=20210113094335"></script>
        

        这个js文件被压缩过,直接Pretty-print后查看

      5. 在源代码中搜pointToLngLat

        function U(a, b) { // 将b 的属性赋值给 a
                for (var c in b)
                    a[c] = b[c]
            }
        
        ....
        
        var Gf = T.prototype;
            U(Gf, {
                lngLatToPoint: Gf.fy,
                pointToLngLat: Gf.Dj  // 绑定 pointToLngLat 的实现,其实就是T.Dj
            });
            var Hf = ib.prototype;
            U(Hf, {
                lngLatToPoint: Hf.fy,
                pointToLngLat: Hf.Dj // 绑定 pointToLngLat 的实现,还是T.Dj
            });
        

        这里Hf.Dj在定义是:

        var Hf = ib.prototype; 
        
        --> 
           function ib() {
                  this.ij = "bj"
              }
            ib.prototype = new T;  // 本质上还是 T.Dj
        

        T.DJ 的定义:

        x.extend(T.prototype, {
        ...
                Dj: function(a) {
                    a = new H(a.x,a.y);
                    return eb(T.ub(a), this.map)
                },
        ...
        }
        

        这里,我们需要确定H,T.ub,eb函数的实现,其中这些函数的内部依赖我就整理到一起了

        H:函数

        // 依赖
        function ab(a) {
                return "string" == typeof a
            }
        
        var Jb = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
            function Kb(a) {
                var b = "", c, d, e = "", f, g = "", i = 0;
                f = /[^A-Za-z0-9+/=]/g;
                if (!a || f.exec(a))
                    return a;
                a = a.replace(/[^A-Za-z0-9+/=]/g, "");
                do
                    c = Jb.indexOf(a.charAt(i++)),
                    d = Jb.indexOf(a.charAt(i++)),
                    f = Jb.indexOf(a.charAt(i++)),
                    g = Jb.indexOf(a.charAt(i++)),
                    c = c << 2 | d >> 4,
                    d = (d & 15) << 4 | f >> 2,
                    e = (f & 3) << 6 | g,
                    b += String.fromCharCode(c),
                    64 != f && (b += String.fromCharCode(d)),
                    64 != g && (b += String.fromCharCode(e));
                while (i < a.length);return b
            }
        
        // 实现: 创建点,百度摩卡托坐标系
        function H(a, b) {
                isNaN(a) && (a = Kb(a),
                a = isNaN(a) ? 0 : a);
                ab(a) && (a = parseFloat(a));
                isNaN(b) && (b = Kb(b),
                b = isNaN(b) ? 0 : b);
                ab(b) && (b = parseFloat(b));
                this.lng = a;
                this.lat = b;
                this.of = "inner"
            }
        

        T.ub函数:

        // 外部依赖:
        p = null
        j = void 0
        
        x.extend(T, {
        			// 内部依赖
                CP: 6370996.81,
                JG: [1.289059486E7, 8362377.87, 5591021, 3481989.83, 1678043.12, 0],
                Lu: [75, 60, 45, 30, 15, 0],
                IP: [[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]],
                GG: [[-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]],
          
          			GK: function(a, b) {
                    if (a && b) {
                        var c = b[0] + b[1] * Math.abs(a.lng)
                          , d = Math.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 H(c,d)
                    }
                },
                  				
          
          		  // 定义: 坐标转换
                ub: function(a) {
                    if (a === p || a === j)
                        return new H(0,0);
                    var b, c;
                    b = new H(Math.abs(a.lng),Math.abs(a.lat));
                    for (var d = 0; d < this.JG.length; d++)
                        if (b.lat >= this.JG[d]) {
                            c = this.IP[d];
                            break
                        }
                    a = this.GK(a, c);
                    return a = new H(a.lng.toFixed(6),a.lat.toFixed(6))
                },
         }
        

        eb函数:

         // 实现:
      function eb(a, b) {
                 if (b && b.B && 3 === b.B.Xw && a instanceof H) {
                     var c = Bc(a);
                     return new N(c.lng,c.lat)
                 }
                 return b && b.B && 5 === b.B.Xw && a instanceof H ? new N(a.lng,a.lat) : a
             }
      
      1. 最后,我们可以定位出以下函数

        function coordtransform
        qc 火星坐标系->百度坐标系
        BC 百度坐标系->火星坐标系
        T.ub 百度墨卡托坐标系 - > 百度坐标系
        T.tb 百度坐标系-> 百度墨卡托坐标系
    如果是此文是转载文章,本人会附上转载链接,此篇文章的版权归原创作者所属,如果侵权请与我联系,我会删除此文。

    若没有标明转载链接,此篇文章属于本人的原创文章,其版权所属:
    作者:feiquan
    出处:http://www.cnblogs.com/feiquan/
    版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    大家写文都不容易,请尊重劳动成果~ 这里谢谢大家啦(*/ω\*)
  • 相关阅读:
    Wannafly #4 F 线路规划
    PKUWC2018 随机算法
    noip模拟赛
    php 正则判断是否是手机号码 最新
    Onethink上传服务器后登录不了的问题
    【php中的curl】php中curl的详细解说
    50种网站引流量方式
    mysql ERROR 1045 (28000): 错误解决办法
    织梦DEDE分类信息实现联动筛选(支持多条件多级选项)解决方案
    dedecms新增联动类别后的使用方法
  • 原文地址:https://www.cnblogs.com/feiquan/p/14398037.html
Copyright © 2011-2022 走看看