# UpdateAngle.py
# assumes rectangular polygons
# find bearing of longest side
# might have trouble with up
# 2 June 2011
# Kim Ollivier
import arcgisscripting
from math import *
import datetime
gp = arcgisscripting.create(9.3)
try:
layer = sys.argv[1]
except:
layer = "stripindex"
ws = 'e:/teararoa/nz/current.gdb'
gp.workspace = ws
if not gp.Exists(ws):
print "ws",ws
raise Exception
rotField = "smap_angle"
if not gp.ListFields(layer,rotField):
gp.AddField(layer,rotField,"FLOAT")
def calcbearing(dPt):
'''
calculate bearing of longest side
'''
# points
pt1 = dPt[1]
pt2 = dPt[2]
pt3 = dPt[3]
# lengths
l1 = hypot(pt2[0] - pt1[0],pt2[1] - pt1[1])
l2 = hypot(pt3[0] - pt2[0],pt3[1] - pt2[1])
# bearings
b1 = atan2(pt2[1] - pt1[1],pt2[0] - pt1[0])
b2 = atan2(pt3[1] - pt2[1],pt3[0] - pt2[0])
# print "test",round(l1),round(l2),degrees(b1),degrees(b2)
# print dPt
if l1 > l2 :
degree = degrees(b1)
else:
degree = degrees(b2)
bearing = 90.0 - degree
if bearing > 90:
bearing = bearing - 180
if bearing < -90:
bearing = bearing + 180
return bearing
cur = gp.UpdateCursor(layer) ##,"ID = 1")
row = cur.next()
while row:
feat = row.Shape
for partNum in range(feat.partCount) :
part = feat.getPart(partNum)
dPt = {}
n = 0
for pt in iter(lambda: part.next(),None): # stops at null pt
n+=1
dPt= (pt.X,pt.Y)
rotation = calcbearing(dPt)
row.setValue(rotField,rotation)
row.setValue("LastUpdate",datetime.datetime.now())
# print row.objectid,row.id,row.island,rotation #,dPt
cur.updateRow(row)
row = cur.next()
del row,cur
Has anyone found a Simple solution to this? I am experiencing the same problem
I believe you will still have to rely on a custom python script, although using arcpy geometry objects will likely shorten Kim's script considerably. I'll try to follow up on this.
Here is a 10.1 script you can use to calculate the data driven page rotation angle into a field called calcAngle, for an index feature class of rectangles.
>>> import math
... with arcpy.da.UpdateCursor("RECTANGLE_INDEX_FEATURE CLASS",["SHAPE@","calcAngle"]) as cursor:
... for row in cursor:
... points = []
... for part in row[0]:
... for pnt in part:
... points.append(pnt)
... lines = []
... for i in range(1,3):
... lines.append(arcpy.Polyline(arcpy.Array([points,points[i-1]])))
... if lines[0].length > lines[1].length:
... firstShort = 0
... else:
... firstShort = 1
... dx = points[firstShort].X - points[firstShort+1].X
... dy = points[firstShort].Y - points[firstShort+1].Y
... ang = math.degrees(math.atan(dy/dx))
... row[1] = 360-ang
... cursor.updateRow(row)
Hi Darren,
This looks exactly like what I need however I cannot get the code to work for me. I am trying this in 10.3. I get the error message :Runtime error
Traceback (most recent call last):
File "<string>", line 6, in <module>
TypeError: 'float' object is not iterable
I changed the Feature class and field names to match my layer. ("Release_Grid",["Shape","calcAngle"]
Any suggestions?
Make sure you use "SHAPE@", a special token for the actual geometry.
Got it! Thank you!!
Thanks for Darren's script which works perfectly. However I found it requires the 4 points of the polygon be created in a certain order, which might be all right for index polygons created via DDP tool, but in our case we often got the index polygons from other source like CAD design where how it was created not always guaranteed. So I modified Darren's code a bit to allow the calculation work on polygons created in any direction. cheers,