# Calculating angle of polyline at midpoint using Python/ArcPy?

Trying to calculate the angle of a line at its mid point using python; this will be used to display flow direction on a water network.

I've developed this script, which works in terms of generating the correct output, however, the angle returned is incorrect. I am currenlty getting some negative values, where I would like to have outputs of 0 to 360, in either an Arithmetic or Geographic format.

``````#OperationAlligator.py
import arcpy, math, datetime, numpy
from arcpy import env

print ("starting")
start = datetime.datetime.now() # for calculating time of process

#setting the test sources
flowArrow = r"J:\PYTHON\Flow_Direction.gdb\test" # pre-added fields "angle"
pipes = r"J:\PYTHON\Flow_Direction.gdb\Pipes"

#UpdateCursor
rows = arcpy.UpdateCursor(pipes)
updateRows_FlowArrow = arcpy.UpdateCursor(flowArrow)

#housekeeping
arcpy.DeleteFeatures_management(flowArrow)
arcpy.env.overwriteOutput = True

#Creating the physical xy locations in memory
shapeName = arcpy.Describe(pipes).shapeFieldName
for row in rows:
feat = row.getValue(shapeName)
x = feat.positionAlongLine(0.51,True).firstPoint.X - feat.positionAlongLine(0.49,True).firstPoint.X
y = feat.positionAlongLine(0.51,True).firstPoint.Y - feat.positionAlongLine(0.49,True).firstPoint.Y

degrees = radian * 180 / math.pi
print degrees
row.angle = degrees
rows.updateRow(row)

#Generating the mid point flow arrow
out_cursor = arcpy.InsertCursor(flowArrow)
midpoint = feat.positionAlongLine(0.50,True).firstPoint
outRow = out_cursor.newRow()
outRow.Shape = midpoint
outRow.angle = row.angle
out_cursor.insertRow(outRow)

del rows, row, updateRows_FlowArrow, outRow, out_cursor
print "Done in ",datetime.datetime.now() - start, " seconds"
``````

• (1) Your formula for the angle is incorrect. (2) Don't use `atan`--which only returns angles in [0, pi]--but use instead `atan2`. (3) Once you have corrected the mistakes you can reduce the result modulo 360 degrees to get it into the desired range. Jan 7, 2014 at 3:41

Try replacing

``````radian = math.atan2((x1 - y1),(x2 - y2))
``````

with

``````radian = math.atan2((y2 - y1),(x2 - x1))
``````

You should also avoid using the ends of your line segments but rather use the points located just before and after your midpoint

``````radian = math.atan2((feat.positionAlongLine(0.51,True).firstPoint.Y - feat.positionAlongLine(0.49,True).firstPoint.Y),(feat.positionAlongLine(0.51,True).firstPoint.X - feat.positionAlongLine(0.49,True).firstPoint.X))
``````
• with this change I am now getting a constant value of -135 for all of the midpoints Jan 7, 2014 at 20:25
• Cecil, the code in your post still has not corrected the most glaring error: look closely at what gets subtracted from what in the arguments to `atan2`. By mixing these up, you are going to get two huge values whose arctangent will be very close to 45 degrees plus some integral number of right angles, so it's no surprise that (after the rounding which occurs when results are stored in a table) you wind up with constant values like 45 or 135 = 90 + 45. Jan 7, 2014 at 21:14