DA Cursor Transfer of Shape Field Geometry is Not Working Correctly

735
3
Jump to solution
12-13-2019 02:39 PM
RichardFairhurst
MVP Honored Contributor

If I use a relate to select the features in the feature class I want to update and delete them, and then use the Append tool to insert the features from the source feature class, the geometry matches exactly. However, this changes the original ObjectIDs of the features in the updated feature class, which I wanted to avoid.

      

The features shown below that are semi-transparent blue with red outlines have the source geometry I want to transfer and features that are orange with grey outlines are the features I want to change before I have done any update.

The features shown below are the result of deleting the original features and using the Append tool.  The geometry matches exactly, but the ObjectIDs have changed.

I have written several versions of a script designed to preserve the ObjectIDs and transfer the geometry in the Shape field of one feature class using an da.UpdateCursor from the Shape field in another that match on the values of another field using both a Dictionary populated by a da.SearchCursor and directly from a da.SearchCursor, but the geometry that is transferred is not the same as the source geometry.  I have tried variations of the script that used or did not use the Spatial Reference parameter of one or both cursors, but that does not fix the problem.

The features shown below are the result of using a da.UpdateCursor to transfer the geometry.  The ObjectIDs have not changed and the geometries have changed, but the transferred geometries are not identical to the source geometry.

Has anyone else experienced this and come up with a solution that both preserves the original OBJECTIDs and correctly transfers geometry that is identical with the source geometry?

Here is one of the scripts I tried.  The script completes without error and the geometry of the updated feature class is being changed, but the output geometry is not identical to the source geometry as shown above.

from time import strftime  
  
print("Start script: " + strftime("%Y-%m-%d %H:%M:%S")  )
  
import arcpy  

desc = arcpy.Describe(r"Y:\GISData\rfairhur\Layers\Transform_Parcel_Layers\Transform_Parcel_Layers.gdb/ZONING_POST_DESERT_EXTRACT")
  
sourceFC = r"Y:\GISData\rfairhur\Layers\Transform_Parcel_Layers\Transform_Parcel_Layers.gdb/ZONING_POST_DESERT_EXTRACT"

sourceFieldsList = ['OIDLIST','SHAPE']
  
# Use list comprehension to build a dictionary from a da SearchCursor  
valueDict = {r[0]:r[1] for r in arcpy.da.SearchCursor(sourceFC, sourceFieldsList, spatial_reference=desc.spatialReference)}  
  
updateFC = r"Y:\GISData\rfairhur\Layers\Transform_Parcel_Layers\Transform_Parcel_Layers.gdb/ZONING_POST_DESERT_CURSOR"  
  
updateFieldsList = ['OIDLIST','SHAPE']  

count = 0  

desc = arcpy.Describe(r"Y:\GISData\rfairhur\Layers\Transform_Parcel_Layers\Transform_Parcel_Layers.gdb/ZONING_POST_DESERT_CURSOR")
with arcpy.da.UpdateCursor(updateFC, updateFieldsList, spatial_reference=desc.spatialReference) as updateRows:  
    desc = arcpy.Describe(r"Y:\GISData\rfairhur\Layers\Transform_Parcel_Layers\Transform_Parcel_Layers.gdb/ZONING_POST_DESERT_EXTRACT")
    for updateRow in updateRows:  
        # store the Join value of the row being updated in a keyValue variable  
        keyValue = updateRow[0]  
         # verify that the keyValue is in the Dictionary  
        if keyValue in valueDict:
            expression = "OIDLIST = '" + keyValue + "'"
            with arcpy.da.SearchCursor(sourceFC, sourceFieldsList, where_clause=expression, spatial_reference=desc.spatialReference) as sourceRows:
                for sourceRow in sourceRows:
                     # transfer the value stored under the keyValue from the dictionary to the updated field.  
                    updateRow[1] = sourceRow[1]
                    count += 1
            updateRows.updateRow(updateRow)  
            if count % 50 == 0:
                print("Fixed " +str(count) + " Zone Features: " + strftime("%Y-%m-%d %H:%M:%S") )

print("Fixed " +str(count) + " Zone Features: " + strftime("%Y-%m-%d %H:%M:%S") )
del valueDict  
  
print( "Finished script: " + strftime("%Y-%m-%d %H:%M:%S") )‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
1 Solution

Accepted Solutions
RichardFairhurst
MVP Honored Contributor

Running the script within an editor session did not make a difference.  The geomety vertices are not changing beyond positioning themselves relative to a new centroid.

I found that I needed to change the field list for both the SearchCursor and the UpdateCursor to use the SHAPE@ field (the shape field geometry) instead of the SHAPE field (the field name, which apparently only affects the Centroid).

View solution in original post

3 Replies
JoshuaBixby
MVP Esteemed Contributor

Are there different spatial references involved, or are all features in the same SR to start with?

0 Kudos
RichardFairhurst
MVP Honored Contributor

They are in the same Spatial Reference to strat with, which is why I tried it with and without the spatial reference parameter.  The output feature class had representations in effect, so I tried exporting the features to eliminate the representations.  However, I just noticed that ObjectID 11375 had 135 vertices in both before and after the update, while the source feature had only 56 vertices.  So the original geometry appears to just have been moved to a new centroid, rather than updating the entire geometry.  This occurred with or without the representations being in effect.

Here are the vertices of the source feature.

Here are the vertices of the output feature prior to update (with representations in effect).

Here are the vertices of the output feature after the cursor updated it (without representations in effect).  The geometry vertices did not change, only the location of the feature centroid.

The script has not used an edit session to do the update.  I will try doing the cursor update within an editor session to see if that affects the geometry vertices.

0 Kudos
RichardFairhurst
MVP Honored Contributor

Running the script within an editor session did not make a difference.  The geomety vertices are not changing beyond positioning themselves relative to a new centroid.

I found that I needed to change the field list for both the SearchCursor and the UpdateCursor to use the SHAPE@ field (the shape field geometry) instead of the SHAPE field (the field name, which apparently only affects the Centroid).