zoukankan      html  css  js  c++  java
  • Google、Soso、Baidu卫星图url研究

    前一段时间因为公司有个项目需要我研究一下Google的卫星图的地址规律,开始我以为会很艰难认为Google那么大公司url应该会加密什么的,结果发现Google和Soso、Baidu、Sogou这几个比较起来Google的url演算是最简单且明了的,废话不说了。

    打开Google Map我们可以看到一张地图,将它放大或者缩小就可以看到不同的地图(很多张的图片)。url像这样:http://khm1.google.com/kh/v=125&src=app&x=0&y=0&z=0   (红色部分均为可变的参数)

    Google的作法是世界的第0层(z=0)就是一张图构成:

    z=1的效果就是将它切分为4份见下图:

    依次类推,我们可以得到一个公式:NUM=2^(N+1)

    NUM:x或者y方向上的图片数

    N:第几层z轴

    然后引入Mercator库(我自己写的麦卡拓转换)code:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Windows;
     6 
     7 namespace MapsDownloader
     8 {
     9     class Mercator
    10     {
    11         private double NormalToMercator(double y)
    12         {
    13             y -= 0.5;
    14             y *= 2.0 * Math.PI;
    15             y = Math.Exp(y * 2.0);
    16             y = (y - 1) / (y + 1.0);
    17             y = Math.Asin(y);
    18             y = y * -180.0 / Math.PI;
    19             return y;
    20         }
    21         private double MercatorToNormal(double y)
    22         {
    23             y = -y * Math.PI / 180.0;
    24             y = Math.Sin(y);
    25             y = (1.0 + y) / (1.0 - y);
    26             y = 0.5 * Math.Log(y);
    27             y *= 1.0 / (2.0 * Math.PI);
    28             y += 0.5;
    29             return y;
    30         }
    31         private double getNormailByY(double y,int picnum)
    32         {
    33             return y/picnum;
    34         }
    35         private double getYByNormail(double y, int picnum)
    36         {
    37             return picnum * y;
    38         }
    39         ///////////////////////////////////////////////
    40         ///传入:-26.851029008675013 返回:-26° 51' 3" 
    41         public string GetSexagesimalNotation(double x)
    42         {
    43             //to string format: 23° 27′ 30"
    44             var ret = "";
    45             if (x < 0)
    46             {
    47                 ret += '-';
    48                 x = -x;
    49             }
    50             ret += Math.Floor(x);
    51             ret += "° ";
    52     
    53             x = (x - Math.Floor(x)) * 60;
    54             ret += Math.Floor(x);
    55             ret += "' ";
    56     
    57             x = (x - Math.Floor(x)) * 60;
    58             ret += Math.Floor(x);
    59             ret += "\" ";
    60 
    61             return ret;
    62         }
    63         public Point Google_XYZ_to_LatLng(int x, int y, int z)     //lat [0]  , lng [1]
    64         {
    65             Point LatLng = new Point();
    66             int picnum = 2 << (z - 1);   //z层在x、y轴上存在多少张
    67             double onex = 360.0 / picnum;    //平均每一张占用多少经纬度
    68             double xlat = onex * x;
    69             if (xlat > 360.0)       //如果超过360就剪掉它
    70                 xlat = xlat % 360.0;
    71             if (xlat > 180.0)
    72                 LatLng.X = onex * x - 180.0;
    73             else
    74                 LatLng.X = -(180.0 - onex * x);
    75             LatLng.Y = NormalToMercator(getNormailByY(y, picnum));
    76             return LatLng;
    77         }
    78         public Point Google_LatLngZ_to_XY(double Lat, double Lng, int z)       //return x,y array
    79         {
    80             Point xy = new Point();
    81             int picnum = 2 << (z - 1);   //z层在x、y轴上存在多少张
    82 double onex = 360.0 / picnum; ////平均每一张占用多少经纬度
    83 Lat += 180.0;
    84 xy.X = Convert.ToInt32(Lat / onex); //x
    85 xy.Y = Convert.ToInt32(getYByNormail(MercatorToNormal(Lng), picnum)); //y
    86 return xy;
    87 }
    88 }
    89 }

    主要是Y轴方向转换麻烦需要用到这些函数,因为Mercator当初设计的缺陷就是越往两极地区越不准确。

    下面两个函数Google_XYZ_to_LatLng、Google_LatLngZ_to_XY提供了将XYZ转换成为 经纬度,和经纬度转换成Google的XYZ轴,有了这些基础我们就可以用html和JQuery写出一个简易的GoogleMap 网页键盘版本:

      1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      2 <html xmlns="http://www.w3.org/1999/xhtml">
      3 <head>
      4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      5 <title>Keyboard Google Map——By MaxHo</title>
      6 <script type="text/javascript" src="jquery-1.8.0.min.js"></script>
      7 <script type="text/javascript">
      8     $(document).ready(function()
      9     {
     10         readImage();
     11     });
     12     function readImage()
     13     {
     14         var url="";
     15         //http://khmdbs0.google.com/pm?v=9&src=app&x=0&y=4&z=4&s=Gali
     16         //http://khm1.google.com/kh/v=125&src=app&x=
     17         //
     18         
     19         
     20         if($("#mapTypeSelect").val() == 1)
     21         {
     22             var xx = parseInt($("#x").val());
     23             var yy = parseInt($("#y").val());
     24             var zz = parseInt($("#z").val());
     25             var picnum = 2<<(zz-1);
     26             var onex = 360 / picnum;
     27             /*var oney = 180 / picnum;
     28             if(oney * yy > 90)
     29                 var lng = -(oney * yy - 90);
     30             else
     31                 var lng = 90 - oney * yy;*/
     32             var lng = NormalToMercator (getNormailByY(yy,picnum));
     33             if(onex * xx > 180)
     34                 var lat = onex * xx - 180;
     35             else
     36                 var lat = -(180 - onex * xx);
     37             $("#latlng").text(lng + " , " + lat);
     38             $("table td").each(function(i){
     39                 var ix = i%5 + parseInt($("#x").val());
     40                 var iy = parseInt(i/5) + parseInt($("#y").val());
     41                 url = "http://khm1.google.com/kh/v=125&src=app&x="+ix
     42                     +"&y="+iy+"&z="+$("#z").val();
     43                 $(this).html("<img style='100%;height:100%;' src='"+url+"'/>");
     44              });
     45         }
     46         else if($("#mapTypeSelect").val() == 2)        //soso
     47         {
     48             var xx = parseInt($("#x").val());
     49             var yy = parseInt($("#y").val());
     50             var zz = parseInt($("#z").val());
     51             $("table td").each(function(i){
     52                 var ix = i%5 + parseInt($("#x").val());
     53                 var iy = 2 - parseInt(i/5) + parseInt($("#y").val());
     54                 var dx = Math.floor(ix/16);
     55                 var dy = Math.floor(iy/16);
     56                 url = "http://p1.map.soso.com/sateTiles/"+$("#z").val()
     57                     +"/"+dx+"/"+dy+"/"+ix+"_"+iy+".jpg";
     58                 $(this).html("<img style='100%;height:100%;' src='"+url+"'/>");
     59              });
     60         }
     61         else if($("#mapTypeSelect").val() == 3)        //baidu
     62         {
     63             var xx = parseInt($("#x").val());
     64             var yy = parseInt($("#y").val());
     65             var zz = parseInt($("#z").val());
     66             $("table td").each(function(i){
     67                 var ix = i%5 + parseInt($("#x").val());
     68                 var iy = 2 - parseInt(i/5) + parseInt($("#y").val());
     69                 url = "http://q1.baidu.com/it/u=x="+ix+";y="+iy+";z="+$("#z").val()
     70                     +";v=009;type=sate&fm=46";
     71                 $(this).html("<img style='100%;height:100%;' src='"+url+"'/>");
     72              });
     73         }
     74         else if($("#mapTypeSelect").val() == 4)        //cangbao
     75         {
     76             var xx = parseInt($("#x").val());
     77             var yy = parseInt($("#y").val());
     78             var zz = parseInt($("#z").val());
     79             var picnum = 2<<(zz-1);
     80             var onex = 360 / picnum;
     81             /*var oney = 180 / picnum;
     82             if(oney * yy > 90)
     83                 var lng = -(oney * yy - 90);
     84             else
     85                 var lng = 90 - oney * yy;*/
     86             var lng = NormalToMercator (getNormailByY(yy,picnum));
     87             if(onex * xx > 180)
     88                 var lat = onex * xx - 180;
     89             else
     90                 var lat = -(180 - onex * xx);
     91             $("#latlng").text(lng + " , " + lat);
     92             $("table td").each(function(i){
     93                 var ix = i%5 + parseInt($("#x").val());
     94                 var iy = parseInt(i/5) + parseInt($("#y").val());
     95                 url = "http://khmdbs0.google.com/pm?v=9&src=app&x="+ix
     96                     +"&y="+iy+"&z="+$("#z").val();
     97                 $(this).html("<img style='100%;height:100%;' src='"+url+"'/>");
     98              });
     99         }
    100     }
    101     function left()
    102     {
    103         var xx = parseInt($("#x").val());
    104         $("#x").val(--xx);
    105     }
    106     function up()
    107     {
    108         var yy = parseInt($("#y").val());
    109         if($("#mapTypeSelect").val() == 2 || $("#mapTypeSelect").val() == 3 )
    110             $("#y").val(++yy);
    111         else
    112             $("#y").val(--yy);
    113     }
    114     function right()
    115     {
    116         var xx = parseInt($("#x").val());
    117         $("#x").val(++xx);
    118     }
    119     function down()
    120     {
    121         var yy = parseInt($("#y").val());
    122         if($("#mapTypeSelect").val() == 2 || $("#mapTypeSelect").val() == 3 )
    123             $("#y").val(--yy);
    124         else
    125             $("#y").val(++yy);
    126     }
    127     function enter()
    128     {
    129         var xx = parseInt($("#x").val());
    130         var yy = parseInt($("#y").val());
    131         var zz = parseInt($("#z").val());
    132         if($("#mapTypeSelect").val() == 1)
    133         {
    134             var centerX = (xx+2)*2 - 2;
    135             var centerY = (yy+1)*2 - 1;
    136             var centerZ = zz+1;
    137         }
    138         else if($("#mapTypeSelect").val() == 2 || $("#mapTypeSelect").val() == 3 )
    139         {
    140             var centerX = (xx+2)*2 - 2;
    141             var centerY = (yy-1)*2 + 3;
    142             var centerZ = zz+1;
    143         }
    144         $("#x").val(centerX);
    145         $("#y").val(centerY);
    146         $("#z").val(centerZ);
    147     }
    148     function exit()
    149     {
    150         var xx = parseInt($("#x").val());
    151         var yy = parseInt($("#y").val());
    152         var zz = parseInt($("#z").val());
    153         if($("#mapTypeSelect").val() == 1)
    154         {
    155             var centerX = parseInt((xx+2)/2) - 2;
    156             var centerY = parseInt((yy+1)/2) - 1;
    157             var centerZ = zz-1;
    158         }
    159         else if($("#mapTypeSelect").val() == 2 || $("#mapTypeSelect").val() == 3 )
    160         {
    161             var centerX = parseInt((xx+2)/2) - 2;
    162             var centerY = parseInt((yy-1)/2);
    163             var centerZ = zz-1;
    164         }
    165         $("#x").val(centerX);
    166         $("#y").val(centerY);
    167         $("#z").val(centerZ);
    168     }
    169     $(this).bind('focus',function(event){
    170         $(this).select();
    171     });
    172         $(document).bind('keydown',function(e){
    173       e = (e) ? e : ((window.event) ? window.event : "");
    174       var key = e.keyCode?e.keyCode:e.which;
    175             switch(key) {
    176             case 37: 
    177                 //left
    178                 left();
    179                 readImage();
    180                 break;
    181             case 38:   
    182                 //up
    183                 up();
    184                 readImage();
    185                 break;
    186             case 39:
    187                 //right
    188                 right();
    189                 readImage();
    190                 break;
    191             case 40:
    192                 //down
    193                 down();
    194                 readImage();
    195                 break;
    196             /*case 13:
    197                 //enter
    198                 enter();
    199                 readImage();
    200                 break;*/
    201             case 69:
    202                 //E
    203                 enter();
    204                 readImage();
    205                 break;
    206             /*case 27:
    207                 //exit
    208                 exit();
    209                 readImage();
    210                 break;*/
    211             case 81:
    212                 //Q
    213                 exit();
    214                 readImage();
    215                 break;
    216             default:
    217                 //alert(key);
    218                 break;
    219             }
    220         });
    221         function MercatorToNormal(y)
    222         {
    223             y = -y * Math.PI / 180;    // convert to radians
    224             y = Math.sin(y);
    225             y = (1+y)/(1-y);
    226             y = 0.5 * Math.log(y);
    227             y *= 1.0 / (2 * Math.PI);    // scale factor from radians to normalized 
    228             y += 0.5;    // and make y range from 0 - 1
    229             return y;
    230         }
    231 
    232         function NormalToMercator(y)
    233         {
    234             y -= 0.5;
    235             y *= 2 * Math.PI;    
    236             y = Math.exp(y * 2);
    237             y = (y-1)/(y+1);
    238             y = Math.asin(y);
    239             y = y * -180/Math.PI;    
    240             return y;
    241         }
    242         function getNormailByY(y,picnum)
    243         {
    244             /*var scale = 1.0;
    245             var ry = 0.0;
    246             for (var i = 0; i< y ; i++)
    247             {
    248                 scale *= 0.5;
    249                 ry += scale;
    250             }
    251             return ry;*/
    252             return y/picnum;
    253         }
    254         function changeMapTypeSelect()
    255         {
    256             if($("#mapTypeSelect").val() == 2)
    257             {
    258                 $("#x").val(10);
    259                 $("#y").val(8);
    260                 $("#z").val(4);
    261             }
    262             else if($("#mapTypeSelect").val() == 1)
    263             {
    264                 $("#x").val(10);
    265                 $("#y").val(5);
    266                 $("#z").val(4);
    267             }
    268             else if ($("#mapTypeSelect").val() == 3 )
    269             {
    270                 $("#x").val(3);
    271                 $("#y").val(0);
    272                 $("#z").val(5);
    273             }
    274             readImage();
    275         }
    276         
    277 </script>
    278 </head>
    279 <body>
    280 <form action="#">
    281 x:<input id="x" type="text" value="10" style="60px;"/>
    282 y:<input id="y" type="text" value="5" style="60px;"/>
    283 z:<input id="z" type="text" value="4" style="60px;"/>
    284 <input type="submit" value="重新載入" onclick="readImage()"/>&nbsp;&nbsp;&nbsp;<span style="font-size:12px; color:#808080">
    285 <select id="mapTypeSelect" onchange="changeMapTypeSelect()">
    286   <option value="1" selected="selected">GoogleMap</option>
    287   <option value="2">SosoMap</option>
    288   <option value="3">BaiduMap</option>
    289   <option value="4">藏宝图</option>
    290 </select>
    291 使用鍵盤熱鍵上下左右鍵調節方向,E、Q控制地圖縮放</span>
    292 <input type="button" value="←" onclick="left(),readImage()"/>
    293 <input type="button" value="↑" onclick="up(),readImage()"/>
    294 <input type="button" value="↓" onclick="down(),readImage()"/>
    295 <input type="button" value="→" onclick="right(),readImage()"/>
    296 <input type="button" value="㈩" onclick="enter(),readImage()"/>
    297 <input type="button" value="㈠" onclick="exit(),readImage()"/>
    298 </form>
    299 左上角經緯度:&nbsp;&nbsp;<span id="latlng"></span>
    300 <table border="0" cellspacing="0" cellpadding="0">
    301   <tr>
    302     <td></td>
    303     <td></td>
    304     <td></td>
    305     <td></td>
    306     <td></td>
    307   </tr>
    308   <tr>
    309     <td></td>
    310     <td></td>
    311     <td></td>
    312     <td></td>
    313     <td></td>
    314   </tr>
    315   <tr>
    316     <td></td>
    317     <td></td>
    318     <td></td>
    319     <td></td>
    320     <td></td>
    321   </tr>
    322 </table>
    323 </body>
    324 </html>

    soso map和baidu map的地图url规律就蛋疼许多,因为他们的Y轴非要与google的方向相反。。没法,为了适应他们单独写了函数

    这还不算什么,soso还单独弄出来一个参数dx、dy,后来我还是自己看sosomap中的已经被搅乱的js代码才分析出来只是由x和y通过Math.floor(x/16)运算得到的,腾讯这样搞这有木有意义@@ ,为了后台省资源?

    百度也是跟着腾讯一样把地图的Y轴弄反,不过没有dx、dy,不过他们我实测都有经过偏移模组的偏移。也就是说你给定一个经纬度通过标准的麦卡拓算出来的xyz总有一点点几百米的偏移。这些倒是怪不到他。更变态的是sogoumap完全没有办法猜清楚是什么规律,我直接选择放弃了,都不想看它的js代码了,还是洗洗睡吧。

  • 相关阅读:
    微信小程序统一管理接口
    微信小程序购物车
    微信小程序表单的取值
    在VS Code中编写IAR项目
    【管理员已阻止你运行此应用】windows defender图标打叉,无法打开mmc.exe解决办法
    Eclipse普通java Project文件路径问题
    【线性表基础】基于线性表的简单算法【Java版】
    【线性表基础】顺序表和单链表的插入、删除等基本操作【Java版】
    Java逆序输出整数
    Java打印实心、空心的三角形和菱形
  • 原文地址:https://www.cnblogs.com/hyb1/p/3042423.html
Copyright © 2011-2022 走看看