Thursday, 11 October 2018

c# - Near analysis with mixed feature types in ArcObjects


I am trying to emulate the Near (analysis) ArcGIS tool in ArcObjects. http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//00080000001q000000


I want to use Mixed Feature Types. I have a point, polygon and line feature class and I want to use Near to compare all three of them with each other. This can be done one featureclass at a time like so (pseudocode logic):




  1. Create IFeatureIndex





  2. Store my feature class in IFeatureIndex.FeatureClass




  3. Use IIndexQuery.NearestFeature for every IGeometry in a feature class to get distance to the nearest feature




The problem I am running into is that I can only store one feature class in IFeatureIndex. I need to store three different feature classes (points, lines and polygons) to be able to properly execute my comparison. How can I do this? ESRI's feature that I linked above has managed to do this but there is unfortunately no way to peek at the code behind the geoprocessing tool that I know of.


Edit: I have solved this. See the answer below.




Answer



I solved this earlier today. Here is the code. A short pseudocode explanation follows.


        ESRI.ArcGIS.Geometry.IGeometryBag pGeometryBag = new GeometryBagClass();
ESRI.ArcGIS.Geometry.IGeometryCollection pGeometryCollection = (IGeometryCollection)pGeometryBag;

ESRI.ArcGIS.Carto.IEnumLayer pEnumLayer; //get all layers in the map
pEnumLayer = pDoc.FocusMap.Layers;


ESRI.ArcGIS.Carto.ILayer pLayer; //create a layer to store looped values of point combobox layers

pLayer = pEnumLayer.Next();

while (pLayer != null)//Get all the features and stick them into the geometry collection
{

ESRI.ArcGIS.Carto.IFeatureLayer pFeatureLayer = (IFeatureLayer)pLayer;
if (pLayer == statusforselectedlayer)
{
ITable pTable = (ITable)pFeatureLayer.FeatureClass;
List OIDList = new List();

IQueryFilter queryFilter = new QueryFilterClass();
queryFilter.SubFields = pFeatureLayer.FeatureClass.OIDFieldName;
ICursor pCursor = pTable.Search(queryFilter, false);
IRow pRow = null;
while((pRow = pCursor.NextRow()) != null)
{
OIDList.Add(pRow.OID);
}

IFeatureCursor blocksCursor = pFeatureLayer.FeatureClass.GetFeatures(OIDList.ToArray(), false);

IFeature blockFeature = null;
while ((blockFeature = blocksCursor.NextFeature()) != null)
{
pGeometryCollection.AddGeometry(blockFeature.Shape);
}

}

ISpatialIndex spatialIndex = (ISpatialIndex)pGeometryBag;
spatialIndex.AllowIndexing = true;

spatialIndex.Invalidate();

ISpatialFilter spatialFilter = new SpatialFilterClass();
spatialFilter.Geometry = pGeometryBag;

ESRI.ArcGIS.Geometry.IEnumGeometry pEnumGeometry = (IEnumGeometry)pGeometryBag;
pEnumGeometry.Reset();
ESRI.ArcGIS.Geometry.IGeometry pGeometry = pEnumGeometry.Next();

List distances = new List();


while (pGeometry != null)
{
IProximityOperator pProximity = (IProximityOperator)pGeometry;

ESRI.ArcGIS.Geometry.IEnumGeometry pEnumGeomBag = (IEnumGeometry)pGeometryBag;
ESRI.ArcGIS.Geometry.IGeometry pGeomBagIterable = pEnumGeomBag.Next();

while (pGeomBagIterable != null)
{


distances.Add(pProximity.ReturnDistance(pGeomBagIterable));
pGeomBagIterable = pEnumGeomBag.Next();
}
pGeometry = pEnumGeometry.Next();


}

The code loops through all layers in the map, takes all the features in a specified layer if it meets a certain criteria, and stores those features into an IGeometryBag. The code then loops through every IGeometry in the created IGeometryBag and compares each IGeometry to all other IGeometry in the IGeometryBag, getting the distance each time using IProximityOperator. These distances are stored in a list of type double named distances.



No comments:

Post a Comment