2

I have 60 polygons saved in one shp file.

Is there a way to rotate them by the angle value stored in the attribute table?

I know how to do it manually; I am looking for more automated way (Every polygon has different angle)

I tried to run this script but I got an error

Runtime error Traceback (most recent call last): File "", line 55, in File "", line 24, in main File "c:\program files (x86)\arcgis\desktop10.3\arcpy\arcpy\management.py", line 6520, in MakeFeatureLayer raise e ExecuteError: Failed to execute. Parameters are not valid. ERROR 000732: Input Features: Dataset P:3円_Workspaces\DDP_REF.gdb\Original does not exist or is not supported Failed to execute (MakeFeatureLayer).

# -*- coding: utf-8 -*-
import math
import arcpy
import numpy
def Transform_coords(x, y, angle, polygon_centroid):
 radians = math.radians(angle)
 (X,Y) = polygon_centroid
 x_trans = x - X
 y_trans = y - Y
 x_transprime = math.cos(radians) * x_trans - math.sin(radians) * y_trans
 y_transprime = math.sin(radians) * x_trans + math.cos(radians) * y_trans
 x_prime = x_transprime + X
 y_prime = y_transprime + Y
 return x_prime, y_prime
def main(shp_file, new_shp_file):
 arcpy.env.overwriteOutput = True
 arcpy.MakeFeatureLayer_management (shp_file, "polygon")
 sr = arcpy.Describe("polygon").spatialReference
 features = []
 with arcpy.da.SearchCursor("polygon", ["SHAPE@", "SHAPE@XY"]) as cursor:
 for row in cursor:
 array = numpy.random.uniform(0, 360, size = 1)
 angle = array.tolist()[0]
 for feature_parts in row[0]:
 feature = []
 polygon_centroid = row[1]
 for coord in feature_parts: 
 x = coord.X
 y = coord.Y
 new_x, new_y = Transform_coords(x, y, angle, polygon_centroid)
 feature.append([new_x, new_y])
 points = arcpy.Array([arcpy.Point(*coords) for coords in feature])
 polygon_feature = arcpy.Polygon(points,sr)
 features.append(polygon_feature)
 arcpy.CopyFeatures_management(features, new_shp_file)
if __name__ == "__main__":
 main(
 shp_file = r"P:3円_Workspaces\DDP_REF.gdb\Original", 
 new_shp_file = r"P:3円_Workspaces\DDP_REF.gdb\Rotated"
 )
PolyGeo
65.5k29 gold badges115 silver badges349 bronze badges
asked Jan 23, 2019 at 12:33
8
  • This Q&A should provide some ideas for starting code: gis.stackexchange.com/q/215283/115 Commented Jan 23, 2019 at 13:09
  • Where is the place in that script to put the name of the column from the attribute table that stores the angle value? I am really sorry but the script is rather complicated Commented Jan 23, 2019 at 13:43
  • BERA do you have an answer? Commented Jan 23, 2019 at 13:57
  • 1
    At the end of this Q&A on geonet is a python solution which requires hooking up to a scripting tool interface. Commented Jan 23, 2019 at 16:07
  • 1
    You need to study the code, determine the order of parameters and then create a script tool interface to it which is discussed here. Or you can dispense with the interface and hard wire the paths in, up to you really. Commented Jan 23, 2019 at 16:13

1 Answer 1

4

Create a function to rotate points then use the da.UpdateCursor to update the geometry for each polygon. Code below will modify your data so backup before you try it:

import arcpy, math
fc = 'aPoly' #Change to match your data
rotatefield = 'Rotation' #Clockwise rotation in degress. Change name to match your data
#Function to rotate one input Point around a pivot point
def rotatepoint(point, pivotpoint, angle):
 #Source: https://stackoverflow.com/questions/34372480/rotate-point-about-another-point-in-degrees-python
 angle_rad = -math.radians(angle)
 ox, oy = pivotpoint.X, pivotpoint.Y
 px, py = point.X, point.Y
 qx = ox + math.cos(angle_rad) * (px - ox) - math.sin(angle_rad) * (py - oy)
 qy = oy + math.sin(angle_rad) * (px - ox) + math.cos(angle_rad) * (py - oy) 
 return arcpy.Point(qx,qy)
#Rebuild each polygon with rotated vertices
with arcpy.da.UpdateCursor(fc,['SHAPE@',rotatefield]) as cursor:
 for row in cursor:
 polylist = []
 for part in row[0]:
 partlist = []
 for pnt in part:
 if pnt is not None: #Polygons with inner rings will have None pnt(s) which can be skipped
 partlist.append(rotatepoint(pnt, row[0].centroid, row[1])) #Centroid is pivot point
 polylist.append(partlist)
 row[0] = arcpy.Polygon(arcpy.Array(polylist))
 cursor.updateRow(row)

enter image description here

answered Jan 23, 2019 at 17:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.