使用HTML5 canvas做地圖(2)瓦片以及如何計算的

HPhone發表於2013-12-02

    上一篇也說到瓦片,我們為什麼使用瓦片?這一篇主要是關於如何拼接地圖?

    下面的一張圖,可以一眼明瞭,地圖是如何切割以及拼接的。

瓦片資訊

    瓦片資訊包括切圖原點,瓦片大小,格式,解析度以及解析度級別等。

    切圖原點,一般是整個座標系的最左上角,比如說,web墨卡託是[-20037508.3427892, 20037508.3427892]。切圖原點右側列數是正數,左側的列數是負數,下側行數是正數,上側行數是負數。

    瓦片的寬度、高度,目前網際網路最常見的瓦片寬度和高度都是256畫素。

    瓦片格式,可能是png,jpg等。

    解析度,這裡不是指電腦的解析度。而這裡意思是一畫素代表多少米,類似於比例尺。

    解析度級別,含有若干級別的解析度,不同的解析度下面,顯示不同的要素資訊。例如,低解析度下面,顯示洲名稱和海洋名稱。中解析度下面,顯示省名。高解析度下面,就顯示POI資訊。網際網路企業當中解析度級別數在20上下。

    地圖範圍,切圖的範圍,只在這個範圍下面才切圖,其他的區域都沒有相應的瓦片。如果把所有的解析度都切完的話,是非常耗時間的。僅僅是中國區域,一臺8核的機器,也得需要一個月才能切完,更何況全世界了。

Google為例

    谷歌使用的web墨卡託投影,解析度級別一共22級,他的每一級解析度大小20037508.3427892*2/(256*(2^i))。20037508.3427892*2代表整個的X軸範圍,256代表圖片的畫素大小,2代表是0級時有兩列(有的地圖0級只有1列,這個時候就是2^(i-1)),i代表級別。

    這個時候,解析度集合就是[78271.51696402031, 39135.758482010155, 19567.879241005077, 9783.939620502539, 4891.969810251269, 2445.9849051256347, 1222.9924525628173, 611.4962262814087, 305.74811314070433, 152.87405657035217, 76.43702828517608, 38.21851414258804, 19.10925707129402, 9.55462853564701, 4.777314267823505, 2.3886571339117526, 1.1943285669558763, 0.5971642834779382, 0.2985821417389691, 0.14929107086948454, 0.07464553543474227, 0.037322767717371134]。

    我們現在需要計算兩個東東,一個是當前解析度下面最大的行和列數,第二個某一個座標在第幾行幾列。下面會列出好幾個公式,一定要理解為什麼這麼計算,否則移植到其他的切圖服務不會自己列出相應的公式了。

最大行數和列數

    計算公式,20037508.3427892*2/(256*scale),20037508.3427892*2代表X軸和Y軸範圍,256代表圖片的畫素大小,scale代表解析度大小。

    通過這個計算公式,我們知道最大的行數和列數,是[2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304],注意的是行列值是從0開始的。

    比如說,1級下面,有兩行和兩列。這四張圖片的地址如下:

    我們把這四張圖片合在一起的話,就變成如下的圖,這就是一個世界的地圖了。

    

計算行,列位置

    計算行位置公式:Math.floor((x-(-20037508.3427892))/256/scale))。x-(-20037508.3427892)是最左側的距離,scale解析度,256代表寬度。Math.floor小於或等於指定數字的最大整數,這樣值是從0開始的。

    計算列位置公式:Math.floor((20037508.3427892-y)/256/scale))。20037508.3427892-y是到最上側的距離,scale解析度,256代表寬度。Math.floor小於或等於指定數字的最大整數,這樣值是從0開始的。

    左上角是X值最小,Y值最大。螢幕是X和Y值都是最小的。這一點轉換關係需要明白,否則Y軸的方向都反了。

    如果切圖不是從左上角開始的,就得計算每一個解析度下面的左上角和右下角所處的行和列,就可以知道行和列的範圍。同理,可計算當前可視區域的行和列。

    我們如果知道行列以及解析度等級,就很容易知道這個瓦片的地址。http://mt2.google.cn/vt/x=0&y=0&z=1,這裡的x代表引數行數,y代表列數,z代表解析度等級。

    Google這種圖片地址屬於非常好計算,幸好也是非常普遍的。比較難的,算是微軟的,行列以及解析度等級計算都差不多,難的是想x,y,z引數不知道怎麼計算的。

    例如,http://ak.dynamic.t2.tiles.virtualearth.net/comp/ch/1232?mkt=en-us&it=G,VE,BX,L,LA&shading=hill&og=31&n=z ,這個圖片地址,這個1232不知道怎麼來的。不過幸好找到一個論文才弄明白,《利用BingMaps地圖切片實現網路地圖服務》,地址http://wenku.baidu.com/link?url=7Mh7h8Vn94V2ha8LJLIy3WF2ONjLwcEaRCywujCR-fk4Pa-PGKrmcKL1zBaOmUK5eDmaIrXbO6SyAPdMHCOAXTn6PnhqBsL6yPsenWdMkfK

    我下面列出相關計算程式碼。

function getBingMapsImageNumber(x,y,z){
    //10進位制轉化為2進位制,前面補充0
    _f=function(n,m){
        var t= n.toString(2)+"";
        for(; t.length<m;){
            t="0"+t;
        }
        return t;
    }
    var _if=_f(x,z);
    var _jf=_f(y,z);
    var r="";
    for(var k=0;k!=z;++k){
        r+=_jf[k]+_if[k];
    }
    r=parseInt(r,2).toString(4);
    return _f(r,z);
}

  

相關文章