ArcEngine|空间查询功能

发布时间 2023-06-09 16:17:17作者: Weltㅤ

所有的代码已经传到了我的GitHub,需要的请自取,GitHub项目地址:https://github.com/weltme/T_ArcMap

(1)界面设计

image-20230609160135515

(2)思路

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

最后在【根据空间位置选择】窗体中完成空间查询功能。在DataGrid view中显示出查询结果。

(3)代码实现

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;

namespace TArcMap.GeoProcessing
{
    public partial class SpatialQueryForm : Form
    {
        private List<IFeatureLayer> _layers = new List<IFeatureLayer>();
        public IFeatureLayer TargetLayer { get; set; }
        private IMap _IMap;
        private ICursor ResultCursor { get; set; }

        public ISpatialFilter SpatialFilter
        {
            get;
            set;
        }

        public SpatialQueryForm()
        {
            InitializeComponent();
        }

        public SpatialQueryForm(IMap map)
            : this()
        {
            this._IMap = map;
            IEnumLayer layerInterator = map.Layers;
            layerInterator.Reset();
            ILayer tmpLayer = layerInterator.Next();
            while (tmpLayer != null)
            {
                //checking the layer type is the Feature layer
                if (tmpLayer is IFeatureLayer)
                {
                    IFeatureLayer tmpFeatureLayer = tmpLayer as IFeatureLayer;
                    this._layers.Add(tmpFeatureLayer);
                    tmpLayer = layerInterator.Next();
                }
            }
            this.SpatialFilter = new SpatialFilter();
            //set the layer name
            this.initializeControlItems();
        }

        private void initializeControlItems()
        {
            if (this._layers != null && this._layers.Count > 0)
            {
                for (int i = 0; i < this._layers.Count; i++)
                {
                    //add to the target list
                    this.comboBox_targetLayer.Items.Add(_layers[i].Name);
                    //add to the sources list
                    this.comboBox_SourceLayer.Items.Add(_layers[i].Name);
                }
            }

            this.comboBox_spRelation.DataSource = Enum.GetNames(typeof(esriSpatialRelEnum));
        }


        /// <summary>
        /// 1.根据提供的图层名称,找到对应 FeatureLayer;
        /// 2.将对应的FeatureLayer中所有的Feature填充到GeometryBag中,作为返回值;
        /// </summary>
        /// <param name="layerName">图层名称</param>
        /// <returns>图层中所有的要素组成的GeometryBag</returns>
        private GeometryBag extractSourceGeometry(string layerName)
        {
            IFeatureLayer sourceFeatureLayer = GetLayerByName(layerName);

            //新建立一个GeometryBag将所有的FeatureClass中的Geometry作为查询的source。
            GeometryBag geometryBag = new GeometryBag();
            IGeometryCollection geometryCollection = geometryBag as IGeometryCollection;
            //提取FeatureLayer中的FeatureClass,提取其中的sp并赋值给GeometryBag
            IGeoDataset sourceGeoDataset = (IGeoDataset)sourceFeatureLayer.FeatureClass;
            ISpatialReference spRef = sourceGeoDataset.SpatialReference;
            geometryBag.SpatialReference = spRef;
            //提取FeatureClass中的每个Feature并添加到GeometryBag中。
            IFeatureCursor soruceFeatureCursor = sourceFeatureLayer.Search(null, false);
            IFeature pFeature = null;
            object missingType = Type.Missing;
            while ((pFeature = soruceFeatureCursor.NextFeature()) != null)
            {
                geometryCollection.AddGeometry(pFeature.Shape, ref missingType, ref missingType);
            }
            //设置GeometryBag中的空间索引,优化检索速度。
            ISpatialIndex spatialIndex = (ISpatialIndex)geometryBag;
            spatialIndex.AllowIndexing = true;
            spatialIndex.Invalidate();

            return geometryBag;
        }

        /// <summary>
        /// 根据图层名称在this._layers中找到对应的FeatureLayer
        /// </summary>
        /// <param name="layerName">string:提供图层名称</param>
        /// <returns>IFeatureLayer:返回矢量图层</returns>
        private IFeatureLayer GetLayerByName(string layerName)
        {
            IEnumerable<IFeatureLayer> sourceLayers = from IFeatureLayer layer in _layers
                                                      where layer.Name == layerName
                                                      select layer;
            List<IFeatureLayer> sourceLayerList = sourceLayers.ToList();
            IFeatureLayer sourceFeatureLayer = sourceLayerList[0];
            return sourceFeatureLayer;
        }

        private esriSpatialRelEnum extractSpRelation(string spRelationName = "esriSpatialRelIntersects")
        {
            //Enum.Parse(typeof(esriSpatialRelationEnum), spRelationName);//不稳定;
            esriSpatialRelEnum spRelation;
            if (Enum.TryParse(spRelationName, out spRelation))
            {
                return spRelation;
            }
            else
            {
                return esriSpatialRelEnum.esriSpatialRelIntersects;
            }
        }

        private void button_buildSpFilter_Click(object sender, EventArgs e)
        {
            //1 提取筛选用图层,转换为GeometryBag
            GeometryBag geometryBag = this.extractSourceGeometry(this.comboBox_SourceLayer.SelectedItem.ToString());
            esriSpatialRelEnum spRelation = this.extractSpRelation(this.comboBox_spRelation.SelectedItem.ToString());
            //构造SpFilter
            this.SpatialFilter.Geometry = geometryBag;
            //SpatialFilter.GeometryField = pInputFeatureLayer.FeatureClass.ShapeFieldName;
            this.SpatialFilter.SpatialRel = spRelation;
            //SpatialFilter.SpatialRelDescription = overlap_typestring;
            //SpatialFilter.SubFields = "shape";
            this.TargetLayer = this.GetLayerByName(this.comboBox_targetLayer.SelectedItem.ToString());
            if (this.SpatialFilter != null && this.TargetLayer != null)
            {
                IFeatureCursor featureCursor = this.PerformSpatialQuery(this.TargetLayer.FeatureClass, this.SpatialFilter);
                this.ResultCursor = featureCursor as ICursor;
            }
            if (this.dataGridView1 != null && this.ResultCursor != null)
            {
                this.FillDataGrid(this.dataGridView1);
            }
        }

        public IFeatureCursor PerformSpatialQuery(IFeatureClass featureClass, ISpatialFilter filter)
        {
            IFeatureCursor featureCursor = featureClass.Search(filter, false);
            return featureCursor;
        }

        private void FillDataGrid(DataGridView gridView)
        {
            if (gridView == null || this.TargetLayer == null || this.ResultCursor == null)
            {
                return;
            }
            IFeatureClass curFeatureClass = this.TargetLayer.FeatureClass;

            this.dataGridView1.Columns.Clear();
            IFields fields = ResultCursor.Fields;
            for (int i = 0; i < fields.FieldCount; i++)
            {
                DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
                column.HeaderText = fields.get_Field(i).Name;
                this.dataGridView1.Columns.Add(column);
            }
            IRow row = ResultCursor.NextRow();
            while (row != null)
            {
                object[] values = new object[row.Fields.FieldCount];
                for (int i = 0; i < row.Fields.FieldCount; i++)
                {
                    values[i] = row.Value[i];

                }
                this.dataGridView1.Rows.Add(values);
                row = ResultCursor.NextRow();
            }
        }

    }
}

(4)结果

加载地图

2023_6_9_1603

打开空间查询窗口

2023_6_9_1603_1

在道路图层中查询地震图层与州图层相交的要素

2023_6_9_1603_2