ArcGIS Engine基础开发教程(5)--学习地图输出
ArcGIS Engine基础开发教程(5)——学习地图查询
地图查询
地图查询、统计是一个GIS系统的基本的功能模块,实际上统计功能的前提也是通过查询获取结果以文字或者图表等报表的形式展现查询结果数据。
地图查询有两种类型的查询:
1.空间查询:在地图上设置一定范围,查询这一范围内的要素。例如在地图上画一范围查询这一区域内的所有消防栓,这一范围的所有消防栓高亮显示(或者其他显示方式)并展现出所有的消防栓的属
性信息。
2.属性查询:通过一定的查询条件获取目标要素。例如我们需要查询中国行政区上人口大于5000万,同时GDP大于1万亿的省份,通过执行查询,符号条件的省份高亮显示(或者其他显示方式)并展现
出这些省份的属性信息。
ArcGIS Engine9.3为开发者提供了无需写代码即可进行查询功能的Identify工具,但是这个工具是一个通用的信息查询新工具。而开发者通常需要自己开发一套符合自己业务需求更加灵活的查询功能模块,甚至一些功能不仅仅是查询信息,很多编辑编辑功能以及和业务相结合的功能开发都用到查询功能。所以很有必要了解ArcGIS Engine的查询机制。
5.1目标
1.熟悉Cursor,FeatureCursor对象,使用IFeatureCursor接口2.熟悉QueryFilter, SpatialFilter对象使用IQueryFilter,ISpatialFilter接口
3.熟悉要素选择集SelectionSet对象,会使用IFeatureSelection,ISelectionSet接口
4.开发一个属性查询小功能Demo, 获取符号查询条件的Feature,并IFeatureLayerDefinition接
口创建一个新的要素图层加载到Mapcontrol上
5.开发一个空间多边形查询功能的小Demo, 学会创建内存半透明图层用于显示选择范围
5.2准备工作
1.IDE:Visual Studio 2005/2008
2.ArcGIS Engine Developer kit 9.3
3.准备一份用于查询的的矢量数据(文章内有说明)
5.3Cursor对象
Cursor(游标)本质上是一个指向数据的指针,本身并不包含数据内容,它是连接到Row对象或要素对
象的桥梁。
游标有三种类型,即查询游标、插入游标和更新游标。每一种游标都是通过与之相适应的方法来获得的,如Search、Insert和Update方法。更新和插入游标都需要使用一个过滤器(Filter)对象,
因为它们首先必须获得需要进行操作的要素。
Cursor对象支持的接口是ICursor,它定义了操作一个Row集合或一个Row对象的属性和方
法,下面是获得插入型、更新型和查询型游标的方法:
pCursor = IFeatureClass.Insert()
使用IFeatureClass的Insert方法返回一个插入型游标,它通常用于往表中插入一条记录。
pCursor = IFeatureClass.Update()
使用IFeatureClass的Update方法会返回一个更新型游标,它用于更新或者删除一条记录。
pCursor= IFeatureClass.Search()
使用IFeatureClass的Sarch方法对表进行查询后,可以得到一个查询型Cursor对象,它指向一个
或多个Row对象。
以我们这章的内容主要使用查询游标。
FeatureCursor是Cursor的一个子类,指向一个或多个要素,它实现了IFeatureCursor接口,ArcGIS Engine开发所对矢量图层实现查询功能都是实行IFeatureCursor。
5.4QueryFilter对象与SpatialFilter对象
在关系型数据库中,查询条件是通过SQL语句的Where子语句来完成的。在ArcGIS Engine 中不能直接使用SQL语句,但ArcGIS Engine提供了QueryFilter和SpatialFilter两个过滤器对象来配合完成查询条件的设置,从而查询到想要的数据。
QueryFilter过滤器主要用于对属性数据查询条件的设置,它主要实现IQueryFilter接
口从而实现属性查询功能。
1.
2.IQueryFilter pQueryFilter = new QueryFilterClass();
3.
4.
5.//设置过滤器对象的属性
6.pQueryFilter.WhereClause = "人口> 10000000";
复制代码
SpatialFilter过滤器主要用于空间范围查询条件的设置,它主要实现
ISpatialFilter(继承 IQueryFilter接口)接口从而实现空间查询功能。
1.
2.ISpatialFilter pSpatialFilter = new SpatialFilterClass();
3.
4.
5.//设置空间过滤器的范围(多边形)
6.pSpatialFilter.Geometry = pGeometry;
7.
8.
9.//设置空间过滤器空间关系类型
10.pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
复制代码
空间过滤器空间关系类型主要有以下几种类型如表一所示:
表1
5.5SelectionSet要素选择集对象
熟悉ArcGIS Desktop使用的开发者一定会知道当在ArcMap中显示查询结果的时,所有的符号查询调教的要素都以蓝色高亮的形式显示在地图控件上,蓝色高亮显示表示高亮选中,这些高亮显示选中的要素对应一个要素选择集对象中。通过IFeatureSelection的SelectionSet属性可以获取选择集,FeatureLayer对象实现
了IFeatureSelection接口。
实现代码如下:
IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(0) as IFeatureLayer;
//QI至IFeatureSelection
IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
//创建过滤器
IQueryFilter pQueryFilter = new QueryFilterClass();
//设置过滤器对象的查询条件
pQueryFilter.WhereClause = "人口> 10000000";
//选择要素
pFeatureSelection.SelectFeatures(pQueryFilter,
esriSelectionResultEnum.esriSelectionResultNew,false);
//获取选择集对象
ISelectionSet pSelectinSet=pFeatureSelection.SelectionSet;
//设置选择集的符号
pFeatureSelection.SelectionSymbol = pSymbol;
5.6属性查询实例
5.6.1程序实现目标:
查询人口大于5000000的城市,并把查询结果创建为一个新的图层,如图1-3
所示:
图1
图2
图3
代码片段如下:
1.
2.private void button1_Click(object sender, EventArgs e)
3.{
4. IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(0) as
IFeatureLayer;
5. //QI到FeatureSelection
6. IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
7.
8. //创建过滤器
9. IQueryFilter pQueryFilter = new QueryFilterClass();
10.
11. //设置过滤器对象的查询条件
12.pQueryFilter.WhereClause = "人口> 5000000";
13.//根据查询条件选择要素
14.pFeatureSelection.SelectFeatures(pQueryFilter,
esriSelectionResultEnum.esriSelectionResultNew, false);
15.
16.//QI到ISelectionSet
17.ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet;
18.
19.if (pSelectionSet.Count > 0)
20.{
21.
22.IFeatureLayerDefinition pFDefinition = pFeatureLayer as IFeatureLayerDefinition;
23.
24.//创建新图层
25.
26.IFeatureLayer pNewFeatureLayer =
pFDefinition.CreateSelectionLayer("newlayerName", true, null, null);
https://www.360docs.net/doc/9f14042282.html, = "查询结果城市";
28.axMapControl1.AddLayer(pNewFeatureLayer as ILayer);
29. }
30.}
31.code]
32.
33. 5.7空间查询实例
34. 5.7.1目标
35.实现多边形查询功能
36. 5.7.2功能开发
37.代码片段如下:
38.
39.引用的命名空间:
40.
41.[code]
https://www.360docs.net/doc/9f14042282.html,ing System;
https://www.360docs.net/doc/9f14042282.html,ing System.Drawing;
https://www.360docs.net/doc/9f14042282.html,ing System.Collections;
https://www.360docs.net/doc/9f14042282.html,ing https://www.360docs.net/doc/9f14042282.html,ponentModel;
https://www.360docs.net/doc/9f14042282.html,ing System.Windows.Forms;
https://www.360docs.net/doc/9f14042282.html,ing System.Data;
https://www.360docs.net/doc/9f14042282.html,ing System.IO;
https://www.360docs.net/doc/9f14042282.html,ing System.Runtime.InteropServices;
https://www.360docs.net/doc/9f14042282.html,ing System.Collections.Generic;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.esriSystem;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.Carto;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.Controls;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.ADF;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.SystemUI;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.Display;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.Geodatabase;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.Geometry;
https://www.360docs.net/doc/9f14042282.html,ing ESRI.ArcGIS.DataSourcesGDB;
60.
61.
62.///
63.在程序运行时的内存中创建矢量要素层,并加到地图控件最顶端
64./// ///
65.地图控件
66.///
67.private IFeatureLayer AddFeatureLayerByMemoryWS(AxMapControl
pMapCtrl,ISpatialReference pSReference)
68.{
69. try
70. {
71. if (pMapCtrl == null) return null;
72.#region
73.创建新的内存工作空间
74.IWorkspaceFactory pWSF = new InMemoryWorkspaceFactoryClass();
75.IWorkspaceName pWSName = pWSF.Create("", "Temp", null, 0);
76.
77.IName pName = (IName)pWSName;
78.IWorkspace pMemoryWS = (IWorkspace)pName.Open();
79.#endregion
80.
81.IField oField = new FieldClass();
82.IFields oFields = new FieldsClass();
83.IFieldsEdit oFieldsEdit = null;
84.IFieldEdit oFieldEdit = null;
85.IFeatureClass oFeatureClass = null;
86.IFeatureLayer oFeatureLayer = null;
87.try
88.{
89.FieldsEdit = oFields as IFieldsEdit;
90.oFieldEdit = oField as IFieldEdit;
https://www.360docs.net/doc/9f14042282.html,_2 = "OBJECTID";
92.oFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
93.oFieldEdit.IsNullable_2 = false;
94.oFieldEdit.Required_2 = false;
95.oFieldsEdit.AddField(oField);
96.
97.oField = new FieldClass();
98.oFieldEdit = oField as IFieldEdit;
99.IGeometryDef pGeoDef = new GeometryDefClass();
100.IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef;
101.pGeoDefEdit.AvgNumPoints_2 = 5;
102.pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;
103.pGeoDefEdit.GridCount_2 = 1;
104.pGeoDefEdit.HasM_2 = false;
105.pGeoDefEdit.HasZ_2 = false;
106.pGeoDefEdit.SpatialReference_2 = pSReference;
https://www.360docs.net/doc/9f14042282.html,_2 = "SHAPE";
108.oFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
109.oFieldEdit.GeometryDef_2 = pGeoDef;
110.oFieldEdit.IsNullable_2 = true;
111.oFieldEdit.Required_2 = true;
112.oFieldsEdit.AddField(oField);
113.
114.oField = new FieldClass();
115.oFieldEdit = oField as IFieldEdit;
https://www.360docs.net/doc/9f14042282.html,_2 = "Code";
117.oFieldEdit.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
118.oFieldEdit.IsNullable_2 = true;
119.oFieldsEdit.AddField(oField);
120.
121.//创建要素类
122.oFeatureClass = (pMemoryWS as IFeatureWorkspace).CreateFeatureClass("Temp", oFields, null, null, esriFeatureType.esriFTSimple, "SHAPE", "");
123.oFeatureLayer = new FeatureLayerClass();
https://www.360docs.net/doc/9f14042282.html, = "TransTemp";
125.oFeatureLayer.FeatureClass = oFeatureClass;
126.//创建唯一值符号化对象
127.IUniqueValueRenderer pURender = new UniqueValueRendererClass();
128.pURender.FieldCount = 1;
129.pURender.set_Field(0, "Code");
https://www.360docs.net/doc/9f14042282.html,eDefaultSymbol = false;
131.ISimpleFillSymbol pFillSym = new SimpleFillSymbolClass();
132.pFillSym.Style = esriSimpleFillStyle.esriSFSSolid;
133.//半透明颜色
134.IRgbColor pColor = new RgbColorClass();
135.pColor.Red = 255;
136.pColor.Green = 255;
137.pFillSym.Color = pColor;
138.pURender.AddValue("1", "", pFillSym as ISymbol);
139.pFillSym = new SimpleFillSymbolClass();
140.pFillSym.Style = esriSimpleFillStyle.esriSFSSolid;
141.//唯一值符号化内存图层
142.(oFeatureLayer as IGeoFeatureLayer).Renderer = pURender as IFeatureRenderer;
143.ILayerEffects pLyrEffect = oFeatureLayer as ILayerEffects;
144.//透明度
145.pLyrEffect.Transparency = 80;
146.}
147.catch(Exception Err)
148.{
149. MessageBox.Show(Err.Message);
150.}
151.
152.
153.finally
154.{
155. try{
156.ystem.Runtime.InteropServices.Marshal.ReleaseComObject(oField);
157.System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields); 158.System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit); 159.System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldEdit);
160.System.Runtime.InteropServices.Marshal.ReleaseComObject(pName);
161.System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSF);
162.System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSName);
163.System.Runtime.InteropServices.Marshal.ReleaseComObject(pMemoryWS); 164.System.Runtime.InteropServices.Marshal.ReleaseComObject(oFeatureClass);
165.}
166.catch
167.{
168.
169.
170.
171.}
172.GC.Collect();
173.}
174. return oFeatureLayer;
175.}
176. catch (Exception Err)
177.{
178.MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK,
https://www.360docs.net/doc/9f14042282.html,rmation);
179.return null;}
180.
181.
182.
183.}
复制代码
1.
2.///
3./// 地图控件
4./// Envelope或Polygon几何实体
5./// 是否清除原有内容
6.public void AddTransTempEle(AxMapControl pMapCtrl, IGeometry pGeo, bool
bAutoClear)
7. {
8. try
9. {
10. if (pMapCtrl == null) return;
11. if (pGeo == null) return;
12. if (pGeo.IsEmpty) return;
13. IGeometry pPolygon = null;
14. if (pGeo is IEnvelope)
15. {
16. object Miss = Type.Missing;
17. pPolygon = new PolygonClass();
18. IGeometryCollection pGeoColl = pPolygon as
IGeometryCollection;
19. pGeoColl.AddGeometry(pGeo, ref Miss, ref Miss);
20. }
21. else if (pGeo is IPolygon)
22. {
23. (pGeo as ITopologicalOperator).Simplify();
24. pPolygon = pGeo;
25. }
26. else
27. {
28. MessageBox.Show( "几何实体类型不匹配","提示
" ,MessageBoxButtons.OK, https://www.360docs.net/doc/9f14042282.html,rmation);
29. return;
30. }
31. //获取透明要素层
32. IFeatureLayer pFlyr = null;
33. for (int i = 0; i < https://www.360docs.net/doc/9f14042282.html,yerCount; i++)
34. {
35. if (pMapCtrl.get_Layer(i).Name == "TransTemp")
36. {
37. pFlyr = pMapCtrl.get_Layer(i) as IFeatureLayer;
38. break;
39. }
40. }
41. //透明临时层不存在需要创建
42. if (pFlyr == null)
43. {
44. pFlyr =
AddFeatureLayerByMemoryWS(pMapCtrl,pMapCtrl.SpatialReference);
45. if (pFlyr == null)
46. {
47. MessageBox.Show("创建透明临时图层发生异常", "提示",
MessageBoxButtons.OK, https://www.360docs.net/doc/9f14042282.html,rmation);
48. return;
49. }
50. }
51. IFeatureClass pFC = pFlyr.FeatureClass;
52. if (bAutoClear)
53. {
54. if (pFC.FeatureCount(null) > 0)
55. {
56. IFeatureCursor pFCursor = pFC.Search(null, false);
57. if (pFCursor != null)
58. {
59.
60. IFeature pFeature = pFCursor.NextFeature();
61. if (pFeature != null)
62. {
63. while (pFeature != null)
64. {
65. pFeature.Delete();
66. pFeature = pFCursor.NextFeature();
67. }
68. }
69. System.Runtime.InteropServices.Marshal.ReleaseComObj
ect(pFCursor);
70. }
71. }
72. }
73. //创建要素
74. IFeature pNFeature = pFC.CreateFeature();
75. pNFeature.Shape = pPolygon;
76. pNFeature.set_Value(pFC.FindField("Code"),"1");
77. pNFeature.Store();
78. pMapCtrl.Refresh(esriViewDrawPhase.esriViewGeography, pFlyr,
pFlyr.AreaOfInterest);
79. }
80. catch (Exception Err)
81. {
82. MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK,
https://www.360docs.net/doc/9f14042282.html,rmation);
83. }
84. }
复制代码
1.
2.///
3. /// 获取查询要素
4. ///
5. /// 要素图层
6. /// 图形范围参数
7. ///
8. private List
pFeatureLayer,IGeometry pGeometry)
9. {
10. try
11. {
12. List
13. //创建SpatialFilter空间过滤器对象
14. ISpatialFilter pSpatialFilter = new SpatialFilterClass();
15. IQueryFilter pQueryFilter = pSpatialFilter as ISpatialFilter;
16. //设置过滤器的Geometry
17. pSpatialFilter.Geometry = pGeometry;
18. //设置空间关系类型
19. pSpatialFilter.SpatialRel =
esriSpatialRelEnum.esriSpatialRelContains;
20. //获取FeatureCursor游标
21. IFeatureCursor pFeatureCursor =
pFeatureLayer.Search(pQueryFilter, false);
22. //遍历FeatureCursor
23. IFeature pFeature = pFeatureCursor.NextFeature();
24. while (pFeature != null)
25. {
26. //获取要素对象
27. pList.Add(pFeature);
28. pFeature = pFeatureCursor.NextFeature();
29. }
30. System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatur
eCursor);
31. return pList;
32. }
33. catch (Exception Err)
34. {
35. MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK,
https://www.360docs.net/doc/9f14042282.html,rmation);
36. return null;
37. }
38. }
复制代码
1.
2. bool bSearch = false;//定义bool变量用于启动多边形查询功能
3. private void button1_Click(object sender, EventArgs e)
4. {
5. try
6. {
7.//向地图控件添加内存图层
8. IFeatureLayer pFeatureLayer =
this.AddFeatureLayerByMemoryWS(this.axMapControl1,this.axMapControl1.SpatialRef
erence);
9. this.axMapControl1.AddLayer(pFeatureLayer);
10. //设置鼠标样式为十字丝
11. this.axMapControl1.MousePointer =
esriControlsMousePointer.esriPointerCrosshair;
12.//启动范围查询功能
13. bSearch = true;
14. }
复制代码
添加一个新的Form在Form上添加一个DataGridView控件用于显示查询结果信息。如图4所示:
1.private void axMapControl1_OnMouseDown(object sender,
IMapControlEvents2_OnMouseDownEvent e)
2. {
3. if (bSearch)
4. {
5. //设置鼠标样式为十字丝
6. this.axMapControl1.MousePointer =
esriControlsMousePointer.esriPointerCrosshair;
7. //获取画定范围的Geometry
8. IGeometry pGeometry = this.axMapControl1.TrackPolygon();
9. //添加半透名临时图形
10. this.AddTransTempEle(this.axMapControl1, pGeometry, false);
11. IFeatureLayer pFeatureLayer=this.axMapControl1.get_Layer(1) as
IFeatureLayer;
12. //执行查询获取符号条件的要素
13. List
pGeometry);
14.
15. attribute pAttribute = new attribute();
16. //设置信息显示窗体中DataGridView的属性
17. //设置行数pFList.Count+1包括字段名哪一行即表头
18. pAttribute.dataGridView1.RowCount =
pFList.Count+1;
19. //设置边界风格
20. pAttribute.dataGridView1.ColumnHeadersBorderStyle =
DataGridViewHeaderBorderStyle.Sunken;
21. //设置列数
22. pAttribute.dataGridView1.ColumnCount =
pFList[0].Fields.FieldCount;
23. //遍历第一个要素的字段用于给列头赋值(字段的名称)
24. for(int m=0;m 25. { 26. pAttribute.dataGridView1.Columns[m].HeaderText = pFList[0].Fields.get_Field(m).AliasName; 27. } 28. //遍历要素 29. for (int i = 0; i < pFList.Count; i++) 30. { 31. IFeature pFeature=pFList; 32. for(int j=0;j 33. { 34. //填充字段值 35. pAttribute.dataGridView1[j, i].Value = pFeature.get_Value(j).ToString(); 36. } 37. } 38. pAttribute.Show(); 39. 40. } 41. } 复制代码 5.7.3功能演示 1.单击按钮向地图控件上添加一内存图层,并启动多边形查询功能如图5示: 图5 2.点击鼠标左键在地图上画以多边形范围,双击结束,将看到在所画的范围以半透明的形式 添加在地图之上,并显示出查询结果的属性信息如图所示: