Silverlight客戶端實現區域像元統計以及地形剖面圖的繪制


開始之前的一段廢話:

放假回家了也就沒有寫博客了,家里沒有網,偶爾也只能用手機上一上,看一看是否有新的評論和回復,是否有和我研究相關的博文和動態。今天是三月一號,學校的校園網帳號解封了,於是便把寒假部分的工作內容總結一下,在此也和大家一起分享我的心得,希望對各位讀者能有所幫助。

本文的例子是我幫一位兄弟做的,算起還是我的學長,只不過不同學校,具體的要求如下:

http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid=124221&extra=page%3D1

於是假期的時候便做了一個該功能的例子,然后還加了一點小功能。后面的文章中將會詳細介紹,下面就進入正題吧!

一、本文實現的功能

1.1 要素查詢功能

根據要素屬性,查詢出相應的要素

1.2 柵格數據的像元統計

例如輸入一個幾何圖形(點,線,面)可以計算出該圖像范圍內柵格數據的像元信息,如:像元最大值,最小值,以及平均值等,具體如下圖所示:                  

       

 1.3 繪制地形剖面圖

 該功能和官網的這個例子差不多:

http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#SurfaceProfile

(不知道為什么,我這里查看不了這里例子)

效果如下圖所示:

二、使用到的數據和知識

2.1地圖數據

        本例的地形高程數據來自於國際科學數據服務平台,下載網址:

http://datamirror.csdb.cn/index.jsp

        本例的各區縣要素數據來自於國家基礎地理信息中心,下載網址:

http://nfgis.nsdi.gov.cn/nfgis/chinese/c_xz.htm

上面的地圖是我自己在ArcMap中制作的一張地圖,外加了一點地形陰影效果,這是在ArcMap中的圖層列表

 

各縣面要素圖層

       

 最后通過以上數據得到了本文使用的底圖。在查詢部分中,實際上查詢的就是各區縣的面要素,可通過輸入曲線的民稱或編號來查詢出相對應的縣,然后再通過調研像元統計的GP服務工具,即可實現像元統計,得到對應區縣范圍內像元的最大值,最小值等信息,實際上這里的值也就是對應區縣的海拔(准確度由下載的高程數據所決定),最后的地圖:

2.2 使用到如下的知識:

2.2.1 要素的屬性查詢

2.2.2 GP服務的調用

2.2.3 通過開源的Silverlight圖表控件:OxyPlot

以上前兩部分內容都在之前的博文中講過,所以不是本文的重點。關於OxyPlot圖表控件也很簡單,這里不會過多的解釋說明。官網有很好的幫助文檔。

三、實現過程

3.1 查詢(要素屬性查詢和空間查詢)

可參考之前的博文:

http://www.cnblogs.com/potential/archive/2013/01/31/2882244.html

3.2 根據查詢得到的面要素,計算出面要素對應區域內的像元信息。

3.2.1  發布像元統計的GP服務

這里主要用到的就是GP服務。下面是本文的GP服務模型:

 

其中ZoneFiled就是統計字段,InputFeature為輸入的要素,ZonalRaster為統計的刪格數據

 

提醒:在10.1中可以將柵格數據作為輸入參數。在10.0中不可以,如果您是10.0版本的,那么這里你只能在建模的時候指定柵格數據,然后去掉設置為模型參數。在10.1中如果你有可數的幾個不同柵格數據,那么你可以將其添加到ArcMap中,在發布GP服務的時候,會提示你從列表選擇還是自定義柵格數據,這個時候你可以選擇從列表選擇。然后你可以將ArcMap中的刪格數據圖層添加到選擇列表中,最后在Web端調用的時候,你只需要輸入柵格數據列表中對於柵格數據的名稱即可,例如本文的列表如下:

 

這里可以看出只有一個柵格數據選項:hunandata。

3.2.2   Web端調用GP服務

調用GP服務的過程之前的博文也有講到,可參考這里:

http://www.cnblogs.com/potential/archive/2012/11/03/2752289.html

下面是本文的調用代碼:

 private void AccessGPService(FeatureSet featureset)
        {
            List<GPParameter> gppara = new List<GPParameter>();
            //輸入GP服務的參數
            gppara.Add(new GPString("ZoneFiled", "OBJECTID"));
            gppara.Add(new GPFeatureRecordSetLayer("InputFeature", featureset));
            gppara.Add(new GPString("ZonalRaster", "hunandata"));
            _geoprocessor.SubmitJobAsync(gppara);
        }

        private void _geoprocessor_JobCompleted(object sender, JobInfoEventArgs e)
        {
            HttpWebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
            Geoprocessor gp = sender as Geoprocessor;
            //請求GP服務的結果
            gp.GetResultDataAsync(e.JobInfo.JobId, "ResultTable");
        }

        private void _geoprocessor_GetResultDataCompleted(object sender, GPParameterEventArgs e)
        {
            MyDataGrid.ItemsSource = null;
            GPRecordSet gpr = e.Parameter as GPRecordSet;
            if (gpr.FeatureSet != null)
            {
                for (int i = 0; i < gpr.FeatureSet.Features.Count; i++)
                {
                    for (int j = 2; j < gpr.FeatureSet.Features[i].Attributes.Count; j++)
                    {
                        //這里本文有個Bug,就是當FeatureDataGrid綁定到GraphicsLayer后,
                        //如果修改GrapicsLayer的屬性(增加或者刪除)會報錯,以下代碼不能通過,所以這里選擇了先修改再綁定
                        List<string> keyList = gpr.FeatureSet.Features[i].Attributes.Keys.ToList<string>();
                        List<object> valueList = gpr.FeatureSet.Features[i].Attributes.Values.ToList();
                        graphicsLayer.Graphics[i].Attributes.Add(keyList[j], valueList[j]);
                    } 
                }
                //在此綁定DataGrid,不然會出現異常
                MyDataGrid.GraphicsLayer = graphicsLayer;
                MyDataGrid.Visibility = Visibility.Visible;
                //繪制地形圖
                if (createPlot == true)
                {
                    CreatePlot();
                    TerrainBorder.Visibility = Visibility.Visible;
                }
                featureSet.Features.Clear();
            }
            //等待過程
            BusyRectangle.Visibility = Visibility.Collapsed;
            busyIndicator.IsBusy = false;
        }

        private void _geoprocessor_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show(e.Error.ToString());
        }

以上是調用GP服務的代碼,這里有個Bug。
最后的統計結果如下所示:

 

3.2.3 Web客戶端繪制地形圖

 這里借助的是開源的圖表控件:OxyPlot。感覺繪制圖表很強大,而且開源啊。

繪制地形剖面圖的功能大致上的過程如下:

首先在地圖上繪制一條線,然后等分這條線,例如一百份,然后得到這一百個點的像元統計值(最后的值就是海拔值,這里數據的准確度和提供的高程數據經度有關,高程數據經度越高,結果也就越准確),得到一百個點的高程數據之后,就通過OxyPlot繪圖了。

具體代碼:

a.OxyPlot繪圖

聲明一個PlotModel,PlotModel代表繪制圖表的類型。

PlotModel plotModel = null;

在構造函數中初始化:

 var linearAxis1 = new LinearAxis(AxisPosition.Bottom) { IsZoomEnabled=false,Title="距離"};
            plotModel.Axes.Add(linearAxis1);
            var linearAxis2 = new LinearAxis(AxisPosition.Left) { IsZoomEnabled=false,Title="海拔"};
            plotModel.Axes.Add(linearAxis2);
            areaSeries1 = new AreaSeries
            {
                Fill=OxyColors.DarkOrange,
                DataFieldX="距離",
                DataFieldY="最高海拔",
                DataFieldX2 = "距離",
                DataFieldY2 = "最低海拔",
                Color=OxyColors.Red,
                StrokeThickness=0,
                MarkerFill=OxyColors.Transparent,
            };

b.然后繪制一條直線並構造點:

    private void CreatPoint(ESRI.ArcGIS.Client.Geometry.Polyline polyline,int count)
        {
            //默認沿直線構造一百個點
            double xStep = (polyline.Paths[0][1].X - polyline.Paths[0][0].X) / count;
            double yStep = (polyline.Paths[0][1].Y - polyline.Paths[0][0].Y) / count;
            interval = Math.Sqrt(xStep * xStep + yStep * yStep);
            //清空FeatureSet便於之后的GP服務調用
            if (featureSet.Features.Count > 0)
            {
                featureSet.Features.Clear();
            }
            for (int i = 0; i < count; i++)
            {
                MapPoint mp = new MapPoint(polyline.Paths[0][0].X + i*xStep, polyline.Paths[0][0].Y + i*yStep);
                mp.SpatialReference = map1.SpatialReference;
                Graphic gPoint = new Graphic()
                {
                    Symbol = new SimpleMarkerSymbol()
                    {
                        Color=new SolidColorBrush(Colors.Blue),
                        Size=8,
                        Style=SimpleMarkerSymbol.SimpleMarkerStyle.Circle
                    },
                    Geometry=mp,
                };
                featureSet.Features.Add(gPoint);
                graphicsLayer.Graphics.Add(gPoint);
            }
        }

c.調用GP服務統計像元值(代碼如上)

d.根據統計值繪制圖表,這里Graphic的MAX屬性表示的即為最高海拔,對於點要素MAX和MIN值是一樣的。

 private void CreatePlot()
        {
            areaSeries1.Points.Clear();
            areaSeries1.Points2.Clear();
            plotModel.Series.Clear();

            for (int i = 0; i < graphicsLayer.Graphics.Count; i++)
            {
                areaSeries1.Points.Add(new DataPoint(interval * i, Convert.ToDouble(graphicsLayer.Graphics[i].Attributes["MAX"])));
                areaSeries1.Points2.Add(new DataPoint(interval * i, 0));
            }
            plotModel.Series.Add(areaSeries1);
            areaSeries1.Title = "海拔";
            Myplot.Model = plotModel;
            createPlot = false;
        }

最后的MainPage.cs代碼:

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client.Symbols;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client;
using System.Text.RegularExpressions;
using OxyPlot.Silverlight;
using OxyPlot;
namespace QueryAndStatisticDemo
{
    public partial class MainPage : UserControl
    {
        //用於查詢的Task
        QueryTask queryTask = new QueryTask();
        //聲明一個Draw,用於繪制查詢的區域,進行空間查詢
        Draw myDraw;
        //繪制的Geomotry
        ESRI.ArcGIS.Client.Geometry.Geometry drawGeometry; 
        //查詢SQL字符串
        string QueryString;
        //選擇查詢結果中的Graphic
        Graphic selectedGraphic;
        //地理處理服務
        Geoprocessor _geoprocessor = null;
        //輸入要素集
        FeatureSet featureSet = new FeatureSet();
        GraphicsLayer graphicsLayer;
        PlotModel plotModel = null;
        //Interval
        AreaSeries areaSeries1;
        double interval;
        bool createPlot = false;

        public MainPage()
        {
            InitializeComponent();
            plotModel = new PlotModel("地形剖面圖");
            var linearAxis1 = new LinearAxis(AxisPosition.Bottom) { IsZoomEnabled=false,Title="距離"};
            plotModel.Axes.Add(linearAxis1);
            var linearAxis2 = new LinearAxis(AxisPosition.Left) { IsZoomEnabled=false,Title="海拔"};
            plotModel.Axes.Add(linearAxis2);
            areaSeries1 = new AreaSeries
            {
                Fill=OxyColors.DarkOrange,
                DataFieldX="距離",
                DataFieldY="最高海拔",
                DataFieldX2 = "距離",
                DataFieldY2 = "最低海拔",
                Color=OxyColors.Red,
                StrokeThickness=0,
                MarkerFill=OxyColors.Transparent,
            };
            
            graphicsLayer = map1.Layers["QueryResultLayer"] as GraphicsLayer;

            queryTask.Url = "http://qzj-pc:6080/arcgis/rest/services/Provinces_Map/HunanMap/MapServer/3";
            queryTask.AutoNormalize = true;
            //很重要,否則出現查詢成功和失敗交替出現的現象
            queryTask.DisableClientCaching = true;
            queryTask.ExecuteCompleted += new EventHandler<QueryEventArgs>(queryTask_ExecuteCompleted);
            queryTask.Failed += new EventHandler<TaskFailedEventArgs>(queryTask_Failed);

            _geoprocessor = new Geoprocessor("http://qzj-pc:6080/arcgis/rest/services/RasterStatisticServer/GPServer/DemStatisticsRaster");
            _geoprocessor.JobCompleted += new EventHandler<JobInfoEventArgs>(_geoprocessor_JobCompleted);
            _geoprocessor.Failed += new EventHandler<TaskFailedEventArgs>(_geoprocessor_Failed);
            _geoprocessor.GetResultDataCompleted += new EventHandler<GPParameterEventArgs>(_geoprocessor_GetResultDataCompleted);

            myDraw = new Draw(map1);
            myDraw.DrawMode = DrawMode.Polygon;
            myDraw.IsEnabled = false;
            myDraw.FillSymbol = new SimpleFillSymbol()
            {
                BorderBrush = new SolidColorBrush(Colors.Black),
                BorderThickness = 3,
                Fill = new SolidColorBrush(Colors.Red),
            };
            myDraw.LineSymbol = new LineSymbol()
            {
                Color=new SolidColorBrush(Colors.Red),
                Width=3
            };
            myDraw.DrawComplete += new EventHandler<DrawEventArgs>(myDraw_DrawComplete);

            QueryTypeCombox.ItemsSource = AttributeString.GraphicAttributesEnNameString;
        }

        private void myDraw_DrawComplete(object sender, DrawEventArgs e)
        {
            graphicsLayer.Graphics.Clear();
            drawGeometry = e.Geometry;
           
            myDraw.IsEnabled = false;

            if (drawGeometry is ESRI.ArcGIS.Client.Geometry.Polyline)
            {
                CreatPoint((ESRI.ArcGIS.Client.Geometry.Polyline)drawGeometry,100);
                BusyRectangle.Visibility = Visibility.Visible;
                busyIndicator.IsBusy = true;
                AccessGPService(featureSet);
            }
            else
            {
                 StartQueryBySpatial(e.Geometry);
            }

        }

        private void ExpressionButton_Click(object sender, RoutedEventArgs e)
        {
            string pattern = @"^[0-9]*$";

            Button button = sender as Button;
            Match m = Regex.Match(button.Content.ToString(), pattern);
            if (m.Success)
                ExpressionTextBox.Text = string.Format("{0}{1}", ExpressionTextBox.Text, button.Content);
            else
                ExpressionTextBox.Text = string.Format("{0} {1} ", ExpressionTextBox.Text, button.Content);
        }

        private void ExpressionQueryButton_Click(object sender, RoutedEventArgs e)
        {
            CreatQueryString();
            StartQueryBySQL(QueryString);
        }

        private void SpatialQueryButton_Click(object sender, RoutedEventArgs e)
        {
            ExpressionTextBox.Text = "";
            myDraw.DrawMode = DrawMode.Polygon;
            myDraw.IsEnabled = true;
        }

        private void FiledsCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox comb = sender as ComboBox;
            if (comb.SelectedIndex != -1)
            {
                int index = comb.SelectedIndex;
                ExpressionTextBox.Text = string.Format("{0}{1}", ExpressionTextBox.Text, comb.SelectedItem.ToString());
            }
            comb.SelectedIndex = -1;
        }

        private void ExpressionTextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            // 按了回車鍵就向服務端發送數據
            if (e.Key == Key.Enter)
            {
                CreatQueryString();
                StartQueryBySQL(QueryString);
            }
        }

        private void QoutButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            ExpressionTextBox.Text = string.Format("{0}{1}", ExpressionTextBox.Text, button.Content);
        }

        private void NoButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            ExpressionTextBox.Text = string.Format("{0} {1}", ExpressionTextBox.Text, button.Content);
        }

        private void ClearGraphicsButton_Click(object sender, RoutedEventArgs e)
        {
            graphicsLayer.Graphics.Clear();
        }

        private void GraphicsLayer_MouseLeftButtonDown(object sender, GraphicMouseButtonEventArgs e)
        {
            if (selectedGraphic != null)
            {
                selectedGraphic.UnSelect();
                selectedGraphic.Symbol = new SimpleFillSymbol()
                {
                    BorderBrush = new SolidColorBrush(Colors.Red),
                    BorderThickness = 2,
                    Fill = new SolidColorBrush(Colors.Green)
                };
            }

            e.Graphic.Select();
            e.Graphic.Symbol = new SimpleFillSymbol()
            {
                Fill=new SolidColorBrush(Colors.Red),
                BorderBrush = new SolidColorBrush(Colors.Yellow),
                BorderThickness=3
            };
            if (e.Graphic.Selected&&MyDataGrid.GraphicsLayer!=null)
                MyDataGrid.ScrollIntoView(e.Graphic, null);
            selectedGraphic = e.Graphic;
        }

        #region 查詢失敗幾完成事件
        private void queryTask_ExecuteCompleted(object sender, QueryEventArgs e)
        {

            graphicsLayer.ClearGraphics();

            if (e.FeatureSet.Features.Count > 0)
            {
                foreach (Graphic resultFeature in e.FeatureSet.Features)
                {
                    if (drawGeometry != null)
                    {
                        //查詢結果落在繪制的多邊形之內
                        if (resultFeature.Geometry.Extent.XMax < drawGeometry.Extent.XMax &&
                           resultFeature.Geometry.Extent.XMin > drawGeometry.Extent.XMin &&
                           resultFeature.Geometry.Extent.YMax < drawGeometry.Extent.YMax &&
                           resultFeature.Geometry.Extent.YMin > drawGeometry.Extent.YMin)
                        {
                            resultFeature.Symbol = new SimpleFillSymbol()
                            {
                                BorderBrush = new SolidColorBrush(Colors.Red),
                                BorderThickness = 2,
                                Fill = new SolidColorBrush(Colors.Green)
                            };
                            featureSet.Features.Add(resultFeature);
                            graphicsLayer.Graphics.Add(resultFeature);
                        }
                    }
                    else
                    {
                        resultFeature.Symbol = new SimpleFillSymbol()
                        {
                            BorderBrush = new SolidColorBrush(Colors.Red),
                            BorderThickness = 2,
                            Fill = new SolidColorBrush(Colors.Green)
                        };
                        featureSet.Features.Add(resultFeature);
                        graphicsLayer.Graphics.Add(resultFeature);
                    }
                }
                if (graphicsLayer.Graphics.Count < 1)
                    MessageBox.Show("沒有查詢到目標要素!");
            }
            else
            {
                MessageBox.Show("沒有查詢到目標要素!");
            }
            drawGeometry = null;
        }

        private void queryTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("Query failed: " + e.Error);
        }

        #endregion

        #region 查詢自定義方法
        /// <summary>
        /// 條件查詢
        /// </summary>
        /// <param name="sqlString">查詢SQL語句</param>
        private void StartQueryBySQL(string sqlString)
        {
            queryTask.CancelAsync();
            if (ExpressionTextBox.Text == "")
                return;
            Query query = new Query();
            query.ReturnGeometry = true;
            query.OutFields.AddRange(new string[] { "NAME99", "ADCODE99" });
            query.Where = sqlString;
            query.OutSpatialReference = map1.SpatialReference;
            queryTask.ExecuteAsync(query);
        }
        /// <summary>
        /// 空間查詢
        /// </summary>
        /// <param name="geometry">幾何圖形</param>
        private void StartQueryBySpatial(ESRI.ArcGIS.Client.Geometry.Geometry geometry)
        {
            queryTask.CancelAsync();
            Query query = new Query();
            query.ReturnGeometry = true;
            query.OutFields.AddRange(new string[] { "NAME99", "ADCODE99" });
            query.Geometry = geometry;
            query.SpatialRelationship = SpatialRelationship.esriSpatialRelContains;
            query.OutSpatialReference = map1.SpatialReference;
            queryTask.ExecuteAsync(query);
        }

        /// <summary>
        /// 構造查詢Where條件的SQL語句
        /// </summary>
        private void CreatQueryString()
        {
            if (QueryTypeCombox.SelectedIndex == 0)
                QueryString =string.Format("NAME99 = '{0}'",ExpressionTextBox.Text);
            else if (QueryTypeCombox.SelectedIndex == 1)
                QueryString = string.Format("ADCODE99 = '{0}'",ExpressionTextBox.Text);
            else
                return;
        }
        #endregion

        # region 調用GP服務進行柵格像元統計
        private void StatisticButton_Click(object sender, RoutedEventArgs e)
        {
            if (featureSet.Features.Count <= 0)
                return;
            BusyRectangle.Visibility = Visibility.Visible;
            busyIndicator.IsBusy = true;
            AccessGPService(featureSet);
        }

        private void AccessGPService(FeatureSet featureset)
        {
            List<GPParameter> gppara = new List<GPParameter>();
            //輸入GP服務的參數
            gppara.Add(new GPString("ZoneFiled", "OBJECTID"));
            gppara.Add(new GPFeatureRecordSetLayer("InputFeature", featureset));
            gppara.Add(new GPString("ZonalRaster", "hunandata"));
            _geoprocessor.SubmitJobAsync(gppara);
        }

        private void _geoprocessor_JobCompleted(object sender, JobInfoEventArgs e)
        {
            HttpWebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
            Geoprocessor gp = sender as Geoprocessor;
            //請求GP服務的結果
            gp.GetResultDataAsync(e.JobInfo.JobId, "ResultTable");
        }

        private void _geoprocessor_GetResultDataCompleted(object sender, GPParameterEventArgs e)
        {
            MyDataGrid.ItemsSource = null;
            GPRecordSet gpr = e.Parameter as GPRecordSet;
            if (gpr.FeatureSet != null)
            {
                for (int i = 0; i < gpr.FeatureSet.Features.Count; i++)
                {
                    for (int j = 2; j < gpr.FeatureSet.Features[i].Attributes.Count; j++)
                    {
                        //這里本文有個Bug,就是當FeatureDataGrid綁定到GraphicsLayer后,
                        //如果修改GrapicsLayer的屬性(增加或者刪除)會報錯,以下代碼不能通過,所以這里選擇了先修改再綁定
                        List<string> keyList = gpr.FeatureSet.Features[i].Attributes.Keys.ToList<string>();
                        List<object> valueList = gpr.FeatureSet.Features[i].Attributes.Values.ToList();
                        graphicsLayer.Graphics[i].Attributes.Add(keyList[j], valueList[j]);
                    } 
                }
                //在此綁定DataGrid,不然會出現異常
                MyDataGrid.GraphicsLayer = graphicsLayer;
                MyDataGrid.Visibility = Visibility.Visible;
                //繪制地形圖
                if (createPlot == true)
                {
                    CreatePlot();
                    TerrainBorder.Visibility = Visibility.Visible;
                }
                featureSet.Features.Clear();
            }
            //等待過程
            BusyRectangle.Visibility = Visibility.Collapsed;
            busyIndicator.IsBusy = false;
        }

        private void _geoprocessor_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show(e.Error.ToString());
        }

     
        #endregion

        private void terrainButton_Click(object sender, RoutedEventArgs e)
        {
            myDraw.DrawMode = DrawMode.Polyline;
            TerrainBorder.Visibility = Visibility.Collapsed;   
            myDraw.IsEnabled = true;
            createPlot = true;
        }

        private void CreatPoint(ESRI.ArcGIS.Client.Geometry.Polyline polyline,int count)
        {
            //默認沿直線構造一百個點
            double xStep = (polyline.Paths[0][1].X - polyline.Paths[0][0].X) / count;
            double yStep = (polyline.Paths[0][1].Y - polyline.Paths[0][0].Y) / count;
            interval = Math.Sqrt(xStep * xStep + yStep * yStep);
            //清空FeatureSet便於之后的GP服務調用
            if (featureSet.Features.Count > 0)
            {
                featureSet.Features.Clear();
            }
            for (int i = 0; i < count; i++)
            {
                MapPoint mp = new MapPoint(polyline.Paths[0][0].X + i*xStep, polyline.Paths[0][0].Y + i*yStep);
                mp.SpatialReference = map1.SpatialReference;
                Graphic gPoint = new Graphic()
                {
                    Symbol = new SimpleMarkerSymbol()
                    {
                        Color=new SolidColorBrush(Colors.Blue),
                        Size=8,
                        Style=SimpleMarkerSymbol.SimpleMarkerStyle.Circle
                    },
                    Geometry=mp,
                };
                featureSet.Features.Add(gPoint);
                graphicsLayer.Graphics.Add(gPoint);
            }
        }

        private void CreatePlot()
        {
            areaSeries1.Points.Clear();
            areaSeries1.Points2.Clear();
            plotModel.Series.Clear();

            for (int i = 0; i < graphicsLayer.Graphics.Count; i++)
            {
                areaSeries1.Points.Add(new DataPoint(interval * i, Convert.ToDouble(graphicsLayer.Graphics[i].Attributes["MAX"])));
                areaSeries1.Points2.Add(new DataPoint(interval * i, 0));
            }
            plotModel.Series.Add(areaSeries1);
            areaSeries1.Title = "海拔";
            Myplot.Model = plotModel;
            createPlot = false;
        }

        private void Button_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            // TODO: Add event handler implementation here.
            BusyButton.Content = "取消";
        }

        private void Button_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            // TODO: Add event handler implementation here.
            BusyButton.Content = "正在計算...";
        }

        private void BusyButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            // TODO: Add event handler implementation here.
            BusyRectangle.Visibility = Visibility.Collapsed;
            busyIndicator.IsBusy = false;
        }
    }
}

最后的MainPage.xaml代碼:

View Code
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:oxy="clr-namespace:OxyPlot.Silverlight;assembly=OxyPlot.Silverlight" 
    xmlns:esri="http://schemas.esri.com/arcgis/client/2009" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" x:Class="QueryAndStatisticDemo.MainPage"
    mc:Ignorable="d"
    d:DesignHeight="760" d:DesignWidth="960" 
    >

    <Grid x:Name="LayoutRoot">
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF65C0A5" Offset="0"/>
                <GradientStop Color="#FF1E1E1F" Offset="1"/>
                <GradientStop Color="#FF22555C" Offset="0.428"/>
                <GradientStop Color="#FF596EA1" Offset="0.681"/>
            </LinearGradientBrush>
        </Grid.Background>
        <Grid.RowDefinitions>
            <RowDefinition Height="120"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <!--Map-->
        <esri:Map x:Name="map1" WrapAround="True" VerticalContentAlignment="Stretch" Grid.RowSpan="2" Margin="0">
            <esri:Map.Layers>
                <esri:LayerCollection>
                    <esri:ArcGISDynamicMapServiceLayer Url="http://qzj-pc:6080/arcgis/rest/services/Provinces_Map/HunanMap/MapServer" />
                    <esri:GraphicsLayer ID="QueryResultLayer" Opacity="0.8" MouseLeftButtonDown="GraphicsLayer_MouseLeftButtonDown"/>
                </esri:LayerCollection>
            </esri:Map.Layers>
        </esri:Map>
      
        <!--QueryBorder-->
        <Border BorderBrush="Black" BorderThickness="1" Margin="8" CornerRadius="5" Background="#7F94BCE0">
            <Grid>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,10,0">
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                            <Button x:Name="MorethanButton1" Content="1" Height="23" Width="48" Click="ExpressionButton_Click" />
                            <Button x:Name="LessthanButton2" Content="2" HorizontalAlignment="Left" Height="23" Width="48" Click="ExpressionButton_Click" />
                            <Button x:Name="EqualButton1" Content="3" Height="23" Width="43" Click="ExpressionButton_Click" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                            <Button x:Name="MoreOrEButton1" Content="4" HorizontalAlignment="Left" Height="23" Width="48" Click="ExpressionButton_Click" />
                            <Button x:Name="LessOrEqualButton1" Content="5" HorizontalAlignment="Left" Height="23" Width="48" Click="ExpressionButton_Click" />
                            <Button x:Name="LessAndMoreButton1" Content="6" Height="23" Width="43" HorizontalAlignment="Left" Click="ExpressionButton_Click" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                            <Button x:Name="LikeButton1" Content="7" HorizontalAlignment="Left" Height="23" Width="48" Click="ExpressionButton_Click" />
                            <Button x:Name="AndButton1" Content="8" HorizontalAlignment="Left" Height="23" Width="48" Click="ExpressionButton_Click" />
                            <Button x:Name="OrButton1" Content="9" Height="23" Width="43" Click="ExpressionButton_Click" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                            <Button x:Name="NotButton1" Content="0" HorizontalAlignment="Left" Height="23" Width="48" Click="ExpressionButton_Click" />
                            <Button x:Name="QoutButton" Content="'" HorizontalAlignment="Left" Height="23" Width="48" ToolTipService.ToolTip="單引號" Click="QoutButton_Click" />
                            <Button x:Name="NoButton" Content="!" Height="23" Width="43" ToolTipService.ToolTip="非運算" Click="NoButton_Click" />
                        </StackPanel>
                    </StackPanel>
                    <StackPanel VerticalAlignment="Top" HorizontalAlignment="Center" Margin="0">
                        <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <TextBlock  TextWrapping="Wrap" Text="查詢條件:" Height="18" Margin="20,0,0,0" FontSize="14" FontWeight="Bold" Foreground="Red"/>
                            <ComboBox x:Name="QueryTypeCombox" Height="23" Width="130" SelectedIndex="0" Margin="0,0,10,0"/>
                            <TextBox x:Name="ExpressionTextBox" TextWrapping="Wrap" Height="27" Margin="0,5,0,0" Width="150" KeyDown="ExpressionTextBox_KeyDown"/>
                        </StackPanel>
                            <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                            <Button x:Name="ExpressionQueryButton" Content="條件查詢" Height="30" Width="70" Margin="20,0,0,0" Click="ExpressionQueryButton_Click"/>
                            <Button x:Name="SpatialQueryButton" Content="空間查詢" Height="30" Width="70" Click="SpatialQueryButton_Click" Margin="10,0,0,0" />
                            <Button Content="繪制地形圖" Height="30" x:Name="terrainButton" Width="75" Margin="20,0,0,0" Click="terrainButton_Click"/>
                        </StackPanel>
                    </StackPanel>
                    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20,0,20,0">
                        <Button Width="135" Height="23" x:Name="StatisticButton" Content="地形統計" Margin="0,5,0,0" Click="StatisticButton_Click" />
                        <Button x:Name="ClearExpressionButton" Content="清空查詢語句" Height="23" Width="135" Click="SpatialQueryButton_Click"  Margin="0,10,0,0" />
                        <Button Width="135" Height="23" x:Name="ClearGraphicsButton" Content="清空圖層" Margin="0,10,0,0" Click="ClearGraphicsButton_Click" />
                      </StackPanel>
                </StackPanel>
            </Grid>
        </Border>
   
        <!--StatisticResultForm-->
        <esri:FeatureDataGrid x:Name="MyDataGrid" HorizontalAlignment="Right" Margin="0,0,20,20" VerticalAlignment="Bottom" 
                              Map="{Binding ElementName=map1}"
                              Width="400" Height="200"
                              Grid.Column="0" Grid.Row="1"  SelectionMode="Single" VerticalGridLinesBrush="#FF31D8D8" HorizontalGridLinesBrush="#FF31B1B1" RowBackground="#AA3C8A99" Visibility="Collapsed" >
            <esri:FeatureDataGrid.Effect>
                <DropShadowEffect/>
            </esri:FeatureDataGrid.Effect>
            <esri:FeatureDataGrid.Background>
                <LinearGradientBrush EndPoint="0.894,0.85" StartPoint="-0.076,-0.033">
                    <GradientStop Color="#FF56585E"/>
                    <GradientStop Color="#FF1B8D85" Offset="1"/>
                </LinearGradientBrush>
            </esri:FeatureDataGrid.Background>
        </esri:FeatureDataGrid>

        <Border BorderThickness="1" Grid.Row="1" Height="260" HorizontalAlignment="Left" Margin="20" x:Name="TerrainBorder" VerticalAlignment="Bottom" Width="400" CornerRadius="10" Visibility="Collapsed">
            <Border.Effect>
                <DropShadowEffect/>
            </Border.Effect>
            <oxy:Plot x:Name="Myplot" Foreground="#FFE9E5E5" >
                <oxy:Plot.Effect>
                    <DropShadowEffect/>
                </oxy:Plot.Effect>
                <oxy:Plot.Background>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF0F4549" Offset="0"/>
                        <GradientStop Color="#B266AABA" Offset="1"/>
                        <GradientStop Color="#DA8F9EA1" Offset="0.471"/>
                    </LinearGradientBrush>
                </oxy:Plot.Background>
            </oxy:Plot>
        </Border>
        <Rectangle x:Name="BusyRectangle" Fill="#FF454552" Stroke="Black" Grid.RowSpan="2" Opacity="0.5" Visibility="Collapsed"/>
        <toolkit:BusyIndicator x:Name="busyIndicator" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" IsBusy="False">
            <toolkit:BusyIndicator.BusyContent>
                <Grid>
                    <Button x:Name="BusyButton" Height="23" Width="199" Content="正在計算..." MouseEnter="Button_MouseEnter" MouseLeave="Button_MouseLeave" Padding="3" Click="BusyButton_Click"/>
                </Grid>
            </toolkit:BusyIndicator.BusyContent>
        </toolkit:BusyIndicator>
    </Grid>
</UserControl>

最終的效果:

按縣區名稱查詢雙峰縣,結果如下圖所示:

正在統計雙峰縣的像元信息

統計結果如下圖所示:

 

繪制一條直線

通過直線得到構造點,並進行像元統計

 

最后的統計結果,及地下剖面圖,根據直線經過的地方來看,地形圖是正確的。

 

在圖上可以查看剖面圖的數據:

空間查詢,並進行統計

 

總結:以上的過程大致上說了一下Web端區域像元統計的過程,其中涉及到了要素查詢,GP服務,Web端柵格數據作為輸入數據的處理問題,OxyPlot圖表控件的使用,FeatureDataGrid的數據綁定等,有些內容進行了詳細的說明,有些由於時間限制就沒有進行細致的說明,在此還望諒解。有什么問題可以留言反映,我一定都會逐一回復。當然程序中還有很多Bug,也沒有處理,程序的結構也不是很好,代碼質量也不高,希望高手勿噴,歡迎您提出寶貴的意見和分享您的解決方法。

還有需要提醒一點的是本文使用的服務都是我自己發布的服務,所以您需要自己發布程序中用到的服務。

 【源碼下載


免責聲明!

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



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