5

I have many polygons, and I want to know how many holes are in the polygon using field calculator. Like this polygon that has three holes.

enter image description here

2
  • 2
    See @Hornbydd answer gis.stackexchange.com/questions/134066/… tiny modification of the script will do.
    – FelixIP
    Commented Aug 6, 2022 at 5:42
  • 1
    In QGIS, there is a function num_interior_rings( $geometry) that you could use directly in the field calculator to get the number of interior rings/holes. Isn't there anything similar in ArcGIS?
    – Babel
    Commented Aug 6, 2022 at 10:26

1 Answer 1

8

ArcGIS Polygon objects can have one or more parts, with each part containing one or more subparts (rings).

Six polygons

There are a number of ways to extract the number of "holes" (interior subparts), but the easiest is to subtract the number of parts from the number of subparts. While there is a Polygon.partCount property, there isn't a subpartCount, but converting the Polygon to Polyline boundaries will generate the subparts, which can be counted. Thus the equation is:

Polygon.boundary().partCount - Polygon.partCount

We can see this work with the following script:

import arcpy

def num_holes(poly):
    return poly.boundary().partCount - poly.partCount

wkts = [
    'POLYGON ((0 0, 9 0, 9 9, 0 9, 0 0))',
    'POLYGON ((0 0, 9 0, 9 9, 0 9, 0 0),(2 2, 2 4, 4 4, 4 2, 2 2))',
    'POLYGON ((0 0, 9 0, 9 9, 0 9, 0 0),(2 2, 2 4, 4 4, 4 2, 2 2),(7 1, 7 8, 8 8, 8 1, 7 1))',
    'MULTIPOLYGON (((0 0, 5 0, 5 9, 0 9, 0 0)),((6 0, 9 0, 9 9, 6 9, 6 0)))',
    'MULTIPOLYGON (((0 0, 5 0, 5 9, 0 9, 0 0),(2 2, 4 2, 4 4, 2 4, 2 2)),((6 0, 9 0, 9 9, 6 9, 6 0)))',
    'MULTIPOLYGON (((0 0, 5 0, 5 9, 0 9, 0 0),(2 2, 4 2, 4 4, 2 4, 2 2)),((6 0, 9 0, 9 9, 6 9, 6 0),(7 1, 7 8, 8 8, 8 1, 7 1)))']

sr = arcpy.SpatialReference(4326)
for i,wkt in enumerate(wkts,start=1):
    shp = arcpy.FromWKT(wkt,sr)
    print("i={:d} parts={:d} subparts={:d} holes={:d}".format(
            i,shp.partCount,shp.boundary().partCount,num_holes(shp)))

Which displays:

i=1 parts=1 subparts=1 holes=0
i=2 parts=1 subparts=2 holes=1
i=3 parts=1 subparts=3 holes=2
i=4 parts=2 subparts=2 holes=0
i=5 parts=2 subparts=3 holes=1
i=6 parts=2 subparts=4 holes=2

In CalculateField, the syntax would be:

!shape!.boundary().partCount - !shape!.partCount
3
  • While revisiting geometry topology to respond to an earlier comment, I came across an uncommon but interesting situation where a given visual shape has two different implementations (at least two I figured out), and those different implementations have many properties in common but not all, including number of holes. For example an inverted polygon,'POLYGON((0 0, 10 0, 10 10, 5 10, 5 15, 10 15, 10 10, 15 10, 15 20, 0 20, 0 0))' , and its donut hole equivalent,'POLYGON((0 0, 10 0, 10 10, 15 10, 15 20, 0 20, 0 0),(10 10, 5 10, 5 15, 10 15, 10 10))'.
    – bixb0012
    Commented Aug 8, 2022 at 20:06
  • Esri topology has a preference, though PostGIS/OGC has a different one. Within a "valid" geometry, the answer will be right for that system. I'll poke at that example and address it if I have some insight.
    – Vince
    Commented Aug 8, 2022 at 20:14
  • Esri Check Geometry tool using Esri's rules said both are valid. Esri Check Geometry using OGC said the inverted was "non simple." I don't work with PostGIS, but SQL Server IsValidDetailed said both were valid. I thought SQL Server would be using an OGC validation but I guess not exactly.
    – bixb0012
    Commented Aug 8, 2022 at 20:22

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.