Changing geometries but keeping attributes

3943
5
04-03-2014 06:01 AM
by Anonymous User
Not applicable
Original User: mconst50

I have a python script that takes a shapefile of points and moves those points to a new location.  The output feature only has FID, ID, and geometry type, is there a way to preserve the attributes from the original shapefile with the new geometries. 

Here is the part of the script that moves the feature, which works great:

infc = Saved_Layer
rows = arcpy.da.SearchCursor(infc, ["Easting", "Northing", "Test_Type"])
point = arcpy.Point()
pointGeometryList=[]
 
for row in rows:
    x = row[0]
    y = row[1]
    TestType = row[2]
    if TestType == 'MTU':
        distance = .3535535
        angle = 45
        (disp_x, disp_y) = (distance * sin(radians(angle)),\
                    distance * cos(radians(angle)))
        (end_x,end_y) = (x + disp_x, y + disp_y)
        point = arcpy.Point(end_x, end_y)
        pointGeometry = arcpy.PointGeometry(point)
        pointGeometryList.append(pointGeometry)                            
      
    elif TestType == 'TU':
        distance = .707107
        angle = 45
        (disp_x, disp_y) = (distance * sin(radians(angle)),\
                    distance * cos(radians(angle)))
        (end_x,end_y) = (x + disp_x, y + disp_y)
        point = arcpy.Point(end_x, end_y)
        pointGeometry = arcpy.PointGeometry(point)
        pointGeometryList.append(pointGeometry)   

# Create feature from geometry list
arcpy.CopyFeatures_management(pointGeometryList, "Points.shp")

fc = "Points.shp"
spatialref = arcpy.SpatialReference(prjfile)
arcpy.DefineProjection_management(fc, spatialref)



I have tried searchcursor, updateCursor,  insertcursor, and spatial joins but when I use the cursor all I get is the first X and Y  repeated in every row. The new geometries only need to include three fields from the original shapefile.
0 Kudos
5 Replies
AdamCox1
Occasional Contributor II
It would be good if you could use the code tags when you post your question, so your indentation is correctly displayed. For example:
for row in rows:
    a = row[0]

It's especially important to see indentations when the question refers to loops and stuff like that.

Just click the # button and place the formatted text between the tags.
0 Kudos
by Anonymous User
Not applicable
Original User: csny490

is there a way to preserve the attributes from the original shapefile with the new geometries


Yes, just run an update cursor on the shape field. For example: https://arcpy.wordpress.com/2012/11/15/shifting-features/
0 Kudos
by Anonymous User
Not applicable
Original User: mconst50

This is my current script:

def shift_features(in_features, x_shift=None, y_shift=None):
    with arcpy.da.UpdateCursor(in_features, ['SHAPE@XY']) as cursor:
        for row in cursor:
            cursor.updateRow([[row[0][0] + x_shift,
                               row[0][1] + y_shift]])
    return

# Set the spatial reference
infc = Saved_Layer
rows = arcpy.da.SearchCursor(infc, ["Easting", "Northing", "Test_Type"])

for row in rows:
    x = row[0]
    y = row[1]
    TestType = row[2]
    if TestType == 'MTU':
        distance = .3535535
        angle = 45
        disp_x = distance * sin(radians(angle))
        disp_y = distance * cos(radians(angle))
 

    elif TestType == 'TU':
        distance = .707107
        angle = 45
        disp_x = distance * sin(radians(angle))
        disp_y = distance * cos(radians(angle))                  

shift_features(infc, x_shift=disp_x, y_shift=disp_y)


I must be doing something wrong because I only now get the points shifted to the distance/angle of TU and the script ignores the MTU statement. 

Thanks
0 Kudos
by Anonymous User
Not applicable
Original User: mconst50

I used disp_x and disp_y instead of the end_x and y and got all the points.  However, they shifted 100 meters instead of the .3 and .7 meters it should shift depending on the if/elif statement. 

Thanks
0 Kudos
by Anonymous User
Not applicable
Original User: mconst50

Changed my code to use only one cursor and one function but I am getting this error:


cursor.updateRow([[row[0][0] + distance * sin(radians(45)), row[0][1] + distance * cos(radians(45))]])
TypeError: sequence size must match size of the row


The complete code is:

import arcpy, os, sys
from math import radians, sin, cos

arcpy.env.workspace = "C:/data"
arcpy.env.overwriteOutput = True


def shift_features(in_features):
    with arcpy.da.UpdateCursor(in_features, ('SHAPE@XY', 'Test_Type')) as cursor:
        for row in cursor:
            if row[1] == 'MTU':
                distance = .3535535 
            elif row[1] == 'TU':
                distance = .707107 
            else:
                print row[1]
                distance = 0 
            cursor.updateRow([[row[0][0] + distance * sin(radians(45)), 
                                       row[0][1] + distance * cos(radians(45))]])

    return 0

#Variables for creating the XY event
infc = r'Database Connections\Test.odc\Units'
x_coords = "Easting"
y_coords = "Northing"
z_coords = ""

out_Layer = "points_layer"
Saved_Layer = "Point.shp"

# Add a spatial reference to the new shapefile
prjfile = "C:/data/LocalGrid.prj"
spRef = arcpy.SpatialReference(prjfile)

# Make the XY event layer...
arcpy.MakeXYEventLayer_management(infc, x_coords, y_coords, out_Layer, spRef, z_coords)
arcpy.CopyFeatures_management(out_Layer, Saved_Layer)
shift_features(Saved_Layer)


# Print feature count and messages
print arcpy.GetMessages()


Been working on this for several days with no success.
0 Kudos