2

in this post Why does the method partCount in ArcGIS always give back a value of 1? a problem occured that could easily be reproduced. partCount is always 1! Is it a wrong usage of partCount or did anybody find a workaround for this? How can i access all parts? i used the following code for testing:

import arcpy
featureclass = r"test_mp"
shapeName = arcpy.Describe(featureclass).shapeFieldName
cursor = arcpy.SearchCursor(featureclass)

for row in cursor:
    shape = row.getValue(shapeName)
    print shape.partCount

Test_mp is a shapefile loaded in arcmap and looks like this: Single- and multiparted polygons in arcmap

I also used feature classes from a file gdb with the same result.

  • 2
    You should review this Q&A. – Hornbydd Feb 7 '16 at 17:45
10

The output you are receiving is correct. Assuming you have two polygons, one without a hole, and one with a hole, then each of these shapes is single-part. Polygon geometry has two levels of construction - parts and rings. Each part must have one exterior ring, but may contain additional interior rings (aka "holes"). The partCount property returns the number of parts, not rings.

Here's my sample set: four sample shapes There are four polygon features:

id=1 single-part without interior ring
id=2 single-part with interior ring
id=3 multi-part without interior rings
id=4 multi-part with interior rings

And running a variant of your arcpy (updated for DA cursors)

import arcpy

featureclass = r"mpoly4.shp"
fields = ["objectid", "shape@"]

with arcpy.da.SearchCursor(featureclass, fields) as cursor:
    for row in cursor:
        shape = row[1]
        print "id={:d} parts={:d}".format(row[0],shape.partCount)

produces:

D:\Temp>python mpoly4.py
id=1 parts=1
id=2 parts=1
id=3 parts=2
id=4 parts=2

In order to detect multiple rings in a part, you have to go a step further, converting the polygon into its boundary rings:

import arcpy

featureclass = r"mpoly4.shp"
fields = ["objectid", "shape@"]

with arcpy.da.SearchCursor(featureclass, fields) as cursor:
    for row in cursor:
        shape = row[1]
        rings = shape.boundary().partCount
        print "id={:d} parts={:d} rings={:d}".format(row[0],shape.partCount,rings)

which gives output:

D:\Temp>python mpolyRings.py
id=1 parts=1 rings=1
id=2 parts=1 rings=2
id=3 parts=2 rings=2
id=4 parts=2 rings=4

You can also go the long way round the block, using JSON:

import arcpy
import json

featureclass = r"mpoly4.shp"
fields = ["objectid", "shape@"]

with arcpy.da.SearchCursor(featureclass, fields) as cursor:
    for row in cursor:
        shape = row[1]
        d = json.loads(shape.JSON)
        rings = len(d['rings'])
        print "id={:d} parts={:d} rings={:d}".format(row[0],shape.partCount,rings)
  • I'm impressed, i always thought that rings and parts are the same things! As Esri uses the term Part in the arcmap editing tools! So Parts are for Multi-Geometries and rings are for a Polygons holes. And you can't read rings from your geometry directly? – Andreas Müller Feb 7 '16 at 17:53
  • I investigated a little further: my polygon with the interior ring has eleven points, but the sixth point is off type None. So it seems that a arcgis/arcpy part stores one Point as None to "mark" the beginning of a ring! – Andreas Müller Feb 7 '16 at 18:09
  • 1
    I'm quite certain that ArcGIS keeps the vertex array pure and maintains arrays of part and subpart offsets for each shape. The null vertex may be an artifact of your shapefile. – Vince Feb 7 '16 at 19:21
  • Hm, I tried a lot of polygones with holes: at the position, where a new ring starts, i got a None-Point. I open the acrmap-editor and looked at the Edit Sketch Properties to verify. But we can only speculate whats inside of the software... – Andreas Müller Feb 7 '16 at 20:24
  • 1
    To correct your summary: No, rings are not for holes. Interior rings are for holes, but each polygon must have at least one exterior ring (and it comes first in the vertex array). Some geometry libraries expose the ring count directly, but ArcPy does not. – Vince Feb 8 '16 at 3:16

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.