liutingxiang的个人博客分享 http://blog.sciencenet.cn/u/liutingxiang

博文

ArcGIS Engine二次开发学习(11)根据空间关系查询

已有 5978 次阅读 2018-5-24 12:48 |个人分类:地理信息系统二次开发|系统分类:教学心得

 要求:实现根据矢量数据的空间关系进行要素查询的功能。

空间查询功能是通过用户选择的空间几何体以及该几何体与当前地图中要素之间的几何关系进行空间查找,从而得到查询结果的操作。


实现思路:


通过ISpatialFilter接口定义空间查询条件,其Geometry属性确定用来查询的空间几何体,SpatialRel属性定义查询所使用的空间关系,为esriSpatialRelEnum枚举类型的变量。包括:esriSpatialRelIntersects(空间相交)、esriSpatialRelTouches(空间相接,共享空间边界),esriSpatialRelOverlaps(空间覆盖)、esriSpatialRelCrosses(空间跨越)、esriSpatialRelWithin(空间被包含)、esriSpatialRelContains(空间包含)等。因为ISpatialFilter接口继承与IQueryFilter接口,因此在定义好空间查询条件后,可以使用IQueryFilter接口的查询方法进行空间查询操作。另外,在合并源图层的几何体时,使用ITopologicalOperator接口的Union方法来进行几何体合并操作,该接口是点、线、面等几何体对象所共同实现的接口。


1、窗体设计


目标图层指的是所选的要素所在的图层;

源图层指的是与所选要素具有空间关系的图层;

选择方式,包括:

空间相交、

空间被包含、

空间包含、

空间覆盖、

空间相接——共享空间边界、

空间跨越。


2、构建frmQureyByLocation()窗体代码

(1)定义一个当前地图的变量

private IMap currentMap;
public IMap CurrentMap
{
   set
   {
     currentMap = value;
   }
}


(2)要在窗体的checkedlistbox中能够显示当前地图中的所有图层

需要在load事件中添加:

private void frmQureyByLocation_Load(object sender, EventArgs e)
{
    
    //清空目标图层列表
    checkListTargetLayer.Items.Clear();
    string layerName;//设置临时变量存储图层名称
    //对Map中的每一个图层进行判断并添加图层名称
    for (int i = 0; i < currentMap.LayerCount; i++)
    {
        //如果该图层为图层组类型,则分别对所包含的每个图层进行操作
        if (currentMap.get_Layer(i) is GroupLayer)
        {
            //使用ICompositeLayer接口进行遍历操作
            ICompositeLayer compositeLayer = currentMap.get_Layer(i) as ICompositeLayer;
            for (int j = 0; 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 = 0;
    //将ComBoxMethod控件的默认选项设置为第一种控件选择方法
    comBoxMethod.SelectedIndex = 0;
}


(3)选中一个图层,就可以对这个图层的空间关系进行判断和操作。首先需要得到这个图层,怎么得到呢?根据图层的名称就可以获取到这个图层。

定义一个根据图层名称获取图层的方法:

//定义方法获取要素图层
private IFeatureLayer GetFeatureLayerByName(IMap map, string layerName)
{
    //对地图图层进行遍历
    for (int i = 0; i < map.LayerCount; i++)
    {
        //如果该图层为图层组类型,则分别对包含的每个图层进行操作
        if (map.get_Layer(i) is GroupLayer)
        {
            //使用ICompositeLayer接口进行遍历操作
            ICompositeLayer compositeLayer = map.get_Layer(i) as ICompositeLayer;
            for (int j = 0; 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;
}


(4)定义方法获取几何对象

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;
}

5)定义指定查询的方法

private void SelectFeaturesBySpatial()
{
    //定义和创建用于查询的ISpatialFilter接口对象
    ISpatialFilter spatialFilter = new SpatialFilterClass();
    //默认设定用于查询的空间几何体为当前地图源图层中所有要素几何体的集合
    spatialFilter.Geometry = GetFeatureLayerGeometryUnion(GetFeatureLayerByName(currentMap, comBoxSourceLayer.SelectedItem.ToString()));
    //根据对空间选择方法的选择采用相应的空间选择方法
    switch (comBoxMethod.SelectedIndex)
    {
        case 0:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            break;
        case 1:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelWithin;
            break;
        case 2:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
            break;
        case 3:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelTouches;
            break;
        case 4:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses;
            break;
        case 5:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelEnvelopeIntersects;
            break;
        case 6:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelOverlaps;
            break;
        default:
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            break;
    }
    //对选择的目标图层进行遍历,并对每一个图层进行空间查询,查询结果将放在选择集中
    IFeatureLayer featureLayer;
    //对所有选择的目标图层进行遍历
    for (int i = 0; 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);
}

(6)定义下面三个按钮的事件

private void btnClose_Click(object sender, EventArgs e)
{
    this.Dispose();
}

private void btnOk_Click(object sender, EventArgs e)
{
    try
    {
        SelectFeaturesBySpatial();
        this.Close();
    }
    catch { }
}

private void btnApply_Click(object sender, EventArgs e)
{
    try
    {
        SelectFeaturesBySpatial();                
    }
    catch { }
}



3、在主窗体中添加菜单,根据空间位置查询,其中运行的代码入下:

frmQureyByLocation form = new frmQureyByLocation();
form.CurrentMap = axMapControl1.Map;
form.Show();
this.axMapControl1.Map.ClearSelection();
axMapControl1.Refresh();


4、思考:鹰眼中没刷新,如何刷新?



https://blog.sciencenet.cn/blog-3373120-1115528.html

上一篇:ArcGIS Engine二次开发学习(10)PageLayoutControl
下一篇:ArcGIS Engine二次开发学习(12)缓冲区分析
收藏 IP: 121.69.12.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-3-29 16:14

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部