本文内容: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属性,通过对这两个属性的设置,我们就可以完成最常见的属性查询和空间查询功能。依然将空间查询这个功能封装成一个工具,在主界面中进行调用。
这里为了清晰起见,我省去与空间查询功能无关的代码(所有程序代码会在教程完结后提供下载)。要使用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几个原生图形。
使用Draw这个对象也比较简单,初始化,设定好要画的几何图形类型,然后将其IsEnabled属性设为True,就进入了交互状态,绘制完毕后,就会触发DrawComplete事件,在事件的参数中就可以得到画出的Geometry结果,得到结果之后,就可以利用Graphic将这个看不见摸不着的Geometry显示出来了,这样就达到了交互的目的。我们空间查询的几何对象就是利用Draw得到的。
参考资料:
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/