Polygon holes

3198
9
11-01-2011 03:16 PM
MikeThompson2
Emerging Contributor
Hello,

I believe the code below should identify polygon features that have holes.  However, it doesn't work in all cases.  On certain individual features it fails to find the hole, even though I have verified in ArcMap that the hole exists. On other individual features, even in the same feature class, it succeeds in finding the holes.  I have not been able to determine any material difference between the features on which it works, and those upon which it does not work.  Has anyone seen this before?  Any fix/work around?

import arcgisscripting

gp = arcgisscripting.create(9.3)
fc = "c:/test.mdb/test/Test"
rows = gp.SearchCursor(fc)       
row = rows.Next()
RowIdx = 0
while row:
    feat = row.shape
    parts = feat.GetPart()
    part = parts.Next()
    PartIdx = 0
    while part:
        PointIdx = 0
        pointTemp = part.Next()
        while(pointTemp):
            pointTemp = part.Next()
            if(not pointTemp):
                pointTemp = part.Next()
                PointIdx = PointIdx + 1
                if(pointTemp):
                    print ("Found inner ring:" + fc + "  ObjectID: " + str(row.GetValue("ObjectId")) + "  RowIdx: " + str(RowIdx) + "  PartIdx: " + str(PartIdx) + "  PointIdx: " + str(PointIdx) + "  Point Count: " + str(part.Count) + "  Part Count: " + str(feat.PartCount))
            PointIdx = PointIdx + 1
        part=parts.Next()
        PartIdx = PartIdx + 1
    row = rows.Next()
    RowIdx = RowIdx + 1
Tags (2)
0 Kudos
9 Replies
RichardFairhurst
MVP Alum
Check out the code of this tool designed to detect and delete holes in Polygons.  It will probably give you some ideas on how to fix your problem.  http://resources.arcgis.com/gallery/file/geoprocessing/details?entryID=C4E10FE5-1422-2418-A06D-33952...
0 Kudos
MikeThompson2
Emerging Contributor
Richard,

Thanks.  I had to fix a couple of bugs in the 9.3 version of the script your referred me to in order to get it to run. 
 Line 44 was: 
    arrayOuter.add(pt) 
  should be
    arrayOuter.add(ptNum)   

 Line 45 was:
    if len(arrayOuter) < part.count :
  should be:
    if arrayOuter.Count < part.count :


After making the above modifications, I ran the script on the feature class in question.  It removed some polygon holes, but not all of them.  This script uses the same basic methodology as my script, it looks for a null in the list of polygon vertices that occur before the end of the list of vertices.  The problem with the features in question whose holes cannot be seen is that the list of vertices ends (based upon part.count) after the outer ring.    

Mike
0 Kudos
MikeThompson2
Emerging Contributor
Someone recommended that I run "Check Geometry" (Arc Toolbox -> Data Management Tools -> Features -> Check Geometry) on the feature class containing the problematic features.  I did this and no errors were found.  I also tried running "Repair Geometry", but that didn't fix the problem either.
0 Kudos
MikeThompson2
Emerging Contributor
Here is some further information about the problem.  I used ArcMap's "Sketch Properties Window" to observe the problematic feature.  The "Sketch Properties Window" listed the inner ring as "Part 0" and the outer ring as "Part 1."  This is the opposite of the non-problematic features.  Is there anyway of reordering the parts automatically?

Mike
0 Kudos
MikeThompson2
Emerging Contributor
And even further information...

If I start editing, move a vertex of the problem feature, and save, "Part 0" becomes the outer ring, "Part 1" become the inner ring, and my script detects the feature as a polygon having a hole!  Now I just need to find a way of making that reordering happen without modifying any vertices.  Any ideas?
0 Kudos
HemingZhu
Frequent Contributor
And even further information...

If I start editing, move a vertex of the problem feature, and save, "Part 0" becomes the outer ring, "Part 1" become the inner ring, and my script detects the feature as a polygon having a hole!  Now I just need to find a way of making that reordering happen without modifying any vertices.  Any ideas?


Here are some of my thoughts. First check if a polygon has multiparts. If it has, then create each polygon out of each part. Then compare those polygons, for example if A contains B. Then B most likely be the hole of A. So you remove the B part....
0 Kudos
MikeThompson2
Emerging Contributor
Heming,

Thanks for your post.

Python reports that the problem polygon IsMultiPart = true, but part count = 1.  However, this is what it reports for all polygons that have holes, whether my script detects them or not.  This contradiction is apparently normal.

As for your specific suggestion, since Python cannot see the vertices of the hole, I can't "create each polygon out of each part", at least within a Python script.  Otherwise your suggestion sounds like a great idea. 

I did run the "Single Part to Multipart" tool and even though all of the polygons in the feature class were already single part (if we do not consider the holes as parts), my script then detects the holes.  So, I have a work around, although I still contend this is a bug.  Either Python should see the hole, or the Check Geometry tool should report it as invalid geometry.

BTW, I find it a bit confusing that in ESRI-speak, sometimes a polygon with a hole is considered "single part" and sometimes it is considered "multipart."

Mike
0 Kudos
KimOllivier
Honored Contributor
Shock horror! A bug in my 9.3 script is true. My apologies, I will update the resource file as soon as I have investigated a bit more with some more examples.

I am very puzzled that it is possible to have a validated feature and yet it does not appear valid.
Surely this is not possible after all these years of polygon features?
Maybe we are still missing some valid combinations in our scripts?

For example it is valid to have ((a lake in an island) in a lake), and so on... recursively, which I have not tested yet.

This would result in a second inner 'outer ring' inside an outer ring in the same part that is not a hole.

The rings must also be ordered clockwise for an outer ring and anti-clockwise for a donut. So it would be useful to show the order of the polygons, maybe turn on arrows, to see if we are covering all possible cases. I can see that multi-part to single may destroy these apparent errors.

It may be valid to have a preceding null point or two null points that would result in some very strange, but maybe "valid" polygons, without a donut, but an inner ring.
0 Kudos
KimOllivier
Honored Contributor
Experiments with the sketch tool have shown up a few things that ArcGIS is doing behind the scenes.


  1. You can only use the polygon tool to create multipart polygon features. The box tool automatically finished the sketch prematurely for example.


  2. I could not find a way to add more parts after the sketch is finished.


  3. The 'parts' in the edit vertices window would be better called 'rings' because some will become parts, and others will be donut rings within a part.


  4. After finishing a sketch the rings will be converted into parts and donut rings, depending on whether they are enclosed by a ring or not.


  5. If the rings are intersecting, they are cracked and additional rings are created. It appears that the order is also recalculated to ensure clockwise. anticlockwise orders with nested rings.


  6. Donut vertices can be coincident at one point with their enclosing ring. (This is slightly different to the OGC rules for simple features)


  7. If you move a donut ring outside the outer ring it will turn into a separate part when saved, so you go from a single part to multiple parts.


  8. If there is a second ring inside the donut, then it turns into the donut, so we need a way of detecting the inner polygons.

0 Kudos