ArcGISDynamicMapServiceLayer以ArcGISTiledMapServiceLaye方式使用

ArcGIS客戶端API(Javascript/Flex/Silverlight)中,我們最常打交道的是ArcGISDynamicMapServiceLayer和ArcGISTiledMapServiceLayer兩個類,基本每個地圖中都要用到。它們都可以直接將服務器端發佈的地圖服務(MapService)作爲圖層,加載到客戶端程序中,分別對應了動態地圖服務和緩存地圖服務。這兩種圖層類型各有優缺點。
ArcGISDynamicMapServiceLayer(動態地圖服務)通常用於實時顯示經常變化的數據,支持控制單個圖層可見性,可動態投影。但缺點是顯示效果較差,整個服務出圖較慢;ArcGISTiledMapServiceLayer可以直接加載服務器端的緩存地圖服務,顯示效果好,速度快,但它的缺點正是ArcGISDynamicMapServiceLayer的優點,即不支持動態投影,不能控制圖層可見性,服務器端需要提前生成緩存等。
這裏嘗試自己來在客戶端封裝一個類,創建一種新的客戶端圖層類型。它能夠綜合以上兩個圖層的優點,而克服其各自的缺點。大致總結一下我們要達到的目的:

ArcGISDynamicMap

ServiceLayer

ArcGISTiledMap

ServiceLayer

自定義的客戶端圖層

實時獲取最新數據

Y

N

Y

切片方式顯示服務

N

Y

Y

需要提前生成緩存

Y

N

客戶端緩存切片加快顯示速度

N

Y

Y

利用subdomain加速緩存加載

N

Y

Y

支持動態投影

Y

N

Y

動態指定圖像輸出格式

Y

N

Y

控制子圖層可見性

Y

N

Y

利用LayerDefination過濾數據

Y

N

Y

利用TimeExtent顯示時態數據

Y

N

Y

其它緩存服務特性

N

Y

Y

其它動態服務特性

Y

N

Y

由於這種圖層類型三種客戶端API(Javascript/Flex/Silverlight)均可使用,因此在這裏我們就不討論具體的實現代碼,只說明一下實現思路。
首先來解決以緩存服務的方式來顯示動態服務的問題。《ArcGIS客戶端API中加載大量數據的幾種解決辦法(以Silverlight API爲例)》一文中其實已經提到,主要是繼承TiledMapServiceLayer,其中獲取切片的GetUrl()方法,返回值是利用REST SDK中的ExportMap拼接的Url。這樣,我們就並不需要提前切圖,輸入動態地圖服務,從而達到緩存地圖服務的顯示效果。
舉一個例子,如果我想讓自己的服務可以和Google Maps/Bing Maps/ArcGIS Online的服務相疊加(WKID 102100/3857),那麼GetUrl()方法中看其來應該是這樣(裏面包括瞭如何根據level,row,col來計算一個切片的四個角點座標):
   1:  public override string GetTileUrl(int level, int row, int col)
   2:          {
   3:              string baseUrl = @"{0}/export?dpi=96&transparent=true&format=png8&bbox={1}%2C{2}%2C{3}%2C{4}&bboxSR=102100&imageSR=102100&size=256%2C256&f=image";
   4:   
   5:              double cornerCoordinate = 20037508.3427892;
   6:              double originResolution = cornerCoordinate * 2 / 256;
   7:              double resolution = originResolution;
   8:              for (int i = 0; i < level; i++)
   9:              {
  10:                  resolution /= 2;
  11:              }
  12:              double xmin, ymin, xmax, ymax;
  13:              //double resolution = 39135.7584820001;
  14:              xmin = -cornerCoordinate + resolution * 256 * col;
  15:              ymin = cornerCoordinate - resolution * 256 * (row + 1);
  16:              xmax = -cornerCoordinate + resolution * 256 * (col + 1);
  17:              ymax = cornerCoordinate - resolution * 256 * row;
  18:   
  19:              return string.Format(baseUrl, Url, xmin, ymin, xmax, ymax);
  20:          }

然後再來看下我們自定義圖層實現ArcGISDynamicMapServiceLayer功能的可行性。

關於動態投影。如果想要疊加到WGS84座標的底圖上,只需要將bboxSR和imageSR改成4326即可。這樣便支持了動態投影。

關於“切片”格式ImageFormat。只需修改上面baseUrl中的format參數。這樣一來既不需要在服務器端提前切圖,也能動態改變“切片”的格式。

關於服務加載速度。如果對於出圖速度不滿意,則可以在服務器端發佈若干個相同的服務,輪詢使用每個服務來出圖,可以達到並行加速的目的。

關於DisableClientCache。默認情況下,與ArcGISTiledMapServiceLayer一樣,這些“切片”會緩存在客戶端,便於再次瀏覽。如果服務器端數據有變,那麼就無法看到最新的變化情況,這是緩存服務的一個缺點。在自定義的圖層類型中,我們可以在exportmap操作的Url最後再加一個時間戳參數,比如_ts=DateTime.Now.Ticks.ToString(),那麼就達到動態地圖服務每次都能看到最新結果的目的。

關於控制子圖層的可見性。REST SDK的ExportMap操作中有layers參數可以控制。比如layers=show:2,4,7,則只會顯示第3、5、8圖層內容。

關於圖層內容過濾。ArcGISDynamicMapServiceLayer有LayerDefinitions屬性可以用SQL語句來篩選地圖服務的輸出內容,而REST中的ExportMap方法也提供了layerDefs供我們調用。比如{"0":"POP2000 > 1000000","5":"AREA > 100000"} ,只輸出第一個圖層中POP2000字段大於1000000的要素,第六個圖層中AREA>100000的要素。

關於ArcGIS Server 10中的TimeExtent。ArcGISDynamicMapServiceLayer有一個TimeExtent屬性用來顯示一定時間範圍內的數據,而ExportMap方法也給我們提供了Time參數來實現這個功能;並且還有layerTimeOptions參數來控制每個圖層的時間段(偏移)。

關於服務的元數據。ArcGISDynamicMapServiceLayer和ArcGISTiledMapServiceLayer中,都有一些關於服務元數據的屬性。比如CapabilitiesCopyrightTextDescriptionInitialExtentFullExtent等,這些在REST的MapService資源中都已經暴露了出來,因此我們可以通過發送請求的方式,在自定義圖層初始化的時候順便取回這些數據。

關於ArcGISTiledMapServiceLayer中的TileInfo。繼承TiledMapServiceLayer類的第一個條件就是得知Tiling Scheme。自然TileInfo也是探囊取物。

細心的朋友已經看出來,其實和ArcGISDynamicMapServiceLayer、ArcGISTiledMapServiceLayer一樣,我們這裏自定的圖層也是對ArcGIS Server REST SDK的一個封裝,但在顯示方式和顯示速度上有所改進。輸入的是動態地圖服務,有緩存服務的效果,但沒有真正做過緩存,所以姑且把它叫做DynamicTileMapServiceLayer。

源碼:http://download.csdn.net/detail/leesmn/3715905

引用自:http://blog.newnaw.com/?p=638

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章