1

I'm new to GIS (so I'm lost on this) and looking for a C# code sample to help me do 2 types of spatial queries. I have 2 Layers only. First layer is pipelines, which are polyline shapes so I can select multiple pipeline segments to make up an entire pipeline. Second Layer is facilities, which are point shapes.

Query 1: Select Pipeline Segments in the Pipeline Layer (Polylines) and find the facilities (in the Facility Layer) that are within a certain distance of selected Pipeline Segments.

Query 2: Select a single Facility in the Facility Layer (Point) and find the Pipeline Segments (Polylines) that are within a certain distance of the Facility Point.

I can do these queries via the ArcMap interface. I select the Source Features in the Attribute Table, then Selection Menu, Select by Location, select the "other" Layer as the Target Layer and for Spatial Selection Method I select "Target layer(s) features are within a distance of the Source layer feature". But now I need to do this in C# code for my ArcMap AddIn.

  • 1
    key words to search "arcobjects query select distance", you should find many code examples – artwork21 Dec 1 '15 at 21:10
  • @Dave Stuart, You should use spatail filter with arcobjects. Take a look at How to execute spatial queries and try to create some sample code and include more details in your question – Farid Cheraghi Dec 2 '15 at 3:15
  • Thanks @Farid Cher but I have searched high and low and visited that link several times. I thought my question is very clear for a GIS developer to answer with a pseudo code example. – Dave Stuart Dec 2 '15 at 15:01
0

Assuming you have a handle of your query featureclass and selected feature, you can use the following code snippet:

double searchDistance = 10; //this is your buffer distance
IFeatureClass fc = ...; //Query1: this is your facility feature class
IFeature feat = ...;// Query1: this is your selected pipeline feature

ISpatialFilter spatialFilter = new SpatialFilterClass();
if (searchDistance == 0)
    spatialFilter.Geometry = feat.Shape; // can be IGeometry
else
{
    ITopologicalOperator topoOperator = (ITopologicalOperator)feat.ShapeCopy;
    spatialFilter.Geometry = topoOperator.Buffer(searchDistance);
}

spatialFilter.GeometryField = fc.ShapeFieldName;
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

IFeatureCursor featureCursor = fc.Search(spatialFilter, true);

//loop through features in the cursor
  • Thanks Farid. I tried this a couple days ago and got some sort of result but it was not what I expected so I will have to look at it again on Monday. Thanks for the code sample though as it has helped. I mark this one UP if I can get the correct results. – Dave Stuart Dec 6 '15 at 20:23
  • We could discuss about the issues you are facing, here! – Farid Cheraghi Dec 7 '15 at 1:26
  • My code returns the same Facilities no matter what Pipeline I Select. In your code sample where would I actually use Selected Features from the Pipeline? I'm using IFeature feat = CurrentLayer.FeatureClass.GetFeature(1); to get the Set the Currently selected layer but these is no mention of the actual selected Pipeline rows. I think that is where I'm going wrong? – Dave Stuart Dec 7 '15 at 15:05
  • I think my question was quite clear that I was selecting Pipeline features (rows in the Pipeline attribute table) and wanted to run a Spatial Query against the Facilities Layer to get the closest Facilities to those selected Pipelines. I have however figured out the solution using this post. gis.stackexchange.com/questions/112018/…. – Dave Stuart Dec 9 '15 at 23:15
0

This was what I did to solve the problem. Some of it might need to be explained but I think it's very clear. Thanks to brenth. https://gis.stackexchange.com/users/19213/brenth

This helped a lot! Selecting features by location based on selected feature using ArcObjects?

   public void GetClosestFeatures(IEnumerable selectedFeatures)
   {
    try
    {
        var mxDocument = ArcMap.Application.Document as IMxDocument;
        if (mxDocument != null)
        {
            var map = mxDocument.FocusMap;
            var searchDistance = 1000.0;

            if(UI.LayerSelection.Equals("Pipeline"))
            {
                if (UI.txtRadiusToFacilities.Text != "")
                {
                    searchDistance = Convert.ToDouble(UI.txtRadiusToFacilities.Text);
                }
                else
                {
                    UI.txtRadiusToFacilities.Text = searchDistance.ToString(CultureInfo.InvariantCulture);
                }

                // This not 100% Accurate due to the Lattitude changing as you move north/south so if we know the lattite we can use
                // the MetersToDecimalDegrees function but this will do!
                searchDistance = Convert.ToDouble((UI.txtRadiusToFacilities.Text)) / (111.32 * 1000); 
            }
            else
            {
                if (UI.txtRadiusToPipelines.Text != "")
                {
                    searchDistance = Convert.ToDouble(UI.txtRadiusToPipelines.Text);
                }
                else
                {
                    UI.txtRadiusToPipelines.Text = searchDistance.ToString(CultureInfo.InvariantCulture);
                }

                // This not 100% Accurate due to the Lattitude changing as you move north/south so if we know the lattite we can use
                // the MetersToDecimalDegrees function but this will do!
                searchDistance = Convert.ToDouble((UI.txtRadiusToPipelines.Text)) / (111.32 * 1000); 
            }

            var cursor = GetSelectedFeatures(CurrentLayer);
            // Default buffer is Decimal Degrees
            var polygon = UnionShapes(cursor, searchDistance);

            // Maybe use the name in place of the CurrentLayer.Name as this is to find Facilities for the Selected Pipelines
            var featureLayer = Utilities.GetOppositeFeatureLayerByFeatureClassName(map, CurrentLayer.Name);
            var filter = CreateSpatialFilter(featureLayer.FeatureClass, polygon);
            var cursor2 = GetSelectedItemsByShape(featureLayer.FeatureClass, filter);

            // Iterate through the features, viewing (as in this case) or editing them.
            IFeatureClass fc = Utilities.GetOppositeFeatureLayerByFeatureClassName(map, CurrentLayer.Name).FeatureClass;
            IFeature feature = null;

            if (UI.LayerSelection.Equals("Pipeline"))
            {
                var nameFacilityNameIndex = fc.Fields.FindField(GeodatabaseFieldNames.FacilityNameFieldName);
                var nameFacilityTypeIndex = fc.Fields.FindField(GeodatabaseFieldNames.FacilityTypeFieldFieldName);
                var counter = 0;
                UI.lvwFacilitiesSpatialResult.Items.Clear();
                try
                {
                    while ((feature = cursor2.NextFeature()) != null)
                    {
                        //Console.WriteLine("Facility Found: {0}", feature.get_Value(nameFieldIndex));
                        counter++;
                        string[] rowData =
                            {
                                (counter).ToString(CultureInfo.InvariantCulture),
                                feature.get_Value(nameFacilityNameIndex).ToString(),
                                feature.get_Value(nameFacilityTypeIndex).ToString()
                            };
                        var lvItem = new ListViewItem(rowData);
                        UI.lvwFacilitiesSpatialResult.Items.Add(lvItem);
                    }
                }
                catch (Exception ex)
                {
                    // Handle any errors that might occur on NextFeature().
                    MessageBox.Show(ex.Message, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }                            
            }
            else // Facility
            {
                var namePipelinenameIndex = fc.Fields.FindField(GeodatabaseFieldNames.PipelineNameFieldName);
                var companyNameFieldIndex = fc.Fields.FindField(GeodatabaseFieldNames.OperatorNameFieldName);
                var counter = 0;
                UI.lvwPipelinesSpatialResult.Items.Clear();
                try
                {
                    while ((feature = cursor2.NextFeature()) != null)
                    {
                        //Console.WriteLine("Facility Found: {0}", feature.get_Value(nameFieldIndex));
                        counter++;
                        string[] rowData =
                            {
                                (counter).ToString(CultureInfo.InvariantCulture),
                                feature.get_Value(namePipelinenameIndex).ToString(),
                                feature.get_Value(companyNameFieldIndex).ToString()
                            };
                        var lvItem = new ListViewItem(rowData);
                        UI.lvwPipelinesSpatialResult.Items.Add(lvItem);
                    }
                }
                catch (Exception ex)
                {
                    // Handle any errors that might occur on NextFeature().
                    MessageBox.Show(ex.Message, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }

}
public static IFeatureCursor GetSelectedFeatures(IFeatureLayer featureLayer)
{
    if (featureLayer == null) return null;
    IFeatureSelection fSel = (IFeatureSelection)featureLayer;
    ISelectionSet selSet = (ISelectionSet)fSel.SelectionSet;
    ICursor cursor = null;
    selSet.Search(null, false, out cursor);
    IFeatureCursor fCursor = cursor as IFeatureCursor;
    return fCursor;
}
public static IPolygon UnionShapes(IFeatureCursor cursor, double bufferDist)
{
    if (cursor == null) return null;
    IFeature pFeat = cursor.NextFeature();
    if (pFeat != null)
    {
        if (pFeat.Shape is IPoint || pFeat.Shape is IPolyline)
        {
            ITopologicalOperator ptopBuffer = (ITopologicalOperator)pFeat.Shape;
            IPolygon pTempPoly = (IPolygon)ptopBuffer.Buffer(bufferDist);
            ITopologicalOperator ptopUnion = (ITopologicalOperator)pTempPoly;
            pFeat = cursor.NextFeature();
            while (pFeat != null)
            {
                ptopBuffer = (ITopologicalOperator)pFeat.Shape;
                pTempPoly = (IPolygon)ptopBuffer.Buffer(bufferDist);
                ptopUnion = (ITopologicalOperator)ptopUnion.Union(pTempPoly);
                pFeat = cursor.NextFeature();
            }
            return (IPolygon)ptopUnion;
        }
        return null;
    }
    return null;
}
public static ISpatialFilter CreateSpatialFilter(IFeatureClass fc, IGeometry shape)
{
    if (fc == null) return null;

    ISpatialFilter sf = new SpatialFilterClass();
    sf.GeometryField = fc.ShapeFieldName;
    sf.Geometry = shape;
    sf.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

    return sf;
}
public static IFeatureCursor GetSelectedItemsByShape(IFeatureClass fc, ISpatialFilter filter)
{
    try
    {
        if (filter == null) return null;
        if (fc == null) return null;
        IFeatureCursor fcursor = fc.Search(filter, true);
        return fcursor;
    }
    catch
    {
        return null;
    }
}
public static ISelectionSet CursorToSelectionSet(IFeatureLayer layer, IFeatureCursor cursor)
{

    IFeatureSelection fSel = (IFeatureSelection)layer;
    if (cursor != null)
    {
        IFeature feat = cursor.NextFeature();
        while (feat != null)
        {
            fSel.Add(feat);
            feat = cursor.NextFeature();
        }
    }
    return fSel.SelectionSet;
}

Since I only have 2 Layers then I can do this.

public static IFeatureLayer GetOppositeFeatureLayerByFeatureClassName(IMap map, string featureClassName) { IFeatureLayer result = null; for (var i = 0; i

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.