2

I try to add a single buffer around the shape of the selected features. So I step through each selected feature and add it's shape to a GeometryBag. With ITopologicalOperator2.ConstructUnion I create a union geometry. But when I use this geometry to add an element, nothing appears after Refresh.

The code part for adding an element does work, when I directly assign element.Geometry = feature.Shape. So ConstructUnion seems to fail here. Any ideas why?

I already found out, that I have to simplify the shapes before adding it to GeometryBag and to set the SpatialReference on the GeometryBag before.

ESRI.ArcGIS.Carto.IGraphicsContainer graphicsContainer = (ESRI.ArcGIS.Carto.IGraphicsContainer)activeView.FocusMap;

ESRI.ArcGIS.Geodatabase.IEnumFeature enumFeature = (ESRI.ArcGIS.Geodatabase.IEnumFeature)map.FeatureSelection;
enumFeature.Reset();
ESRI.ArcGIS.Geodatabase.IFeature feature = enumFeature.Next();

IGeometryBag geoBag = new GeometryBagClass();
geoBag.SpatialReference = activeView.FocusMap.SpatialReference;
IGeometryCollection geometriesToUnion = geoBag as IGeometryCollection;
while (!(feature == null))
{
  ITopologicalOperator2 shape = feature.ShapeCopy as ITopologicalOperator2;
  shape.IsKnownSimple_2 = false; // see nef001's answer
  shape.Simplify();
  geometriesToUnion.AddGeometry(shape as IGeometry);
  feature = enumFeature.Next();
}

IPolygon poly = new PolygonClass();
resultPolygon.SpatialReference = activeView.FocusMap.SpatialReference; // see Petr Krebs's comment
ITopologicalOperator2 resultPolygon = poly as ITopologicalOperator2;
resultPolygon.ConstructUnion(geometriesToUnion as IEnumGeometry);
IFillShapeElement fillShapeElement = new ESRI.ArcGIS.Carto.PolygonElementClass();
fillShapeElement.Symbol = fillSymbol;
ESRI.ArcGIS.Carto.IElement element = (IElement)fillShapeElement;
topologicalOperator = (ESRI.ArcGIS.Geometry.ITopologicalOperator)resultPolygon;
//element.Geometry = topologicalOperator.Buffer(distance);
element.Geometry = resultPolygon as IGeometry; // To make sure, it's not the Buffering that goes wrong
graphicsContainer.AddElement(element, 0);

Update: To address Petr Krebs suggestions

  • I changed the assignment of geometriesToUnion.AddGeometry to feature.ShapeCopy.
  • I changed the assignment of element.Geometry to resultPolygon instead of the buffer output.

Both didn't help.

  • For testing I use a single layer where I select three polygon features. So the are all polygons and have the same SpatialReference.
  • resultPolygon.IsEmpty after ConstructUnion is false.

Update 2

  • Regarding Nef001's answer I added shape.IsKnownSimple_2 = false; but it didn't change the result.

Update 3

  • Regarding Petr's answer I set the spatial reference before Union() but it didn't help.
12
  • 1
    On your initial feature selection that is being enumerated have you verified that only one type of geometry is selected (e.g. just polygons)?
    – AHigh
    Oct 1, 2012 at 15:27
  • @AHigh: Yes, I do make sure that there is only one geometry type. Thanks for pointing it out.
    – gumo
    Oct 2, 2012 at 7:21
  • Does creating the element with polygon geometry directly from, say, the first selected polygon work?
    – Petr Krebs
    Oct 2, 2012 at 9:26
  • @Petr, do you mean without using ConstructUnion? When I directly assign element.Geometry = feature.Shape it does work, as I pointed out. (made that more clear in the question) That's why I think it has to be something with ConstructUnion.
    – gumo
    Oct 2, 2012 at 9:54
  • As an off-chance -- since your geometries don't appear to be empty -- what is your graphicsContainer defined as?
    – AHigh
    Oct 2, 2012 at 19:05

4 Answers 4

1

ESRI Documentation says that this method does not support GeometryBags.

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/index.html#//002m000003vn000000

6
  • He is not using it on a geometry bag, but is using the GeometryBag coclass as a convenient implementation of IEnumGeometry.
    – Petr Krebs
    Oct 1, 2012 at 20:30
  • Petr, it doesn't mater what interface he is sending into the ConstructUnion method. The fact that the base class is a GeometryBag will prevent this from working. Oct 1, 2012 at 20:36
  • 2
    Not sure what you mean. He is calling ITopologicalOperator.ConstructUnion on resultPolygon, which is a Polygon instance. The argument to ConstructUnion is an IEnumGeometry (implemented by a GeometryBag), but none of the geometries in this enumeration is a geometry bag. Thus, there are no geometry bags upon which ConstructUnion operates.
    – Petr Krebs
    Oct 1, 2012 at 20:40
  • Hmm.. Seems I misread the documentation and made the assumption that the constructUnion wouldn't take a geometry bag as an argument rather than the fact that enumeration couldn't contain a geometry bag. My mistake. Oct 1, 2012 at 20:45
  • Agreed it is terrible wording on ESRI's part. As long as the individual elements of the geometry collection are not GeometryBags that shouldn't be the problem. In fact their own samples do it: resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/…
    – blah238
    Oct 1, 2012 at 20:48
1

Few things to try:

  1. Make sure the selection enumerator is either non-recycling (see IEnumFeatureSetup, or otherwise copy the feature geometries prior to adding them to the geometry bag (via IFeature.ShapeCopy).

  2. Make sure all the input geometries, as well as the newly created Polygon have the same spatial reference.

  3. Make sure all the input geometries are polygons, which you seem to be assuming.

  4. Check that it is not actually the subsequent buffer operation that prevents your code snippet from working as expected.

2
  • After every operation (Union and Buffer), check whether the resulting geometry is empty (IGeometry.IsEmpty) or not..
    – Petr Krebs
    Oct 1, 2012 at 20:49
  • Thanks for the hints. 1.) I changed the asignment to ShapeCopy, but with no result. 2. + 3.) For testing I use a single layer where I select three polygon features. 4.) For testing I directly used the resultPolygon instead of the Buffer output as element geometry, but it didn't helped. And 5.) resultPolygon.IsEmpty is false.
    – gumo
    Oct 2, 2012 at 8:44
0

I think calling Simplify() on ITopologicalOperator does nothing unless you first set IsKnownSimple to false.

Try adding to your code before the call to Simplify:

shape.IsKnownSimple_2 = false;

See the following Remarks in the documentation for ITopologicalOperator.Simplify() method:

Remarks This method first looks at the ITopologicalOperator::IsKnownSimple flag before starting processing. If the flag is 'true' then operation is interrupted and the geometry is considered simple. If the flag is 'false' then the geometry consistency is checked and the geometry is updated as needed.

1
  • Thanks. I added it to both my source and the question. Unfortunately it didn't help with the problem.
    – gumo
    Oct 8, 2012 at 7:22
0

I do not think code in question successfully builds at the moment..I made a few edits..Cast the resultpolygon to ITopologicalOperator2 and added a Type.Missing object parameter to the AddGeometry function..It works for me.

IGeometryCollection geometriesToUnion = geoBag as IGeometryCollection;
object missing = Type.Missing;
while (!(feature == null))
{
    ITopologicalOperator2 shape = feature.ShapeCopy as ITopologicalOperator2;
    shape.IsKnownSimple_2 = false; // see nef001's answer
    shape.Simplify();

    geometriesToUnion.AddGeometry(shape as IGeometry, ref missing, ref missing);
    feature = enumFeature.Next();
}

IPolygon poly = new PolygonClass();
poly.SpatialReference = activeView.FocusMap.SpatialReference;
ITopologicalOperator2 topologicalOperator;
topologicalOperator = poly as ITopologicalOperator2;

topologicalOperator.ConstructUnion(geometriesToUnion as IEnumGeometry);
IFillShapeElement fillShapeElement = new ESRI.ArcGIS.Carto.PolygonElementClass();
ISimpleFillSymbol simpleFillSymbol = new SimpleFillSymbolClass();
fillShapeElement.Symbol = simpleFillSymbol;
IElement element = (IElement)fillShapeElement;

topologicalOperator = (ITopologicalOperator2)poly;
element.Geometry = topologicalOperator.Buffer(10);
graphicsContainer.AddElement(element, 0);
1
  • The need for adding Type.Missing arguments is dependent on the version of C# compiler you use. With C# 4.0 and newer compiler, it is not necessary. Note that C# 4 compiler can still target lower versions of .NET, e.g. .NET 3.5.
    – Petr Krebs
    Oct 9, 2012 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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