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"
)
-
This Q&A should provide some ideas for starting code: gis.stackexchange.com/q/215283/115PolyGeo– PolyGeo ♦2019年01月23日 13:09:47 +00:00Commented 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 complicateduser103910– user1039102019年01月23日 13:43:44 +00:00Commented Jan 23, 2019 at 13:43
-
BERA do you have an answer?user103910– user1039102019年01月23日 13:57:36 +00:00Commented Jan 23, 2019 at 13:57
-
1At the end of this Q&A on geonet is a python solution which requires hooking up to a scripting tool interface.Hornbydd– Hornbydd2019年01月23日 16:07:51 +00:00Commented Jan 23, 2019 at 16:07
-
1You 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.Hornbydd– Hornbydd2019年01月23日 16:13:19 +00:00Commented Jan 23, 2019 at 16:13
1 Answer 1
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)