空间查询功能是通过用户选择的空间几何体以及该几何体与当前地图中要素之间的几何关系进行空间查找,从而得到查询结果的操作。
相关类与接口
空间查询相关的类主要是SpatialFilter类,其实现的接口主要为ISpatialFilter接口。SpatialFilter类是空间关系过滤类,ISpatialFilter接口的成员主要用于返回和修改数据过滤器所使用的空间关系。ISpatialFilter接口同时包含了空间和属性两种查询约束,它继承了IQueryFilter接口。
1.Geometry属性:
设置或获取用来筛选数据的几何体,其值为IGeometry接口类型。
2.GeometryField属性:
获取或设置应用于查询过滤器中几何字段的名称。
3.SpatialRel属性
获取或设置过滤器所要使用的控件关系,其值为esriSpatialRelEnum枚举类型,包括相交esriSpatialRelInersects、覆盖esriSpatialRelOverlaps、跨越esriSpatialRelCrosses等多种空间关系。
实现思路:
通过ISpatialFilter接口定义空间查询条件,其Geometry属性确定用来查询的空间几何体,SpatialRel属性定义查询所使用的空间关系,为esriSpatialRelEnum枚举类型的变量。包括:esriSpatialRelIntersects(空间相交)、esriSpatialRelTouches(空间相接,共享空间边界),esriSpatialRelOverlaps(空间覆盖)、esriSpatialRelCrosses(空间跨越)、esriSpatialRelWithin(空间被包含)、esriSpatialRelContains(空间包含)等。因为ISpatialFilter接口继承与IQueryFilter接口,因此在定义好空间查询条件后,可以使用IQueryFilter接口的查询方法进行空间查询操作。另外,在合并源图层的几何体时,使用ITopologicalOperator接口的Union方法来进行几何体合并操作,该接口是点、线、面等几何体对象所共同实现的接口。
代码:
public partial class FormQueryBySpatial : DevExpress.XtraEditors.XtraForm
{
//变量定义
private IMap currentMap;//当前MapControl控件的Map对象
private IFeatureLayer currentFeatureLayer;//设置临时类变量来使用IFeatureLayer接口的当前图层对象
private string currentFileName;//设置临时类变量来存储字段名称
/// <summary>
/// 获得当前MapControl控件中的对象
/// </summary>
public IMap CurrentMap
{
set
{
currentMap = value;
}
}
public FormQueryBySpatial()
{
InitializeComponent();
} private void FormQueryBySpatial_Load(object sender, EventArgs e)
{
//清空目标图层列表
checkListTargetLayer.Items.Clear();
string layerName;//设置临时变量存储图层名称
//对Map中的每一个图层进行判断并添加图层名称
for (int i = ; i < currentMap.LayerCount; i++)
{
//如果该图层为图层组类型,则分别对所包含的每个图层进行操作
if (currentMap.get_Layer(i) is GroupLayer)
{
//使用ICompositeLayer接口进行遍历操作
ICompositeLayer compositeLayer = currentMap.get_Layer(i) as ICompositeLayer;
for (int j = ; j < compositeLayer.Count; j++)
{
//将图层的名称添加到checkListTargetLayer控件中
layerName = compositeLayer.get_Layer(j).Name;
checkListTargetLayer.Items.Add(layerName);
comBoxSourceLayer.Items.Add(layerName);
}
}
//如果图层不是图层组类型,则直接添加名称
else
{
layerName = currentMap.get_Layer(i).Name;
checkListTargetLayer.Items.Add(layerName);
comBoxSourceLayer.Items.Add(layerName);
}
}
//将comboxSourceLayer控件的默认选项设置为第一个图层的名称
comBoxSourceLayer.SelectedIndex = ;
//将ComBoxMethod控件的默认选项设置为第一种控件选择方法
comBoxMethod.SelectedIndex = ;
} //定义方法获取要素图层
private IFeatureLayer GetFeatureLayerByName(IMap map, string layerName)
{
//对地图图层进行遍历
for (int i = ; i < map.LayerCount; i++)
{
//如果该图层为图层组类型,则分别对包含的每个图层进行操作
if (map.get_Layer(i) is GroupLayer)
{
//使用ICompositeLayer接口进行遍历操作
ICompositeLayer compositeLayer = map.get_Layer(i) as ICompositeLayer;
for (int j = ; j < compositeLayer.Count; j++)
{
//如果图层名称为所要查询的图层名称,则返回IFeaturelayer接口的矢量图层对象
if (compositeLayer.get_Layer(j).Name == layerName)
{
return (IFeatureLayer)compositeLayer.get_Layer(j);
}
}
}
//如果图层不是图层组类型,则直接进行判断
else
{
if (map.get_Layer(i).Name == layerName)
{
return (IFeatureLayer)map.get_Layer(i);
}
}
}
return null;
}
//定义方法获取几何对象
private IGeometry GetFeatureLayerGeometryUnion(IFeatureLayer featureLayer)
{
//定义IGeometry接口对象,存储每一步拓扑操作后得到的几何体
IGeometry geometry = null;
//使用ITopologicalOperator接口进行几何体的拓扑操作
ITopologicalOperator topologicalOperator;
//使用null作为查询过滤器得到图层中所有要素的游标
IFeatureCursor featureCursor = featureLayer.Search(null, false);
//获取IFeature接口游标中的第一个元素
IFeature feature = featureCursor.NextFeature();
//当游标不为空时
while (feature != null)
{
//如果几何体不为空
if (geometry != null)
{
//进行接口转换,使当前接口进行拓扑操作
topologicalOperator = geometry as ITopologicalOperator;
//执行拓扑合并操作,将当前要素的几何体与已有的几何体进行Union,返回新的合并后的几何体
geometry = topologicalOperator.Union(feature.Shape);
}
else
geometry = feature.Shape;
feature = featureCursor.NextFeature();//移动游标到下一个要素
}
//返回最新合并的几何体
return geometry;
}
//定义指定查询的方法
private void SelectFeaturesBySpatial()
{
//定义和创建用于查询的ISpatialFilter接口对象
ISpatialFilter spatialFilter = new SpatialFilterClass();
//默认设定用于查询的空间几何体为当前地图源图层中所有要素几何体的集合
spatialFilter.Geometry = GetFeatureLayerGeometryUnion(GetFeatureLayerByName(currentMap, comBoxSourceLayer.SelectedItem.ToString()));
//根据对空间选择方法的选择采用相应的空间选择方法
switch (comBoxMethod.SelectedIndex)
{
case :
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
break;
case :
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelWithin;
break;
case :
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
break;
case :
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelTouches;
break;
case :
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses;
break;
case :
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelEnvelopeIntersects;
break;
case :
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelOverlaps;
break;
default:
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
break;
}
//对选择的目标图层进行遍历,并对每一个图层进行空间查询,查询结果将放在选择集中
IFeatureLayer featureLayer;
//对所有选择的目标图层进行遍历
for (int i = ; i < checkListTargetLayer.CheckedItems.Count; i++)
{
//根据选择的目标图层名称获得对应的矢量图层
featureLayer = GetFeatureLayerByName(currentMap, (string)checkListTargetLayer.CheckedItems[i]);
//进行接口转换,使用IFeatureSelection接口选择要素
IFeatureSelection featureSelection = featureLayer as IFeatureSelection;
//使用IFeatureSelection接口的SelectFeature方法,根据空间查询过滤器选择要素,将其放在新的选择集中
featureSelection.SelectFeatures((IQueryFilter)spatialFilter, esriSelectionResultEnum.esriSelectionResultAdd, false);
}
//进行接口转换,使用IActiveView接口进行视图操作
IActiveView activeView = currentMap as IActiveView;
//进行部分刷新操作,只刷新选择集的内容
activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, activeView.Extent);
} private void btnOk_Click(object sender, EventArgs e)
{
try
{
SelectFeaturesBySpatial();
this.Close();
}
catch { }
} private void btnApply_Click(object sender, EventArgs e)
{
try
{
SelectFeaturesBySpatial();
}
catch { }
} private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}