arcgis engine基础开发教程(5)——学习地图查询

nufront 贡献于2018-04-20

作者   创建于2010-09-19 23:10:31   修改者  修改于1899-12-30 00:00:00字数15497

文档摘要: 地图查询、统计是一个GIS系统的基本的功能模块,实际上统计功能的前提也是通过查询获取结果以文字或者图表等报表的形式展现查询结果数据。
关键词:

ArcGIS Engine基础开发教程(5)——学习地图查询 1 地图查询 地图查询、统计是一个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接口从而实现属性查询功能。 2 IQueryFilter pQueryFilter = new QueryFilterClass(); 3 4 5 //设置过滤器对象的属性 6 pQueryFilter.WhereClause = "人口> 10000000"; 复制代码 SpatialFilter过滤器主要用于空间范围查询条件的设置,它主要实现ISpatialFilter(继承 IQueryFilter接口)接口从而实现空间查询功能。 7 8 ISpatialFilter pSpatialFilter = new SpatialFilterClass(); 9 10 11 //设置空间过滤器的范围(多边形) 12 pSpatialFilter.Geometry = pGeometry; 13 14 15 //设置空间过滤器空间关系类型 16 pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; 复制代码 空间过滤器空间关系类型主要有以下几种类型如表一所示: 表1 空间过滤器空间关系类型 描述(A是待查询图形,B是过滤条件图形) esriSpatialRelUndefined 未定义 esriSpatialRelIntersects A与B图形相交 esriSpatialRelEnvelopeIntersects A的Envelope和B的Envelope相交 esriSpatialRelIndexIntersects A与B索引相交 esriSpatialRelTouches A与B边界相接 esriSpatialRelOverlaps A与B相叠加 esriSpatialRelCrosses A与B相交(两条线相交于一点,一条线和一个面相交) esriSpatialRelWithin A在B内 esriSpatialRelContains A包含B esriSpatialRelRelation A与B空间关联 5.5SelectionSet要素选择集对象 熟悉ArcGIS Desktop使用的开发者一定会知道当在ArcMap中显示查询结果的时,所有的符号查询调教的要素都以蓝色高亮的形式显示在地图控件上,蓝色高亮显示表示高亮选中,这些高亮显示选中的要素对应一个要素选择集对象中。通过IFeatureSelection的SelectionSet属性可以获取选择集,FeatureLayer对象实现了IFeatureSelection接口。 实现代码如下: IFeatureLayer pFeatureLayer =this.axMapControl1.get_Layer(0)as IFeatureLayer; //QI至IFeatureSelection IFeatureSelection pFeatureSelection = pFeatureLayeras IFeatureSelection; //创建过滤器 IQueryFilter pQueryFilter =new QueryFilterClass(); //设置过滤器对象的查询条件 pQueryFilter.WhereClause ="人口> 10000000"; //选择要素 pFeatureSelection.SelectFeatures(pQueryFilter,esriSelectionResultEnum.esriSelectionResultNew,false); //获取选择集对象 ISelectionSet pSelectinSet=pFeatureSelection.SelectionSet; //设置选择集的符号 pFeatureSelection.SelectionSymbol = pSymbol; 17 5.6属性查询实例 5.6.1程序实现目标: 查询人口大于5000000的城市,并把查询结果创建为一个新的图层,如图1-3所示: 图1 图2 图3 代码片段如下: 18 private void button1_Click(object sender, EventArgs e) 19 { 20   IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(0) as IFeatureLayer; 21 //QI到FeatureSelection 22 IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection; 23 24 //创建过滤器 25 IQueryFilter pQueryFilter = new QueryFilterClass(); 26 27 //设置过滤器对象的查询条件 28 pQueryFilter.WhereClause = "人口> 5000000"; 29 //根据查询条件选择要素 30 pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false); 31 32 //QI到ISelectionSet 33 ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet; 34 35 if (pSelectionSet.Count > 0) 36 { 37 38 IFeatureLayerDefinition pFDefinition = pFeatureLayer as IFeatureLayerDefinition; 39 40 //创建新图层 41 42 IFeatureLayer pNewFeatureLayer = pFDefinition.CreateSelectionLayer("newlayerName", true, null, null); 43 pNewFeatureLayer.Name = "查询结果城市"; 44 axMapControl1.AddLayer(pNewFeatureLayer as ILayer); 45 } 46 } 47 code] 48 49 5.7空间查询实例 50 5.7.1目标 51 实现多边形查询功能 52 5.7.2功能开发 53 代码片段如下: 54 55 引用的命名空间: 56 57 [code] 58 using System; 59 using System.Drawing; 60 using System.Collections; 61 using System.ComponentModel; 62 using System.Windows.Forms; 63 using System.Data; 64 using System.IO; 65 using System.Runtime.InteropServices; 66 using System.Collections.Generic; 67 using ESRI.ArcGIS.esriSystem; 68 using ESRI.ArcGIS.Carto; 69 using ESRI.ArcGIS.Controls; 70 using ESRI.ArcGIS.ADF; 71 using ESRI.ArcGIS.SystemUI; 72 using ESRI.ArcGIS.Display; 73 using ESRI.ArcGIS.Geodatabase; 74 using ESRI.ArcGIS.Geometry; 75 using ESRI.ArcGIS.DataSourcesGDB; 76 77 78 ////// 79 在程序运行时的内存中创建矢量要素层,并加到地图控件最顶端 80 /// /// 81 地图控件 82 ///IFeatureLayer 新加的要素层 83 private IFeatureLayer AddFeatureLayerByMemoryWS(AxMapControl pMapCtrl,ISpatialReference pSReference) 84 { 85 try 86 { 87 if (pMapCtrl == null) return null; 88 #region 89 创建新的内存工作空间 90 IWorkspaceFactory pWSF = new InMemoryWorkspaceFactoryClass(); 91 IWorkspaceName pWSName = pWSF.Create("", "Temp", null, 0); 92 93 IName pName = (IName)pWSName; 94 IWorkspace pMemoryWS = (IWorkspace)pName.Open(); 95 #endregion 96 97 IField oField = new FieldClass(); 98 IFields oFields = new FieldsClass(); 99 IFieldsEdit oFieldsEdit = null; 100 IFieldEdit oFieldEdit = null; 101 IFeatureClass oFeatureClass = null; 102 IFeatureLayer oFeatureLayer = null; 103 try 104 { 105 FieldsEdit = oFields as IFieldsEdit; 106 oFieldEdit = oField as IFieldEdit; 107 oFieldEdit.Name_2 = "OBJECTID"; 108 oFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID; 109 oFieldEdit.IsNullable_2 = false; 110 oFieldEdit.Required_2 = false; 111 oFieldsEdit.AddField(oField); 112 113 oField = new FieldClass(); 114 oFieldEdit = oField as IFieldEdit; 115 IGeometryDef pGeoDef = new GeometryDefClass(); 116 IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef; 117 pGeoDefEdit.AvgNumPoints_2 = 5; 118 pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon; 119 pGeoDefEdit.GridCount_2 = 1; 120 pGeoDefEdit.HasM_2 = false; 121 pGeoDefEdit.HasZ_2 = false; 122 pGeoDefEdit.SpatialReference_2 = pSReference; 123 oFieldEdit.Name_2 = "SHAPE"; 124 oFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry; 125 oFieldEdit.GeometryDef_2 = pGeoDef; 126 oFieldEdit.IsNullable_2 = true; 127 oFieldEdit.Required_2 = true; 128 oFieldsEdit.AddField(oField); 129 130 oField = new FieldClass(); 131 oFieldEdit = oField as IFieldEdit; 132 oFieldEdit.Name_2 = "Code"; 133 oFieldEdit.Type_2 = esriFieldType.esriFieldTypeSmallInteger; 134 oFieldEdit.IsNullable_2 = true; 135 oFieldsEdit.AddField(oField); 136 137 //创建要素类 138 oFeatureClass = (pMemoryWS as IFeatureWorkspace).CreateFeatureClass("Temp", oFields, null, null, esriFeatureType.esriFTSimple, "SHAPE", ""); 139 oFeatureLayer = new FeatureLayerClass(); 140 oFeatureLayer.Name = "TransTemp"; 141 oFeatureLayer.FeatureClass = oFeatureClass; 142 //创建唯一值符号化对象 143 IUniqueValueRenderer pURender = new UniqueValueRendererClass(); 144 pURender.FieldCount = 1; 145 pURender.set_Field(0, "Code"); 146 pURender.UseDefaultSymbol = false; 147 ISimpleFillSymbol pFillSym = new SimpleFillSymbolClass(); 148 pFillSym.Style = esriSimpleFillStyle.esriSFSSolid; 149 //半透明颜色 150 IRgbColor pColor = new RgbColorClass(); 151 pColor.Red = 255; 152 pColor.Green = 255; 153 pFillSym.Color = pColor; 154 pURender.AddValue("1", "", pFillSym as ISymbol); 155 pFillSym = new SimpleFillSymbolClass(); 156 pFillSym.Style = esriSimpleFillStyle.esriSFSSolid; 157 //唯一值符号化内存图层 158 (oFeatureLayer as IGeoFeatureLayer).Renderer = pURender as IFeatureRenderer; 159 ILayerEffects pLyrEffect = oFeatureLayer as ILayerEffects; 160 //透明度 161 pLyrEffect.Transparency = 80; 162 } 163 catch(Exception Err) 164 { 165 MessageBox.Show(Err.Message); 166 } 167 168 169 finally 170 { 171 try{ 172 ystem.Runtime.InteropServices.Marshal.ReleaseComObject(oField); 173 System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields); 174 System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit); 175 System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldEdit); 176 System.Runtime.InteropServices.Marshal.ReleaseComObject(pName); 177 System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSF); 178 System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSName); 179 System.Runtime.InteropServices.Marshal.ReleaseComObject(pMemoryWS); 180 System.Runtime.InteropServices.Marshal.ReleaseComObject(oFeatureClass); 181 } 182 catch 183 { 184 185 186 187 } 188 GC.Collect(); 189 } 190 return oFeatureLayer; 191 } 192 catch (Exception Err) 193 { 194 MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 195 return null;} 196 197 198 199 } 复制代码 200 201 /// 在地图控件上添加透明临时图元/// 202 /// 地图控件 203 /// Envelope或Polygon几何实体 204 /// 是否清除原有内容 205 public void AddTransTempEle(AxMapControl pMapCtrl, IGeometry pGeo, bool bAutoClear) 206 { 207 try 208 { 209 if (pMapCtrl == null) return; 210 if (pGeo == null) return; 211 if (pGeo.IsEmpty) return; 212 IGeometry pPolygon = null; 213 if (pGeo is IEnvelope) 214 { 215 object Miss = Type.Missing; 216 pPolygon = new PolygonClass(); 217 IGeometryCollection pGeoColl = pPolygon as IGeometryCollection; 218 pGeoColl.AddGeometry(pGeo, ref Miss, ref Miss); 219 } 220 else if (pGeo is IPolygon) 221 { 222 (pGeo as ITopologicalOperator).Simplify(); 223 pPolygon = pGeo; 224 } 225 else 226 { 227 MessageBox.Show( "几何实体类型不匹配","提示" ,MessageBoxButtons.OK, MessageBoxIcon.Information); 228 return; 229 } 230 //获取透明要素层 231 IFeatureLayer pFlyr = null; 232 for (int i = 0; i < pMapCtrl.LayerCount; i++) 233 { 234 if (pMapCtrl.get_Layer(i).Name == "TransTemp") 235 { 236 pFlyr = pMapCtrl.get_Layer(i) as IFeatureLayer; 237 break; 238 } 239 } 240 //透明临时层不存在需要创建 241 if (pFlyr == null) 242 { 243 pFlyr = AddFeatureLayerByMemoryWS(pMapCtrl,pMapCtrl.SpatialReference); 244 if (pFlyr == null) 245 { 246 MessageBox.Show("创建透明临时图层发生异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 247 return; 248 } 249 } 250 IFeatureClass pFC = pFlyr.FeatureClass; 251 if (bAutoClear) 252 { 253 if (pFC.FeatureCount(null) > 0) 254 { 255 IFeatureCursor pFCursor = pFC.Search(null, false); 256 if (pFCursor != null) 257 { 258 259 IFeature pFeature = pFCursor.NextFeature(); 260 if (pFeature != null) 261 { 262 while (pFeature != null) 263 { 264 pFeature.Delete(); 265 pFeature = pFCursor.NextFeature(); 266 } 267 } 268 System.Runtime.InteropServices.Marshal.ReleaseComObject(pFCursor); 269 } 270 } 271 } 272 //创建要素 273 IFeature pNFeature = pFC.CreateFeature(); 274 pNFeature.Shape = pPolygon; 275 pNFeature.set_Value(pFC.FindField("Code"),"1"); 276 pNFeature.Store(); 277 pMapCtrl.Refresh(esriViewDrawPhase.esriViewGeography, pFlyr, pFlyr.AreaOfInterest); 278 } 279 catch (Exception Err) 280 { 281 MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 282 } 283 } 复制代码 284 285 /// 286 /// 获取查询要素 287 /// 288 /// 要素图层 289 /// 图形范围参数 290 /// 符号条件要素集合 291 private List GetSeartchFeatures( IFeatureLayer pFeatureLayer,IGeometry pGeometry) 292 { 293 try 294 { 295 List pList = new List(); 296 //创建SpatialFilter空间过滤器对象 297 ISpatialFilter pSpatialFilter = new SpatialFilterClass(); 298 IQueryFilter pQueryFilter = pSpatialFilter as ISpatialFilter; 299 //设置过滤器的Geometry 300 pSpatialFilter.Geometry = pGeometry; 301 //设置空间关系类型 302 pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; 303 //获取FeatureCursor游标 304 IFeatureCursor pFeatureCursor = pFeatureLayer.Search(pQueryFilter, false); 305 //遍历FeatureCursor 306 IFeature pFeature = pFeatureCursor.NextFeature(); 307 while (pFeature != null) 308 { 309 //获取要素对象 310 pList.Add(pFeature); 311 pFeature = pFeatureCursor.NextFeature(); 312 } 313 System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatureCursor); 314 return pList; 315 } 316 catch (Exception Err) 317 { 318 MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 319 return null; 320 } 321 } 复制代码 322 323 bool bSearch = false; //定义bool变量用于启动多边形查询功能 324 private void button1_Click(object sender, EventArgs e) 325 { 326 try 327 { 328         //向地图控件添加内存图层 329 IFeatureLayer pFeatureLayer = this.AddFeatureLayerByMemoryWS(this.axMapControl1,this.axMapControl1.SpatialReference); 330 this.axMapControl1.AddLayer(pFeatureLayer); 331   //设置鼠标样式为十字丝 332 this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; 333         //启动范围查询功能 334 bSearch = true; 335 } 复制代码 336 添加一个新的Form在Form上添加一个DataGridView控件用于显示查询结果信息。如图4所示: private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e) 337 { 338 if (bSearch) 339 { 340 //设置鼠标样式为十字丝 341 this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; 342 //获取画定范围的Geometry 343 IGeometry pGeometry = this.axMapControl1.TrackPolygon(); 344 //添加半透名临时图形 345 this.AddTransTempEle(this.axMapControl1, pGeometry, false); 346 IFeatureLayer pFeatureLayer=this.axMapControl1.get_Layer(1) as IFeatureLayer; 347 //执行查询获取符号条件的要素 348 List pFList = this.GetSeartchFeatures(pFeatureLayer, pGeometry); 349 350 attribute pAttribute = new attribute(); 351 //设置信息显示窗体中DataGridView的属性 352 //设置行数pFList.Count+1包括字段名哪一行即表头 353 pAttribute.dataGridView1.RowCount = pFList.Count+1; 354 //设置边界风格 355 pAttribute.dataGridView1.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Sunken; 356 //设置列数 357 pAttribute.dataGridView1.ColumnCount = pFList[0].Fields.FieldCount; 358 //遍历第一个要素的字段用于给列头赋值(字段的名称) 359 for(int m=0;m pFeatures = new List(); IFeature pFeature = pFeatureCursor.NextFeature(); while (pFeature != null) { pFeatures.Add(pFeature); pFeature = pFeatureCursor.NextFeature(); } for (int i = 0; i < pFeatures.Count; i++) { MessageBox.Show(((pFeatures.Shape as IPolygon) as IArea).Area.ToString()); } 分析:pFeatures集合存储了指向FeatureClass上所有Feature的引用,但是由于Recycling参数设置为TRUE也就是说每执行一个NextFeautre方法上一条记录的Feature值在内存中被回收,所以到最后遍历pFeatures集合的时候所有的IFeature引用指向的Feature对象都为Null。所以会引发一下错误(如下图7所示): 图7 .参数Recycling设置为False IFeatureClass pFeatureClass = (this.axMapControl1.get_Layer(0) as IFeatureLayer).FeatureClass; //IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, true); IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false); List pFeatures = new List(); IFeature pFeature = pFeatureCursor.NextFeature(); while (pFeature != null) { pFeatures.Add(pFeature); pFeature = pFeatureCursor.NextFeature(); } for (int i = 0; i < pFeatures.Count; i++) { MessageBox.Show(((pFeatures.Shape as IPolygon) as IArea).Area.ToString()); } 分析:pFeatures集合存储了指向FeatureClass上所有Feature的引用,但是由于Recycling参数设置为False也就是说每执行一个NextFeautre方法上一条记录的Feature值在内存中依然存在,所以到最后遍历pFeatures集合的时候所有的IFeature引用指向的Feature对象都依然存在。所以会执行的很Happy(如下图8所示): 图8

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档