周 海,謝雨芮,葛 平,劉毅錕
(1.西安測繪總站,陜西 西安710054)
局域網(wǎng)條件下的瓦片地圖應(yīng)用研究
周 海1,謝雨芮1,葛 平1,劉毅錕1
(1.西安測繪總站,陜西 西安710054)
通過Python網(wǎng)絡(luò)爬蟲獲取互聯(lián)網(wǎng)地圖瓦片并存儲到本地數(shù)據(jù)庫MongoDB中,在B/S架構(gòu)下利用Leaflet實現(xiàn)瓦片地圖瀏覽功能,利用Python-PIL在服務(wù)器端實現(xiàn)瓦片地圖拼接。為適應(yīng)地圖和地圖拼接服務(wù)高并發(fā)的需求,利用Nginx實現(xiàn)多臺服務(wù)器間的負載均衡。該項研究提供了網(wǎng)絡(luò)地圖瓦片的獲取、存儲、瀏覽和拼接方法,服務(wù)器端拼接的方式降低了客戶端依賴,為局域網(wǎng)條件下瓦片地圖應(yīng)用提供良好的思路。
瓦片地圖;爬蟲;Leaflet;瓦片拼接
目前,國內(nèi)外已有很多成熟軟件提供瓦片地圖的生產(chǎn)、服務(wù)發(fā)布、訪問和拼接功能,如SuperMap、ArcGIS均可用來切割瓦片[1]、服務(wù)發(fā)布和地圖訪問,稻歌、水經(jīng)注和太樂等提供瓦片地圖的拼接功能。許多學者開展了瓦片地圖存儲[2,3]、訪問[4]和拼接方面的研究,如韋勝[5]在ArcEngine上結(jié)合ArcBruTile(GitHub),利用Win32類庫和GDAL兩種不同方式實現(xiàn)對地圖瓦片的拼接。這些工具和研究對推進瓦片地圖應(yīng)用發(fā)揮了重要作用,但仍然存在一些問題:對地圖瓦片獲取研究較少,不能直接利用Google Map等互聯(lián)網(wǎng)瓦片地圖來構(gòu)建自己的地圖服務(wù);地圖拼接工作大都是在C/S架構(gòu)的Client端完成,只有安裝客戶端才能使用,受網(wǎng)絡(luò)影響大不易擴展。針對這些問題,首先研究通過Python爬蟲對Google Map等地圖瓦片進行獲取,基于B/S架構(gòu)實現(xiàn)地圖瓦片的瀏覽與服務(wù)器端的拼接,最后實現(xiàn)拼接服務(wù)的負載均衡以提高服務(wù)器性能。
傳統(tǒng)的瓦片生產(chǎn)由矢量地圖或影像來切割生成,預(yù)先對地圖數(shù)據(jù)渲染、切片,然后存放在服務(wù)器端,客戶端訪問時直接訪問這些瓦片數(shù)據(jù),以避免服務(wù)器端地圖實時渲染給服務(wù)器造成的壓力[2]。在全球范圍內(nèi),無論是地圖數(shù)據(jù)采集還是編繪都是巨大的工作量,通過網(wǎng)絡(luò)爬蟲來獲取現(xiàn)有互聯(lián)網(wǎng)地圖瓦片以便直接利用。局域網(wǎng)內(nèi)應(yīng)用互聯(lián)網(wǎng)地圖瓦片的技術(shù)路線如圖1。
圖1 局域網(wǎng)內(nèi)應(yīng)用互聯(lián)網(wǎng)地圖瓦片的技術(shù)路線
地圖瓦片數(shù)據(jù)一般采用金字塔結(jié)構(gòu)對不同分辨率(比例尺)的數(shù)據(jù)進行組織,由于數(shù)據(jù)坐標系統(tǒng)和地圖用途的不同,采用的投影和瓦片切割算法也可能不同[2]。目前,主流的網(wǎng)絡(luò)地圖多采用WGS 1984Web Mercator投影(地球近似為圓球體),經(jīng)度的投影范圍取(-180,180),緯度投影范圍?。?85.051 129,85.051 129)。金字塔的不同級別對應(yīng)于不同分辨率的地圖,地圖瓦片的大小通常采用256×256或512×512像素,并采用PNG格式。特定級別的地圖范圍(通常是全球)可以確定每塊瓦片的地理跨度和實際分辨率,進而計算出該瓦片在地圖圖層中的相對位置,即行列號。確定地圖等級z,行列號x、y便對應(yīng)于網(wǎng)絡(luò)地圖中的一塊瓦片[6]。
能夠通過網(wǎng)絡(luò)爬蟲來獲取網(wǎng)絡(luò)地圖瓦片,是因為這些網(wǎng)絡(luò)地圖服務(wù)提供了獲得每一塊瓦片的接口,通常每一塊瓦片均由獨立的URL地址唯一確定??梢酝ㄟ^Request請求獲取指定位置和級別的地圖瓦片。以Google Map影像為例,用戶request請求以下URL可以分別獲得圖2中4張瓦片。其中的主要參數(shù)x、y、z分別表示瓦片的行號、列號和級別。
1)http://mt0.google.cn/maps/vt?lyrs=s%40699&hl=zh-CN&gl=CN&&x=1&y=0&z=1;
2)http://mt0.google.cn/maps/vt?lyrs=s%40699&hl=zh-CN&gl=CN&&x=0&y=0&z=1;
3)http://mt0.google.cn/maps/vt?lyrs=s%40699&hl=zh-CN&gl=CN&&x=1&y=1&z=1;
4)http://mt0.google.cn/maps/vt?lyrs=s%40699&hl=zh-CN&gl=CN&&x=0&y=1&z=1;
圖2 Google影像數(shù)據(jù)
其他地圖瓦片可以通過URL來獲取,并根據(jù)其行列號和級別反解出其角點坐標。主要對Google Map的影像層(含注記層)、地圖層以及OpenStreetMap的標準圖層進行獲取,這些圖層的投影方式、投影范圍、瓦片切割算法相同,可以在地圖顯示時很好地集成和切換。實際工作中通過Python爬蟲程序獲取Google Map影像、地圖及OpenStreetMap3種地圖0~10級全球范圍內(nèi)的瓦片數(shù)據(jù)。
地圖瓦片是固定尺寸的圖片,通常為PNG格式,隨著地圖級別的增加,地圖瓦片的數(shù)據(jù)量呈指數(shù)級上升,如在第10級全球瓦片的數(shù)量達到410,如何實現(xiàn)地圖瓦片的高效存取非常重要。若將這些海量的地圖瓦片以文件的形式存儲在硬盤中,則不僅造成磁盤存儲碎片化嚴重、數(shù)據(jù)冗余,而且I/O性能差、不便于備份和恢復(fù)。通常的做法是將瓦片存儲在數(shù)據(jù)庫中,而且是非關(guān)系型數(shù)據(jù)庫(NoSQL)中,因為傳統(tǒng)關(guān)系型數(shù)據(jù)庫對文件、二進制等數(shù)據(jù)的讀寫性能依然受限[3,7]。
MongoDB[3,7]是一個開源、基于分布式文件存儲的NoSQL數(shù)據(jù)庫。它使用一種類似JSON的BSON格式進行數(shù)據(jù)存儲,因格式松散而支持復(fù)雜數(shù)據(jù)格式,尤其是內(nèi)置GridFS功能,特別適應(yīng)于大量小文件存儲。在數(shù)據(jù)備份和恢復(fù)方面,可以使用mongodump和mongorestore工具輕易實現(xiàn)數(shù)據(jù)遷移。此外,MongoDB還支持Python、Java、C++、PHP等多種語言,而且操作簡單便捷。基于這些特點,選用MongoDB來存儲獲取的地圖瓦片,以實現(xiàn)對地圖瓦片的高效存儲和訪問。采用Python的MongoDB操作工具pymongo實現(xiàn)對數(shù)據(jù)庫中瓦片的讀寫。存儲的信息除了圖片文件,還包含行列號、文件格式、圖層類別、下載時間等其他信息。
地圖訪問的實現(xiàn)主要包括服務(wù)器端地圖服務(wù)發(fā)布和Web端地圖服務(wù)調(diào)用及交互兩部分,如圖3所示。
圖3 地圖訪問與拼接的實現(xiàn)
服務(wù)器端主要實現(xiàn)地圖服務(wù)器的功能,完成對數(shù)據(jù)庫中瓦片的讀取,并暴露服務(wù)接口。目前有許多商業(yè)GIS軟件(如ArcGIS Server)和開源GIS(如GeoServer)可以用來發(fā)布瓦片地圖服務(wù)。這些軟件雖提供了豐富的GIS服務(wù)功能,但部署和操作復(fù)雜。本研究僅涉及地圖服務(wù)和拼接服務(wù),因此運用Python的Tornado框架來搭建自己輕量級的GIS服務(wù)器。
Tornado是 FriendFeed的Web服務(wù)器及其常用工具的開源版本,采用epoll非阻塞I/O,響應(yīng)快速,每秒可處理數(shù)千并發(fā)連接,特別適用于實時的Web服務(wù)?;谠摽蚣芾肞ython實現(xiàn)RESTful風格的地圖瓦片服務(wù)。每塊瓦片對應(yīng)唯一一個URL,結(jié)構(gòu)為http://localhost:3000/tile?z={z}&x={x}&y={y}&layer=g oogle_sat,其中x、y、z分別對應(yīng)于瓦片的行號、列號和級別,layer為幾種不同的瓦片圖層,如Google影像、OpenStreetMap標準圖層等。這樣,瀏覽器端便可以通過URL獲取每一塊瓦片。
Web端(客戶端)主要實現(xiàn)地圖的瀏覽、漫游、縮放、定位等功能。要實現(xiàn)這些功能,一般要借助于WebGIS工具。目前,地圖服務(wù)廠商和GIS廠商都有自己的WebGIS產(chǎn) 品, 如 GoogleMap JavaScript API、ArcGIS API for JavaScript等。除此之外,出現(xiàn)了越來越多的JavaScript開源WebGIS客戶端,如 Leaflet、Openlayers、MapEasy、OpenScales等。由于開源GIS產(chǎn)品具有免費、開放、可擴展性和可定制性強,以及開發(fā)周期短、成本低等特點,基于開源GIS軟件的應(yīng)用項目越來越多[9,10]。
Leaflet 是一個為建設(shè)移動設(shè)備友好的互動地圖而開發(fā)的開源JavaScript 庫。代碼量雖小,但具有開發(fā)人員開發(fā)在線地圖的大部分功能。而且支持插件擴展,有一個友好、易于使用的API文檔和一個簡單的、可讀的源代碼。利用leaflet實現(xiàn)了瀏覽器端對瓦片地圖的瀏覽、漫游、縮放、定位等功能,并利用leaflet工具實現(xiàn)對要素層的編輯(框選要拼接的地圖范圍)。
地圖拼接在服務(wù)器端完成,客戶端和服務(wù)器配合完成。通過在瀏覽器端輸入坐標范圍、圖層、圖幅大小等參數(shù),在服務(wù)器端實現(xiàn)瓦片的拼接,返回給瀏覽器端。瓦片拼接的一般過程如圖4。
圖4 拼接的實現(xiàn)過程
在客戶端(瀏覽器):首先利用leaflet的draw工具在地圖上繪制矩形范圍框,為避免用戶選擇的地圖范圍過大,將用戶選擇的拼接范圍分割成多個圖幅進行拼接,因而用戶還需要輸入拼接后的圖幅大小。為避免瓦片的裁剪,圖幅大小采用瓦片大小的整數(shù)倍,如2 560×2 560、5 120×5 120像素等;接著選擇要拼接的圖層等級,并根據(jù)范圍對級別進行限定,以避免拼接任務(wù)過于龐大;最后,選擇需要拼接的圖層,以滿足不同地圖瓦片的拼接需求。
在服務(wù)器端:根據(jù)從客戶端接收過來的圖幅范圍、等級、圖幅大小、圖層等參數(shù)開始拼接任務(wù),為了讓客戶端實時獲取服務(wù)器端瓦片的拼接進度,在服務(wù)器端給每一個任務(wù)生成一個唯一的ID,然后將拼接的進度存儲在Session中,這樣瀏覽器就可以實時獲取拼接進度,并在完成拼接后下載。
地圖瓦片拼接服務(wù)使用Python來編寫,主要用到兩個工具:Imaging Library (PIL)和Geospatial Data Abstraction Library(GDAL)。PIL是 Python下的圖像處理模塊,支持多種格式,并提供強大的圖形與圖像處理功能。利用PIL將多塊瓦片PNG圖像拼接到一起。GDAL是一個在X/MIT許可協(xié)議下的開源柵格空間數(shù)據(jù)轉(zhuǎn)換庫。用它將EPSG描述的坐標系轉(zhuǎn)換為WKT坐標系。瓦片拼接的成果主要包括3類文件:拼接好的圖片PNG文件,記錄圖幅左上角點坐標及圖片分辨率等參數(shù)的PNW文件,以及采用WKT描述的坐標系PRJ文件。后兩者文件共同構(gòu)成了PNG文件的空間參考。地圖瓦片拼接將選定范圍的瓦片拼接成一個或多個圖幅,地圖拼接的算法如下:
1)根據(jù)輸入的拼接范圍和級別計算要拼接的起始行列號、終止行列號以及瓦片分辨率;
2)根據(jù)起始行列號和終止行列號以及輸入的圖幅大小,計算出每一塊圖幅的起止行列號以及起始坐標;
3)根據(jù)每塊圖幅的起止行列號,將落在該范圍的瓦片從數(shù)據(jù)庫中取出拼在一起,完成每一個圖幅的拼接,并根據(jù)起始坐標生成WKT描述的坐標系PRJ文件,將起始坐標及分辨率等參數(shù)記錄到PRJ參數(shù)文件中;
4)將拼接的每一個圖幅的PNG、PNW和PRJ文件壓縮為一個壓縮包。
為適應(yīng)用戶對地圖和瓦片拼接的大量并發(fā)訪問,對服務(wù)器進行優(yōu)化。利用Nginx反向代理實現(xiàn)對地圖服務(wù)和瓦片拼接服務(wù)的負載均衡。Nginx是一個高性能的HTTP和反向代理服務(wù)器,作為負載均衡服務(wù)器時,支持作為HTTP代理服務(wù)器對外進行服務(wù)。當用戶訪問網(wǎng)站時,負載均衡服務(wù)器(Nginx)將應(yīng)用服務(wù)請求轉(zhuǎn)發(fā)至5臺應(yīng)用服務(wù)器,以保證某一臺應(yīng)用服務(wù)器負載過高,或是當某臺應(yīng)用服務(wù)器宕機時,系統(tǒng)能夠繼續(xù)運行。負載均衡部署如圖5。
圖5 服務(wù)器負載均衡
當對地圖拼接服務(wù)實現(xiàn)負載均衡時,由于拼接任務(wù)是在某一臺應(yīng)用服務(wù)器上完成的,因此需要將所有任務(wù)的進度存儲在一個Memcached的session服務(wù)器上,這樣便可以獲得每個拼接任務(wù)的進度。當拼接任務(wù)完成后,若拼接文件不在本機,同樣需將下載請求轉(zhuǎn)發(fā)至實際任務(wù)進行的應(yīng)用服務(wù)器。
實驗下載了全球范圍內(nèi)Google Map影像、地圖及OpenStreetMap三類瓦片的0~10級數(shù)據(jù),并將數(shù)據(jù)存儲在mongodb中,數(shù)據(jù)大小約為26 GB。系統(tǒng)部署在VMware的centos虛擬機中,部署的結(jié)構(gòu)如圖5。系統(tǒng)主要包括地圖瀏覽和瓦片拼接下載功能,截圖如圖6。
圖6 瓦片拼接效果圖
地圖瀏覽:地圖瀏覽允許用戶實現(xiàn)Google地圖、Google影像、OpenStreetMap 3類瓦片地圖的瀏覽、漫游、縮放和圖層切換。地圖瀏覽界面包括了右下角的圖層切換按鈕和右上角的地圖拼接下載工具條,圖層切換按鈕允許用戶切換瀏覽不同的圖層,地圖下載工具條主要完成地圖拼接等功能,如圖6a。
瓦片拼接下載:地圖拼接下載主要通過地圖拼接下載工具條完成,通過輸入拼接范圍、拼接圖層、拼接圖層的級別以及拼接圖幅尺寸,向服務(wù)器提交拼接請求(如圖6b),在拼接過程中界面將顯示拼接進度,完成拼接后瀏覽器會彈出文件下載提示。圖6c是下載拼接好的文件,圖6d是將下載的文件在Global Mapper中打開的效果。
通過爬蟲獲取Google Map等互聯(lián)網(wǎng)地圖瓦片并存儲在數(shù)據(jù)庫,利用Python搭建輕量級地圖服務(wù)器并利用leaflet實現(xiàn)地圖的瀏覽功能。在此基礎(chǔ)上,利用PIL和GDAL等工具實現(xiàn)瓦片地圖的拼接服務(wù),實現(xiàn)服務(wù)的負載均衡。實際應(yīng)用效果較好,為局域網(wǎng)下利用互聯(lián)網(wǎng)瓦片數(shù)據(jù)提供了一套有效的解決方案。下一步工作將實現(xiàn)瓦片緩存以便進一步提高系統(tǒng)性能,并研究局域網(wǎng)條件下瓦片地圖服務(wù)的具體應(yīng)用,如將瓦片地圖服務(wù)引入生產(chǎn)作業(yè)網(wǎng)以直接作為數(shù)據(jù)參考、在瓦片拼接基礎(chǔ)上利用瓦片完成地圖的在線制作等。
[1]蘇旭明, 譚建成. WebGIS中瓦片地圖關(guān)鍵技術(shù)研究[J].北京測繪, 2012(2):9-12
[2]羅智勇,黎小東.基于數(shù)據(jù)庫存儲方案的高性能瓦片地圖服務(wù)研究[J].地理與地理信息科學,2013,29(3): 52-55
[3]陳超, 王亮, 閆浩文,等. 一種基于NoSQL的地圖瓦片數(shù)據(jù)存儲技術(shù)[J].測繪科學, 2013, 38(1):142-143
[4]張廣春, 仲偉政. 基于ArcGIS Engine組件實現(xiàn)瓦片地圖的應(yīng)用[J].測繪通報, 2015(3):115-116
[5]韋勝. ArcEngine環(huán)境下實現(xiàn)瓦片地圖的訪問與拼接[J].武漢大學學報(信息科學版), 2012, 37(6):737-740
[6]OpenStreetMap Wiki. Slippy Map Tilenames [EB/OL]. http://wiki.openstreetmap.org/w/index.php?title=Slippy_map_tilenam es&oldid=1342885.2016-09-08 / 2016-11-15
[7]邱新忠. 基于MongoDB GridFS的地圖瓦片數(shù)據(jù)存儲研究[J].地理空間信息, 2016(2):50-52
[8]邱儒瓊, 鄭麗娜, 李兵. 基于MongoDB的電子地圖瓦片數(shù)據(jù)存儲和服務(wù)研究[J].地理空間信息, 2014(6):155-157
[9]李光師. 基于開源平臺構(gòu)建WebGIS應(yīng)用系統(tǒng)[J].測繪科學,2011, 36(6):259-261
[10]胡達天, 胡慶武. 基于開源系統(tǒng)的跨平臺地圖客戶端開發(fā)[J].測繪科學, 2015, 40(7):142-145
P208
B
1672-4623(2017)12-0018-04
10.3969/j.issn.1672-4623.2017.12.006
2016-11-18。
地理信息工程國家重點實驗室開放研究基金資助項目(SKLGIE2015-Z—2-1)。
周海,碩士研究生,主要從事地理編碼、空間數(shù)據(jù)挖掘、GIS應(yīng)用開發(fā)等工作。