Create a multipart polygon with arcpy

12059
12
Jump to solution
02-27-2015 09:53 AM
XanderBakker
Esri Esteemed Contributor

I am trying to create a multipart polygon based on 3 x 5 squares, but when I look at the result it dissolves the polygons and the enclosed squares are no longer part of it. If I do the same and store the result as a line (also multipart), the inner parts do appear in the result.

multiparts.png

Can anyone explain me what I am doing wrong or show me how I can create a valid multipart polygon that consists in this case of 15 partes?

This is the code that I used.

import arcpy

# a square
part = [[0,0],[0,1],[1,1],[1,0],[0,0]]

mp = []
for x_shift in range(0,3):
    for y_shift in range(0,5):
        part_new = [[x+x_shift,y+y_shift] for [x,y] in part]
        print part_new
        mp.append(part_new)

# the nested list for the multipart
##mp = [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]],
##      [[0, 1], [0, 2], [1, 2], [1, 1], [0, 1]],
##      [[0, 2], [0, 3], [1, 3], [1, 2], [0, 2]],
##      [[0, 3], [0, 4], [1, 4], [1, 3], [0, 3]],
##      [[0, 4], [0, 5], [1, 5], [1, 4], [0, 4]],
##      [[1, 0], [1, 1], [2, 1], [2, 0], [1, 0]],
##      [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]],
##      [[1, 2], [1, 3], [2, 3], [2, 2], [1, 2]],
##      [[1, 3], [1, 4], [2, 4], [2, 3], [1, 3]],
##      [[1, 4], [1, 5], [2, 5], [2, 4], [1, 4]],
##      [[2, 0], [2, 1], [3, 1], [3, 0], [2, 0]],
##      [[2, 1], [2, 2], [3, 2], [3, 1], [2, 1]],
##      [[2, 2], [2, 3], [3, 3], [3, 2], [2, 2]],
##      [[2, 3], [2, 4], [3, 4], [3, 3], [2, 3]],
##      [[2, 4], [2, 5], [3, 5], [3, 4], [2, 4]]]

# construct the array for the feature
lst_part = []
for part in mp:
    lst_pnt = []
    for pnt in part:
        lst_pnt.append(arcpy.Point(float(pnt[0]), float(pnt[1])))
    lst_part.append(arcpy.Array(lst_pnt))
array = arcpy.Array(lst_part)

# handle the array as polygon
polygon = arcpy.Polygon(array)
arcpy.CopyFeatures_management([polygon], r"D:\Xander\GeoNet\MultiPart\data.gdb\test_pol_mp")
print "Polygon partCount : {0}".format(polygon.partCount)
print "Polygon pointCount: {0}".format(polygon.pointCount)

# handle the array as polyline
polyline = arcpy.Polyline(array)
arcpy.CopyFeatures_management([polyline], r"D:\Xander\GeoNet\MultiPart\data.gdb\test_line_mp")
print "Polyline partCount : {0}".format(polyline.partCount)
print "Polyline pointCount: {0}".format(polyline.pointCount)
0 Kudos
12 Replies
DarrenWiens2
MVP Honored Contributor

Fine with me, although I just copy/pasted from here:

Creating and editing multipart polygons

DanPatterson_Retired
MVP Emeritus

hahaha .... but you see "editing" to me is on-screen digitizing etc...I never do it, so rarely check that section.  I think the reference should at the least be duplicated within the union etc sections and at least within the arcpy section...and I have noted it as such...So you will get kudos for bringing the jackass to water

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Since the OGC Simple Feature Access - Part 1: Common Architecture doesn't allow parts of a multipart polygon to share edges, what you are really after is either a geometry bag or geometry collection, neither of which are implemented in ArcPy.  Even if ArcPy implemented geometry bags, you still can't store them in a feature class because Esri doesn't have a geometry bag/collection type for feature classes.

If you work outside of ArcGIS, in SQL Server for example, you can build and store a geometry collection.  Using your original example and a SQL Server workspace, you can see what I am speaking to:

import arcpy

# a square
part = [[0,0],[0,1],[1,1],[1,0],[0,0]]

mp = ""
for x_shift in range(0,3):
    for y_shift in range(0,5):
        new_part = ", ".join(["{} {}".format(x+x_shift,y+y_shift) for [x,y] in part])
        mp = "{}, POLYGON(({}))".format(mp, new_part)
mp = mp[2:]

sqlWS = #SQL Server or SQL Server Express SDE connection file
out_name = "test_pol_mp"

fc = arcpy.CreateFeatureclass_management(sqlWS, out_name, "POLYGON")
shape = arcpy.Describe(fc).shapeFieldName

sde_conn = arcpy.ArcSDESQLExecute(sqlWS)
sql = ("INSERT INTO {} ({}) "
      "VALUES (\'GEOMETRYCOLLECTION({})\')".format(out_name, shape, mp))
sde_conn.execute(sql)

sql = ("SELECT [{}].STNumGeometries() AS partCount, "
              "[{}].STNumPoints() AS pointCount "
          "FROM {}".format(shape, shape, out_name))
partCount, pointCount = sde_conn.execute(sql)[0]
print "Polygon partCount : {0}".format(partCount)  
print "Polygon pointCount: {0}".format(pointCount)

#... Polygon partCount : 15
#... Polygon pointCount: 75

Viewing the geometry collection in SQL Server Management Studio gives:

geometrybag_sql_server_mgmt_studio.PNG

Wheres trying to view it in ArcMap gives:

geometrybag_arcmap_error.PNG