[GIS] Geometry from multiple selected features into one geometry

arcmaparcobjectscfeaturesgeometry

Lets see if I can explain what I'm trying to do. First of all I have developed an AddIn for ArcMap that can take one selected feature (Polygon) on a layer, grab the geometry of that feature, and save it to a SQL Server database. What I would like to do is to save multiple selected features, not as individual geometries (ie. one row per feature/geometry) but as one "piece of geometry" containing the selected polygons. This is the code I have so far:

IFeatureLayer featureLayer = ArcMap.Document.CurrentContentsView.SelectedItem as IFeatureLayer;
        if (featureLayer != null)
        {
            IFeatureSelection featSel = featureLayer as IFeatureSelection;
            IEnumIDs idList = featSel.SelectionSet.IDs;

            int index = idList.Next();
            List<int> indexes = new List<int>();

            while (index != -1)
            {
                indexes.Add(index);
                index = idList.Next();
            }

            IFeatureClass featureClass = featureLayer.FeatureClass;
            IFeature feature = featureClass.GetFeature(indexes[0]);
            IGeometry geometry = feature.Shape as IGeometry;
            // Save to database
        }

As you can see I can get all the indexes of the selected features of the selected layer and get the geometry, the challenge is to "concatenate" all the geometries into one…hope it makes sense 🙂

Any suggestions?

P.S …and if any of you have a better way of looping through the idList…please let me know 🙂

UPDATE:

A BIG thanks to Petr! Followed your instructions and it worked in the first try!

Here's the code I ended up with:

IFeatureSelection featSel = featureLayer as IFeatureSelection;

                if (featSel.SelectionSet.Count > 0)
                {
                    ITopologicalOperator resultPolygon = new Polygon() as ITopologicalOperator;
                    IGeometryCollection geometriesToUnion = new GeometryBag() as IGeometryCollection;

                    ICursor cursor;
                    featSel.SelectionSet.Search(null, false, out cursor);

                    IFeatureCursor featureCursor = cursor as IFeatureCursor;
                    IFeature feature;
                    while ((feature = featureCursor.NextFeature()) != null)
                    {
                        geometriesToUnion.AddGeometry(feature.Shape as IGeometry);
                    }

                    resultPolygon.ConstructUnion(geometriesToUnion as IEnumGeometry);

                    // Save resultPolygon to a database
                }

Best Answer

You can use ITopologicalOperator.ConstructUnion.

The steps would be as follows:

  1. Create an instance of the Polygon class and cast that to ITopologicalOperator. This polygon instance will contain the result.
  2. Since ITopologicalOperator.ConstructUnion takes an IEnumGeometry to specify the geometries to union (or in your words, concatenate), create an instance of GeometryBag class, which implements IEnumGeometry.
  3. Cast the geometry bag to IGeometryCollection so that you can add your source polygons to it.
  4. Pass your geometry bag to the ITopologicalOperator.ConstructUnion method on the polygon created in step 1.

As far as enumerating the selection is concerned, your method of retrieving list of IDs and getting the row for every single ID is VERY inefficient. Performance is much better if you just use IFeatureSelection.SelectionSet.Search() method. You would specify a null query filter argument when calling this method since you want all the features in the selection. The result will be a cursor which you can enumerate.