<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: polygon with holes + arcpy.AsShape is broken? in Python Questions</title>
    <link>https://community.esri.com/t5/python-questions/polygon-with-holes-arcpy-asshape-is-broken/m-p/96956#M7491</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;SPAN&gt;The key to understanding "donuts" is that there is a&amp;nbsp; [null point] separating the nested rings list of points in each part. Not between parts.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;There are some conference technical workshop presentations that set this out very well.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;A polygon array in a python pseudocode list would look like this: (of course it has to be in an Arcpy array in internal binary, you cannot just pour this into the array, maybe you can with AsShape, but assembling the list as a JSON string is just as hard). Your example list does not distinguish between parts and donuts.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;[[pt,pt,pt,,pt,pt,pt],[pt,pt,pt,pt]]&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;This is a polygon containing two separate parts, with the first part containing a hole.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;You don't have to reverse the directions, ArcGIS does that for you automatically to generate a valid shape. You can have islands inside donuts and so on. Lakes can be like this, an island in the lake that has a small lake in the island.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;When you assemble the part array of points and you get to the donut, just add a null point and carry on. I think of it as a 'pen down - pen up' operation that we used to program for pen plotters.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;It appears that your error is to add a null point at the end of a part, rather than making the hole within the same part. Likewise adding a null point between parts would not make a donut, just a null part which would be erases by the validator.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Earlier when you reversed the coordinates, it seems that ArcObjects detected that and added in a null for you to make a donut, but I wouldn't rely on that.&lt;/SPAN&gt;&lt;BR /&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;
# donut example
# with explicit null pair to flag a donut
# this example only has one feature and one part in the feature
# coordinate pairs are shown as tuples for clarity
# Kim Ollivier
coordList = [[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [(-88.684979400000032, 38.154361399999985), (-88.666690199999962, 38.154329800000042),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.67131005539963, 38.154337782166039), (-88.675899944207302, 38.154345712555887),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.675899944207302, 38.150691003182175), (-88.67131005539963, 38.150691003182175),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.67131005539963, 38.147037172952786), (-88.675899944207302, 38.147037172952786),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.685066075460313, 38.147037172952786), (-88.684979400000032, 38.154361399999985),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.680463013034853, 38.152519617763254), (-88.680463013034853, 38.15068957953018),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.678182297717754, 38.15068957953018), (-88.678182297717754, 38.152519617763254),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.680463013034853, 38.152519617763254)]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]]
def main():
&amp;nbsp; array = arcpy.Array()
&amp;nbsp; point = arcpy.Point()
&amp;nbsp; null_point = arcpy.Point()
&amp;nbsp; # Create a list to store the features
&amp;nbsp; features = []
&amp;nbsp; # Read the coordinates
&amp;nbsp; for feature in coordList:
&amp;nbsp;&amp;nbsp;&amp;nbsp; print "feature", feature
&amp;nbsp;&amp;nbsp;&amp;nbsp; for part in feature:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for coordPair in part:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print coordPair
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(coordPair) == 0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(null_point)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.X = coordPair[0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.Y = coordPair[1]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(point)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Create the polygon object
&amp;nbsp;&amp;nbsp;&amp;nbsp; polygon = arcpy.Polygon(array)
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Clear the array for the next feature
&amp;nbsp;&amp;nbsp;&amp;nbsp; array.removeAll()
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Append to the feature list
&amp;nbsp;&amp;nbsp;&amp;nbsp; features.append(polygon)

&amp;nbsp;&amp;nbsp;&amp;nbsp; # Copy the features to an output feature class
&amp;nbsp;&amp;nbsp;&amp;nbsp; arcpy.CopyFeatures_management(features, outputFeatureClass)

if __name__ == '__main__':
&amp;nbsp;&amp;nbsp;&amp;nbsp; import arcpy
&amp;nbsp;&amp;nbsp;&amp;nbsp; arcpy.env.overwriteOutput = True
&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeDir = "c:/temp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeFile = "test.shp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; if not arcpy.Exists(outputShapeDir+"/"+outputShapeFile):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; spatialRef = arcpy.SpatialReference(4326) #&amp;nbsp; or "GCS_WGS_1984"
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputFeatureClass = arcpy.CreateFeatureclass_management( outputShapeDir, outputShapeFile, "POLYGON", "", "", "", spatialRef )
&amp;nbsp;&amp;nbsp;&amp;nbsp; else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputFeatureClass = outputShapeDir+"/"+outputShapeFile
&amp;nbsp;&amp;nbsp;&amp;nbsp; main()
&lt;/PRE&gt;&lt;BR /&gt;&lt;SPAN&gt;To go back the other way, see my resource example tool "Fill Donut" on the resources page.&lt;/SPAN&gt;&lt;BR /&gt;&lt;A href="http://resources.arcgis.com/gallery/file/Geoprocessing-Model-and-Script-Tool-Gallery/details?entryID=C4E10FE5-1422-2418-A06D-33952BB8D1D7" rel="nofollow noopener noreferrer" target="_blank"&gt;http://resources.arcgis.com/gallery/file/Geoprocessing-Model-and-Script-Tool-Gallery/details?entryID=C4E10FE5-1422-2418-A06D-33952BB8D1D7&lt;/A&gt;&lt;BR /&gt;&lt;SPAN&gt;I know that Esri has added a tool to do this and you can manually edit donuts, but this is a script to show how to program them.&lt;/SPAN&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Sat, 11 Dec 2021 06:05:16 GMT</pubDate>
    <dc:creator>KimOllivier</dc:creator>
    <dc:date>2021-12-11T06:05:16Z</dc:date>
    <item>
      <title>polygon with holes + arcpy.AsShape is broken?</title>
      <link>https://community.esri.com/t5/python-questions/polygon-with-holes-arcpy-asshape-is-broken/m-p/96955#M7490</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;SPAN&gt;Hi,&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I was searching for a way to programmatically create a polygon with a hole, as there isn't any obvious way of doing this in the documentation, I started fumbling around on my own.&amp;nbsp; I came up with this test script:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;gjPolygonWithHole&amp;nbsp; = {
&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "Polygon",
&amp;nbsp;&amp;nbsp;&amp;nbsp; "coordinates": [
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [[-88.684979400000032, 38.154361399999985], [-88.666690199999962, 38.154329800000042], [-88.67131005539963, 38.154337782166039], [-88.675899944207302, 38.154345712555887], [-88.675899944207302, 38.150691003182175], [-88.67131005539963, 38.150691003182175], [-88.67131005539963, 38.147037172952786], [-88.675899944207302, 38.147037172952786], [-88.685066075460313, 38.147037172952786], [-88.684979400000032, 38.154361399999985]],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [[-88.680463013034853, 38.152519617763254], [-88.680463013034853, 38.15068957953018], [-88.678182297717754, 38.15068957953018], [-88.678182297717754, 38.152519617763254], [-88.680463013034853, 38.152519617763254]]]
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

def main():

&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeDir = r"c:\temp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeFile = r"test.shp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; spatialRef = r'X:\Nadel&amp;amp;Gussman\McLeansboro\Sections.prj'
&amp;nbsp;&amp;nbsp;&amp;nbsp; newFC = arcpy.CreateFeatureclass_management( outputShapeDir, outputShapeFile, "POLYGON", "", "", "", spatialRef )
&amp;nbsp;&amp;nbsp;&amp;nbsp; cur = arcpy.InsertCursor(newFC)
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; array = arcpy.Array()
&amp;nbsp;&amp;nbsp;&amp;nbsp; point = arcpy.Point()
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Create a list to store the features
&amp;nbsp;&amp;nbsp;&amp;nbsp; features = []
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Read the coordinates
&amp;nbsp;&amp;nbsp;&amp;nbsp; for part in gjPolygonWithHole["coordinates"]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for coordPair in part:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.X = coordPair[0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.Y = coordPair[1]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(point)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat = cur.newRow()
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat.shape = array
&amp;nbsp;&amp;nbsp;&amp;nbsp; cur.insertRow( feat )

if __name__ == '__main__':
&amp;nbsp;&amp;nbsp;&amp;nbsp; import arcpy
&amp;nbsp;&amp;nbsp;&amp;nbsp; arcpy.env.overwriteOutput = True
&amp;nbsp;&amp;nbsp;&amp;nbsp; main()&lt;/PRE&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Amazingly, it works (I'm not really sure how, since I don't do anything to separate the interior from the exterior, other than suddenly switch winding order):&lt;/SPAN&gt;&lt;BR /&gt;&lt;IMG src="https://lh3.googleusercontent.com/-u70_GHpWBw0/To4S8P508QI/AAAAAAAAAOU/3P-X8YF81JA/s912/correct_result.JPG" /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Unfortunately, this doesn't work in all polygon-with-a-hole cases that I am working with.&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;So...I noticed the seemingly useful "AsShape" functionality &lt;/SPAN&gt;&lt;A href="http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//000v00000153000000" rel="nofollow noopener noreferrer" target="_blank"&gt;here&lt;/A&gt;&lt;SPAN&gt;.&amp;nbsp; Specifically, (notice the AsShape example on doing just this at the bottom of the page i linked).&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I put together a little sample script to test this:&lt;/SPAN&gt;&lt;BR /&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;gjPolygonWithHole&amp;nbsp; = {
&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "Polygon",
&amp;nbsp;&amp;nbsp;&amp;nbsp; "coordinates": [
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [[-88.684979400000032, 38.154361399999985], [-88.666690199999962, 38.154329800000042], [-88.67131005539963, 38.154337782166039], [-88.675899944207302, 38.154345712555887], [-88.675899944207302, 38.150691003182175], [-88.67131005539963, 38.150691003182175], [-88.67131005539963, 38.147037172952786], [-88.675899944207302, 38.147037172952786], [-88.685066075460313, 38.147037172952786], [-88.684979400000032, 38.154361399999985]],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [[-88.680463013034853, 38.152519617763254], [-88.680463013034853, 38.15068957953018], [-88.678182297717754, 38.15068957953018], [-88.678182297717754, 38.152519617763254], [-88.680463013034853, 38.152519617763254]]]
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

def main():

&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeDir = r"c:\temp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeFile = r"test.shp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; spatialRef = r'X:\Nadel&amp;amp;Gussman\McLeansboro\Sections.prj'
&amp;nbsp;&amp;nbsp;&amp;nbsp; newFC = arcpy.CreateFeatureclass_management( outputShapeDir, outputShapeFile, "POLYGON", "", "", "", spatialRef )
&amp;nbsp;&amp;nbsp;&amp;nbsp; cur = arcpy.InsertCursor(newFC)
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat = cur.newRow()
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat.shape = arcpy.AsShape( gjPolygonWithHole )
&amp;nbsp;&amp;nbsp;&amp;nbsp; cur.insertRow( feat )

if __name__ == '__main__':
&amp;nbsp;&amp;nbsp;&amp;nbsp; import arcpy
&amp;nbsp;&amp;nbsp;&amp;nbsp; arcpy.env.overwriteOutput = True
&amp;nbsp;&amp;nbsp;&amp;nbsp; main()&lt;/PRE&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;FAILURE:&lt;/SPAN&gt;&lt;BR /&gt;&lt;IMG src="https://lh4.googleusercontent.com/-RQjyL9myBD4/To4S-VscWmI/AAAAAAAAAOs/NIO5AqH9y9A/s752/incorrect_result.JPG" /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;The hole is completely ignored.&amp;nbsp; Any clue as to why?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Regarding holes, I found &lt;/SPAN&gt;&lt;A href="http://forums.arcgis.com/threads/18985-Bug-Creating-polygons-with-holes-using-Arcpy" rel="nofollow noopener noreferrer" target="_blank"&gt;this&lt;/A&gt;&lt;SPAN&gt; thread, and adapted their method to my test script + data.&amp;nbsp; It almost works:&lt;/SPAN&gt;&lt;BR /&gt;&lt;IMG src="https://lh4.googleusercontent.com/-YLkTZXBTgSg/To4VGiE_R0I/AAAAAAAAAOo/oHeiX6FqXIw/s751/nearly_correct_result.JPG" /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Here's my example code:&lt;/SPAN&gt;&lt;BR /&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;gjPolygonWithHole&amp;nbsp; = {
&amp;nbsp;&amp;nbsp;&amp;nbsp; "type": "Polygon",
&amp;nbsp;&amp;nbsp;&amp;nbsp; "coordinates": [
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [[-88.684979400000032, 38.154361399999985], [-88.666690199999962, 38.154329800000042], [-88.67131005539963, 38.154337782166039], [-88.675899944207302, 38.154345712555887], [-88.675899944207302, 38.150691003182175], [-88.67131005539963, 38.150691003182175], [-88.67131005539963, 38.147037172952786], [-88.675899944207302, 38.147037172952786], [-88.685066075460313, 38.147037172952786], [-88.684979400000032, 38.154361399999985]],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [[-88.680463013034853, 38.152519617763254], [-88.680463013034853, 38.15068957953018], [-88.678182297717754, 38.15068957953018], [-88.678182297717754, 38.152519617763254], [-88.680463013034853, 38.152519617763254]]]
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

def main():

&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeDir = r"c:\temp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeFile = r"test.shp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; spatialRef = r'X:\Nadel&amp;amp;Gussman\McLeansboro\Sections.prj'
&amp;nbsp;&amp;nbsp;&amp;nbsp; newFC = arcpy.CreateFeatureclass_management( outputShapeDir, outputShapeFile, "POLYGON", "", "", "", spatialRef )
&amp;nbsp;&amp;nbsp;&amp;nbsp; cur = arcpy.InsertCursor(newFC)
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; array = arcpy.Array()
&amp;nbsp;&amp;nbsp;&amp;nbsp; point = arcpy.Point()
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Create a list to store the features
&amp;nbsp;&amp;nbsp;&amp;nbsp; features = []
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Read the coordinates
&amp;nbsp;&amp;nbsp;&amp;nbsp; for part in gjPolygonWithHole["coordinates"]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for coordPair in part:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.X = coordPair[0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.Y = coordPair[1]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(point)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null_point = arcpy.Point()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(null_point)
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat = cur.newRow()
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat.shape = arcpy.Polygon( array )
&amp;nbsp;&amp;nbsp;&amp;nbsp; cur.insertRow( feat )

if __name__ == '__main__':
&amp;nbsp;&amp;nbsp;&amp;nbsp; import arcpy
&amp;nbsp;&amp;nbsp;&amp;nbsp; arcpy.env.overwriteOutput = True
&amp;nbsp;&amp;nbsp;&amp;nbsp; main()&lt;/PRE&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Any ideas why this doesn't work?&amp;nbsp; Why is creating geometry such a hassle with arcpy?&amp;nbsp; Why do some methods work and some do not? &lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Most likely I'm missing something obvious...&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;Thanks,&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;Dustin&lt;/SPAN&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Sat, 11 Dec 2021 06:05:13 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/polygon-with-holes-arcpy-asshape-is-broken/m-p/96955#M7490</guid>
      <dc:creator>DustinReagan</dc:creator>
      <dc:date>2021-12-11T06:05:13Z</dc:date>
    </item>
    <item>
      <title>Re: polygon with holes + arcpy.AsShape is broken?</title>
      <link>https://community.esri.com/t5/python-questions/polygon-with-holes-arcpy-asshape-is-broken/m-p/96956#M7491</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;SPAN&gt;The key to understanding "donuts" is that there is a&amp;nbsp; [null point] separating the nested rings list of points in each part. Not between parts.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;There are some conference technical workshop presentations that set this out very well.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;A polygon array in a python pseudocode list would look like this: (of course it has to be in an Arcpy array in internal binary, you cannot just pour this into the array, maybe you can with AsShape, but assembling the list as a JSON string is just as hard). Your example list does not distinguish between parts and donuts.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;[[pt,pt,pt,,pt,pt,pt],[pt,pt,pt,pt]]&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;This is a polygon containing two separate parts, with the first part containing a hole.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;You don't have to reverse the directions, ArcGIS does that for you automatically to generate a valid shape. You can have islands inside donuts and so on. Lakes can be like this, an island in the lake that has a small lake in the island.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;When you assemble the part array of points and you get to the donut, just add a null point and carry on. I think of it as a 'pen down - pen up' operation that we used to program for pen plotters.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;It appears that your error is to add a null point at the end of a part, rather than making the hole within the same part. Likewise adding a null point between parts would not make a donut, just a null part which would be erases by the validator.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Earlier when you reversed the coordinates, it seems that ArcObjects detected that and added in a null for you to make a donut, but I wouldn't rely on that.&lt;/SPAN&gt;&lt;BR /&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;
# donut example
# with explicit null pair to flag a donut
# this example only has one feature and one part in the feature
# coordinate pairs are shown as tuples for clarity
# Kim Ollivier
coordList = [[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [(-88.684979400000032, 38.154361399999985), (-88.666690199999962, 38.154329800000042),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.67131005539963, 38.154337782166039), (-88.675899944207302, 38.154345712555887),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.675899944207302, 38.150691003182175), (-88.67131005539963, 38.150691003182175),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.67131005539963, 38.147037172952786), (-88.675899944207302, 38.147037172952786),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.685066075460313, 38.147037172952786), (-88.684979400000032, 38.154361399999985),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.680463013034853, 38.152519617763254), (-88.680463013034853, 38.15068957953018),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.678182297717754, 38.15068957953018), (-88.678182297717754, 38.152519617763254),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (-88.680463013034853, 38.152519617763254)]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]]
def main():
&amp;nbsp; array = arcpy.Array()
&amp;nbsp; point = arcpy.Point()
&amp;nbsp; null_point = arcpy.Point()
&amp;nbsp; # Create a list to store the features
&amp;nbsp; features = []
&amp;nbsp; # Read the coordinates
&amp;nbsp; for feature in coordList:
&amp;nbsp;&amp;nbsp;&amp;nbsp; print "feature", feature
&amp;nbsp;&amp;nbsp;&amp;nbsp; for part in feature:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for coordPair in part:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print coordPair
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(coordPair) == 0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(null_point)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.X = coordPair[0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.Y = coordPair[1]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(point)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Create the polygon object
&amp;nbsp;&amp;nbsp;&amp;nbsp; polygon = arcpy.Polygon(array)
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Clear the array for the next feature
&amp;nbsp;&amp;nbsp;&amp;nbsp; array.removeAll()
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Append to the feature list
&amp;nbsp;&amp;nbsp;&amp;nbsp; features.append(polygon)

&amp;nbsp;&amp;nbsp;&amp;nbsp; # Copy the features to an output feature class
&amp;nbsp;&amp;nbsp;&amp;nbsp; arcpy.CopyFeatures_management(features, outputFeatureClass)

if __name__ == '__main__':
&amp;nbsp;&amp;nbsp;&amp;nbsp; import arcpy
&amp;nbsp;&amp;nbsp;&amp;nbsp; arcpy.env.overwriteOutput = True
&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeDir = "c:/temp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; outputShapeFile = "test.shp"
&amp;nbsp;&amp;nbsp;&amp;nbsp; if not arcpy.Exists(outputShapeDir+"/"+outputShapeFile):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; spatialRef = arcpy.SpatialReference(4326) #&amp;nbsp; or "GCS_WGS_1984"
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputFeatureClass = arcpy.CreateFeatureclass_management( outputShapeDir, outputShapeFile, "POLYGON", "", "", "", spatialRef )
&amp;nbsp;&amp;nbsp;&amp;nbsp; else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputFeatureClass = outputShapeDir+"/"+outputShapeFile
&amp;nbsp;&amp;nbsp;&amp;nbsp; main()
&lt;/PRE&gt;&lt;BR /&gt;&lt;SPAN&gt;To go back the other way, see my resource example tool "Fill Donut" on the resources page.&lt;/SPAN&gt;&lt;BR /&gt;&lt;A href="http://resources.arcgis.com/gallery/file/Geoprocessing-Model-and-Script-Tool-Gallery/details?entryID=C4E10FE5-1422-2418-A06D-33952BB8D1D7" rel="nofollow noopener noreferrer" target="_blank"&gt;http://resources.arcgis.com/gallery/file/Geoprocessing-Model-and-Script-Tool-Gallery/details?entryID=C4E10FE5-1422-2418-A06D-33952BB8D1D7&lt;/A&gt;&lt;BR /&gt;&lt;SPAN&gt;I know that Esri has added a tool to do this and you can manually edit donuts, but this is a script to show how to program them.&lt;/SPAN&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Sat, 11 Dec 2021 06:05:16 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/polygon-with-holes-arcpy-asshape-is-broken/m-p/96956#M7491</guid>
      <dc:creator>KimOllivier</dc:creator>
      <dc:date>2021-12-11T06:05:16Z</dc:date>
    </item>
    <item>
      <title>Re: polygon with holes + arcpy.AsShape is broken?</title>
      <link>https://community.esri.com/t5/python-questions/polygon-with-holes-arcpy-asshape-is-broken/m-p/96957#M7492</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;SPAN&gt;Thank you very much for the reply.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Unfortunately your script also produces incorrect (but close) results:&lt;/SPAN&gt;&lt;BR /&gt;&lt;IMG src="https://lh3.googleusercontent.com/-oJ14mwswbSA/To8dnuDR9LI/AAAAAAAAAOw/9yp03xaizJ8/s912/another_nearly_correct_result.JPG" /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Additionally, your method appears to be functionally equivalent to the last method that I posted.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;You say:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BLOCKQUOTE class="jive-quote"&gt;It appears that your error is to add a null point at the end of a part, rather than making the hole within the same part. Likewise adding a null point between parts would not make a donut, just a null part which would be erases by the validator.&lt;/BLOCKQUOTE&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;If you'll look closely at my code, you'll see that I only ever add a single part to "array", putting a null Point between the points that describe exterior and the points that describe the interior (all in the same part).&lt;/SPAN&gt;&lt;BR /&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;array = arcpy.Array()
&amp;nbsp;&amp;nbsp;&amp;nbsp; point = arcpy.Point()
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Create a list to store the features
&amp;nbsp;&amp;nbsp;&amp;nbsp; features = []
&amp;nbsp;&amp;nbsp;&amp;nbsp; # Read the coordinates
&amp;nbsp;&amp;nbsp;&amp;nbsp; for part in gjPolygonWithHole["coordinates"]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for coordPair in part:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.X = coordPair[0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.Y = coordPair[1]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(point)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null_point = arcpy.Point()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array.add(null_point)
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat = cur.newRow()
&amp;nbsp;&amp;nbsp;&amp;nbsp; feat.shape = arcpy.Polygon( array )
&amp;nbsp;&amp;nbsp;&amp;nbsp; cur.insertRow( feat )&lt;/PRE&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Unless I am mistaken, adding multiple parts to a polygon would involve something like:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;
point = arcpy.Point()
polygonArray = arcpy.Array()
partArray = arcpy.Array()
for part in coordinateList:
&amp;nbsp;&amp;nbsp;&amp;nbsp; for coordPair in part:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.X = coordPair[0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; point.Y = coordPair[1]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; partArray.add(point)
&amp;nbsp;&amp;nbsp;&amp;nbsp; #add the null point
&amp;nbsp;&amp;nbsp;&amp;nbsp; partArray.add( arcpy.Point() )
&amp;nbsp;&amp;nbsp;&amp;nbsp; polygonArray.add(partArray)
&amp;nbsp;&amp;nbsp;&amp;nbsp; partArray.removeAll()
newMultiPartPolygon = arcpy.Polygon( polygonArray )
polygonArray.removeAll()
&lt;/PRE&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Thanks for your time,&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;Dustin&lt;/SPAN&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Sat, 11 Dec 2021 06:05:18 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/polygon-with-holes-arcpy-asshape-is-broken/m-p/96957#M7492</guid>
      <dc:creator>DustinReagan</dc:creator>
      <dc:date>2021-12-11T06:05:18Z</dc:date>
    </item>
  </channel>
</rss>

