Select to view content in your preferred language

Is a polygon with a hole a multipart polygon?

6979
25
01-09-2018 10:47 AM
EidurEidsson
Emerging Contributor

Consider the following script, the polygon is a simple one with a hole inside:

import arcpy

poly1 = arcpy.FromWKT("POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10), (20 30, 35 35, 30 20, 20 30))")

print(poly1.isMultipart)
print(poly1.partCount)‍‍‍‍‍‍

The result I get is

>>>
True
1

So is a polygon "multipart" if it has holes? ArcGIS Data Reviewer does not agree.

Thanks

ArcGIS Desktop 10.5.1

Tags (1)
25 Replies
DanPatterson_Retired
MVP Emeritus

it is a multipart and the count is 1.  one point ring is clockwise, the other is clockwise, hence the hole

To experiment, repeat the experiment with both point rings oriented in a clockwise order

VinceAngelo
Esri Esteemed Contributor

In truth, a polygon with a hole is multi-ring, but not multi-part. If the proper WKT starts with "POLYGON" not "MULTIPOLYGON", it is single part, with one or more interior rings (which is why even a single-ring polygon has two left and right parens - "(( ... ))"). The Geometry object method is poorly documented on this score.

- V

EidurEidsson
Emerging Contributor

Outer–inner: CCW–CW, CCW–CCW, CW–CW, CW–CCW, all same result.

The WKT is first converted to an arcpy geometry object, which I don't know how is structured exactly. If they are printed as WKT they all become CCW–CW multipolgygons. What I can read from the documentation is that isMultipart should agree with partCount.

0 Kudos
XanderBakker
Esri Esteemed Contributor

I kinda agree that a polygon with a hole that contains only 1 part should not be a multipart. Maybe it is implemented this way since the polygon object does not have a "hasHoles" property (or something similar). To understand how ArcGIS stores the geometry you can run something like this:

import arcpy

poly1 = arcpy.FromWKT("POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10), (20 30, 35 35, 30 20, 20 30))")

print(poly1.isMultipart)
print(poly1.partCount)

cnt_part = 0
for part in poly1:
    cnt_part += 1
    print("Part: {}".format(cnt_part))
    cnt_pnt = 0
    for pnt in part:
        cnt_pnt += 1
        print(" - Pnt {}: {}".format(cnt_pnt, pnt))

It will yield this:

True
1
Part: 1
 - Pnt 1: 35 10 NaN NaN
 - Pnt 2: 10 20 NaN NaN
 - Pnt 3: 15 40 NaN NaN
 - Pnt 4: 45 45 NaN NaN
 - Pnt 5: 35 10 NaN NaN
 - Pnt 6: None
 - Pnt 7: 20 30 NaN NaN
 - Pnt 8: 30 20 NaN NaN
 - Pnt 9: 35 35 NaN NaN
 - Pnt 10: 20 30 NaN NaN

As you can see Pnt 6 is None and indicates the start of a hole.

EidurEidsson
Emerging Contributor

Then I suppose it is "multipart" if there exists a break in the sequence, no matter what comes after it. That might be useful for some tasks, but this meaning is quite different from what the description implies.

Thanks

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Both Dan Patterson‌ and myself have touched on this topic here and there on GeoNet in the past.  You might find a blog post I a couple years back informative:  /blogs/tilting/2016/02/20/the-single-multipart-polygons-with-interior-boundaries.

I spent some time trying the example above in different spatial systems, even other Esri software components outside of ArcPy, and I have come to the conclusion the real problem is in the labels themselves.  Specifically, the problem lies in the use of "part" to talk about geometries.  Take a look at the List of SQL functions for Esri's ST_Geometry data type, the OGC Methods on Geometry Instances for Microsoft's geometry data type, or the PostGIS Reference; you will not find a single function, method, or property with the word "part" in it.  There are accessor functions for counting geometries, but they count "geometries" and not "parts."  There are accessor functions for counting interior rings, but they count "interior rings" and not "parts."  You see where this is going.

 

The problem with the ArcPy Geometry classes, at least one of them, is that Esri replaced multiple, specific geometry components with a single generic one, the "part."  By abstracting geometries and rings with parts, not only did they deviate from geospatial standards and norms, they created the sideshow-worthy multi-part single-part polygon.

VinceAngelo
Esri Esteemed Contributor

All geometry objects are ingested from Well-Known Text using the SgShape geometry library, which has a default "Left Hand Rule" storage orientation*. No matter how you incorrectly wrap the polygons, if the import succeeds, the result polygon will be native left-hand rule (with the polygon shells corrected, if necessary, so that holes follow the outer rings to which they belong, with opposite ring wrapping direction).

- V

*Not to be confused with what Google calls "Right Hand Rule" which is the same orientation, but as described with the hand over the "upward" face of the shape with the thumb pointing out, and fingers curling in the direction of outer ring rotation.

XanderBakker
Esri Esteemed Contributor

Hi Dan Patterson‌, Vince Angelo‌ and Joshua Bixby‌,

I made a note at the help page with a link to this thread today and Jim Barry‌ contacted me directly after, asking what a good description could be or what should be changed at the help page (or if this is something that should be changed in the software)?

IMHO I think that when you talk about parts (in case of a polygon) this would refer to the number of individual disconnected areas in a single feature, and should not refer to "parts" of an inferior geometry dimension (like rings or lines). Maybe an addition property like "hasHoles" could be useful, however this could lead to unfortunate misspellings

Since I consider that each one of you has more experience in this field, my question to you guys is, what suggestions do you have to obtain a clear explanation at the help page or is there something that should be changed in the behavior of the software?

0 Kudos
DanPatterson_Retired
MVP Emeritus

I agree, multipart should be separate, clockwise oriented geometry, whether they overlap or not (which is possible).

A counterclockwise ring within a clockwise ring should be 'hasholes' and that the number of 'holes' should be tracked at the same time as the number of parts.

In this way I could have a 3 part polygon, the first part could have 2 holes, the second part might have no holes, while the third part could have any number of holes (0 to n)

I would want to know this without me having to go through hoops, which I currently do.

It may not be as 'cool' as other stuff... but this is geometry, and fundamentally it is geometry that is used to answer questions.  

Vector geometry has been ignored for too long.  I can't even draw a 3D vertical cliff in 3D so that an xy coordinate can have 2 or more z-values.  Not extrusion, ... actual geometry.

Rings, holes, they are the tip of the iceberg, but we should start somewhere. 

Changes?????

Help file ...definitely. 

Software behaviour... definitely