Mapbar地图切片的抓取和拼接算法

来源:互联网 发布:购物车图片淘宝 搞笑 编辑:程序博客网 时间:2024/05/31 13:14
转自:http://blog.csdn.net/mygisforum/article/details/7022860

1.MapBar 地图瓦片抓取算法

此地图瓦片抓取算法是根据Mapbarapi里的绘图算法写出来的,使用PHP编写,将代码保存为一个PHP文件后,然后使用命令行运行: $ php -f filename.php。

注:cmd>cd "x:\...\php.exe"。

[php] view plaincopy
  1. <?php  
  2. /** 
  3.  * 抓取mapbar切片的算法 by CrossYou at 2011/01/22 
  4.  * 
  5.  * @version 1.0.0 
  6.  * @link    http://crossyou.cn/ 
  7.  */  
  8. $mapbarImgRoot = './mapbar/';  
  9.   
  10. //每层地图切片的文件夹名称  
  11. $levelFolder = array('W','0','1','2','3','4','5','6','7','8','9','10','11','12','13','16');  
  12.   
  13. //每层地图切片所跨的经度数  
  14. $cutImgLonRange=array(90,40,20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01,0.005,0.002,0.001);  
  15.   
  16. //每层地图切片所跨的维度数  
  17. $cutImgLatRange=array(90*0.8,40*0.8,20*0.8,10*0.8,5*0.8,2*0.8,0.8,0.5*0.8,0.2*0.8,0.1*0.8,0.05*0.8,0.02*0.8,0.01*0.8,0.005*0.8,0.002*0.8,0.001*0.8);  
  18.   
  19. $blockSize=array(10,10,10,10,10,10,10,10,10,10,50,50,50,50,50,50);  
  20.   
  21. for($zoomLevel=0;$zoomLevel<16;$zoomLevel++){  
  22.   
  23.     $clipXNum=ceil(360/$cutImgLonRange[$zoomLevel]);  
  24.     $clipYNum=ceil(90/$cutImgLatRange[$zoomLevel]);  
  25.   
  26.     $clipLonRange = $cutImgLonRange[$zoomLevel];  
  27.     $clipLatRange = $cutImgLatRange[$zoomLevel];  
  28.   
  29.     $clipXGap = -180-$clipLonRange/2;  
  30.   
  31.     //从缩放级别5开始,只抓取中国范围内的地图,因为此级别以后的,非国内的都是背景图,抓了无意义。  
  32.     if($zoomLevel>3){  
  33.   
  34.         //--------中国范围的地图  
  35.         $west = 73;  
  36.         $east = 136;  
  37.         $north = 54;  
  38.         $south = 3;  
  39.   
  40.         $chinaLonRange = 63;//中国经度跨度  
  41.         $chinaLatRange = 51;//中国维度跨度  
  42.   
  43.         $chinaClipXNum = ceil($chinaLonRange/$clipLonRange);  
  44.         $chinaClipYNum = ceil($chinaLatRange/$clipLatRange);  
  45.   
  46.         for($i=0;$i<$chinaClipXNum;$i++){  
  47.             $lon = $west+$clipLonRange*$i;  
  48.   
  49.             for($j=0;$j<$chinaClipYNum;$j++){  
  50.                 $lat = $south+$clipLatRange*$j;  
  51.   
  52.                 $clipXNo =  floor($lon/$cutImgLonRange[$zoomLevel]);  
  53.                 $clipYNo =  floor($lat/$cutImgLatRange[$zoomLevel]);  
  54.   
  55.                 $clipXNo=($clipXNo)%$clipXNum;  
  56.                 if($clipXNo>=$clipXNum/2)$clipXNo-=$clipXNum;  
  57.                 if($clipXNo<-$clipXNum/2)$clipXNo+=$clipXNum;  
  58.   
  59.                 echo "\n新的切片... => \n";  
  60.                 echo '经纬度:'.$lon.' , '.$lat."\n";  
  61.                 echo "-------------------------------\n";  
  62.                 echo '切片序号:'.$clipXNo.' , '.$clipYNo."\n";  
  63.                 echo "-------------------------------\n";  
  64.   
  65.                 //切片分文件夹存放位置  
  66.                 $folderXNo = (int)floor($clipXNo/$blockSize[$zoomLevel]);  
  67.                 //切片分文件夹存放位置  
  68.                 $folderYNo = (int)floor($clipYNo/$blockSize[$zoomLevel]);  
  69.   
  70.                 if($folderXNo<0){  
  71.                     $folderXNo+=1;  
  72.                 }  
  73.   
  74.                 if($folderYNo<0){  
  75.                     $folderYNo+=1;  
  76.                 }  
  77.   
  78.                 $fileXNo =($clipXNo)-$folderXNo*$blockSize[$zoomLevel];  
  79.                 $fileYNo =($clipYNo)-$folderYNo*$blockSize[$zoomLevel];   
  80.   
  81.                 $imgPre = 'http://img.mapbar.com/maplite/mapbank/mapbar/';  
  82.   
  83.                 $imgDir = $levelFolder[$zoomLevel].'/'.$folderXNo.'_'.$folderYNo.'/';  
  84.                 $imgName = $fileXNo.'_'.$fileYNo.'.png';  
  85.                 $imgUrl = $imgPre.$imgDir.$imgName;  
  86.                 $localImgDir = $mapbarImgRoot.$imgDir;  
  87.   
  88.                 $localImgName = $localImgDir.$imgName;  
  89.                 if (!is_file($localImgName)){  
  90.                     createdir($localImgDir);  
  91.                     if(copy($imgUrl,$localImgName)){  
  92.                         echo '图片:=> '.$imgDir.$imgName." 成功下载到本地\n\n";  
  93.                     }  
  94.                 }  
  95.             }  
  96.         }  
  97.     }else{  
  98.         for($i= -$clipXNum/2;$i<=$clipXNum/2;$i++){  
  99.             $lon = $clipLonRange*$i;  
  100.             if($i<0)$lon+=$clipLonRange/2;  
  101.             if($i==0)continue;  
  102.             if($i>0)$lon-=$clipLonRange/2;  
  103.   
  104.             for($j=-$clipYNum;$j<=$clipYNum;$j++){  
  105.   
  106.                 $lat = $clipLatRange*$j;  
  107.   
  108.                 if($j<0)$lat+=$clipLatRange/2;  
  109.                 if($j==0)continue;  
  110.                 if($j>0)$lat-=$clipLatRange/2;  
  111.   
  112.                 $clipXNo =  floor($lon/$cutImgLonRange[$zoomLevel]);  
  113.                 $clipYNo =  floor($lat/$cutImgLatRange[$zoomLevel]);  
  114.   
  115.                 $clipXNo=($clipXNo)%$clipXNum;  
  116.                 if($clipXNo>=$clipXNum/2)$clipXNo-=$clipXNum;  
  117.                 if($clipXNo<-$clipXNum/2)$clipXNo+=$clipXNum;  
  118.   
  119.                 echo "\n新的切片... => \n";  
  120.                 echo '经纬度:'.$lon.' , '.$lat."\n";  
  121.                 echo "-------------------------------\n";  
  122.                 echo '切片序号:'.$clipXNo.' , '.$clipYNo."\n";  
  123.                 echo "-------------------------------\n";  
  124.   
  125.                 //切片分文件夹存放位置  
  126.                 $folderXNo = (int)floor($clipXNo/$blockSize[$zoomLevel]);  
  127.                 //切片分文件夹存放位置  
  128.                 $folderYNo = (int)floor($clipYNo/$blockSize[$zoomLevel]);  
  129.   
  130.                 if($folderXNo<0){  
  131.                     $folderXNo+=1;  
  132.                 }  
  133.   
  134.                 if($folderYNo<0){  
  135.                     $folderYNo+=1;  
  136.                 }  
  137.   
  138.                 $fileXNo =($clipXNo)-$folderXNo*$blockSize[$zoomLevel];  
  139.                 $fileYNo =($clipYNo)-$folderYNo*$blockSize[$zoomLevel];   
  140.   
  141.                 $imgPre = 'http://img.mapbar.com/maplite/mapbank/mapbar/';  
  142.   
  143.                 $imgDir = $levelFolder[$zoomLevel].'/'.$folderXNo.'_'.$folderYNo.'/';  
  144.                 $imgName = $fileXNo.'_'.$fileYNo.'.png';  
  145.                 $imgUrl = $imgPre.$imgDir.$imgName;  
  146.                 $localImgDir = $mapbarImgRoot.$imgDir;  
  147.   
  148.                 $localImgName = $localImgDir.$imgName;  
  149.                 if (!is_file($localImgName)){  
  150.                     createdir($localImgDir);  
  151.                     if(copy($imgUrl,$localImgName)){  
  152.                         echo '图片:=> '.$imgDir.$imgName." 成功下载到本地\n\n";  
  153.                     }  
  154.                 }  
  155.   
  156.             }  
  157.         }  
  158.     }  
  159. }  
  160.   
  161. /** 
  162.  * 创建多级目录 摘自网络 
  163.  * 如有好的建议,请到 http://crossyou.cn/给我留言 谢谢! 
  164.  * 
  165.  * @since 1.0.5 
  166.  * @param string $dir 
  167.  */  
  168. function createdir($dir){  
  169.   
  170.     $array_dir=explode("/",$dir);//把多级目录分别放到数组中  
  171.   
  172.     $depth = count($array_dir);  
  173.     $path = '';  
  174.     for($i=0;$i<$depth;$i++){  
  175.   
  176.         $path .= $array_dir[$i]."/";  
  177.   
  178.         if(!is_dir($path)){  
  179.             mkdir($path);  
  180.         }  
  181.     }  
  182. }  
  183. ?>  
2.MapBar地图瓦片拼接算法

作者制作的一个Demo:http://www.crossyou.cn/attachments/2011/03/mapbar.html。下面的源代码可能用到了一小点的jQuery。

[javascript] view plaincopy
  1. var divId = 'map';  
  2. var imgWidth        = 300;  
  3. var imgHeight       = 300;  
  4. var imgExt          = 'png';  
  5. var centerpoint     = '120.15689,35.96333';  
  6. var point           = centerpoint.split(',');  
  7. var _centerLon      = point[0];  
  8. var _centerLat      = point[1];  
  9. var zoomlevel       = 8;  
  10. var $map            = $('#'+divId);  
  11.   
  12. //每层地图切片的文件夹名称  
  13. var levelFolder     = new Array('W','0','1','2','3','4','5','6','7','8','9','10','11','12','13','16');  
  14. //每层地图切片所跨的经度数  
  15. var cutImgLonRange  = new Array(90,40,20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01,0.005,0.002,0.001);  
  16. //每层地图切片所跨的维度数  
  17. var cutImgLatRange  = new Array(90*0.8,40*0.8,20*0.8,10*0.8,5*0.8,2*0.8,0.8,0.5*0.8,0.2*0.8,0.1*0.8,0.05*0.8,0.02*0.8,0.01*0.8,0.005*0.8,0.002*0.8,0.001*0.8);  
  18. //地图区块大小 将不同区块的放在不同的文件夹下面进行管理  
  19. var blockSize       = new Array(10,10,10,10,10,10,10,10,10,10,50,50,50,50,50,50);  
  20.   
  21. //纬度的偏移  
  22. var latOffset       = new Array(0,0,0,0,0,0,0,0,75,0,0,-150,0,0,0,0);  
  23.   
  24. function drawMap(){  
  25.     var LatLon          = coordOffsetDecrypt(_centerLon,_centerLat);//解密Mapbar坐标  
  26.     centerLon           = LatLon[0];  
  27.     centerLat           = LatLon[1];  
  28.   
  29.     var mapwidth        = $map.width();  
  30.     var mapheight       = $map.height();  
  31.   
  32.     var halfNum5clipX   = Math.ceil(mapwidth/imgWidth/2);  
  33.     var halfNum5clipY   = Math.ceil(mapheight/imgHeight/2);  
  34.   
  35.     var _blockSize      = blockSize[zoomlevel];  
  36.     var clipLonRange    = cutImgLonRange[zoomlevel];  
  37.     var clipLatRange    = cutImgLatRange[zoomlevel];  
  38.     var multiple        = 100000;  
  39.   
  40.     var clipXNum=(360/clipLonRange);  
  41.     rotationCosVal=1.0;  
  42.     rotationSinVal=0.0;  
  43.   
  44.     var Clip = [];  
  45.     clipNo5X=Math.floor((centerLon)/clipLonRange);  
  46.     clipNo5Y=Math.floor((centerLat)/clipLatRange);  
  47.     if(clipNo5X<0)clipNo5X+=1;  
  48.   
  49.     var mapX=mapwidth/2-Math.round(((centerLon*multiple)%(clipLonRange*multiple))*imgWidth/(clipLonRange*multiple));  
  50.     if(centerLat>=0) {  
  51.         mapY=mapheight/2-imgHeight+Math.round(((centerLat*multiple)%(clipLatRange*multiple))*imgHeight/(clipLatRange*multiple));  
  52.     }else {  
  53.         mapY=mapheight/2+Math.round(((centerLat*multiple)%(clipLatRange*multiple))*imgHeight/(clipLatRange*multiple));  
  54.     }  
  55.     $map.html('');  
  56.     // -- 真正给力的开始  
  57.     for (var _clipXNo = -halfNum5clipX - 1; _clipXNo <= halfNum5clipX; _clipXNo++) {  
  58.         for (var _clipYNo = -halfNum5clipY - 1; _clipYNo <= halfNum5clipY; _clipYNo++) {  
  59.             try {  
  60.                 var clipXNo = parseInt(clipNo5X + _clipXNo);//地图横向切片序列号  
  61.                 var clipYNo = parseInt(clipNo5Y + _clipYNo);  
  62.                 clipXNo = (clipXNo) % clipXNum  
  63.                 if (clipXNo >= (clipXNum / 2))  
  64.                     clipXNo -= clipXNum;  
  65.                 if (clipXNo < (-clipXNum / 2))  
  66.                     clipXNo += clipXNum;  
  67.                 var folderX = parseInt(Math.floor((clipXNo) / _blockSize));  
  68.                 var folderY = parseInt(Math.floor((clipYNo) / _blockSize));  
  69.   
  70.                 if (folderX < 0)  
  71.                     folderX += 1;  
  72.                 if (folderY < 0)  
  73.                     folderY += 1;  
  74.   
  75.                 var fileXNo = (clipXNo) - folderX * _blockSize;  
  76.                 var fileYNo = (clipYNo) - folderY * _blockSize;  
  77.   
  78.                 var _strImgUrl = 'http://img.mapbar.com/maplite/mapbank/mapbar/' + levelFolder[zoomlevel] + '/';  
  79.                 if (zoomlevel >= 14)  
  80.                     _strImgUrl += folderX + "/";  
  81.   
  82.                 _strImgUrl += folderX + "_" + folderY + "/";  
  83.                 _strImgUrl += fileXNo + "_" + fileYNo + "." + imgExt;  
  84.   
  85.                 var clipLeft = (_clipXNo * imgWidth) + parseInt(mapX);  
  86.                 var clipTop = (-(_clipYNo * imgHeight) + parseInt(mapY));  
  87.   
  88.                 clipTop = clipTop + latOffset[zoomlevel];  
  89.   
  90.                 var isClearImgUrl = false;  
  91.   
  92.                 if ((clipLeft < -imgWidth || clipLeft > mapwidth || clipTop > mapheight || clipTop < -imgHeight))  
  93.                     isClearImgUrl = true;  
  94.   
  95.                 if (isClearImgUrl)  
  96.                     continue;  
  97.   
  98.                 var clipId = ((zoomlevel).toString(16) + (clipNo5X + _clipXNo).toString(16) + 'l' + (clipNo5Y + _clipYNo).toString(16)).toLowerCase();  
  99.   
  100.                 if (_strImgUrl && _strImgUrl.indexOf("NaN") < 0) {  
  101.                     if (Clip[clipId] == null) {  
  102.                         Clip[clipId] = new Image();  
  103.                         Clip[clipId].id = clipId;  
  104.                         Clip[clipId].name = clipId;  
  105.                         Clip[clipId].unselectable = "on";  
  106.                         Clip[clipId].style.position = "absolute";  
  107.                         Clip[clipId].style.MozUserSelect = "none";  
  108.                         Clip[clipId].src = _strImgUrl;  
  109.   
  110.                     }  
  111.   
  112.                     var p2 = (clipLeft + imgWidth / 2 - mapwidth / 2) * rotationCosVal - (clipTop + imgHeight / 2 - mapheight / 2) * rotationSinVal + mapwidth / 2;  
  113.                     var p5 = (clipLeft + imgWidth / 2 - mapwidth / 2) * rotationSinVal + (clipTop + imgHeight / 2 - mapheight / 2) * rotationCosVal + mapheight / 2;  
  114.   
  115.                     Clip[clipId].style.top = parseInt(p5 - imgHeight / 2) + "px";  
  116.                     Clip[clipId].style.left = parseInt(p2 - imgWidth / 2) + "px";  
  117.                     //var interval = parseInt($('#interval').val());  
  118.   
  119.                     $map.append(Clip[clipId]);  
  120.                 }  
  121.                 _strImgUrl = null;  
  122.             }  
  123.             catch (e) {  
  124.                 throw (e);  
  125.             }  
  126.         }  
  127.     }  
  128. }  
  129.   
  130. // The follow is two helper functions  
  131.   
  132. /** 
  133.  * 将真实地理坐标加密为Mapbar经纬度坐标 
  134.  * 
  135.  * @param x 经度值 
  136.  * @param y 维度值 
  137.  * @returns [x,y] 
  138.  */  
  139. function coordOffsetEncrypt(x,y){  
  140.     x = parseFloat(x)*100000%36000000;  
  141.     y = parseFloat(y)*100000%36000000;  
  142.   
  143.     _X = parseInt(((Math.cos(y/100000))*(x/18000))+((Math.sin(x/100000))*(y/9000))+x);  
  144.     _Y = parseInt(((Math.sin(y/100000))*(x/18000))+((Math.cos(x/100000))*(y/9000))+y);  
  145.   
  146.     return [_X/100000.0,_Y/100000.0];  
  147. }  
  148.   
  149. /** 
  150.  * 将Mapbar经纬坐标解密为真实地理坐标 
  151.  * 
  152.  * @param x 经度值 
  153.  * @param y 维度值 
  154.  * @returns [x,y] 
  155.  */  
  156. function coordOffsetDecrypt(x,y){  
  157.     x = parseFloat(x)*100000%36000000;  
  158.     y = parseFloat(y)*100000%36000000;  
  159.   
  160.     x1 = parseInt(-(((Math.cos(y/100000))*(x/18000))+((Math.sin(x/100000))*(y/9000)))+x);  
  161.     y1 = parseInt(-(((Math.sin(y/100000))*(x/18000))+((Math.cos(x/100000))*(y/9000)))+y);  
  162.   
  163.     x2 = parseInt(-(((Math.cos(y1/100000))*(x1/18000))+((Math.sin(x1/100000))*(y1/9000)))+x+((x>0)?1:-1));  
  164.     y2 = parseInt(-(((Math.sin(y1/100000))*(x1/18000))+((Math.cos(x1/100000))*(y1/9000)))+y+((y>0)?1:-1));  
  165.   
  166.     return [x2/100000.0,y2/100000.0];  
  167. }  

 

原文出自 CrossYou'Blog :

抓取算法:http://www.crossyou.cn/an-algorithm-to-crawl-mapbar-map.htm 

瓦片拼接算法:http://www.crossyou.cn/a-simple-map-of-the-source-code-mapbar.htm

注:以上内容仅供学习,在此严重感谢作者分享。


后记:经验证,百度使用的MapBar的地图,算法相同,其url前缀为:

 http://img.mapbar.com/maplite/mapbank/baidu/