昨天一QQ好友問了一個關於裁剪的問題,感覺自己也沒有幫上什么忙,之后自己做了一個裁剪的例子,不過在做這個例子的時候還遇到了不少的問題,在此和大家分享一下.
1.裁剪功能的實現過程
這里的裁剪功能很簡單,只需要一個Clip(裁剪)工具即可。
但是這里需要注意的問題是裁剪工具的參數:
裁剪工具有兩個輸入參數:
a.輸入要素:這里指的是你用什么來裁剪目標要素,也就是你用什么裁剪
b.裁剪要素:這里指的被裁剪的要素,即目標要素,也就是說你要裁剪誰。
例如,我現在有一幅中國地圖,我想根據我輸入的任意形狀,裁剪出任意形狀所包含的中國地圖部分。
如下圖所示:
中國地圖作為底圖(裁剪要素)

輸入多邊形(輸入要素),裁剪中國地圖

輸入多變行包含的中國地圖部分

以上主要是說一下裁剪工具,如果這里弄反了,則無法得到結果。
2.GP服務模型
以上說了一下裁剪工具注意的東西,以及其功能。下面給出的是GP服務的模型,比較簡單,只需要注意輸入要素和裁剪要素別弄反就行,上面已經給出,在此不再解釋。

3.發布GP服務
右鍵工具箱——發布到ArcGIS Server

輸入GP服務名稱,點擊下一步知道完成發布即可。

到此實現裁剪功能的GP服務已經發布完畢,在此推薦最好在ArcMap中驗證一下裁剪功能是否好使。
注意:
上面說到,裁剪工具需要注意輸入要素和裁剪要素別弄反。實際上,當裁剪工具的兩個要素參數弄反了之后,我們再發布實現裁剪的GP服務,同樣不會報錯,而且在ArcMap中驗證還會得到和沒有弄反時一樣的結果,也就是說如果只針對於ArcMap來講,裁剪工具的這兩個參數弄反都無所謂,即不影響最后的結果,但是當我們在Web端調用(本文只針對於Silverlight客戶端)時,就會得不到正確的結果,但是Silverlight客戶端調用GP服務的整個過程不會報錯。
關於GP服務的發布及注意事項可以參考之前的博文。
2.Silverlight客戶端代碼
(1).聲明一個Draw對象,繪制多邊形,作為裁剪要素。
Draw myDraw = null;
(2).聲明一個地理處理服務變量,用於請求GP服務
Geoprocessor _geoprocessor = null;
(3).聲明一個GraphicsLayer,存儲繪制的多邊形和最后裁剪的結果
GraphicsLayer graphicLayer = null;
(4).實例化上面的參數
myDraw= new Draw(map1); myDraw.DrawComplete += new EventHandler<DrawEventArgs>(myDraw_DrawComplete); myDraw.DrawMode = DrawMode.Polygon; myDraw.IsEnabled = false; DrawButton.Click += new RoutedEventHandler(DrawButton_Click); ClipButton.Click += new RoutedEventHandler(ClipButton_Click); ClearButton.Click += new RoutedEventHandler(ClearButton_Click);
graphicLayer = map1.Layers["ClipGraphic"] as GraphicsLayer; _geoprocessor = new Geoprocessor("http://qzj-pc/arcgis/rest/services/ClipService/GPServer/ClipTool"); _geoprocessor.JobCompleted += new EventHandler<JobInfoEventArgs>(_geoprocessor_JobCompleted); _geoprocessor.Failed += new EventHandler<TaskFailedEventArgs>(_geoprocessor_Failed);
上面聲明了實例化了Draw對象,以及Geoprocessor,並注冊相應的Button事件。
(5).首先是點擊繪制多邊形按鈕,開始繪制裁剪要素多邊形,所以在DrawButton的Click事件函數中添加如下代碼:
private void DrawButton_Click(object sender, RoutedEventArgs e) { //設置Draw為True,開始繪制 myDraw.IsEnabled = true; }
(6).然后是繪制完成,在DrawComplete事件函數中獲得繪制的多邊形,並添加到圖層中,示例代碼如下:
private void myDraw_DrawComplete(object sender, DrawEventArgs e) { graphicLayer.Graphics.Clear(); myDraw.IsEnabled = false; //因為上面指定DrawMode為Polygon所以得到的就是多邊形,如果DrawMode指定的是矩形,那么這里會出錯 //因為矩形不是Polygon,因為只有Polygon或者Polyline以及MapPoint才能夠被指定為Graphic的Geometry Polygon clipPolygon = e.Geometry as Polygon; Graphic graphic = new Graphic() { Geometry=clipPolygon, Symbol = LayoutRoot.Resources["FillSymbol"] as SimpleFillSymbol, }; graphicLayer.Graphics.Add(graphic); }
(7).繪制完成以后,接下來就是開始裁剪工作,在ClipButton的Click事件函數中開始Clip操作。
首先取得存儲GraphicLayer中的Graphic。在此之前需要做一個判斷,就是確認GraphicsLayer不為空。
然后由這些Graphic構成一個FeatureSet,將這個FeatureSet作為GP服務的輸入參數,
最后請求GP服務。示例代碼如下:
private void ClipButton_Click(object sender, RoutedEventArgs e) { if (graphicLayer.Graphics.Count == 0) { MessageBox.Show("裁剪要素不能為空!"); return; } FeatureSet featureSet= new FeatureSet(); //遍歷Graphic,添加到FeatureSet中 foreach (Graphic g in graphicLayer.Graphics) { featureSet.Features.Add(g); } //聲明GP服務參數 List<GPParameter> gpparameter = new List<GPParameter>(); //添加給名為ClipPolygon的GP服務參數名賦值 gpparameter.Add(new GPFeatureRecordSetLayer("ClipPolygon", featureSet)); //請求GP服務 _geoprocessor.SubmitJobAsync(gpparameter); }
(8).接着我們在GP服務的JobCompleted事件中注冊GetResultDataCompleted事件,並請求GP服務的結果,示例代碼如下:
void _geoprocessor_JobCompleted(object sender, JobInfoEventArgs e) { //如果GP服務執行成功,則獲取結果 if (e.JobInfo.JobStatus == esriJobStatus.esriJobSucceeded) { _geoprocessor.GetResultDataCompleted += new EventHandler<GPParameterEventArgs>(_geoprocessor_GetResultDataCompleted); _geoprocessor.GetResultDataAsync(e.JobInfo.JobId, "ClipResult"); } else if(e.JobInfo.JobStatus==esriJobStatus.esriJobFailed) { MessageBox.Show("GP服務執行失敗!"); } }
(9).最后在GetResultDataCompleted事件函數中,獲得GP服務的執行結果,並將其現實在地圖上。示例代碼:
private void _geoprocessor_GetResultDataCompleted(object sender, GPParameterEventArgs e) { graphicLayer.Graphics.Clear(); if (e.Parameter is GPFeatureRecordSetLayer) { GPFeatureRecordSetLayer featureSetLayer = e.Parameter as GPFeatureRecordSetLayer; if (featureSetLayer.FeatureSet.Features.Count == 0) { MessageBox.Show("裁剪的結果為空!"); } else { for (int i = 0; i < featureSetLayer.FeatureSet.Features.Count;i++) { featureSetLayer.FeatureSet.Features[i].Symbol = LayoutRoot.Resources["ResultFillSymbol"] as ESRI.ArcGIS.Client.Symbols.FillSymbol; graphicLayer.Graphics.Add(featureSetLayer.FeatureSet.Features[i]); } } } }
最后的示意圖:

裁剪結果:

(版權所有,轉載請標明出處)
