arcgis_engine地图查询


地图查询、统计是一个 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 接口 从而实现属性查询功能。 CODE: IQueryFilter pQueryFilter = new QueryFilterClass(); //设置过滤器对象的属性 pQueryFilter.WhereClause = "人口> 10000000"; SpatialFilter 过滤器主要用于空间范围查询条件的设置,它主要实现 ISpatialFilter(继承 IQueryFilter 接口)接口从而实现空间查询功能。 CODE: ISpatialFilter pSpatialFilter = new SpatialFilterClass(); //设置空间过滤器的范围(多边形) pSpatialFilter.Geometry = pGeometry; //设置空间过滤器空间关系类型 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 接口。 实现代码如下: IFeatureLayerpFeatureLayer =this.axMapControl1.get_Layer(0)asIFeatureLayer; //QI 至 IFeatureSelection IFeatureSelectionpFeatureSelection = pFeatureLayerasIFeatureSelection; //创建过滤器 IQueryFilterpQueryFilter =newQueryFilterClass(); //设置过滤器对象的查询条件 pQueryFilter.WhereClause ="人口> 10000000"; //选择要素 pFeatureSelection.SelectFeatures(pQueryFilter,esriSelectionResultEnum.esriSelectionResultNew ,false); //获取选择集对象 ISelectionSetpSelectinSet=pFeatureSelection.SelectionSet; //设置选择集的符号 pFeatureSelection.SelectionSymbol = pSymbol; 5.6 属性查询实例 5.6.1 程序实现目标: 查询人口大于 5000000 的城市,并把查询结果创建为一个新的图层,如图 1-3 所示: 代码片段如下: CODE: private void button1_Click(object sender, EventArgs e) { IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(0) as IFeatureLayer; //QI 到 FeatureSelection IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection; //创建过滤器 IQueryFilter pQueryFilter = new QueryFilterClass(); //设置过滤器对象的查询条件 pQueryFilter.WhereClause = "人口> 5000000"; //根据查询条件选择要素 pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false); //QI 到 ISelectionSet ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet; if (pSelectionSet.Count > 0) { IFeatureLayerDefinition pFDefinition = pFeatureLayer as IFeatureLayerDefinition; //创建新图层 IFeatureLayer pNewFeatureLayer = pFDefinition.CreateSelectionLayer("newlayerName", true, null, null); pNewFeatureLayer.Name = "查询结果城市"; axMapControl1.AddLayer(pNewFeatureLayer as ILayer); } } 5.7 空间查询实例 5.7.1 目标 实现多边形查询功能 5.7.2 功能开发 代码片段如下: 引用的命名空间: [code] using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.IO; using System.Runtime.InteropServices; using System.Collections.Generic; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.ADF; using ESRI.ArcGIS.SystemUI; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.DataSourcesGDB; ////// 在程序运行时的内存中创建矢量要素层,并加到地图控件最顶端 /// /// 地图控件 ///IFeatureLayer 新加的要素层 private IFeatureLayer AddFeatureLayerByMemoryWS(AxMapControl pMapCtrl,ISpatialReference pSReference) { try { if (pMapCtrl == null) return null; #region 创建新的内存工作空间 IWorkspaceFactory pWSF = new InMemoryWorkspaceFactoryClass(); IWorkspaceName pWSName = pWSF.Create("", "Temp", null, 0); IName pName = (IName)pWSName; IWorkspace pMemoryWS = (IWorkspace)pName.Open(); #endregion IField Field = new FieldClass(); IFields Fields = new FieldsClass(); IFieldsEdit FieldsEdit = null; IFieldEdit FieldEdit = null; IFeatureClass FeatureClass = null; IFeatureLayer FeatureLayer = null; try { FieldsEdit = oFields as IFieldsEdit; oFieldEdit = oField as IFieldEdit; oFieldEdit.Name_2 = "OBJECTID"; oFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID; oFieldEdit.IsNullable_2 = false; oFieldEdit.Required_2 = false; oFieldsEdit.AddField(oField); oField = new FieldClass(); oFieldEdit = oField as IFieldEdit; IGeometryDef pGeoDef = new GeometryDefClass(); IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef; pGeoDefEdit.AvgNumPoints_2 = 5; pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon; pGeoDefEdit.GridCount_2 = 1; pGeoDefEdit.HasM_2 = false; pGeoDefEdit.HasZ_2 = false; pGeoDefEdit.SpatialReference_2 = pSReference; oFieldEdit.Name_2 = "SHAPE"; oFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry; oFieldEdit.GeometryDef_2 = pGeoDef; oFieldEdit.IsNullable_2 = true; oFieldEdit.Required_2 = true; oFieldsEdit.AddField(oField); oField = new FieldClass(); oFieldEdit = oField as IFieldEdit; oFieldEdit.Name_2 = "Code"; oFieldEdit.Type_2 = esriFieldType.esriFieldTypeSmallInteger; oFieldEdit.IsNullable_2 = true; oFieldsEdit.AddField(oField); //创建要素类 oFeatureClass = (pMemoryWS as IFeatureWorkspace).CreateFeatureClass("Temp", oFields, null, null, esriFeatureType.esriFTSimple, "SHAPE", ""); oFeatureLayer = new FeatureLayerClass(); oFeatureLayer.Name = "TransTemp"; oFeatureLayer.FeatureClass = oFeatureClass; //创建唯一值符号化对象 IUniqueValueRenderer pURender = new UniqueValueRendererClass(); pURender.FieldCount = 1; pURender.set_Field(0, "Code"); pURender.UseDefaultSymbol = false; ISimpleFillSymbol pFillSym = new SimpleFillSymbolClass(); pFillSym.Style. = esriSimpleFillStyle.esriSFSSolid; //半透明颜色 IRgbColor pColor = new RgbColorClass(); pColor.Red = 255; pColor.Green = 255; pFillSym.Color = pColor; pURender.AddValue("1", "", pFillSym as ISymbol); pFillSym = new SimpleFillSymbolClass(); pFillSym.Style. = esriSimpleFillStyle.esriSFSSolid; //唯一值符号化内存图层 (oFeatureLayer as IGeoFeatureLayer).Renderer = pURender as IFeatureRenderer; ILayerEffects pLyrEffect = oFeatureLayer as ILayerEffects; //透明度 pLyrEffect.Transparency = 80; } catch(Exception Err) { MessageBox.Show(Err.Message); } finally { try{ ystem.Runtime.InteropServices.Marshal.ReleaseComObject(oField); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldEdit); System.Runtime.InteropServices.Marshal.ReleaseComObject(pName); System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSF); System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSName); System.Runtime.InteropServices.Marshal.ReleaseComObject(pMemoryWS); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFeatureClass); } catch { } GC.Collect(); } return oFeatureLayer; } catch (Exception Err) { MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return null;} } CODE: /// 在地图控件上添加透明临时图元/// /// 地图控件 /// Envelope 或 Polygon 几何实体 /// 是否清除原有内容 public void AddTransTempEle(AxMapControl pMapCtrl, IGeometry pGeo, bool bAutoClear) { try { if (pMapCtrl == null) return; if (pGeo == null) return; if (pGeo.IsEmpty) return; IGeometry pPolygon = null; if (pGeo is IEnvelope) { object Miss = Type.Missing; pPolygon = new PolygonClass(); IGeometryCollection pGeoColl = pPolygon as IGeometryCollection; pGeoColl.AddGeometry(pGeo, ref Miss, ref Miss); } else if (pGeo is IPolygon) { (pGeo as ITopologicalOperator).Simplify(); pPolygon = pGeo; } else { MessageBox.Show( "几何实体类型不匹配","提示" ,MessageBoxButtons.OK, MessageBoxIcon.Information); return; } //获取透明要素层 IFeatureLayer pFlyr = null; for (int i = 0; i < pMapCtrl.LayerCount; i++) { if (pMapCtrl.get_Layer(i).Name == "TransTemp") { pFlyr = pMapCtrl.get_Layer(i) as IFeatureLayer; break; } } //透明临时层不存在需要创建 if (pFlyr == null) { pFlyr = AddFeatureLayerByMemoryWS(pMapCtrl,pMapCtrl.SpatialReference); if (pFlyr == null) { MessageBox.Show("创建透明临时图层发生异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } } IFeatureClass pFC = pFlyr.FeatureClass; if (bAutoClear) { if (pFC.FeatureCount(null) > 0) { IFeatureCursor pFCursor = pFC.Search(null, false); if (pFCursor != null) { IFeature pFeature = pFCursor.NextFeature(); if (pFeature != null) { while (pFeature != null) { pFeature.Delete(); pFeature = pFCursor.NextFeature(); } } System.Runtime.InteropServices.Marshal.ReleaseComObject(pFCursor); } } } //创建要素 IFeature pNFeature = pFC.CreateFeature(); pNFeature.Shape = pPolygon; pNFeature.set_Value(pFC.FindField("Code"),"1"); pNFeature.Store(); pMapCtrl.Refresh(esriViewDrawPhase.esriViewGeography, pFlyr, pFlyr.AreaOfInterest); } catch (Exception Err) { MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } CODE: /// /// 获取查询要素 /// /// 要素图层 /// 图形范围参数 /// 符号条件要素集合 private List GetSeartchFeatures( IFeatureLayer pFeatureLayer,IGeometry pGeometry) { try { List pList = new List(); //创建 SpatialFilter 空间过滤器对象 ISpatialFilter pSpatialFilter = new SpatialFilterClass(); IQueryFilter pQueryFilter = pSpatialFilter as ISpatialFilter; //设置过滤器的 Geometry pSpatialFilter.Geometry = pGeometry; //设置空间关系类型 pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; //获取 FeatureCursor 游标 IFeatureCursor pFeatureCursor = pFeatureLayer.Search(pQueryFilter, false); //遍历 FeatureCursor IFeature pFeature = pFeatureCursor.NextFeature(); while (pFeature != null) { //获取要素对象 pList.Add(pFeature); pFeature = pFeatureCursor.NextFeature(); } System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatureCursor); return pList; } catch (Exception Err) { MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return null; } } CODE: bool bSearch = false; //定义 bool 变量用于启动多边形查询功能 private void button1_Click(object sender, EventArgs e) { try { //向地图控件添加内存图层 IFeatureLayer pFeatureLayer = this.AddFeatureLayerByMemoryWS(this.axMapControl1,this.axMapControl1.SpatialReference); this.axMapControl1.AddLayer(pFeatureLayer); //设置鼠标样式为十字丝 this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; //启动范围查询功能 bSearch = true; }添加一个新的 Form 在 Form 上添加一个 DataGridView 控件用于显示查询结果信息。如图 4 所示: CODE: private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e) { if (bSearch) { //设置鼠标样式为十字丝 this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; //获取画定范围的 Geometry IGeometry pGeometry = this.axMapControl1.TrackPolygon(); //添加半透名临时图形 this.AddTransTempEle(this.axMapControl1, pGeometry, false); IFeatureLayer pFeatureLayer=this.axMapControl1.get_Layer(1) as IFeatureLayer; //执行查询获取符号条件的要素 List pFList = this.GetSeartchFeatures(pFeatureLayer, pGeometry); attribute pAttribute = new attribute(); //设置信息显示窗体中 DataGridView 的属性 //设置行数 pFList.Count+1 包括字段名哪一行即表头 pAttribute.dataGridView1.RowCount = pFList.Count+1; //设置边界风格 pAttribute.dataGridView1.ColumnHeadersBorderStyle. = DataGridViewHeaderBorderStyle.Sunken; //设置列数 pAttribute.dataGridView1.ColumnCount = pFList[0].Fields.FieldCount; //遍历第一个要素的字段用于给列头赋值(字段的名称) 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 所示): .参数 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 所示):
还剩24页未读

继续阅读

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

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

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

下载pdf

pdf贡献者

nufront

贡献于2018-04-17

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf