How do I Remove Donut From A Polygon

3894
4
10-21-2016 03:20 AM
chandrasekhar_reddyguda
New Contributor III

Hi All,

I have thousands of buildings which few contains donuts, according to the customer requirement would like to remove  donuts.

Hence, Kindly provide a solution how can i remove these donuts using .net program.

Thanks in Advance

0 Kudos
4 Replies
JoshuaBixby
MVP Esteemed Contributor

A haven't done .NET programming in years, well, years and years.  Although I can't offer you specific objects and functions, I can say that polygons are made up of a series of linear rings.  If you can find and extract the exterior ring, you can create a polygon using it, and the donuts won't exist.  Or, you could try to remove the interior linear rings.  I am not sure which would be easier. 

by Anonymous User
Not applicable

Yep, IPolygon.FindExteriorRings is the method.

If you want to use geoprocessing or python you can also use the Eliminate Polygon Part tool.

JaredCaccamo
Esri Contributor

I think Joshua Bixby‌ has the right idea. Take a look at "IPolygon4.ExteriorRingBagwhich creates and returns a geometrybag that contains references to all exterior rings. You can take this and create a polygon with it and the donuts won't exist.

KristenE
New Contributor III

Here is a Python function that does what you need:

def fill_donut(in_lyr):
    '''Edits a layer in-place and fills all donut holes or gaps in the selected
    features. Will operate on entire layer if there are no features selected.
    Requires layer to honor selected features.
    '''
    desc = arcpy.Describe(in_lyr)
    shapefield = desc.ShapeFieldName
    rows = arcpy.UpdateCursor(in_lyr)
    n = 0
    polyGeo = arcpy.Array() # to hold edited shape
    polyOuter = arcpy.Array() # to hold outer ring
    for row in rows:
        feat = row.getValue(shapefield)
        qInterior = False
        for partNum in range(feat.partCount) :
            part = feat.getPart(partNum)
            for pt in iter(lambda:part.next(),None) : # iter stops on null pt
                polyOuter.append(pt)
            if part.count > len(polyOuter) :
                qInterior = True
            polyGeo.append(polyOuter) # reassemble each part
            polyOuter.removeAll() # ready for next part
        if qInterior : # in any part of this feature, otherwise skip update
            n+=1
            row.setValue(shapefield,polyGeo)
            rows.updateRow(row)
        polyGeo.removeAll()
    del rows,row
    msg = "Features with interior ring filled "+str(n)
    arcpy.AddMessage(msg)
    arcpy.RefreshActiveView()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍