查询在GIS领域应该是一个很频繁的操作,在GIS中除了具有属性查询(和其他关系型数据库的查询类似),还提供了空间查询。在介绍查询的时候,让我们先了解下面的对象。
1.Table 对象
Table 是不含有空间信息的一张二维表,它主要实现了 ITable 接口。在这张二维表中,每一行称之为 Row(IRow),ITable 接口 定义了对这张二维表行的插入,更新,查询,以及删除等操作。 独立表(standalone table):就是一个单独的不含空间信息的表也就是只能在 ArcMap 中 Table of Contents 的 Source 选项卡中看到的。
2.对象类
对象类是在 Table 的基础上扩展起来的,因此在外观上来看,它也是一个二维表,也是用来存储非空间数据,它与 Table 的区别在于它的一行是一个 Object(对象),尽管在形式上也是一条记录,但它是具有属性和行为的一个对象,而非简单的记录了。
3.FeatureClass 对象
要素类是存储在工作空间中的一种数据组织方式,要素类是在对象类的基础上的进一步扩展,包含了现实世界中的空间实体。要素类由要素组成(Feature),要素对应要素类中的一行,要素相当于空间对象(Geometry ) +相应的属性信息。IFeatureClass 定义了对要素的查询,更新,删除等操作。关于 ROW,Table,对象类,Feature,要素类,我们可以从下面的图上得到启示:
FeatureClass 对 象 实 现 了 IFeatureClass 接 口 , IFeatureClass 对 查 询 定 义 了 两 个 方 法IFeatureClass.Search 和 IFeatureClass.Select。 Search 方法需要传入两个参数,一个是过滤器;另外一个是布尔值,用于说明放回的要素游标是否被回收,一般的,如果仅仅是为了读取数据,那么这个参数应该是 true,如果要对选择出来的要素更新,那么这个参数应该设置为 false。那么这两个参数到底有什么意义,我们从下面的代码中看一下。
3.1 false 和 true 参数的差别
我们定义一个 Search 函数,通过传 false 和 true 来对这两个参数进行说明,代码如下:
void Search(IFeatureClass _pFeatureClass,bool _Bool) { IFeature pFt1, pFt2; IFeatureCursor pFtCursor; if (_Bool == false) { pFtCursor = _pFeatureClass.Search(null, _Bool); pFt1 = pFtCursor.NextFeature(); while (pFt1 != null) { pFt2 = pFtCursor.NextFeature(); if (pFt1 == pFt2) { MessageBox.Show("Recycling 参数是 false"); } pFt1 = pFtCursor.NextFeature(); } } else { pFtCursor = _pFeatureClass.Search(null, _Bool); pFt1 = pFtCursor.NextFeature(); while (pFt1 != null) { pFt2 = pFtCursor.NextFeature(); if (pFt1 == pFt2) { MessageBox.Show("Recycling 参数是true"); } pFt1 = pFtCursor.NextFeature(); } } } 当 recycling 为 true 的时候,我们会看到程序执行到 MessageBox.Show("Recycling 参数是 true"),如 下图:
3.2 Search和 Select 方法的比较
Search 返回游标,Select 返回选择集 游标:必须遍历游标才能得到所有的结果,不必太关注内存 选择集: 查询后既可得到,但是通常只保留 OID 字段,数据量大的时候要考虑内存压力 。
3.3 Cursor 和 FeatureCursor对象
Cursor 中文‘游标“,它本质上是一个指向数据的指针,自身并不包含数据。游标有三类,查询游标,插入游标和更新游标,每一中游标都是有其相应的方法得到,如查询游标是由 ITable.Search 方法得到。游标是 GIS 中使用频率很高的,凡是和数据的查询,更新,删除等都跟他有关。ICursor 定义了对游标的操作。当我们通过 ITable.Search 对数据进行查询,要获取具体 Row 的信息的时候,要通过 ICursor.NextRow方法向前遍历,游标是不能后退的。游标是和 Table 相对应的。IFeatureCursor 继承了 ICursor,IFeatureCursor 是和要素类相对应。
3.4 QueryFilter 与 SpatialFilter对象
在 ArcGIS Engine 中进行查询或者选择,都需要传给一个查找条件,或者过滤条件,这个条件就相当于一般的 SQL 语句中的 Where 语句,如 Select * from 用户 where 性别=’女’;我们知道 GIS 不仅仅有属性查询,还有一般关系型数据库不具有的空间查询。而 QueryFilter 对象和 SpatialFilter 对象分别对应了ArcGIS Engine 中的属性查询和空间查询。 IQueryFilter 被两个类实现 QueryFilterClass 和 SpatialFilterClass,前者是针对属性查询的,后者是针对空间查询的。 在介绍下这些对象后,我们现在来做一个高亮显示的查询操作。
3.5 IFeatureSelection接口
IFeatureSelection 接口负责管理一个图层中的要素选择集的方法和属性。 IFeatureSelection 接口的 Add方法可以把本图层中的一个要素添加到图层的选择集中;SelectFeatures 方法则利用过滤器对象将符合条件的要素放入到图层的选择集中。使用IFeatureSelection接口可以实现要素的高亮显示。在ArcGIS Engine中有很多类实现了这个接口,如下图:
3.5.1 使用 IFeatureSelection接口高亮显示
在介绍 IMap 接口那一节,我们用 IMap 的 IMap.SelectFeature 方法实现了对查询的要素高亮显示,现在我们用 IFeatureSelection 接口实现查询高亮显示
IMap pMap = axMapControl1.Map; IFeatureLayer pFeaturelayer = GetLayer(pMap, "Roads") as IFeatureLayer; IFeatureSelection pFeatureSelection = pFeaturelayer as IFeatureSelection; IQueryFilter pQuery = new QueryFilterClass(); pQuery.WhereClause = "TYPE=" +"'paved'"; pFeatureSelection.SelectFeatures(pQuery,esriSelectionResultEnum.esriSelectionResultNew,false ); axMapControl1.ActiveView.Refresh();
其中 GetLayer 函数是我们写的一个根据图层的名称获取图层的方法,代码如下图:
private ILayer GetLayer(IMap pMap, string LayerName) { IEnumLayer pEnunLayer; pEnunLayer = pMap.get_Layers(null, false); pEnunLayer.Reset(); ILayer pRetureLayer; pRetureLayer = pEnunLayer.Next(); while (pRetureLayer != null) { if (pRetureLayer.Name == LayerName) { break; } pRetureLayer = pEnunLayer.Next(); } return pRetureLayer; }