? ?在上一篇文章中,細(xì)致介紹了瓦片數(shù)據(jù)在webgis中的組織結(jié)構(gòu)沐旨,得知了瓦片數(shù)據(jù)文件的組織其實是按照瓦片的級別榨婆、行、列號來組織的谊迄。如果給定一個坐標(biāo)(一般為經(jīng)緯度坐標(biāo))烟央,我們該怎樣計算出所需瓦片的行列號呢?我們在這一節(jié)中就來探討瓦片行列號的換算關(guān)系粮呢。在繼續(xù)下文之前钞艇,我們需要搞清楚幾個webgis中的基礎(chǔ)概念,且看下文詳述挺物。
“?地圖中的比例尺(Scale)和分辨率(Resolution)??”
? ? ? 在用arcgis切完圖之后飘弧,打開發(fā)布的服務(wù)或者打開config.xml配置文件次伶,即可看到切圖的相關(guān)配置,如下圖所示:
? ? ??在上圖中赶撰,levels表示該套切圖共有7個層級,每一個層級中又有Resolution和Scale兩個參數(shù)扣囊,它們分別代表該層級下的分辨率和比例尺侵歇。比例尺即為地圖上的一厘米代表實際上的多少厘米吓蘑。分辨率即為在當(dāng)前地圖范圍內(nèi),1個像素代表多少地圖單位溃蔫,地圖單位取決于當(dāng)前的空間參考琳猫。可見分辨率跟dpi(dpi代表每英寸的像素數(shù))有關(guān)系统刮,也跟地圖的單位有關(guān)系账千。
“?屏幕上1像素代表的實際距離(分辨率)??”
? ? ? ?現(xiàn)在來看下分辨率計算的原理,假設(shè)地圖的坐標(biāo)單位是米鞭衩,dpi為96,即1英寸=96像素娃善。1英寸=2.54厘米论衍,也就是說96個像素=2.54厘米,換算成米后聚磺,即1個像素=0.0254 / 96米饲齐。如果當(dāng)前層級下的地圖比例尺為1:125000000,則代表圖上1米等于實地125000000米咧最,那么1個像素代表的實際距離為125000000*0.0254/96 = 33072.9166666667米捂人。
“?瓦片行列號換算原理??”
在計算地圖上某點所對應(yīng)的瓦片行數(shù)時,有如下計算步驟:首先已知一個瓦片的實際長度是lrealTileSize(注意這里的單位不是像素矢沿,而是實際距離單位)滥搭,再計算出當(dāng)前屏幕某點距離瓦片原點的實際距離lreal,然后用實際距離lreal除以一個瓦片的實際長度lrealTileSize就可以得到瓦片的列數(shù)瑟匆,即col=floor(lreal/lrealTileSize)。
?????? 假設(shè)栽惶,地圖切圖的原點坐標(biāo)為(x0,y0)愁溜,瓦片的大小是tileSize疾嗅,地圖分辨率為res,則計算地圖上點(x,y)所在的瓦片行列號公式為:
????? col? = Math.floor((x – x0)/( tileSize*res))
? ? ? ?row = Math.floor((y – y0)/( tileSize*res))
? ? ? ?注冕象,Math.floor(number)函數(shù)返回小于number的最大整數(shù)代承。即浮點數(shù)向下取整。
? ? ? ?在實際webgis系統(tǒng)中渐扮,我們需要得到畫布的高度和寬度以及此時需要顯示的地圖的幾何范圍论悴,還要知道當(dāng)前需要顯示的地圖層級,在確定了這些需求后墓律,既可以計算需要加載的瓦片行列號范圍膀估。
? ? ? ?假設(shè)畫布寬為cvWidth,高為cvHeight耻讽,當(dāng)前地圖坐標(biāo)系下的地圖左下角坐標(biāo)為extentX_min,extentY_min察纯,右上角坐標(biāo)為extentX_max,extentY_max。
具體計算流程如下所示:
計算請求地理范圍的中心點坐標(biāo)(centerGeoPt)
? ? ? ?比如當(dāng)前要加載經(jīng)緯度為(lng,lat)针肥,需要將其轉(zhuǎn)為平面坐標(biāo)值捐寥,計算過程在本文附帶源碼中,不在此處做詳細(xì)論述祖驱。
計算出畫布范圍內(nèi)所對應(yīng)的地理范圍(min_x,min_y,max_x,max_y)
? ? ? ?根據(jù)當(dāng)前地圖層級握恳,得到分辨率res(即1個像素代表的實際距離大小)捺僻,用上步中得到的centerGeoPt的x坐標(biāo)加上或者減去半個畫布的寬度就可以得到max_x和min_x的值乡洼,即min_x = centerGeoPt.x – cvWidth*res/2;max_x = centerGeoPt.x + cvWidth*res /2匕坯。同理可得min_y與max_y的值束昵。示意圖如下所示:
計算瓦片起始行列號
? ? ? ?在得到上步的地理范圍后,再計算起始瓦片的行列號就會容易很多葛峻。起始瓦片的行列號計算公式分別如下所示:
列號:tileLeftTopX =Math.floor((Math.abs(min_x-extentX_min))/res* tileSize);
行號:tileLeftTopY =Math.floor((Math.abs(max_y-extentY_max))/res* tileSize);
計算實際地理范圍
? ? ? ?此前得到的地理范圍只是畫布對應(yīng)的地理范圍锹雏,當(dāng)計算出這個范圍所需的瓦片后,這些瓦片所覆蓋的地理范圍不一定就是畫布對應(yīng)的地理范圍术奖,如下圖所示礁遵。這時,就需要再計算出瓦片覆蓋的實際地理范圍采记。
實際地理范圍計算公式:
realmin_x = tileLeftTopX * res* tileSize + extentX_min;
realmax_y= extentY_max- tileLeftTopY * res* tileSize;
計算左上角偏移像素
? ? ? ?如上圖所示佣耐,左上角瓦片與畫布左上角是存在offset_x與offset_y這兩個偏移值的,所以我們需要計算出這兩個值(注意唧龄,這里是像素值哦)兼砖,以便在畫布加載瓦片的時候使用。計算公式如下所示:
offset_x= ((realmin_x- min_x )/res);
offset_y = ((realmax_y – max_y )/res);
計算瓦片個數(shù)(x,y軸上的瓦片個數(shù))
計算公式如下所示:
tileNum_x = Math.ceil((cvWidth + Math.abs(offset_x))/tileSize);
tileNum_y = Math.ceil((cvHeight + Math.abs(offset_y))/tileSize);
注,Math.ceil(number)函數(shù)返回大于number的最小整數(shù)讽挟。即浮點數(shù)向上取整懒叛。
“?繪制瓦片”
? ? ? ?我們在前面用了不少篇幅來討論了瓦片換算的整個計算原理,現(xiàn)在終于可以來實現(xiàn)算法繪制瓦片了耽梅!
繪制代碼這里需要說明下使用方法薛窥,在main.js中就是整個瓦片換算的算法實現(xiàn),而config.js是有關(guān)于當(dāng)前坐標(biāo)系下(EPSG:3857褐墅,就是webgis中常用的墨卡托投影坐標(biāo)系)的各個層級的比例尺及分辨率的設(shè)置參數(shù)拆檬。在MapTiles目錄中存放了0至5洪己,6個層級的地圖瓦片數(shù)據(jù)妥凳。
? ? ? ?感興趣的讀者可以在main.js中修改地圖中心經(jīng)緯度與地圖顯示層級的參數(shù)值,可以觀察地圖變化答捕,如下圖所示:
“?本期文章附帶源碼下載地址”
鏈接:http://pan.baidu.com/s/1i526MXn??
密碼:ahda
本文轉(zhuǎn)自微信公眾號:OpenGiser的文章