Castelo 发表于 2013-4-6 23:17:30

SILVERLIGHT,前端

技术贴果然是没有人看啊。。。。。。上一个发的技术贴也是寥寥零落。
或许这个前端口味不好。以后或许应该走后端路线或者开源框架路线。


之前说了flex,也顺便说说silverlight,这种前端的东西。silverlight跨平台,微软家,但是ios没有支持的意愿。

转发个,感受下silverlight的强大。之前有见过朋友用它搭过项目,真是长得不错。用起来很是方便,GIS系统我也愿意用他 而非flex。

Silverlight客户端实现区域像元统计以及地形剖面图的绘制一、本文实现的功能1.1 要素查询功能根据要素属性,查询出相应的要素1.2 栅格数据的像元统计例如输入一个几何图形(点,线,面)可以计算出该图像范围内栅格数据的像元信息,如:像元最大值,最小值,以及平均值等,具体如下图所示:                         http://images.cnitblog.com/blog/357342/201303/01105954-f0376234dc8b48e6af223adf55e7ed29.png 1.3 绘制地形剖面图 该功能和官网的这个例子差不多:http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#SurfaceProfile(不知道为什么,我这里查看不了这里例子)效果如下图所示:http://images.cnitblog.com/blog/357342/201303/01111208-31be34082dd945d5afce2deac727572e.png二、使用到的数据和知识2.1地图数据      本例的地形高程数据来自于国际科学数据服务平台,下载网址:http://datamirror.csdb.cn/index.jsp      本例的各区县要素数据来自于国家基础地理信息中心,下载网址:http://nfgis.nsdi.gov.cn/nfgis/chinese/c_xz.htm上面的地图是我自己在ArcMap中制作的一张地图,外加了一点地形阴影效果,这是在ArcMap中的图层列表 http://images.cnitblog.com/blog/357342/201303/01111231-a01a495ec19b4153805e8815bd74f08f.png各县面要素图层       http://images.cnitblog.com/blog/357342/201303/01111239-710d43cc789c49178ecfc9a811555438.png 最后通过以上数据得到了本文使用的底图。在查询部分中,实际上查询的就是各区县的面要素,可通过输入曲线的民称或编号来查询出相对应的县,然后再通过调研像元统计的GP服务工具,即可实现像元统计,得到对应区县范围内像元的最大值,最小值等信息,实际上这里的值也就是对应区县的海拔(准确度由下载的高程数据所决定),最后的地图:http://images.cnitblog.com/blog/357342/201303/01111333-eee6379762634929b0fc5e77efe54651.png2.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.html3.2 根据查询得到的面要素,计算出面要素对应区域内的像元信息。3.2.1发布像元统计的GP服务这里主要用到的就是GP服务。下面是本文的GP服务模型: http://images.cnitblog.com/blog/357342/201303/01111407-275cad049df542a2b3acc33037f8e81e.png其中ZoneFiled就是统计字段,InputFeature为输入的要素,ZonalRaster为统计的删格数据
提醒:在10.1中可以将栅格数据作为输入参数。在10.0中不可以,如果您是10.0版本的,那么这里你只能在建模的时候指定栅格数据,然后去掉设置为模型参数。在10.1中如果你有可数的几个不同栅格数据,那么你可以将其添加到ArcMap中,在发布GP服务的时候,会提示你从列表选择还是自定义栅格数据,这个时候你可以选择从列表选择。然后你可以将ArcMap中的删格数据图层添加到选择列表中,最后在Web端调用的时候,你只需要输入栅格数据列表中对于栅格数据的名称即可,例如本文的列表如下: http://images.cnitblog.com/blog/357342/201303/01111418-6393e8a7c1f64dfcaad9a0e5da745e83.png这里可以看出只有一个栅格数据选项:hunandata。3.2.2   Web端调用GP服务调用GP服务的过程之前的博文也有讲到,可参考这里:http://www.cnblogs.com/potential/archive/2012/11/03/2752289.html下面是本文的调用代码:http://common.cnblogs.com/images/copycode.gif
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.Attributes.Count; j++)                  {                        //这里本文有个Bug,就是当FeatureDataGrid绑定到GraphicsLayer后,                        //如果修改GrapicsLayer的属性(增加或者删除)会报错,以下代码不能通过,所以这里选择了先修改再绑定                        List<string> keyList = gpr.FeatureSet.Features.Attributes.Keys.ToList<string>();                        List<object> valueList = gpr.FeatureSet.Features.Attributes.Values.ToList();                        graphicsLayer.Graphics.Attributes.Add(keyList, valueList);                  }               }                //在此绑定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());      }http://common.cnblogs.com/images/copycode.gif

以上是调用GP服务的代码,这里有个Bug。
最后的统计结果如下所示: http://images.cnitblog.com/blog/357342/201303/01130115-626e3beb770345188fdee4aec2d5abea.png3.2.3 Web客户端绘制地形图 这里借助的是开源的图表控件:OxyPlot。感觉绘制图表很强大,而且开源啊。绘制地形剖面图的功能大致上的过程如下:首先在地图上绘制一条线,然后等分这条线,例如一百份,然后得到这一百个点的像元统计值(最后的值就是海拔值,这里数据的准确度和提供的高程数据经度有关,高程数据经度越高,结果也就越准确),得到一百个点的高程数据之后,就通过OxyPlot绘图了。具体代码:a.OxyPlot绘图声明一个PlotModel,PlotModel代表绘制图表的类型。PlotModel plotModel = null;
在构造函数中初始化:http://common.cnblogs.com/images/copycode.gif
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,            };http://common.cnblogs.com/images/copycode.gif

b.然后绘制一条直线并构造点:http://common.cnblogs.com/images/copycode.gif
    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);            }      }http://common.cnblogs.com/images/copycode.gif

c.调用GP服务统计像元值(代码如上)d.根据统计值绘制图表,这里Graphic的MAX属性表示的即为最高海拔,对于点要素MAX和MIN值是一样的。http://common.cnblogs.com/images/copycode.gif
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.Attributes["MAX"])));                areaSeries1.Points2.Add(new DataPoint(interval * i, 0));            }            plotModel.Series.Add(areaSeries1);            areaSeries1.Title = "海拔";            Myplot.Model = plotModel;            createPlot = false;      }http://common.cnblogs.com/images/copycode.gif

最后的MainPage.cs代码:http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifView Code
最后的MainPage.xaml代码:http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifView Code
最终的效果:按县区名称查询双峰县,结果如下图所示:
http://images.cnitblog.com/blog/357342/201303/01123336-6ac524d776f24bcaa3614078ae8f939d.png正在统计双峰县的像元信息http://images.cnitblog.com/blog/357342/201303/01123353-e62ac69a301b4b0b8e5096140e890393.png统计结果如下图所示: http://images.cnitblog.com/blog/357342/201303/01123410-a94a74089bf14b45887f39f2dea9f6a6.png绘制一条直线http://images.cnitblog.com/blog/357342/201303/01123428-834cb3631a484b5bb70a3e792cb0c482.png通过直线得到构造点,并进行像元统计 http://images.cnitblog.com/blog/357342/201303/01123452-ed93d4b559df44b4b978e492f6ff4c79.png最后的统计结果,及地下剖面图,根据直线经过的地方来看,地形图是正确的。 http://images.cnitblog.com/blog/357342/201303/01123506-6102e8f0794f4359bc931e222288b3e2.png在图上可以查看剖面图的数据:http://images.cnitblog.com/blog/357342/201303/01132026-8d0e4d04829a40c5805f067cf50d7efe.png空间查询,并进行统计http://images.cnitblog.com/blog/357342/201303/01123524-4a72b292d84746658408b3d31b0ac7bb.png
总结:以上的过程大致上说了一下Web端区域像元统计的过程,其中涉及到了要素查询,GP服务,Web端栅格数据作为输入数据的处理问题,OxyPlot图表控件的使用,FeatureDataGrid的数据绑定等,有些内容进行了详细的说明,有些由于时间限制就没有进行细致的说明,在此还望谅解。有什么问题可以留言反映,我一定都会逐一回复。当然程序中还有很多Bug,也没有处理,程序的结构也不是很好,代码质量也不高,希望高手勿喷,欢迎您提出宝贵的意见和分享您的解决方法。



Castelo 发表于 2013-4-6 23:18:20

我为咩要发技术贴,我就应该去灌水,灌水,罐。{:5_156:}

阎魔あい 发表于 2013-4-6 23:33:13

不是不看。。。。。。真心看不懂啊。。。。。。

coolsmilee 发表于 2013-4-7 09:21:15

赞技术贴,有营养,但是好难消化吸收..另外代码应该有插件可用..看上去好纠结..

独慕冷风 发表于 2013-4-7 11:45:54

技术贴 必须顶

独慕冷风 发表于 2013-4-7 11:46:12

阎魔あい 发表于 2013-4-6 23:33 static/image/common/back.gif
不是不看。。。。。。真心看不懂啊。。。。。。

我也不想看···

阎魔あい 发表于 2013-4-7 12:40:15

独慕冷风 发表于 2013-4-7 11:46 static/image/common/back.gif
我也不想看···

你有这个责任~~~~加油!继续受摧残与折磨吧哈哈哈!!!{:10_436:}
页: [1]
查看完整版本: SILVERLIGHT,前端