ArcGIS API for Windows Phone开发实例(5):对超市信息进行空间查询

  本文内容:ArcGIS API中Task的概念,QueryTask的使用,以及Draw对象。
  空间查询GIS中一个非常常用的功能:在地图上画出任意多边形,从自己感兴趣的事物中筛选出与所画多边形有指定空间关系(通常是相交)的要素来,进一步查看。在本次开发实例中,第二个功能就是空间查询。用手势在地图上画一个范围,筛选出落入该范围的超市店面,从而进一步查看它们的营业额统计信息。
  ArcGIS API中,给我们提供了许多Task类,来完成一些常见的GIS功能,比如属性/控件查询,几何对象的拓扑处理,特定工作流的地理任务等。它们都是已经封装好的Task类,使用起来都遵循3个步骤的原则:1、为某个Task设置所需的相应参数;2、通过Task对象向服务器发送处理请求;3、接受服务器端返回的结果。所有的计算和处理工作都是由ArcGIS Server发布的REST服务来完成,是典型的客户端请求,服务器端相应的流程。
  QueryTask是ArcGIS API提供的诸多Task之一,它接受Query类型的参数。该参数有几个常用的属性,比如Where属性和Geometry属性,通过对这两个属性的设置,我们就可以完成最常见的属性查询和空间查询功能。依然将空间查询这个功能封装成一个工具,在主界面中进行调用。

clip_image002

  这里为了清晰起见,我省去与空间查询功能无关的代码(所有程序代码会在教程完结后提供下载)。要使用QueryTask的功能,我们按照前面说三个步骤来做。首先设置好查询参数Query,然后通过QueryTask对象提交查询请求:

   1: void _draw_DrawComplete(object sender, DrawEventArgs e)

   2:         {

   3:             Polygon polygon = null;

   4:             if (_usingFreeHand) //geometry is freehand polyline

   5:             {

   6:                 Polyline polyline = e.Geometry as Polyline;

   7:                 ESRI.ArcGIS.Client.Geometry.PointCollection pc = polyline.Paths[0];

   8:                 pc.Add(pc[0]);

   9:                 polygon = new Polygon()

  10:                 {

  11:                     SpatialReference = map1.SpatialReference,

  12:                 };

  13:                 polygon.Rings.Add(pc);

  14:             }

  15:             else //geometry is polygon

  16:             {

  17:                 polygon = e.Geometry as Polygon;

  18:             }

  19:  

  20:             _GLayer.Graphics.Clear();

  21:             Graphic g = new Graphic()

  22:             {

  23:                 Geometry = polygon,

  24:                 Symbol = new SimpleFillSymbol()

  25:                 {

  26:                     Fill=new SolidColorBrush(Color.FromArgb(33,255,0,0)),

  27:                     BorderBrush=new SolidColorBrush(Colors.Red),

  28:                     BorderThickness=2

  29:                 }

  30:             };

  31:             _GLayer.Graphics.Add(g); //display the geometry created by Draw object

  32:  

  33:             QueryTask queryTask = new QueryTask(App.Current.Resources["BusinessLayer"] as string);

  34:             Query query = new Query();

  35:             //102100 to 4326

  36:             ESRI.ArcGIS.Client.Projection.WebMercator wm = new ESRI.ArcGIS.Client.Projection.WebMercator();

  37:             query.Geometry = wm.ToGeographic(polygon);

  38:             query.OutFields.AddRange(new string[] { "*" });//return all attributes fields

  39:             query.SpatialRelationship = SpatialRelationship.esriSpatialRelIntersects;

  40:             queryTask.ExecuteCompleted += new System.EventHandler<QueryEventArgs>(queryTask_ExecuteCompleted);

  41:             queryTask.Failed += (s, a) =>

  42:             {

  43:                 MessageBox.Show("查询失败" + a.Error.Message);

  44:             };

  45:             _busyIndicator.Visibility = Visibility.Visible;

  46:             queryTask.ExecuteAsync(query);     

  47:         }

  代码中,我们首先利用超市图层的服务地址,初始化了一个QueryTask对象。对于Query参数,这里设置了Geometry属性,作为空间查询的图形;对OutFields参数的设置表示在查询结果中返回所有属性字段;指定空间关系为与Geometry相交。然后通过ExecuteAsync方法将查询请求提交到服务器端。注意到在设置Query的Geometry属性之前,我们对Polygon对象做了空间参考的转换,将其从102100坐标系(WGS 1984 Web Mercator Auxiliary Sphere,这是地图控件的坐标系)转换到了4326坐标系(WGS 1984,这是超市图层的坐标系),如果Query中Geometry的坐标系不正确,查询结果往往会不可预料。
  发出请求后,我们就可以在设置好的queryTask_ExecuteCompleted方法中取得查询结果了。

   1: void queryTask_ExecuteCompleted(object sender, QueryEventArgs e)

   2:         {

   3:             _busyIndicator.Visibility = Visibility.Collapsed;

   4:             if (e.FeatureSet.Features.Count == 0) //typeof(e.FeatureSet.Features)==GraphicCollection

   5:             {

   6:                 MessageBox.Show("未选中任何店面");

   7:             }

   8:             else

   9:             {

  10:                 string str = "是否查看图表详情?";

  11:                 if (MessageBox.Show(str,

  12:                 "查询结果", MessageBoxButton.OKCancel) == MessageBoxResult.OK)

  13:                 {

  14:                     //add selected graphics to app level, so spatialquerychart.xaml could retrieve them

  15:                     App app = Application.Current as App;

  16:                     if (app.AppParameters.ContainsKey("QueryedGraphics"))

  17:                         app.AppParameters["QueryedGraphics"] = e.FeatureSet.Features;

  18:                     else

  19:                         app.AppParameters.Add("QueryedGraphics", e.FeatureSet.Features);

  20:  

  21:                     (app.AppParameters["MainPage"] as PhoneApplicationPage).NavigationService.Navigate(new Uri("/Tools/SpatialQueryChart.xaml", UriKind.Relative));

  22:                 }

  23:                 _GLayer.ClearGraphics();

  24:             }

  25:         }

  可以看到,查询结果(落入所选范围内的超市)以Graphic的形式存储在事件参数中。Graphic的Geometry就是超市的图形信息,而Attributes属性中是我们想要的所有营业信息。如果查询结果不为空,我们将其存入全局变量中,以便在另一个页面中用图表的形式来显示。这里我们使用VisiFire控件来显示图表,它是一套可用于WP上的Silverlight插件,此处不进行过多讨论,有兴趣同学可自己搜索。
  整个查询的过程在QueryTask的帮助下变得非常简单。细心的朋友可能会有疑问,我们这个空间查询的图形是如何得到的?在前面的代码中可以看到,发起查询请求的代码是写在_draw_DrawComplete这个事件中的。_draw是我们提前定义好的一个Draw对象:private Draw _draw;。
  为了方便与用户的交互,ArcGIS API中提供了Draw这个类,可以利用鼠标或手势来交互地画出Point,Polyline,Polygon,Freehand(Polyline)等几何对象,在2.2版本的API中,Draw还新增了arrow,triangle,circle,ellipses几个原生图形。

clip_image002

  使用Draw这个对象也比较简单,初始化,设定好要画的几何图形类型,然后将其IsEnabled属性设为True,就进入了交互状态,绘制完毕后,就会触发DrawComplete事件,在事件的参数中就可以得到画出的Geometry结果,得到结果之后,就可以利用Graphic将这个看不见摸不着的Geometry显示出来了,这样就达到了交互的目的。我们空间查询的几何对象就是利用Draw得到的。

clip_image004

clip_image006

参考资料:

ArcGIS API中各种Task介绍:
http://bbs.esrichina-bj.cn/ESRI/thread-45302-1-1.html

Draw对象的使用:
http://help.arcgis.com/en/arcgismobile/10.0/apis/WindowsPhone/help/011v/011v00000019000000.htm

QueryTask的使用:
http://help.arcgis.com/en/arcgismobile/10.0/apis/WindowsPhone/help/011v/011v00000016000000.htm

VisiFire:
http://www.visifire.com/

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>