Silverlight調用GP服務第二篇之調用GP服務(Geoprocessing Service)過程詳解


 

 

Silverlight調用GP服務詳解

上一篇主要講了如何發布GP服來繪制等值線及等直面,這里主要將如何通過Silverlight來調用GP服務。

這里先寫一下具體的調用過程:

  1. 聲明GP服務變量(Geoprocessor),並實例化
  2. 注冊GP服務任務完成事件及失敗事件
  3. 根據發布的GP服務,定義GP服務的參數
  4. 輸入GP服務參數請求GP服務
  5. 獲取結果:在Compeleted事件函數中完成獲取結果的代碼,對於是要素類結果,需要注冊GetResultDataCompleted事件,對於是柵格數據結果需要注冊GetResultImageLayerCompleted事件,然后在事件的回調函數中完成最終結果的獲取。

這里需要注意的問題:

a.  GP服務是同步調用還是異步調用

b.  獲得結果的坐標系是否和當前一致

c.  GP服務的輸入參數必須和發布的GP服務一致(之后會詳細說明)

d.  獲取結果的名稱必須和發布的GP服務一致(之后會詳細講到)

以上大致的說了一下GP服務調用的基本過程,下面就開始正式的工作吧。

一.基本界面

首先我們構建一個簡單的Web界面,如下圖所示:

 

   這里需要實現的基本功能是:可以保存每一次添加的Graphic(xml格式),並能夠再次讀取這些Graphic.根據加載的Graphic實現基本的預測,即調用GP服務。

說明:為了節省時間,這里我已將用到的點的數據保存成了一個xml文檔,所有需要的數據都從xml中讀取。

 二.加載xml格式的Graphic信息

     這里就是遍歷xml中所有Graphic節點,然后讀取相應的信息(節點的名稱根據我們保存xml時定義的不同而不同,后面會給出保存xml的代碼)。讀取xml信息的代碼如下:

View Code
 1  //打開加載數據對話框
 2             OpenFileDialog openFileDialog = new OpenFileDialog();
 3             //指定xml問價格式
 4             openFileDialog.Filter = "XML Files(*.xml)|*.xml";
 5             if (openFileDialog.ShowDialog() == true)
 6             {
 7                 using (Stream stream = openFileDialog.File.OpenRead())
 8                 {
 9                     XDocument doc = XDocument.Load(stream);
10                     //遍歷xml中的Graphic節點
11                     foreach (XElement element in doc.Descendants("Graphic"))
12                     {
13                         //遍歷Graphic節點下的Location節點
14                         foreach (XElement LocationElement in element.Descendants("Location"))
15                         {
16                             //獲得Location節點下的坐標
17                             double LocationX = Convert.ToDouble(LocationElement.Element("LocationX").Value);
18                             double LocationY = Convert.ToDouble(LocationElement.Element("LocationY").Value);
19                             //獲得Graphic節點下的濃度值
20                             double PollutionC = Convert.ToDouble(element.Element("PolutionC").Value);
21                             //繪制Graphic
22                             CreatGraphic(LocationX, LocationY, PollutionC);
23                         }
24                     }
25                 }
26             }

     CreatGraphic方法表示在地圖上根據獲得的坐標和濃度值繪制出一個點。

View Code
//定義一個圖層,所以的Graphic將在此圖層上繪制
private GraphicsLayer graphicsLayer = null;

private void CreatGraphic(double locationx, double locationy, double pollutionc)
        {
            //構建一個Graphic,並定義其樣式
            Graphic g = new Graphic()
            {
                Geometry = new MapPoint()
                {
                X=locationx,
                Y=locationy,
                SpatialReference=map.SpatialReference
                },
                Symbol = new SimpleMarkerSymbol()
                {
                    Size = 9,
                    Color = new SolidColorBrush(Colors.Blue),
                    Style = SimpleMarkerSymbol.SimpleMarkerStyle.Circle
                },
            };
            
            if (map.Layers["GraphicsPoints"] == null)
            {
                graphicsLayer = new GraphicsLayer()
                {
                    ID = "GraphicsPoints"
                };
                map.Layers.Add(graphicsLayer);
            }
            //添加濃度屬性
            g.Attributes.Add("PolutionC", pollutionc);
            //
            graphicsLayer.Graphics.Add(g);
        }

三.保存xml格式的Graphic信息

     這里我們將GraphicLayer上所有的點的信息保存成xml格式。需要注意的是,xml中節點名稱必須和讀取xml文件時使用的節點名保持一致。否則之后我們無法讀取我們保存的信息。具體代碼如下:

View Code
 1  //若要素圖層不存在則返回
 2             if (map.Layers["GraphicsPoints"] == null)
 3                 return;
 4             //若圖層要素為空也返回
 5             GraphicsLayer graphicslayer = map.Layers["GraphicsPoints"] as GraphicsLayer;
 6             if (graphicslayer.Graphics.Count <= 0)
 7                 return;
 8             //打開保存對話框
 9             SaveFileDialog saveFileDialog = new SaveFileDialog();
10             //指定xml文件格柵
11             saveFileDialog.DefaultExt = "xml";
12             saveFileDialog.Filter = "XML Files (*.xml)|*.xml";
13             //指定默認的文件名為當前的時間
14             saveFileDialog.DefaultFileName = string.Format("GraphicInfo{0}", GetCurrentDateTimeString());
15 
16             if (saveFileDialog.ShowDialog() == true)
17             {
18                 using (Stream stream = saveFileDialog.OpenFile())
19                 {
20                     StreamWriter streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8);
21                     int GraphicNum = 1;
22 
23                     foreach (Graphic g in graphicslayer.Graphics)
24                     {
25                         //調用自定義GetGeneratedXML方法,構建xml
26                         GetGeneratedXML(GraphicNum, g);
27                         GraphicNum++;
28                     }
29                     streamWriter.Write(doc.ToString());
30                     streamWriter.Close();
31                     stream.Close();
32                 }
33             }

 GetGeneratedXML方法代碼如下:

View Code
 1  private void GetGeneratedXML(int graphicID, Graphic g)
 2         {
 3             MapPoint mapPoint = g.Geometry as MapPoint;
 4             XElement graphic = new XElement("Graphic", new XAttribute("ID", graphicID),
 5                 new XElement("Location",
 6                 new XElement("LocationX", mapPoint.X),
 7                 new XElement("LocationY", mapPoint.Y)),
 8                 new XElement("PolutionC", Convert.ToDouble(g.Attributes["PolutionC"])));
 9             doc.Root.Add(graphic);
10         }

GetCurrentDateTimeString方法如下:

View Code
 1   private string GetCurrentDateTimeString()
 2         {
 3             string TimeString;
 4             DateTime CurrentTime = new DateTime();
 5             CurrentTime = System.DateTime.Now;
 6             int year = CurrentTime.Year;
 7             int month = CurrentTime.Month;
 8             int day = CurrentTime.Day;
 9             int hour = CurrentTime.Hour;
10             int minute = CurrentTime.Minute;
11             int second = CurrentTime.Second;
12             TimeString = string.Format("{0}{1}{2}{3}{4}{5}", year, month, day, hour, minute, second);
13             return TimeString;
14         }

四.根據添加的點,進行預測及可視化表達(繪制等值線及等值面)

       到這里為止,才算是真正開始我們的GP服務。具體的調用過程在開始的時候作了一個大致的介紹,下面開始詳細的講解。

4.1 定義GP服務變量

View Code
1  //定義GP服務變量
2         private Geoprocessor InterpolationTask = null;//繪制等值面
3         private Geoprocessor ContourTask = null;//繪制等值線

並且實例化GP服務變量,並注冊相應的事件

View Code
 1             //等值線GP服務
 2             ContourTask = new Geoprocessor("http://qzj-pc/ArcGIS/rest/services/ContourService_with_Focal_Statistics/GPServer/ContourService");
 3             ContourTask.JobCompleted += new EventHandler<JobInfoEventArgs>(ContourTask_JobCompleted);
 4             ContourTask.GetResultDataCompleted += new EventHandler<GPParameterEventArgs>(ContourTask_GetResultDataCompleted);
 5             ContourTask.Failed += new EventHandler<TaskFailedEventArgs>(ContourTask_Failed);
 6             //等值面GP服務
 7             InterpolationTask = new Geoprocessor("http://qzj-pc/ArcGIS/rest/services/InterpolationService_Stretch/GPServer/InterpolationModel");
 8             InterpolationTask.JobCompleted += new EventHandler<JobInfoEventArgs>(InterpolationTask_JobCompleted);
 9             InterpolationTask.GetResultImageLayerCompleted += new EventHandler<GetResultImageLayerEventArgs>(InterpolationTask_GetResultImageLayerCompleted);
10             InterpolationTask.Failed += new EventHandler<TaskFailedEventArgs>(InterpolationTask_Failed);

4.2 定義GP服務的請求參數
 這里需要的參數必須和我們發布的GP服務一致。我們打開繪制等值線的GP服務鏈接,基本參數如下所示:

 以上是繪制等值面的GP服務參數列表,並給出了參數信息的詳細說明,這里我們可以看出繪制等值面的GP服務只有一個輸入參數:PollutionPoints,類型是GPFeatureRecordSetLayer,也就是要素集。同時只有一個輸出參數:RasterData,類型是GPRasterDataLayer,即柵格數據。

下面我們定義繪制等值面的GP服務參數。

 1  //添加這段代碼,非常有用,否則將無法獲取GP服務的結果
 2             HttpWebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
 3             //將從xml中解析出來的點構建成要素集,並作為我們GP服務輸入的參數
 4             FeatureSet featureSet = new FeatureSet(graphicsLayer.Graphics);
 5             //定義GP服務參數:InterpolationJobParameter
 6             List<GPParameter>InterpolationJobParameter = new List<GPParameter>();
 7             //添加GP服務參數
 8             InterpolationJobParameter.Add(new GPFeatureRecordSetLayer("PollutionPoints", featureSet));
 9             //請求等直面GP服務
10             InterpolationTask.SubmitJobAsync(InterpolationJobParameter);

注意這里的PollutionPoints,這里的名稱必須和之前我們發布的GP服務參數列表一致。而且還需要注意這里的GP服務參數類型,必須是要素集。
同理,我們可以看看繪制等值線的GP服務參數列表,如下圖所示:

 后台定義的繪制等值線的GP服務參數代碼:

 1 //定義繪制等值線的GP服務參數
 2             List<GPParameter> ContourJobParameter = new List<GPParameter>();
 3             //添加要素集參數
 4             ContourJobParameter.Add(new GPFeatureRecordSetLayer("PollutionPoints", featureSet));
 5             //添加等值線間距參數
 6             ContourJobParameter.Add(new GPDouble("Contour_interval", 4.0001));
 7             //添加容差設置參數
 8             ContourJobParameter.Add(new GPLinearUnit("XY_Tolerance", esriUnits.esriMeters, 1));
 9             //請求等值線GP服務
10             ContourTask.SubmitJobAsync(ContourJobParameter);

注意上面的GP服務參數名稱必須保持一致。


五.獲取GP服務的結果,並在地圖上顯示

     之前說過,請求GP服務結果都會有一個Completed事件,所以我們獲取結果的代碼將在該事件回調函數中完成。之前我們已注冊了GP事件,其回調函數如下:

 

下面我們就開始獲取等值面的結果。

在請求等值面GP服務的完成事件中添加如下代碼:

 1  private void InterpolationTask_JobCompleted(object sender, JobInfoEventArgs e)
 2         {
 3             
 4             if (e.JobInfo.JobStatus == esriJobStatus.esriJobFailed)
 5             {
 6                 MessageBox.Show("請求服務失敗!" + e.JobInfo.Messages.ToString());
 7                 return;
 8             }
 9             HttpWebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
10            //獲取GP服務結果,這里需要注意的是結果的名稱必須和我們發布的GP服務參數列表一致
11             InterpolationTask.GetResultImageLayerAsync(e.JobInfo.JobId, "RasterData");
12         }

注意這里的RasterData必須和之前我們發布的GP服務輸出參數名稱一致,否則將無法獲取到結果。
這里我們注意到,GetResultImageLayerAsync也是一個異步請求,因此我們需要在其完成事件的回調函數中獲得最終的結果,之前我們已經注冊了其完成的事件函數,現在添加如下代碼:

 1  private void InterpolationTask_GetResultImageLayerCompleted(object sender, GetResultImageLayerEventArgs e)
 2         {
 3             //返回的結果實際上是一張圖片
 4             GPResultImageLayer imagelayer = e.GPResultImageLayer;
 5            //定義圖層的ID
 6             imagelayer.ID = "InterpolationLayer";
 7            //設置透明度
 8             imagelayer.Opacity = 0.7;
 9            //清空原有的結果
10             if (map.Layers["InterpolationLayer"] != null)
11             {
12                 map.Layers.Remove(map.Layers["Interpolation"]);
13             }
14            //添加當前結果到圖層中
15             map.Layers.Add(imagelayer);
16             MessageBox.Show("繪制完成!");
17         }

這里說明一點:由於柵格數據不支持在Web客戶端直接讀取,因此我們通過結果地圖服務,將其在服務器端根據我們設置的渲染格式,生成一張圖片。然后在客戶端實際上是獲取這張圖片,而不是柵格數據,當客戶端的地圖范圍發生改變時(移動,縮放),就會在服務器端動態的生成響應的圖片,並在Web客戶端顯示其相應的結果。

最后,你還可以在Failed事件中添加GP服務請求失敗時的相應處理。

  private void InterpolationTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("請求服務失敗:" + e.Error.ToString());
        }

以上的過程便是獲取GP繪制等直面的結果。
下面是獲得的結果:

點擊加載xml文檔,打開xml文件,就會添加相應的Graphic,如下圖所示:

接着點擊預測,結果如下:

接下來,我們看看如何獲取等值線的結果。其過程和等值面的獲取相似,只不過等值線的結果是線要素,而等值面則是一張圖片,兩則在獲取和顯示上有一點點的差別。

下面是繪制等值線GP請求的Completed事件響應函數代碼,和等值面的差不多,唯一不同的就是異步請求的函數,以及闡述不一樣。

 1  private void ContourTask_JobCompleted(object sender, JobInfoEventArgs e)
 2         {
 3             if (e.JobInfo.JobStatus == esriJobStatus.esriJobFailed)
 4             {
 5                 MessageBox.Show("請求等值線服務失敗:" + e.JobInfo.Messages);
 6                 return;
 7             }
 8             HttpWebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
 9            //請求繪制等值線GP服務,注意這里和等值面的異步請求函數不一樣
10             ContourTask.GetResultDataAsync(e.JobInfo.JobId, "ContourLine_shp");
11         }

同樣需要注意請求結果的參數必須和發布的等值線GP服務輸出參數名稱一致。
然后我們在GetResultDataCompleted事件響應函數中添加相應的代碼獲取結果,並在地圖上顯示出來。代碼如下:

 1 private void ContourTask_GetResultDataCompleted(object sender, GPParameterEventArgs e)
 2         {
 3             if (map.Layers["ContourLayer"] != null)
 4             {
 5                 map.Layers.Remove(map.Layers["ContourLayer"]);
 6             }
 7             GraphicsLayer contourLayer = new GraphicsLayer() { 
 8             ID="ContourLayer"
 9             };
10             
11             GPFeatureRecordSetLayer featureSetLayer = e.Parameter as GPFeatureRecordSetLayer;
12            //遍歷結果獲取其中包含的要素,並添加到等值線圖層中
13             foreach (Graphic graphic in featureSetLayer.FeatureSet.Features)
14             {
15                 //設置等值線的樣式
16                 graphic.Symbol = new SimpleLineSymbol()
17                 {
18                     Style = SimpleLineSymbol.LineStyle.Solid,
19                     Color = new SolidColorBrush(Colors.Blue),
20                     Width = 3
21                 };
22                 contourLayer.Graphics.Add(graphic);
23             }
24             //將結果添加到當前的地圖中
25             map.Layers.Add(contourLayer);
26              MessageBox.Show("等值線繪制完成!");
27         }

同理添加GP服務請求失敗處理函數:

 private void ContourTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("請求等值線服務失敗:" + e.Error.ToString());
        }

這樣獲取等值線結果的工作已經完成,下面看一看效果:

到此,關於Silverlight調用GP服務繪制等值線以及等值面的所有過程已經講述完畢。

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM