Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

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.
share
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 '12 at 15:27
    
@AHigh: Yes, I do make sure that there is only one geometry type. Thanks for pointing it out. –  gumo Oct 2 '12 at 7:21
    
Does creating the element with polygon geometry directly from, say, the first selected polygon work? –  Petr Krebs Oct 2 '12 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 '12 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 '12 at 19:05

4 Answers 4

ESRI Documentation says that this method does not support GeometryBags.

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

share
    
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 '12 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. –  Jeff Machamer Oct 1 '12 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 '12 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. –  Jeff Machamer Oct 1 '12 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 '12 at 20:48

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.

share
    
After every operation (Union and Buffer), check whether the resulting geometry is empty (IGeometry.IsEmpty) or not.. –  Petr Krebs Oct 1 '12 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 '12 at 8:44

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.

share
    
Thanks. I added it to both my source and the question. Unfortunately it didn't help with the problem. –  gumo Oct 8 '12 at 7:22

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);
share
    
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 '12 at 18:13

This site is currently not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .