ArcPro how to COPY multipart GEOMETRY between separate layers?

2280
4
Jump to solution
11-15-2021 11:49 AM
Labels (3)
Wolfgang_Grunberg_AZ_DFFM
New Contributor III

How can I copy and replace the multipart polygon GEOMETRY from one feature (e.g. input FGDB layer record) to another feature (e.g. master AGOL Feature Service layer record)?   

Geometry copy - not feature copy - to avoid messing with: existing attributes (Object ID, GUID, create/edit name/date), nested relates, and dependent apps.

Currently, I'm tracing the "input" shapes by using the "Replace Geometry" and "Continue Feature" tools to updated the master feature record. This is tedious and error prone given complex shapes with up to 100+ multipart parts. 

There is a python way to replace geometries but I don't know how to create a safe "press button" or copy/paste solution in ArcPro. 

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
4 Replies
JohannesLindner
MVP Frequent Contributor

If the input and master layers have a common field:

geometry_layer_name = "name_of_the_layer_with_the_right_geometry"
attribute_layer_name = "name_of_the_layer_with_attributes_and_wrong_geometry"
common_field = "name_of_the_common_field"

# this will change the geometry of the second layer's underlying data, so back it up!

active_map = arcpy.mp.ArcGISProject("current").activeMap
geometry_layer = active_map.listLayers(geometry_layer_name)[0]
attribute_layer = active_map.listLayers(attribute_layer_name)[0]

# read the correct geometries and save them in a dictionary
# {common_field_value: shape}
cursor = arcpy.da.SearchCursor(geometry_layer, [common_field, "SHAPE@"])
shapes = dict([row for row in cursor])

# loop through the second layer and update the geometries
updated_features = []
with arcpy.da.UpdateCursor(attribute_layer, [common_field, "SHAPE@"]) as cursor:
    for row in cursor:
        try:
            new_shape = shapes[row[0]]
            # only update if the geometry is different, fill the updated_features list
            if not new_shape.equals(row[1]):
                cursor.updateRow([row[0], new_shape])
                updated_features.append(row[0])
        except KeyError:
            print("No new geometry found for feature with {} = {}".format(common_field, row[0]))


# build an SQL query of the updated_features, depending on whether common_field is a text field or not
if updated_features and isinstance(updated_features[0], str):
    sql = "{} IN ('{}')".format(common_field, "', '".join(updated_features))
else:
    sql = "{} IN ({})".format(common_field, ", ".join([str(uf) for uf in updated_features]))
# print the SQL query
print("Updated the geometry of {} features:\n{}".format(len(updated_features), sql))

 


Have a great day!
Johannes
Wolfgang_Grunberg_AZ_DFFM
New Contributor III

Thanks Johannes for the code example!

I'm updating just one record in the master and the input has one record with random unrelated attributes. With enough skill, all doable in python. However, having to manually and correctly modify a script on every record update makes me very nervous. Have to look into the costs of developing an Add-In if there are no other options.

0 Kudos
JohannesLindner
MVP Frequent Contributor

Ah. Then the script gets easier.

Select the feature you want to update in the master layer. If the input layer has more than one record, select the corresponding feature there, too. Run the script in the python window.

You just have to edit lines 1 and 2.

input_layer_name = "name_of_the_input_layer"
master_layer_name = "name_of_the_master_layer"

active_map = arcpy.mp.ArcGISProject("current").activeMap
input_layer = active_map.listLayers(input_layer_name)[0]
master_layer = active_map.listLayers(master_layer_name)[0]

new_shape = [r[0] for r in arcpy.da.SearchCursor(input_layer, ["SHAPE@"])][0]
with arcpy.da.UpdateCursor(master_layer, ["SHAPE@"]) as cursor:
    for row in cursor:
        cursor.updateRow([new_shape])

 


Have a great day!
Johannes
SepidehDadashi_DFFM_AZ
New Contributor

Untitled1.pngUntitled2.pngUntitled3.png