3

I am currently writing an an addin for ArcGIS in C#. The premise of the application is, the user will select a polygon, a multi ring buffer is created from the centroid of the polygon. The buffer distances in this case being 250m and 500m.

I have found a bit of code which works, in that the multiring buffer is created

            IBufferConstructionProperties bcp = new BufferConstructionClass();
            ESRI.ArcGIS.esriSystem.IDoubleArray dis = new ESRI.ArcGIS.esriSystem.DoubleArrayClass();
            dis.Add(250);
            dis.Add(500);
            bcp.DistanceOffsets = dis;
            IBufferConstruction bc = bcp as BufferConstruction;

            IGeometryCollection originalGeometryBag;
            IEnumGeometry originalGeometryEnum;
            IGeometryCollection outBufferedGeometryCol;
            IGeometry resultGeo = null;
            originalGeometryBag = new GeometryBagClass();
            originalGeometryBag.AddGeometry(centroid, Type.Missing, Type.Missing);
            ISimpleFillSymbol simpleFillSymbol = new ESRI.ArcGIS.Display.SimpleFillSymbolClass();
            IFillShapeElement fillShapeElement;


            simpleFillSymbol.Style = esriSimpleFillStyle.esriSFSHollow;
            originalGeometryEnum = originalGeometryBag as IEnumGeometry;
            outBufferedGeometryCol = new GeometryBagClass();
            bc.ConstructBuffersByDistances2(originalGeometryEnum, dis, outBufferedGeometryCol);
            IEnumGeometry resultingGeometries;
            resultingGeometries = outBufferedGeometryCol as IEnumGeometry;
            if (resultingGeometries != null)
                resultGeo = resultingGeometries.Next();
            while (resultGeo != null)
            {
                fillShapeElement = new ESRI.ArcGIS.Carto.PolygonElementClass();
                fillShapeElement.Symbol = simpleFillSymbol;
                element = (ESRI.ArcGIS.Carto.IElement)fillShapeElement; // Explicit Cast

                element.Geometry = resultGeo;
                gc.AddElement(element, 0);
                resultGeo = resultingGeometries.Next();
            }

            mxDoc.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

However the end result is not what I was expecting enter image description here

As you can see from the hollow buffer, it has created the 500m buffer but has then added the 250m buffer onto the end, when I was expecting something similar to the coloured buffer, where the origin of the buffer is where the centroid of the point is.

Does anyone have any idea on creating a buffer that looks like the coloured one, which was done using the Create Multiple Rings Buffer tool in ArcToolbox.

EDIT** I should have added, from my final buffer, the larger buffer needs to have a donut hole in the middle.

Thanks

1

I had a go at this in VBA (sorry don't use C#) and was able to create the desired output. The trick is to add the same number of points in your input geometry bag as there are distances in your distance DoubleArray. So the code below worked for me:

Public Sub createBuffers()
    ' Get Map document and graphics container
    Dim pMXD As IMxDocument
    Set pMXD = ThisDocument
    Dim pGC As IGraphicsContainer
    Set pGC = pMXD.FocusMap

    ' Create a collection of TWO points, imagine these as stacked
    Dim pGeometryCollection As IGeometryCollection
    Set pGeometryCollection = New GeometryBag
    Dim pPoint As IPoint
    Set pPoint = New Point
    pPoint.PutCoords 1000, 1000
    pGeometryCollection.AddGeometry pPoint
    pGeometryCollection.AddGeometry pPoint
    Dim pEnumGeometry As IEnumGeometry
    Set pEnumGeometry = pGeometryCollection

    ' Create the distance array 1 for EACH point
    Dim dis As IDoubleArray
    Set dis = New DoubleArray
    dis.Add 250
    dis.Add 500

    ' Construct buffers
    Dim pBufferConstructionProperties As IBufferConstructionProperties
    Set pBufferConstructionProperties = New BufferConstruction
    Set pBufferConstructionProperties.DistanceOffsets = dis
    pBufferConstructionProperties.UnionOverlappingBuffers = False
    pBufferConstructionProperties.ExplodeBuffers = True
    Dim pBufferConstruction As IBufferConstruction
    Set pBufferConstruction = pBufferConstructionProperties
    Dim pBuffGeomColl As IGeometryBag
    Set pBuffGeomColl = New GeometryBag
    pBufferConstruction.ConstructBuffersByDistances2 pEnumGeometry, dis, pBuffGeomColl
    Set pEnumGeometry = pBuffGeomColl
    pEnumGeometry.Reset

    ' Draw buffers as simple graphics
    Dim pGeom As IGeometry
    Dim pElement As IElement
    Dim pSimpleFillSymbol As ISimpleFillSymbol
    Set pSimpleFillSymbol = New SimpleFillSymbol
    pSimpleFillSymbol.Style = esriSFSHollow
    Dim pFillShapeElement As IFillShapeElement
    Set pFillShapeElement = New PolygonElement
    pFillShapeElement.Symbol = pSimpleFillSymbol
    Set pGeom = pEnumGeometry.Next
    Do While Not pGeom Is Nothing
        Set pFillShapeElement = New PolygonElement
        pFillShapeElement.Symbol = pSimpleFillSymbol
        Set pElement = pFillShapeElement
        pElement.Geometry = pGeom
        pGC.AddElement pElement, 0
        Set pGeom = pEnumGeometry.Next
    Loop
    pMXD.ActiveView.Refresh
End Sub

Multi-ringed

EDIT - Donuts!

OK well in that case I would never have used that approach I would have done it like this:

Public Sub createBuffers()
    ' Get Map document and graphics container
    Dim pMXD As IMxDocument
    Set pMXD = ThisDocument
    Dim pGC As IGraphicsContainer
    Set pGC = pMXD.FocusMap

    ' Create a point
    Dim pPoint As IPoint
    Set pPoint = New Point
    pPoint.PutCoords 1000, 1000

    ' Create Buffers
    Dim pPolygon1 As IPolygon
    Dim pPolygon2 As IPolygon
    Dim pTopoOp As ITopologicalOperator
    Set pTopoOp = pPoint
    Set pPolygon1 = pTopoOp.Buffer(250)
    Set pPolygon2 = pTopoOp.Buffer(500)

    ' Symmetric Difference (the outer ring - polygon with a hole in it)
    Dim pGeom As IGeometry
    Set pTopoOp = pPolygon1
    Set pGeom = pTopoOp.SymmetricDifference(pPolygon2)

    ' Draw buffers as simple graphics
    ' First outer ring
    Dim pElement As IElement
    Dim pSimpleFillSymbol As ISimpleFillSymbol
    Set pSimpleFillSymbol = New SimpleFillSymbol
    pSimpleFillSymbol.Style = esriSFSHollow
    Dim pFillShapeElement As IFillShapeElement
    Set pFillShapeElement = New PolygonElement
    pFillShapeElement.Symbol = pSimpleFillSymbol
    Set pElement = pFillShapeElement
    pElement.Geometry = pGeom
    pGC.AddElement pElement, 0

    ' Now add solid inner circle
    Set pFillShapeElement = New PolygonElement
    pFillShapeElement.Symbol = pSimpleFillSymbol
    Set pElement = pFillShapeElement
    pElement.Geometry = pPolygon1
    pGC.AddElement pElement, 0
    pMXD.ActiveView.Refresh
End Sub

This should give you the output you require, I have coloured the graphics in and deliberately displaced them to prove the outer is a polygon with a hole in it.

Donut ring

  • I'll give it a whirl... From your code and resulting buffer, if you were to remove inner buffer, does the larger buffer (500m) have a donut hole? – MapMan Sep 16 '14 at 23:24
  • No they are overlapping circles. I think you can create the donut hole by altering one of the BufferConstructionProperties? – Hornbydd Sep 17 '14 at 9:07
  • The BufferConstructionProperties has nothing, tried the various properties. But nothing seems to do the donut'ing. – MapMan Sep 17 '14 at 15:27
  • any ideas? Check varius properties but I seem to be going round in circles (pun intended) – MapMan Sep 18 '14 at 13:37

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.