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"
        )
8
  • This Q&A should provide some ideas for starting code: gis.stackexchange.com/q/215283/115
    – PolyGeo
    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
    – user103910
    Jan 23, 2019 at 13:43
  • BERA do you have an answer?
    – user103910
    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.
    – Hornbydd
    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.
    – Hornbydd
    Jan 23, 2019 at 16:13

1 Answer 1

3

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.