How to select polygons that have a hole cutout in its interior?

388
3
02-14-2018 01:06 PM
Highlighted
New Contributor

I'm dealing with vector data in which the square outline of a house has been cut out of the polygon.  Is there a specific way to select the polygons that have or do not have this cutout?

Reply
0 Kudos
3 Replies
Highlighted
Occasional Contributor

I'm not sure if there's a way to do it with standard tools, but I know of a way using Python given that in a polygon with holes, null point values (None in Python) separate the outer ring from inner rings:

def findHoles(polygonLayerName):
    # Get the layer from the current map document.
    mxd = arcpy.mapping.MapDocument("CURRENT")
    lyrList = arcpy.mapping.ListLayers(mxd, polygonLayerName)
    if len(lyrList) == 0:
        print("Layer not found")
        return
    layer = lyrList[0]

    # Iterate through the layer's features.
    oidList = []
    with arcpy.da.SearchCursor(layer, ["OID@", "SHAPE@"]) as cursor:
        for row in cursor:
            polygon = row[1]
            for partIdx in range(0, polygon.partCount):
                if None in list(polygon.getPart(partIdx)):
                    oidList.append(row[0])
                    break

    # Select the features and refresh the view.
    layer.setSelectionSet("NEW", oidList)
    arcpy.RefreshActiveView()
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Reply
0 Kudos
Highlighted
Frequent Contributor II

I would put the houses back in as a polygon layer and the do a select by location to find the polygons that don't have a house.

Reply
0 Kudos
Highlighted
MVP Esteemed Contributor

This is yet another example where file geodatabases fall down (I am getting more and more down on file geodatabases, Esri really needs to update them).  Enterprise geodatabases provide more options here.  For example with SQL Server, the following in the WHERE clause of the Select By Attributes dialog would work (assuming the shape file is "shape":

SHAPE.STNumInteriorRing() > 0