您的位置:首页 > 其它

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

2012-11-23 22:52 453 查看

转自:/article/8302531.html



1.MapBar 地图瓦片抓取算法


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

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

[php] view
plaincopy

<?php

/**

* 抓取mapbar切片的算法 by CrossYou at 2011/01/22

*

* @version 1.0.0

* @link http://crossyou.cn/
*/

$mapbarImgRoot = './mapbar/';

//每层地图切片的文件夹名称

$levelFolder = array('W','0','1','2','3','4','5','6','7','8','9','10','11','12','13','16');

//每层地图切片所跨的经度数

$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);

//每层地图切片所跨的维度数

$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);

$blockSize=array(10,10,10,10,10,10,10,10,10,10,50,50,50,50,50,50);

for($zoomLevel=0;$zoomLevel<16;$zoomLevel++){

$clipXNum=ceil(360/$cutImgLonRange[$zoomLevel]);

$clipYNum=ceil(90/$cutImgLatRange[$zoomLevel]);

$clipLonRange = $cutImgLonRange[$zoomLevel];

$clipLatRange = $cutImgLatRange[$zoomLevel];

$clipXGap = -180-$clipLonRange/2;

//从缩放级别5开始,只抓取中国范围内的地图,因为此级别以后的,非国内的都是背景图,抓了无意义。

if($zoomLevel>3){

//--------中国范围的地图

$west = 73;

$east = 136;

$north = 54;

$south = 3;

$chinaLonRange = 63;//中国经度跨度

$chinaLatRange = 51;//中国维度跨度

$chinaClipXNum = ceil($chinaLonRange/$clipLonRange);

$chinaClipYNum = ceil($chinaLatRange/$clipLatRange);

for($i=0;$i<$chinaClipXNum;$i++){

$lon = $west+$clipLonRange*$i;

for($j=0;$j<$chinaClipYNum;$j++){

$lat = $south+$clipLatRange*$j;

$clipXNo = floor($lon/$cutImgLonRange[$zoomLevel]);

$clipYNo = floor($lat/$cutImgLatRange[$zoomLevel]);

$clipXNo=($clipXNo)%$clipXNum;

if($clipXNo>=$clipXNum/2)$clipXNo-=$clipXNum;

if($clipXNo<-$clipXNum/2)$clipXNo+=$clipXNum;

echo "\n新的切片... => \n";

echo '经纬度:'.$lon.' , '.$lat."\n";

echo "-------------------------------\n";

echo '切片序号:'.$clipXNo.' , '.$clipYNo."\n";

echo "-------------------------------\n";

//切片分文件夹存放位置

$folderXNo = (int)floor($clipXNo/$blockSize[$zoomLevel]);

//切片分文件夹存放位置

$folderYNo = (int)floor($clipYNo/$blockSize[$zoomLevel]);

if($folderXNo<0){

$folderXNo+=1;

}

if($folderYNo<0){

$folderYNo+=1;

}

$fileXNo =($clipXNo)-$folderXNo*$blockSize[$zoomLevel];

$fileYNo =($clipYNo)-$folderYNo*$blockSize[$zoomLevel];

$imgPre = 'http://img.mapbar.com/maplite/mapbank/mapbar/';

$imgDir = $levelFolder[$zoomLevel].'/'.$folderXNo.'_'.$folderYNo.'/';

$imgName = $fileXNo.'_'.$fileYNo.'.png';

$imgUrl = $imgPre.$imgDir.$imgName;

$localImgDir = $mapbarImgRoot.$imgDir;

$localImgName = $localImgDir.$imgName;

if (!is_file($localImgName)){

createdir($localImgDir);

if(copy($imgUrl,$localImgName)){

echo '图片:=> '.$imgDir.$imgName." 成功下载到本地\n\n";

}

}

}

}

}else{

for($i= -$clipXNum/2;$i<=$clipXNum/2;$i++){

$lon = $clipLonRange*$i;

if($i<0)$lon+=$clipLonRange/2;

if($i==0)continue;

if($i>0)$lon-=$clipLonRange/2;

for($j=-$clipYNum;$j<=$clipYNum;$j++){

$lat = $clipLatRange*$j;

if($j<0)$lat+=$clipLatRange/2;

if($j==0)continue;

if($j>0)$lat-=$clipLatRange/2;

$clipXNo = floor($lon/$cutImgLonRange[$zoomLevel]);

$clipYNo = floor($lat/$cutImgLatRange[$zoomLevel]);

$clipXNo=($clipXNo)%$clipXNum;

if($clipXNo>=$clipXNum/2)$clipXNo-=$clipXNum;

if($clipXNo<-$clipXNum/2)$clipXNo+=$clipXNum;

echo "\n新的切片... => \n";

echo '经纬度:'.$lon.' , '.$lat."\n";

echo "-------------------------------\n";

echo '切片序号:'.$clipXNo.' , '.$clipYNo."\n";

echo "-------------------------------\n";

//切片分文件夹存放位置

$folderXNo = (int)floor($clipXNo/$blockSize[$zoomLevel]);

//切片分文件夹存放位置

$folderYNo = (int)floor($clipYNo/$blockSize[$zoomLevel]);

if($folderXNo<0){

$folderXNo+=1;

}

if($folderYNo<0){

$folderYNo+=1;

}

$fileXNo =($clipXNo)-$folderXNo*$blockSize[$zoomLevel];

$fileYNo =($clipYNo)-$folderYNo*$blockSize[$zoomLevel];

$imgPre = 'http://img.mapbar.com/maplite/mapbank/mapbar/';

$imgDir = $levelFolder[$zoomLevel].'/'.$folderXNo.'_'.$folderYNo.'/';

$imgName = $fileXNo.'_'.$fileYNo.'.png';

$imgUrl = $imgPre.$imgDir.$imgName;

$localImgDir = $mapbarImgRoot.$imgDir;

$localImgName = $localImgDir.$imgName;

if (!is_file($localImgName)){

createdir($localImgDir);

if(copy($imgUrl,$localImgName)){

echo '图片:=> '.$imgDir.$imgName." 成功下载到本地\n\n";

}

}

}

}

}

}

/**

* 创建多级目录 摘自网络

* 如有好的建议,请到 http://crossyou.cn/给我留言 谢谢!

*

* @since 1.0.5

* @param string $dir

*/

function createdir($dir){

$array_dir=explode("/",$dir);//把多级目录分别放到数组中

$depth = count($array_dir);

$path = '';

for($i=0;$i<$depth;$i++){

$path .= $array_dir[$i]."/";

if(!is_dir($path)){

mkdir($path);

}

}

}

?>


2.MapBar地图瓦片拼接算法


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

[javascript] view
plaincopy

var divId = 'map';

var imgWidth = 300;

var imgHeight = 300;

var imgExt = 'png';

var centerpoint = '120.15689,35.96333';

var point = centerpoint.split(',');

var _centerLon = point[0];

var _centerLat = point[1];

var zoomlevel = 8;

var $map = $('#'+divId);

//每层地图切片的文件夹名称

var levelFolder = new Array('W','0','1','2','3','4','5','6','7','8','9','10','11','12','13','16');

//每层地图切片所跨的经度数

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);

//每层地图切片所跨的维度数

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);

//地图区块大小 将不同区块的放在不同的文件夹下面进行管理

var blockSize = new Array(10,10,10,10,10,10,10,10,10,10,50,50,50,50,50,50);

//纬度的偏移

var latOffset = new Array(0,0,0,0,0,0,0,0,75,0,0,-150,0,0,0,0);

function drawMap(){

var LatLon = coordOffsetDecrypt(_centerLon,_centerLat);//解密Mapbar坐标

centerLon = LatLon[0];

centerLat = LatLon[1];

var mapwidth = $map.width();

var mapheight = $map.height();

var halfNum5clipX = Math.ceil(mapwidth/imgWidth/2);

var halfNum5clipY = Math.ceil(mapheight/imgHeight/2);

var _blockSize = blockSize[zoomlevel];

var clipLonRange = cutImgLonRange[zoomlevel];

var clipLatRange = cutImgLatRange[zoomlevel];

var multiple = 100000;

var clipXNum=(360/clipLonRange);

rotationCosVal=1.0;

rotationSinVal=0.0;

var Clip = [];

clipNo5X=Math.floor((centerLon)/clipLonRange);

clipNo5Y=Math.floor((centerLat)/clipLatRange);

if(clipNo5X<0)clipNo5X+=1;

var mapX=mapwidth/2-Math.round(((centerLon*multiple)%(clipLonRange*multiple))*imgWidth/(clipLonRange*multiple));

if(centerLat>=0) {

mapY=mapheight/2-imgHeight+Math.round(((centerLat*multiple)%(clipLatRange*multiple))*imgHeight/(clipLatRange*multiple));

}else {

mapY=mapheight/2+Math.round(((centerLat*multiple)%(clipLatRange*multiple))*imgHeight/(clipLatRange*multiple));

}

$map.html('');

// -- 真正给力的开始

for (var _clipXNo = -halfNum5clipX - 1; _clipXNo <= halfNum5clipX; _clipXNo++) {

for (var _clipYNo = -halfNum5clipY - 1; _clipYNo <= halfNum5clipY; _clipYNo++) {

try {

var clipXNo = parseInt(clipNo5X + _clipXNo);//地图横向切片序列号

var clipYNo = parseInt(clipNo5Y + _clipYNo);

clipXNo = (clipXNo) % clipXNum

if (clipXNo >= (clipXNum / 2))

clipXNo -= clipXNum;

if (clipXNo < (-clipXNum / 2))

clipXNo += clipXNum;

var folderX = parseInt(Math.floor((clipXNo) / _blockSize));

var folderY = parseInt(Math.floor((clipYNo) / _blockSize));

if (folderX < 0)

folderX += 1;

if (folderY < 0)

folderY += 1;

var fileXNo = (clipXNo) - folderX * _blockSize;

var fileYNo = (clipYNo) - folderY * _blockSize;

var _strImgUrl = 'http://img.mapbar.com/maplite/mapbank/mapbar/' + levelFolder[zoomlevel] + '/';

if (zoomlevel >= 14)

_strImgUrl += folderX + "/";

_strImgUrl += folderX + "_" + folderY + "/";

_strImgUrl += fileXNo + "_" + fileYNo + "." + imgExt;

var clipLeft = (_clipXNo * imgWidth) + parseInt(mapX);

var clipTop = (-(_clipYNo * imgHeight) + parseInt(mapY));

clipTop = clipTop + latOffset[zoomlevel];

var isClearImgUrl = false;

if ((clipLeft < -imgWidth || clipLeft > mapwidth || clipTop > mapheight || clipTop < -imgHeight))

isClearImgUrl = true;

if (isClearImgUrl)

continue;

var clipId = ((zoomlevel).toString(16) + (clipNo5X + _clipXNo).toString(16) + 'l' + (clipNo5Y + _clipYNo).toString(16)).toLowerCase();

if (_strImgUrl && _strImgUrl.indexOf("NaN") < 0) {

if (Clip[clipId] == null) {

Clip[clipId] = new Image();

Clip[clipId].id = clipId;

Clip[clipId].name = clipId;

Clip[clipId].unselectable = "on";

Clip[clipId].style.position = "absolute";

Clip[clipId].style.MozUserSelect = "none";

Clip[clipId].src = _strImgUrl;

}

var p2 = (clipLeft + imgWidth / 2 - mapwidth / 2) * rotationCosVal - (clipTop + imgHeight / 2 - mapheight / 2) * rotationSinVal + mapwidth / 2;

var p5 = (clipLeft + imgWidth / 2 - mapwidth / 2) * rotationSinVal + (clipTop + imgHeight / 2 - mapheight / 2) * rotationCosVal + mapheight / 2;

Clip[clipId].style.top = parseInt(p5 - imgHeight / 2) + "px";

Clip[clipId].style.left = parseInt(p2 - imgWidth / 2) + "px";

//var interval = parseInt($('#interval').val());

$map.append(Clip[clipId]);

}

_strImgUrl = null;

}

catch (e) {

throw (e);

}

}

}

}

// The follow is two helper functions

/**

* 将真实地理坐标加密为Mapbar经纬度坐标

*

* @param x 经度值

* @param y 维度值

* @returns [x,y]

*/

function coordOffsetEncrypt(x,y){

x = parseFloat(x)*100000%36000000;

y = parseFloat(y)*100000%36000000;

_X = parseInt(((Math.cos(y/100000))*(x/18000))+((Math.sin(x/100000))*(y/9000))+x);

_Y = parseInt(((Math.sin(y/100000))*(x/18000))+((Math.cos(x/100000))*(y/9000))+y);

return [_X/100000.0,_Y/100000.0];

}

/**

* 将Mapbar经纬坐标解密为真实地理坐标

*

* @param x 经度值

* @param y 维度值

* @returns [x,y]

*/

function coordOffsetDecrypt(x,y){

x = parseFloat(x)*100000%36000000;

y = parseFloat(y)*100000%36000000;

x1 = parseInt(-(((Math.cos(y/100000))*(x/18000))+((Math.sin(x/100000))*(y/9000)))+x);

y1 = parseInt(-(((Math.sin(y/100000))*(x/18000))+((Math.cos(x/100000))*(y/9000)))+y);

x2 = parseInt(-(((Math.cos(y1/100000))*(x1/18000))+((Math.sin(x1/100000))*(y1/9000)))+x+((x>0)?1:-1));

y2 = parseInt(-(((Math.sin(y1/100000))*(x1/18000))+((Math.cos(x1/100000))*(y1/9000)))+y+((y>0)?1:-1));

return [x2/100000.0,y2/100000.0];

}

原文出自 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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: