ArcEngine空间查询优化
开发环境:VS2013 + ArcEngine 10.4
开发背景:有两个图层,一个点图层,一个线图层,现在需要查询与线相交的点有哪些~大多数书上的方法如下:
public void Method_A(IFeatureLayer pSourceFeatureLayer, IFeatureLayer pTargetFeatureLayer)
{
IQueryFilter pQueryFilter = new QueryFilter();
pQueryFilter.AddField("Shape");
// 源图层
IFeatureClass pSourceFeatureClass = pSourceFeatureLayer.FeatureClass;
IFeatureCursor pSourceFeatureCursor = pSourceFeatureClass.Search(pQueryFilter, true);
IFeature pSourceFeature = pSourceFeatureCursor.NextFeature();
if (pSourceFeature == null)
{
return;
}
// 目标图层
IFeatureSelection pTargetFeatureSelection = pTargetFeatureLayer as IFeatureSelection;
ISpatialFilter pSpatialFilter = new SpatialFilter();
while (pSourceFeature != null)
{
pSpatialFilter.Geometry = pSourceFeature.ShapeCopy;
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
pTargetFeatureSelection.SelectFeatures(pSpatialFilter, esriSelectionResultEnum.esriSelectionResultAdd, false);
pSourceFeature = pSourceFeatureCursor.NextFeature();
}
Marshal.ReleaseComObject(pSourceFeatureCursor);
// 刷新视图
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null);
}
20毫秒!!!该方法的缺点:一旦数据量较大时,遍历次数较多,时间效率就会较低。我们可以回想一下,传统关系型数据库怎么优化查询?除了优化SQL,创建索引也是一个较好的方法,在ArcEngne中也同样可以创建空间索引,代码如下:
public void Method_B(IFeatureLayer pSourceFeatureLayer, IFeatureLayer pTargetFeatureLayer)
{
IFeatureClass pSourceFeatureClass = pSourceFeatureLayer.FeatureClass;
IGeoDataset pGeoDataset = pSourceFeatureClass as IGeoDataset;
ISpatialReference pSpatialReference = pGeoDataset.SpatialReference;
// 实体几何
IGeometryBag pGeometryBag = new GeometryBag() as IGeometryBag;
pGeometryBag.SpatialReference = pSpatialReference;
IGeometryCollection pGeometryCollection = pGeometryBag as IGeometryCollection;
// 要素游标
IFeatureCursor pSourceFeatureCursor = pSourceFeatureClass.Search(null, true);
IFeature pSourceFeature = pSourceFeatureCursor.NextFeature();
if (pSourceFeature == null)
{
return;
}
// 添加实体
object missing = Type.Missing;
while (pSourceFeature != null)
{
pGeometryCollection.AddGeometry(pSourceFeature.ShapeCopy, ref missing, ref missing);
pSourceFeature = pSourceFeatureCursor.NextFeature();
}
Marshal.ReleaseComObject(pSourceFeatureCursor);
// 创建空间索引
ISpatialIndex pSpatialIndex = pGeometryBag as ISpatialIndex;
pSpatialIndex.AllowIndexing = true;
pSpatialIndex.Invalidate();
// 创建空间过滤器
ISpatialFilter pSpatialFilter = new SpatialFilter();
pSpatialFilter.Geometry = pGeometryBag;
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
// 刷新视图
IFeatureSelection pTargetFeatureSelection = pTargetFeatureLayer as IFeatureSelection;
pTargetFeatureSelection.SelectFeatures(pSpatialFilter, esriSelectionResultEnum.esriSelectionResultAdd, false);
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null);
}
15毫秒!!!这种方法已经能够满足大部分需求,但还有没有更快的方法?ArcEngine有一个IQueryByLayer接口,这个接口很有意思,首先贴上代码:
public void Method_C(IFeatureLayer pSourceFeatureLayer, IFeatureLayer pTargetFeatureLayer)
{
IQueryByLayer pQueryByLayer = new QueryByLayer();
pQueryByLayer.FromLayer = pTargetFeatureLayer;
pQueryByLayer.ByLayer = pSourceFeatureLayer;
pQueryByLayer.LayerSelectionMethod = esriLayerSelectionMethod.esriLayerSelectIntersect;
pQueryByLayer.UseSelectedFeatures = false;
// 刷新视图
IFeatureSelection pFeatureSelection = pTargetFeatureLayer as IFeatureSelection;
ISelectionSet pSelectionSet = pQueryByLayer.Select();
pFeatureSelection.SelectionSet = pSelectionSet;
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null);
}
13毫秒!!!对于图层与图层之间的查询,这个方法速度最快~而且大家可以看一下IQueryByLayer的成员:
// 摘要:
// The type of selection method to be performed.
[DispId(1610678275)]
double BufferDistance { set; }
//
// 摘要:
// The buffer units.
[DispId(1610678276)]
esriUnits BufferUnits { set; }
//
// 摘要:
// The layer features will be selected from.
[DispId(1610678273)]
IFeatureLayer ByLayer { set; }
//
// 摘要:
// Provides access to the methods and properties of QueryByLayer.
[DispId(1610678272)]
IFeatureLayer FromLayer { set; }
//
// 摘要:
// The input layer that contains features to base the selection on.
[DispId(1610678274)]
esriLayerSelectionMethod LayerSelectionMethod { set; }
//
// 摘要:
// The result type of the selection where it can be specified that the selection
// adds to a current selection etc.
[DispId(1610678278)]
esriSelectionResultEnum ResultType { set; }
//
// 摘要:
// Indicates whether selected features will be used.
[DispId(1610678277)]
bool UseSelectedFeatures { set; }
// 摘要:
// Selects the features based on the input parameters and returns a selection
// set.
ISelectionSet Select();
我们再来看一下ArcMap中的空间查询界面,如下图:
我们发现,IQueryByLayer接口中的BuferDistance对应“应用搜索距离”,BufferUnits对应搜索距离的单位,由于ArcGIS Desktop和ArcEngine都是基于ArcObjects,所以Desktop中的空间查询也是基于IQueryByLayer接口。
转载自:https://blog.csdn.net/HerryDong/article/details/82817022