系统架构是B/S,开发语言是C#、silverlight,开发平台是.NET,数据库为sqlserver,这是我读研究生时候自己做的作品,以自己的母校为地图,进行GIS相关的功能分析,核心的模块有:空间查询、GPS定位模拟、搜索模块、统计分析;其中说的不足之处,望各位指点出来。 一、空间查询  整体思路:空间查询是用户在地图上框选一定范围,然后根据框选范围Geometry来进行query查询。框选利用Draw工具有多边形、矩形、圆线等方式。实现方式,前台界面设计: <!--Toolbar工具栏--> - <Grid x:Name="ToolbarGrid" HorizontalAlignment="Left" VerticalAlignment="Top" Width="600" Height="0" RenderTransformOrigin="0.5,0.5">
- <Grid.RenderTransform>
- <ScaleTransform x:Name="ToolbarGridScaleTransform" ScaleX="0" ScaleY="0" />
- </Grid.RenderTransform>
- <StackPanel Orientation="Vertical">
- <esriToolkit:Toolbar x:Name="MyToolbar" MaxItemHeight="40" MaxItemWidth="40"
- VerticalAlignment="Top" HorizontalAlignment="Left"
- Loaded="MyToolbar_Loaded"
- ToolbarItemClicked="MyToolbar_ToolbarItemClicked"
- ToolbarIndexChanged="MyToolbar_ToolbarIndexChanged"
- Width="600" Height="40">
- <esriToolkit:Toolbar.Items>
- <esriToolkit:ToolbarItemCollection>
- <!--Zoom in-->
- <esriToolkit:ToolbarItem Text="放大">
- <esriToolkit:ToolbarItem.Content>
- <Image Source="Images/i_zoomin.png" Stretch="UniformToFill" Margin="3" />
- </esriToolkit:ToolbarItem.Content>
- </esriToolkit:ToolbarItem>
- <!--Zoom out-->
- <esriToolkit:ToolbarItem Text="缩小">
- <esriToolkit:ToolbarItem.Content>
- <Image Source="Images/i_zoomout.png" Stretch="UniformToFill" Margin="3" />
- </esriToolkit:ToolbarItem.Content>
- </esriToolkit:ToolbarItem>
- <!--PolygonQuery-->
- <esriToolkit:ToolbarItem Text="多边形查询">
- <esriToolkit:ToolbarItem.Content>
- <Image Source="Images/DrawPolygon.png" Stretch="UniformToFill" Margin="5"/>
- </esriToolkit:ToolbarItem.Content>
- </esriToolkit:ToolbarItem>
- <!--Polyline-->
- <esriToolkit:ToolbarItem Text="线查询">
- <esriToolkit:ToolbarItem.Content>
- <Image Source="Images/DrawPolyline.png" Stretch="UniformToFill" Margin="5"/>
- </esriToolkit:ToolbarItem.Content>
- </esriToolkit:ToolbarItem>
- <!--RectangleQuery-->
- <esriToolkit:ToolbarItem Text="矩形查询">
- <esriToolkit:ToolbarItem.Content>
- <Image Source="Images/DrawRectangle.png" Stretch="UniformToFill" Margin="5"/>
- </esriToolkit:ToolbarItem.Content>
- </esriToolkit:ToolbarItem>
- </esriToolkit:ToolbarItemCollection>
- </esriToolkit:Toolbar.Items>
- </esriToolkit:Toolbar>
- <TextBlock x:Name="StatusTextBlock" FontWeight="Bold" HorizontalAlignment="Center"/>
- </StackPanel>
- </Grid>
复制代码 这里只讲空间查询部分,其他的距离量算、面积量算等具体见源代码。 后台代码实现: - public MainPageII() //构造函数初始化
- {
- //初始化MyDrawObject,draw工具
- MyDrawObject = new Draw(MyMap)
- {
- FillSymbol = DefaultFillSymbol, //初始化默认的填充颜色
- LineSymbol = DefaultLineSymbol //初始化默认的线颜色
- };
- MyDrawObject.DrawComplete += myDrawObject_DrawComplete; //draw完成触发函数,为了获取框选的范围geometry结果
- MyDrawObject.DrawBegin += myDrawObject_DrawBegin; //draw之前触发函数,设置一些画之前的动作
- }
- private void myDrawObject_DrawBegin(object sender, EventArgs args)
- {
- GraphicsLayer graphicsLayer = MyMap.Layers["MapTipGraphicsLayer"] as GraphicsLayer;//设置GraphicsLayer
- graphicsLayer.ClearGraphics();//draw之前,清空所有的graphics
- }
- ////////////////////////下面是实现工具栏的功能
- private void myDrawObject_DrawComplete(object sender, DrawEventArgs args)
- {
- if (toolMode == "Rectangle_Query")//toolMode变量来判断是哪种模式框选,此处为矩形,其他框选模式原理是一样的,这里不再写出来
- {
- GraphicsLayer graphicsLayer = MyMap.Layers["MapTipGraphicsLayer"] as GraphicsLayer;
- ESRI.ArcGIS.Client.Geometry.Envelope clickEnvelope = args.Geometry as Envelope;//获取几何范围geometry
- //先判断一下是矢量地图还是遥感地图
- if (rasterMap.IsChecked == true)
- {
- graphicsLayer.ClearGraphics();
- }
- else
- {
- graphicsLayer.ClearGraphics();
- ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic() //定义框选出来的矩形样式颜色
- {
- Geometry = clickEnvelope,
- Symbol = DefaultFillSymbol
- };
- graphicsLayer.Graphics.Add(graphic);//添加框选出来的图形显示在地图上
- }
- QueryTask queryTask = new QueryTask("http://192.168.1.4/arcgis/rest/services/SWUMap/MapServer/9");//定义QueryTask
- queryTask.ExecuteCompleted += QueryTask1_ExecuteCompleted; //query查询结果
- queryTask.Failed += QueryTask_Failed;//query查询失败
- Query query = new ESRI.ArcGIS.Client.Tasks.Query(); //定义query对象
- // Specify fields to return from query
- query.OutFields.AddRange(new string[] { "ID", "NAME", "Area", "Length", "X", "Y", "ImagePath" });//设置query条件
- //query.OutFields.Add("*");
- query.Where = "1=1";
- query.Geometry = args.Geometry;//几何条件
- query.ReturnGeometry = true;
- queryTask.ExecuteAsync(query);//执行query查询
- Binding resultFeaturesBinding = new Binding("LastResult");/query查询结果值获取,绑定在datagrid表格用
- resultFeaturesBinding.Source = queryTask;
- Find_QueryDetailsDataGrid.SetBinding(DataGrid.ItemsSourceProperty, resultFeaturesBinding);//获取的查询结果值绑定在datagrid表格
- ShowFindQueryWindow.Begin();
- }
- }
- /// <summary>
- /// 显示选择元素颜色
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="args"></param>
- private void QueryTask1_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
- {
- FeatureSet Query_featureSet = args.FeatureSet;//获取到查询结果集合
- GraphicsLayer graphicsLayer = MyMap.Layers["MapTipGraphicsLayer"] as GraphicsLayer;
- if (Query_featureSet == null || Query_featureSet.Features.Count < 1)
- {
- information.Text = "没有查询记录!";
- ShowImageRoot.Begin();
- return;
- }
- if (Query_featureSet != null && Query_featureSet.Features.Count > 0)
- {
- foreach (Graphic feature in Query_featureSet.Features)
- {
- //先判断一下是矢量地图还是遥感地图
- if (rasterMap.IsChecked == true)
- {
- feature.Symbol = LayoutRoot.Resources["RemotePicture"] as ESRI.ArcGIS.Client.Symbols.PictureMarkerSymbol;//定义符号颜色样式
- feature.Geometry = new MapPoint(Convert.ToDouble(feature.Attributes["X"]), Convert.ToDouble(feature.Attributes["Y"]));
- graphicsLayer.Graphics.Add(feature);
- RemotePictureStoryboard.Begin();
- }
- else
- {
- feature.Symbol = LayoutRoot.Resources["ParcelSymbol"] as FillSymbol;//定义符号颜色样式
- graphicsLayer.Graphics.Insert(0, feature);//查询结果的几何图形显示在地图上
- }
- }
- }
- }
复制代码二、搜索模块,主要包括路径搜索、关键字搜索、范围搜索 1、关键字搜索,就是普通的query查询,其实应该用locator地理编码服务来实现的,当时自己水平有限,没能使用。把所有兴趣的信息集合在一个图层里面,然后发布地图服务,这样用query查询方式可以达到跟locator一样的目的。 这里贴上核心后台代码好了,前台界面很简单就是一个文本框输入和按钮。 - QueryTask queryTask = new QueryTask("http://192.168.1.4/arcgis/rest/services/SWUMap/MapServer/9");//定义QueryTask
- queryTask.ExecuteCompleted += QueryTask2_ExecuteCompleted; //query查询结果
- Query query = new ESRI.ArcGIS.Client.Tasks.Query(); //定义query对象
- query.OutFields.AddRange(new string[] { "ID", "NAME", "Area", "Length", "X", "Y", "ImagePath" });//设置query条件
- query.text =****;//文本框获取的文本值
- query.ReturnGeometry = true;
- queryTask.ExecuteAsync(query);//执行query查询
复制代码很类似框选查询的query,不过是设置条件换了,geometry换为text,查询结果一样是在 queryTask.ExecuteCompleted里面获取,获取到关键字查询的结果然后定位到其地理位置显示在地图上。 2、范围搜索,这里用buffer分析方式来实现的,利用buffer获取到几何范围geometry,然后再利用query方式来实现,这里很类似空间查询部分的框选查询,不同的是获取geometry方式不太一样,一个是draw,一个是buffer。 此处是用地图单击事件获取某点,然后利用某点为中心来buffer的,贴上buffer部分代码,后果query代码跟空间查询部分是一样的。 GeometryService _geometryService; (1)初始化函数定义 _geometryService = new GeometryService("http://192.168.1.4/arcgis/rest/services/Geometry/GeometryServer");
_geometryService.BufferCompleted += GeometryService_BufferCompleted;
_geometryService.Failed += GeometryService_Failed; (2) 地图单击事件函数 - ////先判断一下,输入条件是否为空
- if (Buffertextbox.Text == "")
- { //MessageBox.Show("请您输入范围搜索条件!");
- information.Text = "请您输入范围搜索条件!";
- ShowImageRoot.Begin();
- return;
- }
- GraphicsLayer graphicsLayer = MyMap.Layers["MapTipGraphicsLayer"] as GraphicsLayer;
- graphicsLayer.ClearGraphics();
- _geometryService.CancelAsync();
- _queryTask.CancelAsync();
- Graphic stop = new Graphic();
- if (rasterMap.IsChecked == true)
- {
- stop.Symbol = RemotePicture1;
- }
- else
- {
- stop.Symbol = StopSymbol;
- }
- stop.Geometry = e.MapPoint;//获取地图点坐标
- stop.Geometry.SpatialReference = MyMap.SpatialReference;
- stop.SetZIndex(2);
- graphicsLayer.Graphics.Add(stop);
- // Use a projection appropriate for your area of interest
- ESRI.ArcGIS.Client.Tasks.BufferParameters bufferParams = new ESRI.ArcGIS.Client.Tasks.BufferParameters()
- {
- //BufferSpatialReference = new SpatialReference(4326),
- BufferSpatialReference = new SpatialReference(32648),
- OutSpatialReference = MyMap.SpatialReference,
- Unit = LinearUnit.Meter//设置地图单位
- };
- double R = Convert.ToDouble(Buffertextbox.Text);//buffer半径
- bufferParams.Distances.Add(R);
- bufferParams.Features.Add(stop);
- _geometryService.BufferAsync(bufferParams); //执行缓冲分析
复制代码 (3)获取buffer范围结果函数,然后利用geomerey来query查询 - private void GeometryService_BufferCompleted(object sender, GraphicsEventArgs args)
- {
- Graphic bufferGraphic = new Graphic();
- bufferGraphic.Geometry = args.Results[0].Geometry;//获取buffer范围geometry
- bufferGraphic.Symbol = BufferSymbol;//定义buffer符号
- bufferGraphic.SetZIndex(1);
- GraphicsLayer graphicsLayer = MyMap.Layers["GLayer"] as GraphicsLayer;
- graphicsLayer.Graphics.Add(bufferGraphic);
- ESRI.ArcGIS.Client.Tasks.Query query = new ESRI.ArcGIS.Client.Tasks.Query();
- //query.OutFields.Add("*");
- query.OutFields.AddRange(new string[] { "DW", "Shape", "ID", "Area", "Length", "NAME","X","Y","ImagePath" });
- query.ReturnGeometry = true;
- query.Where = "1=1";
- query.Geometry = bufferGraphic.Geometry;
- _queryTask.ExecuteAsync(query);
- Binding resultFeaturesBinding = new Binding("LastResult.Features");
- resultFeaturesBinding.Source = _queryTask;
- huanchongqujieguo.SetBinding(DataGrid.ItemsSourceProperty, resultFeaturesBinding);
- // BufferResultWindow.IsOpen = true;
- //huanchongqujieguo.Visibility = Visibility.Visible;
- ShowBufferResultWindow.Begin();
- }
复制代码 3、路径搜索,最短路径和最优路径,重点详细描述最短路径,最优路径是在最短的路径基础上改造的,这里篇数问题,不再讲。 (1)最短路径,界面是两个文本框和查询按钮,这里不贴了,贴上核心代码: - //下面是实现路径添加障碍点网络分析
- MapPoint MapPointRoute1, MapPointRoute2;
- RouteTask _routeTask;
- List<Graphic> _stops = new List<Graphic>();
- List<Graphic> _barriers = new List<Graphic>();
- RouteParameters _routeParams = new RouteParameters();
- /////定义Direction
- Graphic _activeSegmentGraphic;
- DirectionsFeatureSet _directionsFeatureSet;
- /// <summary>
- /// 最短路径分析初始化
- /// </summary>
- private void MyShortPathToChoice()
- {
- _routeTask = new RouteTask("http://192.168.1.4/arcgis/rest/services/SWUMap/NAServer/Route");
- _routeTask.SolveCompleted += routeTask_SolveCompleted;
- _routeTask.Failed += routeTask_Failed;
- _routeParams.Stops = _stops;
- _routeParams.Barriers = _barriers;
- _routeParams.UseTimeWindows = false;
- ////定义Direction的
- _routeParams.ReturnRoutes = true;/////
- _routeParams.ReturnDirections = true;
- _routeParams.DirectionsLengthUnits = esriUnits.esriMiles;
- }
- ///////////////执行路径分析
- if (_stops.Count > 1)
- {
- // GraphicsLayer stopsLayer = MyMap.Layers["MyStopsGraphicsLayer"] as GraphicsLayer;
- if (_routeTask.IsBusy)
- {
- _routeTask.CancelAsync();
- stopsLayer.Graphics.RemoveAt(stopsLayer.Graphics.Count - 1);
- }
- _routeTask.SolveAsync(_routeParams);
- }
- ///////路径分析结果
- private void routeTask_SolveCompleted(object sender, RouteEventArgs e)
- {
- GraphicsLayer routeLayer = MyMap.Layers["MyRouteGraphicsLayer"] as GraphicsLayer;
- if (e.RouteResults.Count() > 0 && Which_Path1 == "ShortPath")
- {
- ////先清空DirectionsStackPanel
- DirectionsStackPanel.Children.Clear();
- RouteResult routeResult = e.RouteResults[0];
- ////定义Direction
- _directionsFeatureSet = routeResult.Directions;
- routeResult.Route.Geometry = _directionsFeatureSet.MergedGeometry;
- //routeResult.Route.Symbol = RouteSymbol;
- routeResult.Route.Symbol = LayoutRoot.Resources["RouteSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol;
- routeLayer.Graphics.Clear();
- Graphic lastRoute = routeResult.Route;
- //decimal totalLength = (decimal)lastRoute.Attributes["Shape_Length"];
- decimal totalLength = (decimal)lastRoute.Attributes["Total_Length"];
- string length = string.Format("{0} Meters", totalLength.ToString("#0.000"));
- Total_Length.Text = length;
- //decimal totalTime = (decimal)lastRoute.Attributes["Total_Time"];
- string tip = string.Format("{0} minutes", (totalLength/100).ToString("#0.000"));
- Total_Time.Text = tip;
- routeLayer.Graphics.Add(lastRoute);
- ////Direction
- int i = 1;
- foreach (Graphic graphic in _directionsFeatureSet.Features)
- {
- System.Text.StringBuilder text = new System.Text.StringBuilder();
- text.AppendFormat("{0}. {1}", i, graphic.Attributes["text"]);
- if (i > 1 && i < _directionsFeatureSet.Features.Count)
- {
- string distance = (Convert.ToDouble(graphic.Attributes["length"])*1609.329).ToString();
- // string distance = graphic.Attributes["length"].ToString();
- // string distance = graphic.Attributes["length"].ToString();
- string time = null;
- if (graphic.Attributes.ContainsKey("time"))
- {
- //time = FormatTime(Convert.ToDouble(graphic.Attributes["time"]));
- time = graphic.Attributes["time"].ToString();
- }
- if (!string.IsNullOrEmpty(distance) || !string.IsNullOrEmpty(time))
- text.Append(" (");
- text.Append(distance);
- if (!string.IsNullOrEmpty(distance) && !string.IsNullOrEmpty(time))
- text.Append(", ");
- text.Append(time);
- if (!string.IsNullOrEmpty(distance) || !string.IsNullOrEmpty(time))
- text.Append(")");
- }
- TextBlock textBlock = new TextBlock() { Text = text.ToString(), Tag = graphic, Margin = new Thickness(4), Cursor = Cursors.Hand };
- textBlock.MouseLeftButtonDown += new MouseButtonEventHandler(directionsSegment_MouseLeftButtonDown);
- DirectionsStackPanel.Children.Add(textBlock);
- i++;
- }
- MyMap.ZoomTo(Expand(_directionsFeatureSet.Extent));
- }
- }
- private void directionsSegment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- TextBlock textBlock = sender as TextBlock;
- Graphic feature = textBlock.Tag as Graphic;
- MyMap.ZoomTo(Expand(feature.Geometry.Extent));
- if (_activeSegmentGraphic == null)
- {
- _activeSegmentGraphic = new Graphic() { Symbol = LayoutRoot.Resources["SegmentSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol };
- GraphicsLayer graphicsLayer = MyMap.Layers["MyRouteGraphicsLayer"] as GraphicsLayer;
- graphicsLayer.Graphics.Add(_activeSegmentGraphic);
- }
- _activeSegmentGraphic.Geometry = feature.Geometry;
- }
- private void stackPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (_directionsFeatureSet != null)
- {
- GraphicsLayer graphicsLayer = MyMap.Layers["MyRouteGraphicsLayer"] as GraphicsLayer;
- MyMap.ZoomTo(Expand(_directionsFeatureSet.Extent));1n
- }
- }
- private Envelope Expand(Envelope e)
- {
- double factor = 0.6;
- MapPoint centerMapPoint = e.GetCenter();
- return new Envelope(centerMapPoint.X - e.Width * factor, centerMapPoint.Y - e.Height * factor,
- centerMapPoint.X + e.Width * factor, centerMapPoint.Y + e.Height * factor);
- }
复制代码 三、GPS模拟定位,这里说说思路好了,具体见源代码。主要是模拟校车每个时刻的地位Point,然后再描绘出来连接成线line,最后添加再地图上显示出来。应用到arcgis api的对象point、line、graphic、geometry、graphiclayer等等。 四、统计分析,这里不描述了,具体见源代码。
GIS毕业设计&项目承接群:238339408; GIS技术交流群:432512093
|