轉載聲明:http://www.cnblogs.com/ninemilli/archive/2011/12/26/2289285.html
概述:主要是闡述如何將瓦片地圖圖片拼接成完整地圖的一些概念以及相關算法。
基本概念:
現在就是要將一張張這類的地圖瓦片,在客戶端拼接成一幅完整的地圖。
瓦片大小為:256x256。
url中關鍵參數解析:
參數 | 描述 |
mt2.google.cn | Google瓦片服務服務器,可以嘗試mt1.google.cn依然有效。Google提供多台瓦片服務器,減輕服務器負載,提高網絡訪問效率。 |
x | 瓦片的橫向索引,起始位置為最左邊,數值為0,向右+1遞增。 |
y | 瓦片的縱向索引,起始位置為最上面,數值為0,向下+1遞增。 |
z | 地圖的級別,以Google為例,最上一級為0,向下依次遞增。 |
- 地圖投影:Web墨卡托——互聯網地圖通用的地圖投影方式,將橢圓形地圖投影成平面上的正文形,欲了解詳情請baidu之,如無特殊說明本文所指均為Web墨卡托投影下。
- Bounds(地圖范圍):[ -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892],單位為米,20037508.3427892表示地圖周長的一半,以地圖中心點做為(0,0)坐標。
- Levels:地圖的級別,例如:0……22。
- Resolutions:分辨率數組,與級別相對應,即一個級別對應一個分辨率,分辨率表示當前級別下單個像素代表的地理長度。
Resolutions[n] = 20037508.3427892 * 2 / 256 / (2^n)
- Center:地圖顯示中心點。
- Level:地圖顯示級別。
- viewSize:地圖控件窗口的大小。
根據已知地圖中心點、顯示級別可以將地圖顯示范圍計算出來:
viewBounds = [Center.x - Resolutions[l]*viewSize.width/2, Center.y - Resolutions[l]*viewSize.height/2, Center.x + Resolutions[l].viewSize.width/w, Center.y + Resolutions[l].viewSize.height/h]
地圖切圖方式:
一幅地圖由4^n個256的正方形組成,n為級別
例如:第0級為4^0個,即世界地圖由一個256圖片表示。
第1級世界地圖應由4^1(4)個256圖片組成,也就是將世界地圖(上一級的單個圖片)等分成4塊256圖片。
往下每一級依此類推……
拼圖算法剖析:
1、計算瓦片url
要想出圖就發須知道地圖控件可視范圍起始點瓦片索引、末尾瓦片索引,中間區域的瓦片索引循環遍歷即可得出。
下面看看如果計算出起始點、末尾瓦片url索引:
已知:l(縮放級別)、bounds(地圖范圍——[ -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892])、viewBounds(地圖控件可視范圍)、分辨率(Resolutions[l])、瓦片像素寬高(256)。
未知:startX(視圖起始瓦片X方向索引)、startY(視圖起始瓦片Y方向索引)、endX(視圖未尾瓦片x方向索引)、endY(視圖未尾瓦片y方向索引)。
求解:
startX = floor(((viewBounds.leftBottom.x - bounds.leftBottom.x) / Resolutions[l]) / 256); startY = floor(((viewBounds.leftBottom.y - bounds.leftBottom.y) / Resolutions[l]) / 256); endX = floor(((viewBounds.rightTop.x - bounds.rightTop.x) / Resolutions[l]) / 256); endY = floor(((viewBounds.rightTop.y - bounds.rightTop.y) / Resolutions[l]) / 256);
firstTileUrl(起始瓦片Url) = http://**********?x=startX&y=startY&z=l;
endTileUrl(末尾瓦片Url) = http://**********?x=endX&y=startY&z=l;
中間部分的url循環遍歷即可得出。
好啦!組成視圖所有瓦片的url都已得出。下面就是要解決將這些瓦片放到哪的問題。
2、計算瓦片放在地圖控件上的位置
先分析一下:其實只要將起始位置的瓦片像素位置算出來就可以了,由於瓦片像素大小為256,后面的各瓦片位置也就明了了。
所以這里只探討一下起始瓦片的像素位置。
已知:startX(視圖起始瓦片X方向索引)、startY(視圖起始瓦片Y方向索引)、分辨率(Resolutions[l])、瓦片像素寬高(256)、bounds(地圖范圍——[ -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892])、viewBounds(地圖控件可視范圍)。
未知:startTileX(起始瓦片左上角X方向地理坐標)、startTileY(起始瓦片左上角Y方向地理坐標)、distanceX(瓦片左邊與地圖控件左邊相距的像素距離)、distanceY(瓦片上邊與地圖控件上邊相距的像素距離)。
求解:
startTileX = bounds.leftBottom.x + (startX * 256 * Resolutions[l]); startTileY = bounds.rightTop.y - (startY * 256 * Resolutions[l]); distanceX = (viewBounds.leftBottom.x - startTileX) / Resolutions[l]; distanceY = (startTileY - viewBounds.rightTop.y) / Resolutions[l]
公式不是最簡,以方便理解,相信看官此時已經知道起始瓦片在地圖控件中的擺放位置了——設地圖控件起始像素位置為(0,0),那么此瓦片的像素的位置就是(-distanceX、-distanceY)。其它瓦片依據256像素寬高的關系依次而出。
到此已經算出了各瓦片的url以及它們應該擺放的位置,准備工作已完成,直接帖圖即可完成出圖工作。
算法可應用於Google、Baidu、Yahoo、Bing等web墨卡托投影的地圖瓦片。