郭啟倩,武曉紅,李盛樂
(1.中國地震局 地震研究所, 湖北 武漢 430071;2.西安測繪總站, 陜西 西安 710054)
瓦片式震中分布圖生成及局部自動更新
郭啟倩1,武曉紅2,李盛樂1
(1.中國地震局 地震研究所, 湖北 武漢 430071;2.西安測繪總站, 陜西 西安 710054)
針對目前在線震中分布圖存在的問題,提出瓦片式地震震中分布圖。使用ArcGIS Engine開發瓦片切圖工具及局部瓦片自動更新程序,結合Google Maps實現瓦片式震中分布圖的展示。基于Web GIS的瓦片式震中分布圖在顯示歷史地震和最新地震方面較以往在線震中分布圖有很大改善,瓦片局部自動更新程序也克服了瓦片式地圖本身更新速度慢的缺陷。
瓦片;震中分布圖;局部自動更新; ArcGIS Engine ;Google Maps

目前地震系統可用于在線瀏覽的震中分布圖主要有2類:第1類是在地震信息門戶網站直接訪問靜態震中分布圖,該靜態圖件是由應急人員人工或通過程序生成的,這種方式增加了應急時期的響應時間,且靜態圖件的比例尺難以滿足公眾需求。第2類是基于Web GIS的地震震中分布圖[1],是目前使用最廣泛的在線震中分布圖形式。該方法是通過Internet上主流的網絡地圖,如Google Maps、百度地圖、MapABC等公布的基于Web的API接口,在地圖上添加覆蓋類標注顯示地震震中地點。這種方式優點在于其信息更新迅速、訪問速度快[2],在顯示少量地震,如最近一段時期的地震信息時效果顯著,但在顯示大量地震,如歷史地震信息時,會造成網絡響應速度慢,甚至出現頁面崩潰情況。本文提出基于Web GIS的瓦片式地震震中分布圖,在顯示歷史地震和最新地震方面較以往在線震中分布圖有很大改善,并利用局部瓦片自動更新程序在震后快速更新地圖數據,縮短應急響應時間。
Web GIS是Internet技術應用于GIS開發的產物。利用Internet在Web上發布和出版空間數據,為用戶提供空間數據瀏覽、查詢和分析的功能,已經成為GIS發展的必然趨勢。傳統的Web GIS服務根據用戶請求參數實時渲染地圖數據再返回給客戶端,由于GIS數據通常是海量的,用戶對每次請求的等待時間較長,數據傳輸與瀏覽速度較慢,成了Web GIS應用推廣的瓶頸。Google Maps將Ajax技術引入Web GIS[3],打破了傳統Web GIS根據用戶請求來實時渲染數據的服務模式,采用了地圖緩存,即瓦片技術提高訪問速度,減緩服務器壓力。
地圖瓦片技術是將地圖和影像采用特定的預切割方式進行切片,按一定規則存儲在服務器上,客戶端異步加載當前屏幕可視區域的瓦片數據。瓦片式地圖采用金字塔模型結構(如圖1)。這是一種多分辨率的層次模型,每一層對應一個地圖級別,從瓦片金字塔的底層到頂層,地圖級別及分辨率越來越低,但表示的地理范圍不變。當用戶提出數據請求時,服務器根據當前的地圖級別,只返回屏幕區域對應的瓦片到客戶端并緩存,有效避免了一次性請求所有數據導致的服務器壓力及帶寬浪費,提高了Web瀏覽器的地圖訪問能力。目前,越來越多的地圖服務網站(如Google Maps、百度地圖、MapABC、Microsoft Live Map等)都采用了這種技術來提高地圖訪問的速度。

圖 1 瓦片金字塔結構
地圖瓦片技術讓Web GIS系統的性能得到極大改善。然而,地圖生成瓦片以后,只是以圖片的形式存在,地理空間數據發生變化后只有等待后臺管理員重建地圖緩存才能在客戶端得到反映,而重建地圖瓦片通常需要幾h甚至更長的時間。實際上,地理空間數據變更通常只是局部區域變更,無需對整個地圖文檔重建瓦片,若能夠在后臺自動獲取更新的地理空間數據,編輯地圖文檔,并輸出局部區域地圖瓦片替換舊的瓦片文件,在很大程度上減少耗時,克服瓦片式地圖本身更新速度慢的缺陷。
將地圖瓦片技術運用于震中分布圖中,可以彌補目前在線震中分布圖存在的不足。
1)瓦片式地圖利用Ajax實現數據的按需獲取、異步加載,根據地震目錄資料制作歷史地震震中分布地圖,預處理為地圖瓦片作為專題底圖,用戶在地震速報頁面查看最近地震的同時可加載該地區歷史地震震中分布瓦片,無論震例多少,用戶一次瀏覽只需加載當前屏幕范圍的地圖瓦片,且瀏覽過的瓦片緩存到客戶端,無需重復請求數據,大大提高了網頁訪問速度,減小服務器壓力。
2)瓦片式震中分布圖便于和目前互聯網主流的地圖服務結合,利用API接口將震中分布專題底圖與Google Maps、百度地圖等疊加,還可利用API實現簡單的查詢、測距等功能,取得較好的應用效果。
3)地震分層逐級顯示,地圖級別越高,顯示震級越低,震例越多。
4)瓦片式震中分布圖分級縮放顯示,彌補了靜態震中分布圖比例尺無法滿足用戶需求的不足。
5)局部自動更新代替瓦片金字塔重建,改善了瓦片式地圖本身存在的更新困難的問題。
瓦片切圖工具是基于Visual Studio2010平臺和ArcGIS Engine 10.0,利用C#語言編程實現的。ArcGIS Engine是ESRI公司發布的用于構建定制應用的嵌入式GIS組件庫。ArcGIS Engine包括構建ArcGIS產品的所有核心組件,提供COM、.NET和C++的應用程序編程接口(API)。利用ArcGIS Engine提供的編程接口,可以方便地設計GIS程序,操作ArcMap地圖文檔。
3.1 切圖算法流程
切圖數據源采用ArcMap地圖文檔(.mxd格式)。首先確定將要進行瓦片切圖的地圖的初始地理坐標范圍,該范圍可自定義,也可利用IEnvelope接口的QueryCoords方法輸出。然后選取坐標范圍起始點,根據切片級別確定比例尺,由比例尺(dMapScale)、瓦 片 尺 寸(dImageWidth、dImageHeight) 及 跨度(detaX、detaY)循環計算每個瓦片的地理范圍(dTempXMin、dTempXMax、dTempYMax、dTempYMin);最后利用IExport接口輸出瓦片。瓦片切圖算法流程如圖2所示。

圖 2 切圖算法流程圖
程序對各個級別切割完成的瓦片按照瓦片切割等級、相應等級的切圖列數、相應列下的切圖行數進行分級組織存儲,便于客戶端對瓦片庫進行索引和查找。本文采用Google Maps瓦片組織方式存儲地圖瓦片。Google Maps所使用的地圖投影被稱作Web Mercator,它與常規墨卡托投影的主要區別就是把地球模擬為球體而非橢球體。程序中起始瓦片所對應的列、行號,即在瓦片坐標系下的X坐標、Y坐標,分別根據切圖范圍最小經度值、最大緯度值轉換而來,結合墨卡托投影函數將經度、緯度值轉換為瓦片X、Y坐標,轉換算法如下:
//經度轉換瓦片X坐標
int getXFromLongitude(double lon,int level)
{
return (int)((lon+180)/360)*Math.Pow(2, level);
}
//緯度轉換瓦片Y坐標
int getYFromLatitude(double lat,int level)
{
double sinLat = Math.sin(Math.PI * lat/180);
double y=0.5 - Math.Log((1+sinLat)/(1-sinLat))/ (4*Math.PI);
return(int)(y*Math.Pow(2, level))
}
切圖算法根據圖幅范圍自適應每一地圖級別對應的瓦片數,整體執行效率較高,瓦片約以20張/s 的速度輸出。
3.2 切圖工具開發
切圖工具程序實現主要利用ArcGIS Engine中的IExport、IActive View、IEnvelope等接口進行地圖瓦片的生成,根據切圖等級和切割的行列數不斷調整地圖的可視范圍,然后將當前地圖范圍的顯示內容導出為預定義格式的圖片,并按照瓦片庫的目錄組織結構進行存儲[4,5]。工具界面如圖3所示。

圖 3 切圖工具界面圖
瓦片導出函數如下:
private void exportToImage(IActiveView pActiveView, string sImagePath, IEnvelope pEnvelope, int right, int bottom)
{
IExportPNG pExpng = new ExportPNGClass(); IExport export = pExpng as IExport;
IEnvelope envelope = new EnvelopeClass();
ITrackCancel cancel = new CancelTrackerClass(); tagRECT grect; grect.left = 0; grect.top = 0;
grect.right = right;
grect.bottom = bottom;
int num = Convert.ToInt32(export.Resolution); envelope.PutCoords((double)grect.left, (double)grect. bottom, (double)grect.right, (double)grect.top);
export.ExportFileName = sImagePath;
export.PixelBounds = envelope;
pActiveView.Output(export.StartExporting(), num, ref grect, pEnvelope, cancel);
export.FinishExporting();
}
如前所述,瓦片式地圖是金字塔形分級存儲的圖片格式數據,當地理要素發生變化后需要重建瓦片金字塔,這一過程將耗費很長時間。瓦片局部自動更新旨在用更新變化區域瓦片數據的方法替代整體瓦片金字塔重建,更新過程只需要幾s。這一改進大大縮短了瓦片數據更新、準備時間,對于及時更新震中分布圖優勢顯著。
瓦片地圖局部自動更新程序分為更新地圖文檔和替換瓦片2個部分。更新地圖文檔,即根據需要更新的地圖要素數據通過后臺程序修改.mxd文檔。當地圖文檔更新以后,首先要獲取更新后的地圖要素對應的坐標范圍,然后根據這個坐標范圍計算該范圍內對應地圖瓦片的行列號,接著在后臺重新生成這個范圍內的地圖瓦片,最后以新生成的瓦片替換舊的瓦片,最終實現圖形與數據更新的同步[6]。
當點要素發生變化時,根據點要素在地圖投影坐標系下的坐標值計算該點在不同地圖級別下所在瓦片的行列號(X、Y),生成對應地圖級別的瓦片。線要素、面要素發生變化,根據變化要素的最小外包矩形計算該要素地理范圍所在瓦片的行列號序列,生成對應地圖級別的瓦片集合。下面以更新一個震中點pGeom要素為例,說明瓦片式震中分布圖局部自動更新流程。
4.1 更新地圖文檔
更新地圖文檔是獲取指定地圖文檔的當前圖層,對當前圖層添加新的地理要素,保存修改后的.mxd文檔作為瓦片數據新的地圖數據源。主要利用IFeatureClass、IFeature等接口向指定圖層添加新的地圖要素,關鍵代碼如下:
IFeatureLayer pFeatureLayer = (IFeatureLayer)m_ pCurrentLayer;
IFeatureClass pFeatureClass = pFeatureLayer. FeatureClass;
//開始創建地理要素
IFeature pFeature = pFeatureClass.CreateFeature(); //定義要素類型
pFeature.Shape = pGeom;
//要素賦字段值
int fi eldindex = pFeature.Fields.FindField("字段名"); pFeature.set_Value(f i eldindex, "字段值"); //保存地理要素pFeature.Store();
由于地震目錄采用經緯度記錄震中位置,點pGeom要素的坐標值是經過轉換處理的投影坐標系下的坐標值。
4.2 替換瓦片
1)將經緯度值轉換為對應地圖級別下的地圖瓦片坐標X、Y,轉換算法見§3.1。
2)根據瓦片號計算瓦片地理范圍。
double dTempXMin = dTileOriginX + dImageWidth * (detaX - 1);
double dTempXMax = dTileOriginX + dImageWidth * detaX;
double dTempYMax = dTileOriginY - dImageHeight * detaY;
double dTempYMin = dTileOriginY - dImageHeight * (detaY - 1);
IEnvelope envelope = new EnvelopeClass();
envelope.PutCoords(dTempXMin, dTempYMin, dTempXMax, dTempYMax);
pActiveView.Extent = envelope;
其中,dTileOriginX、dTileOriginY分別是該mxd文檔的X最小值和Y最大值,dImageWidth、dImageHeight代表瓦片的地理跨度值,detaX、detaY分別是瓦片號X、Y與該mxd文檔最小瓦片號OriginX、OriginY的差值。
3)輸出瓦片替換舊瓦片。
string sImagePath = sFolderDir + "\" + X+ "\" + Y +".PNG";
exportToImage(pActiveView, sImagePath, envelope, 256,256)。
本文基于Google Maps提供的JavaScript API接口對Google Maps進行二次開發[7]。對于歷史地震信息,采用疊加瓦片式震中分布圖的方式分震級縮放顯示,地圖級別越高,能夠顯示的震級越小,震例越多;對于最近一段時間發生的地震事件A,采用疊加覆蓋類標注的方式動態閃爍顯示。當新增地震事件B時,后臺程序自動將地震事件A寫入.mxd地圖文檔,并更新對應的各級地圖瓦片,地震事件B閃爍標注。
5.1 疊加震中分布圖瓦片
1)切圖數據源準備。按照逐級顯示地震的原則,在ArcMap中完成震中分布圖制圖,地圖投影方式采用與Google Maps一致的Web Mercator投影。
2)地圖瓦片制作。使用瓦片切圖工具制作地圖瓦片,不同級別的地圖瓦片選擇顯示對應震級范圍的地圖數據源,如2級地圖顯示7級以上地震,10級地圖顯示3級以上地震。
3)地圖瓦片疊加。Google Maps API為基本類型google.maps.Map提供了overlayMapTypes屬性疊加自定義瓦片地圖,關鍵腳本如下:
//疊加自定義瓦片
map.overlayMapTypes.insertAt(0, new OverLayer (new google.maps.Size(256, 256)));
//瓦片的tileSize、getTile屬性
function OverLayer(tileSize) {}
OverLayer.prototype.tileSize = new google.maps. Size(256, 256);
OverLayer.prototype.getTile = function (coord, zoom, ownerDocument)
{
var overlay = ownerDocument.createElement ('overlay');
overlay.style.width = this.tileSize.width + 'px';
overlay.style.height = this.tileSize.height + 'px';
var strURL = "EQMs7/";
strURL += zoom + "/" + coord.x + "/" + coord.y + ".PNG";
overlay.style.backgroundImage = 'url(' + strURL + ')';
return overlay;
}
其中coord.x、coord.y分別是Google Maps定義的瓦片坐標系中的瓦片坐標值X、Y,§4.2中程序生成的瓦片存儲路徑為zoom/ coord.x/coord.y,與strURL對應。圖4為7級地圖疊加Ms5以上地震的震中分布圖瓦片。

圖 4 瓦片式震中分布圖
5.2 標注最新地震事件
對于最新地震事件,采用Google Maps API提供的覆蓋類型google.maps.Marker動態閃爍顯示,并添加信息窗。圖5所示為在6級地理底圖上顯示全球5級以上地震震中分布圖,閃爍標注湖北巴東5.1級地震。

圖 5 標注最新地震
瓦片式地震震中分布圖結合主流的Web GIS服務平臺,彌補了傳統在線震中分布圖的不足,并改進瓦片數據更新方法,進一步優化了應用效果。功能方面,主要優勢在于將歷史地震震中分布圖作為專題底圖,以瓦片形式分級分層顯示,地圖級別越高,能夠顯示的地震級數越小,震例越多;同時利用Google Maps API提供的Marker覆蓋類顯示最新地震震情信息,實現歷史地震和最新地震同時顯示,效果較好。技術方面,采用局部瓦片自動更新的方法替代瓦片金字塔重建,在區域地理空間數據發生變化后(例如在震中分布圖上新增震中點),僅需要更新每個瓦片級別對應該區域的瓦片數據,最大程度地縮短了地圖瓦片的更新時間。
[1] 董星宏,賈寧.基于Web GIS的地震震中分布圖實現方式探討[J].高原地震,2011,23(1):63-64
[2] 吳阿丹,李勝樂.生成GoogleMap地震震中分布圖的一種方法[J].地震地磁觀測與研究,2012,33(2):120-123
[3] 吳云超,王汶,牛錚,等.Ajax在WebGIS中的應用[J].地理與地理信息科學,2007,23(2):43-46
[4] 寇曼曼,王勤忠,譚同德.Google map數字柵格地圖算法及應用[J].計算機技術與發展,2012,22(4):204-206
[5] 王小軍,劉璐.基于ArcGIS Engine進行瓦片式切圖的技術研究[J].測繪與空間地理信息,2010,33(4):49-54
[6] 郭明武,彭青山,李黎.ArcGIS Server中地圖瓦片實時在線局部更新方法研究[J].測繪通報,2012(2):35-38
[7] Google. Google Maps JavaScript API V3[EB/OL].https:// developers.google.com/maps/documentation/javascript/ maptypes?hl=zh-CN#TileCoordinates,2014-05-21
P208
B
1672-4623(2015)01-0115-04
10.3969/j.issn.1672-4623.2015.01.038
郭啟倩,碩士,主要研究方向為地震與地理信息系統。
2014-05-21。
項目來源:“十二五”國家科技支撐計劃資助項目(2012BAK19B02-05)。