苦逼的研究生課程終於在今天結束了,也許從今以后再也不會坐在大學的課堂上正式的聽老師講課了,接下來的時間就得開始找工作了.....前段時間一直比較忙,上課,考試,論文,以及聯系實習單位...現在就差實習還沒有着落了。
前些天幫一網友做了個在線坡度分析的例子,大概的功能就是勾選任意的地形區域,然后實現Web端的地形坡度分析和可視化顯示,效果圖如下:
實現的基本思路大致分為以下三部分:
1.在ArcMap中建立坡度求解模型和坡度統計分析模型
2.發布模型為結果地圖服務,並在客戶端調用
3.根據將結果添加地形渲染的分級視圖。
一、建立坡度分析和統計分析模型
打開ArcMap,使用ModelBuilder建立如下所示的模型:
這里需要注意兩個地方:
1.SlopeData我們發現是中間數據,中間數據是模型創建的數據,但不是模型的輸出,如果這里沒有設置為模型參數,那么任務創建的中間數據將會被 ArcGIS Server 自動刪除。
在 10.1 版本之前,必須在模型構建器中明確設置中間數據變量,並且強烈推薦使用輸出路徑下的 %scratchworkspace% 約定將所有輸出寫入地理處理 scratchworkspace 環境。在10.1中不必使用此約定。
2.該模型具有兩個輸出模型參數:SlopeData,表示坡度的柵格數據,和ZonalTable,表示對坡度柵格數據統計的結果(如:坡度的最大值,最小值,平均值等)。
在模型建好以后,需要將該模型發布為結果地圖服務,關於10.1中結果地圖服務的發布可參考之前的博文。
二、Silverlight客戶端調用結果地圖服務,獲得坡度分析結果和統計結果(坡度最大值,最小值,平均值等)。
Web端調用的過程和調用GP服務的過程一致,大致如下:
1.聲明地理處理變量:
Geoprocessor _geoprocessor;
2.實例化地理處理服務變量,並注冊相應事件:
_geoprocessor = new Geoprocessor("http://localhost:6080/arcgis/rest/services/MyGPService/SlopeAnalysis/GPServer/SlopeTool"); _geoprocessor.JobCompleted += new EventHandler<JobInfoEventArgs>(_geoprocessor_JobCompleted); _geoprocessor.GetResultDataCompleted += new EventHandler<GPParameterEventArgs>(_geoprocessor_GetResultDataCompleted); _geoprocessor.GetResultImageLayerCompleted += new EventHandler<GetResultImageLayerEventArgs>(_geoprocessor_GetResultImageLayerCompleted); _geoprocessor.Failed += new EventHandler<TaskFailedEventArgs>(_geoprocessor_Failed);
3.輸入GP服務相關參數,請求GP服務
從以上建立的模型可知:
輸入的模型參數有:
polygon:表示勾選的區域,也就是執行坡度分析的地形區域
輸出測量單位:表示坡度分析的結果如何表示,有兩種選擇,Degree:坡度以角度表示,值得范圍在0-90度之間,PERCENT_RISE:表示以高程的百分比表示,默認為DEGREE.
Z 因子:一個Z單位與x,y方向單位的比值,這里
后台輸入GP服務參數,調用服務代碼:
//e.Geometry為繪制的多邊形 FeatureSet featureSet = new FeatureSet(e.Geometry); List<GPParameter> parameter = new List<GPParameter>(); parameter.Add(new GPFeatureRecordSetLayer("polygon", featureSet)); parameter.Add(new GPString("輸出測量單位", "DEGREE")); //x,y方向單位是經緯度表示,高程值用米表示 //經緯度與米的轉化公式:degree = meter / (2 * Math.PI * 6378137.0) * 360; parameter.Add(new GPDouble("Z_因子", 8.98315E-6)); _geoprocessor.SubmitJobAsync(parameter);
請求GP服務之后接下來就是獲取GP服務的結果,這里我們需要取得兩個結果,一是坡度分析結果(柵格數據,對應的格式是:GPResultImageLayer),一是坡度統計結果(表格,對應的數據格式:GPRecordSet)
這里我們先來獲取坡度分析結果,即柵格數據。
獲取柵格數據可以通過地理處理服務的GetResultImageLayerCompleted事件來獲得結果,但是我們需要在地理處理服務的Completed事件中進行請求,Completed事件表示本次地理處理任務已經完成,接下來才能獲取地理處理服務的結果。示例代碼:
在開始部分我們已經注冊地理處理服務的JobCompleted,GetResultDataCompleted和GetResultImageLayerCompleted事件,接下來在相應部分完成相應的代碼,
其中JobCompleted是獲取結果的前提,所有的獲取地理處理結果的請求,都要等地理處理服務完成(及JobCompleted),同時請求結果的時候不能同時請求兩個結果,如獲取柵格數據的代碼如下:
private void _geoprocessor_JobCompleted(object sender, JobInfoEventArgs e) { if (e.JobInfo.JobStatus == esriJobStatus.esriJobSucceeded) { jobID = e.JobInfo.JobId; HttpWebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp); _geoprocessor.GetResultImageLayerAsync(e.JobInfo.JobId, "SlopeData"); //注意不能同時請求GP服務的結果,如果在此添加下面的額代碼會出錯 //_geoprocessor.GetResultDataAsync(jobID, "ZonalTable"); } else { MessageBox.Show("請求GP服務失敗" + e.JobInfo.Messages.ToString()); } }
接下來就是獲得坡度的柵格數據,然后在地圖上顯示,並同時發送獲取統計表格的請求:
private void _geoprocessor_GetResultImageLayerCompleted(object sender, GetResultImageLayerEventArgs e) { //返回的結果實際上是一張圖片 GPResultImageLayer imagelayer = e.GPResultImageLayer; //定義圖層的ID imagelayer.ID = "InterpolationLayer"; //設置透明度 imagelayer.Opacity = 0.7; imagelayer.DisplayName = "坡度圖層"; //清空原有的結果 if (map1.Layers["InterpolationLayer"] != null) { map1.Layers.Remove(map1.Layers["Interpolation"]); } //添加當前結果到圖層中 map1.Layers.Add(imagelayer); //獲取坡度統計表格數據 _geoprocessor.GetResultDataAsync(jobID, "ZonalTable"); }
獲取坡度統計表格的數據,表格在Web客戶端傳輸的的格式是GPRecordSet,直接遍歷即可,這里因為執行一次坡度分析,所以表格中只有一條記錄,示例代碼如下:
private void _geoprocessor_GetResultDataCompleted(object sender, GPParameterEventArgs e) { GPRecordSet gpr = e.Parameter as GPRecordSet; if (gpr.FeatureSet != null) { double slope_MaxValue = Convert.ToDouble(gpr.FeatureSet.Features[0].Attributes["MAX"]); double slope_MinValue = Convert.ToDouble(gpr.FeatureSet.Features[0].Attributes["MIN"]); double slope_MeanValue = Convert.ToDouble(gpr.FeatureSet.Features[0].Attributes["MEAN"]); MEANSlopeValue.Text = slope_MeanValue.ToString("0.000"); List<SolidColorBrush> RenderColors = new List<SolidColorBrush>(); //默認設定10等分,顏色由綠到紅 RenderColors = CreateColors.CreateColorList(10); //間隔值 double stepValue = (slope_MaxValue - slope_MinValue) / RenderColors.Count; //構造不同等級的顏色和描述 List<RenderModel> RenderModels = new List<RenderModel>(); for (int i = 0; i < RenderColors.Count; i++) { RenderModels.Add(new RenderModel() { EndValue = (i + 1) * stepValue, StartValue = i * stepValue, RenderColor = RenderColors[i] }); } //綁定到渲染等級顯示的ListBox中 RenderColorListBox.ItemsSource = RenderModels; RenderColorBorder.Visibility = Visibility.Visible; } }
以上代碼包含了柵格數據渲染的顏色等級顯示圖例,其中用到了一個方法:CreateColorList,該方法用來構造由綠到黃再到紅的不同的漸變顏色。
public static List<SolidColorBrush> CreateColorList(int _classCount) { List<SolidColorBrush> ColorList=new List<SolidColorBrush> (); double step=255/_classCount; for (int i = 0; i <= _classCount/2; i++) { ColorList.Add(new SolidColorBrush(Color.FromArgb(255, (byte)(i*step*2), 255, 0))); } for (int i = _classCount / 2 + 1; i <= _classCount; i++) { ColorList.Add(new SolidColorBrush(Color.FromArgb(255, 255,(byte)((_classCount-i)*step*2) , 0))); } return ColorList; }
以及RenderModel,該類代碼如下:
public class RenderModel { public SolidColorBrush RenderColor { get; set; } public double StartValue { get; set; } public double EndValue { get; set; } public string Description { get { return string.Format("{0}-{1}", StartValue.ToString("#0.00"), EndValue.ToString("#0.00")); } } }
這樣便完成了坡度分析和顏色等級圖例。
最后再來幾張效果圖吧!
初始界面:
勾選地形區域進行坡度分析:
正在進行坡度分析:
坡度分析結果顯示:
PS:蛋疼的博客園,為了寫這篇日志耗了我一個晚上,上傳圖片一直失敗,失敗后直接刷新,之前寫的沒有保存,直接沒有了,代碼弄了好久也還是沒有成功,所以需要代碼的請留下您的郵箱,我會在第一時間將代碼發送到您的郵箱。
最后感謝您能認真的看完我的文章,感謝您的支持!