[專家講座] ArcGIS API for Silverlight開發入門(5):任務外包——Tasks)

來源:互聯網
上載者:User

  通過上一節的學習,我們已經知道了如何與GraphicLayer互動,但畢竟GIS不是一個畫板,所以這節來看一下如何通過Silverlight API完成GIS中的分析功能。
        GIS之所以是一個通用的工具,就是因為它具有各種各樣分析和處理資料的能力。Silverlight API中提供了Task,使我們能夠輕鬆完成常見的分析任務。
        先來考慮一下吃餃子的情境。要想吃餃子,我們需要先去買菜,買肉,回家後在廚房裡洗菜,揉面, 拌餡,包餃子,煮餃子,吃餃子,之後別忘了洗碗;另一種情況就是去飯館,告訴服務員我要吃3兩茴香,3兩韭菜的餃子,然後等著餃子端到你面前,開吃,走人。
        在ArcGISServer程式開發中,要完成GIS的分析功能其實和吃餃子是一樣的。用ADF編程就像在家裡吃餃子,除了架設伺服器,所有的工作基本上也都得我們自己在伺服器端來完成,要處理的地方比較多;而用用戶端API編程相當於去外面吃餃子,我們只要把任務交給相應的Task,之後接受結果就行了,不用做餃子。唯一不同的就是在外面吃完餃子別忘了付錢,而用Task完成分析任務則是免費的。這點也體現在使用用戶端API中的Task時,是由ArcGISOnline提供給你的,不需要自己購買AGS軟體。
        現在來看看Silverlight API目前給我們提供了那些Task功能:
Query:能夠在已經發布的服務資料中,通過屬性條件(可以屬性欄位中進行關係判斷,字元尋找等),圖形條件(與輸入的圖形相交、包含、相離等),或者是兩者的組合,查詢出滿足條件的資料並返回。相當於Engine中的SpatialFilter,當然也是QueryFilter。
Find:在地圖資料的屬性欄位中尋找包含有關鍵字參數的資料並返回。
Identity:對滑鼠當前點擊位置上的資料進行辨識並返回結果,可以對多個圖層的資料進行辨識。
Address Locator:輸入經緯度,返回地址結果(Geocoding);輸入一個地方的地址,返回經緯度結果(Reverse Geocoding)。由於國內地圖資料保密工作做的相當好,這個Task暫時用不到。
Geometry Service:可以對輸入的地理資料進行如緩衝區,動態投影,面積/周長量算等幾何操作。
Geoprocessing:能夠完成複雜的GIS任務,類似ToolBox中的工具。
        抽象一下,可以看出,Query完全可以完成Identity和Find的工作,但後兩者在特定場合下使用起來比Query要方便的多;Geoprocessing完全可以替代Geometry Service,但是在利用REST API編寫的程式中,要盡量使用GeometryService。
        再抽象一下,Silverlight API中的這幾個Task和JavaScript/FlexAPI中的Task是大同小異的,因為其實它們都是AGS 9.3 REST API中暴露出來的操作資源(OperationResource)見:

 

        後面的代碼中實際上也是把輸入參數封裝起來提交到了REST API的特定Endpoint上。要理解好用戶端API中的Task,建議熟讀AGS的REST SDK。
        Task的用法基本上相同,都遵循這幾個步驟:初始化Task,設定Task所需參數,提交任務,等待伺服器完成任務後,處理返回的結果;進飯館,想好你要吃什麼餃子,告訴服務員,等餃子做好端上來,開始吃。好了,下面我們就通過一個執行個體(點擊這裡,查看執行個體),來學習一下Query和Geometry兩個Task的用法。

 

        首先選擇工具條中的畫線工具,在螢幕上畫一條曲線,會根據曲線自動產生一個距離100公裡的緩衝區顯示在地圖上,之後開始查詢緩衝區圖形經過的州(相交),將結果顯示在地圖上。可以單擊每個州查看詳細資料。這裡假設你已學習了前幾節的內容,只討論Task用法的部分。
1、利用所畫的線產生緩衝區。畫線利用的是Draw工具中的Freehand,在這個動作完成後會觸發Draw的OnDrawCompleted事件,自然可以在這裡開始進行緩衝區的工作,用的是Geometry Service裡的Buffer。
        初始化Geometry Service。假設已經在Map1中添加了ID為glayerResult的GraphicsLayer,linesymbolred是提前設定好的CartographicLineSymbol:

  1. private void Draw1_OnDrawComplete(object sender, DrawEventArgs args)
  2. {
  3. Draw1.Deactivate();//Freehand動作失效
  4. //將Freehand畫的曲線顯示在地圖上
  5. GraphicsLayer glayer = Map1.Layers["glayerResult"] as GraphicsLayer;
  6. Graphic g = new Graphic();
  7. g.Symbol = linesymbolred;
  8. g.Geometry = args.Geometry;
  9. glayer.Graphics.Add(g);
  10. //初始化Geometry Service
  11. GeometryService geometrytask = new GeometryService("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
  12. }

複製代碼

GeometryService的初始化使用建構函式來完成的,裡面接受一個URL,這個是Geometry Service的REST APIEndpoint。順便說一下,不同於其他服務比如MapService,一個GISServer只能發布一個GeometryService,並且它的名稱必須是Geometry。
        當一個Task完成時會觸發Completed事件,失敗時也有Failed事件,對這兩個事件進行監聽:

  1. geometrytask.BufferCompleted += new EventHandler(geometrytask_BufferCompleted);
  2. geometrytask.Failed += new EventHandler(geometrytask_Failed);

複製代碼

設定Buffer操作所需的參數:

  1. BufferParameters bufferparameters = new BufferParameters();
  2. bufferparameters.Unit = LinearUnit.Kilometer;
  3. //必須指定下面兩個spatialreference,否則buffer結果集為空白
  4. bufferparameters.BufferSpatialReference = new SpatialReference(3395);
  5. bufferparameters.OutSpatialReference = Map1.SpatialReference;
  6. bufferparameters.Distances.Add(100);
  7. bufferparameters.Features.Add(g);

複製代碼

BufferParameters是專門用於Buffer的參數;BufferSpatialReference是將要Buffer的圖形重新投影到這個座標系下(常常需要根據地圖資料所在地方的情況來設定這個參數),並設定Buffer距離的單位為公裡,Buffer的輸出一般與地圖座標系一致;Buffer參數有一個Features屬性,是List類型,裡面的Graphic都將被Buffer。下來將Buffer的任務提交到伺服器(可以看出為什麼這些動作要叫Task):

  1. geometrytask.BufferAsync(bufferparameters);

複製代碼

以上代碼都放在Draw1_OnDrawComplete函數中。任務提交到伺服器後,由GeometryService接管,計算,完成後會立刻將結果返回給我們,通知我們結果已經完成的方式就是前面綁定的Completed事件。接收到結果後,首先將緩衝區顯示出來:

  1. private void geometrytask_BufferCompleted(object sender, GraphicsEventArgs args)
  2. {
  3. if (args.Results.Count>0)
  4. {
  5. GraphicsLayer glayer = Map1.Layers["glayerResult"] as GraphicsLayer;
  6. Graphic g = new Graphic();
  7. g.Symbol = fillsymbolBuffer;
  8. g.Geometry = args.Results[0].Geometry;
  9. glayer.Graphics.Add(g);
  10. }
  11. }

複製代碼

 

2、利用產生緩衝區的緩衝區進行空間查詢。要達到我們的目的,就還需要進行一個Query的Task,那麼就可以在這裡馬不停蹄的開始Query的Task。步驟基本都是一樣的,初始化,設定參數,提交結果,處理結果:

  1. private void geometrytask_BufferCompleted(object sender, GraphicsEventArgs args)
  2. {
  3. if (args.Results.Count>0)
  4. {
  5. GraphicsLayer glayer = Map1.Layers["glayerResult"] as GraphicsLayer;
  6. Graphic g = new Graphic();
  7. g.Symbol = fillsymbolBuffer;
  8. g.Geometry = args.Results[0].Geometry;
  9. glayer.Graphics.Add(g);
  10. //初始化QueryTask
  11. QueryTask querytask = new QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/5");
  12. //準備接收結果或者處理失敗的通知
  13. querytask.ExecuteCompleted += new EventHandler(querytask_ExecuteCompleted);
  14. querytask.Failed += new EventHandler(querytask_Failed);
  15. //設定Query Task所需的參數
  16. Query query = new Query();
  17. query.OutFields.Add("*");//也順便設定了query.ReturnGeometry=true;
  18. query.Geometry = g.Geometry;
  19. query.SpatialRelationship = SpatialRelationship.esriSpatialRelIntersects;
  20. //向伺服器上的對應圖層提交任務
  21. querytask.ExecuteAsync(query);
  22. Map1.Cursor = System.Windows.Input.Cursors.Wait;
  23. }
  24. }

複製代碼

這裡的查詢實在美國州的圖層上進行的,詳細資料將QueryTask建構函式裡的那個參數輸入瀏覽器查看;query.Geometry是設定需要進行空間查詢的圖形,就是上面緩衝區的結果;OutFields是查詢結果需要返回的欄位,這裡返回全部欄位,如果返回全部欄位,則強制設定了ReturnGeometry為true,如果我們不需要處理結果的圖形資訊,則可以將這個參數設為false,以節省流量,顯然這裡不是;空間關係可以參考API,與Engine中的完全一致。
        接下來處理QueryTask完成後的結果:

  1. private void querytask_ExecuteCompleted(object sender, QueryEventArgs args)
  2. {
  3. GraphicsLayer graphicslayer = Map1.Layers["glayerResult"] as GraphicsLayer;
  4. FeatureSet featureset = args.FeatureSet;
  5. if (featureset != null && featureset.Features.Count > 0)
  6. {
  7. graphicslayer.ClearGraphics();
  8. listboxResults.Items.Clear();
  9. foreach (Graphic graphic in featureset.Features)
  10. {
  11. graphic.Symbol = fillsymbolresult;
  12. graphicslayer.Graphics.Add(graphic);
  13. }
  14. }
  15. MyMapTip.GraphicsLayer = graphicslayer;
  16. Map1.Cursor = System.Windows.Input.Cursors.Arrow;
  17. }

複製代碼

上面處理空間查詢的結果只是將圖形顯示了出來,那麼對於單擊某個州後,顯示出其詳細資料該怎麼辦呢?從圖一可以看出,用到了Silverlight的DataGrid控制項,資訊從哪裡去呢?記得上面我們設定結果中返回的全部屬性欄位嗎?它們儲存在每個Graphic的Attributes屬性中。要麼綁定到DataGrid裡,要麼一條條添加……你可能已經發現了這條語句MyMapTip.GraphicsLayer =graphicslayer;,還記得第三節的Widgets嗎?那裡我們落下了MapTip這個小傢伙,現在派上用場了。除了在這裡設定MapTip的GraphicsLayer屬性外,在xaml中有如下的定義:

  1. <esriWidgets:MapTip x:Name="MyMapTip" BorderBrush="#99000000"
  2. BorderThickness="1" Title="詳細資料" VerticalOffset="10"
  3. HorizontalOffset="10" Background="#DDFFFFFF" />

複製代碼

僅此而已。MapTip會自動找尋自己GraphicsLayer中的Graphic,當滑鼠移至上方在某個Grpahic上時,會自動讀取它的Attributes屬性並顯示,小玩具又發揮了大作用。
        別忘了萬一處理任務失敗時的提示:

  1. private void geometrytask_Failed(object sender, TaskFailedEventArgs args)
  2. {
  3. MessageBox.Show("Buffer Error:" + args.Error);
  4. }
  5. private void querytask_Failed(object sender, TaskFailedEventArgs args)
  6. {
  7. MessageBox.Show("Query failed: " + args.Error);
  8. Map1.Cursor = System.Windows.Input.Cursors.Arrow;
  9. GraphicsLayer graphicslayer = Map1.Layers["glayerResult"] as GraphicsLayer;
  10. graphicslayer.ClearGraphics();
  11. }

複製代碼

本節內容完畢。上面講的相對簡略,要理解各個Task和參數的用法,還是需要熟悉Silverlight API和前面提到的REST API。另外,Geoprocessing Service實際上是最強大Task,如果有自己的GISServer,完全可以在上面發布自製的Model或者Python指令碼,以完成各種GIS分析任務,簡單的線上編輯也是可能的。它的用法也萬變不離其宗:初始化,設定參數,提交任務,處理結果。不同的是GeoprocessingService有兩種提交任務的方法:同步和非同步。前者伺服器端處理完任務後會立即將結果發送回用戶端;後者將任務提交後會得到伺服器端返回的一個JobID,即使任務處理完成也不會立即返回,而是需要你拿這個JobID去詢問伺服器:完成了嗎?完成了嗎?完成了嗎?如果完成,則可以取回相應的結果。
        前面說到,雖然去外面吃餃子很方便,但是畢竟那是人家做好的,對於老饕來說還需要自己的口感,自己下廚畢竟能控制整個過程的方方面面,哪怕你想做出餃立方也都是有可能的。同樣,ADF編程可以調用伺服器端的ArcObjects,讓你為所欲為,這點是用戶端API無論如何也辦不到的。
        下一節我們來對Silverlight API中的圖層類型做一個小結。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.