Get line direction/orientation as a numeric field

43311
15
05-01-2011 08:48 PM
AlanAitken
New Contributor
Should be a simple one here.


How do I get ArcGIS 10 to return the orientation (or direction) of each line in a polyline feature into a field.

what do I need to type into field calculator (or is there a better way)

Ta
Alan
Tags (2)
0 Kudos
15 Replies
MarcoRusmini
New Contributor
I'm not a phyton programmer but I run into the same problem: finding the deviation from North. I solved it (or it seems) by swopping firstpoint and lastpoint in the following way:

180+math.atan2(( !Shape.firstpoint.X! - !Shape.lastpoint.X! ),( !Shape.firstpoint.Y! - !Shape.lastpoint.Y! ) ) * (180 / math.pi )

It seems to me that it returns exactly the deviation from North!!

Please check this out

Cheers

Marco Rusmini

Hi!
I wanted to use the Code to define the deviation from north in degree. Where north would be 0 east 90 south 180 and west 270. So I changed the code to this:

180 + math.atan2((!Shape.lastpoint.X! - !Shape.firstpoint.X!),(!Shape.lastpoint.Y! - !Shape.firstpoint.Y!)) * (180 / math.pi)

So far so good, BUT for everything in western direction I get a negative value eg. -90 instead of 270.

Any mathematical genius that can enlighten me?
Thanks
Chris
RichardFairhurst
MVP Honored Contributor

The formula by Brady is the only correct formula proposed above.

The basic formula to calculate degrees from two points is only correct in Brady's formula:

math.degrees(math.atan2((!Shape.lastPoint.X! - !Shape.firstPoint.X!),(!Shape.lastPoint.Y! - !Shape.firstPoint.Y!)))

or

math.atan2((!Shape.lastpoint.X! - !Shape.firstpoint.X!),(!Shape.lastpoint.Y! - !Shape.firstpoint.Y!)) * (180 / math.pi)

This formula starts with 0 degrees pointing north and produces positive angles in the positive X axis (east half) and negative angles in the negative x axis (west half) of the quadrants:  To make all angles positive so that it is clearer that they are all increasing in a clockwise direction, the formula needs to only add 360 to all of the negative angles in the West half of the quadrants.  Brady's codeblock does this and using the codeblock this way is the only efficient way to do this calculation.

Although the expression below runs much slower than Brady's codeblock, it is possible to do this calculation correctly without using a codeblock by using a single in-line if python expression:

360 + math.degrees(math.atan2((!Shape.lastpoint.X! - !Shape.firstpoint.X!),(!Shape.lastpoint.Y! - !Shape.firstpoint.Y!))) if math.degrees(math.atan2((!Shape.lastpoint.X! - !Shape.firstpoint.X!),(!Shape.lastpoint.Y! - !Shape.firstpoint.Y!))) < 0 else math.degrees(math.atan2((!Shape.lastpoint.X! - !Shape.firstpoint.X!),(!Shape.lastpoint.Y! - !Shape.firstpoint.Y!)))

This code is slower than Brady's code since it has to extract the end points from the line and do the degree calculation multiple times, while his calculation only does those 2 steps once.

By adding 180 degrees to the basic formula, Criss has made 0 and 360 degrees represent a line that is pointed South and messed up the quadrants of the angles.  Marco's formula defaults to a South (180 degree) line orientation, but by swapping the points he has reversed the orientation of the line relative to its real orientation, which I believe restores the real line orientation to show north as 0 or 360 degrees and fixes the messed up quadrants of the angles.  I think Marco's formula may actually work except when it is used with a closed line (both ends are the same point) which will be reported as 180 degrees and not as 0 degrees.  However, closed lines are a special case, and none of the formulas make it possible to distinguish that situation from a line that is actually oriented due north (for Brady's formula) or due south (for Marco's formula).

The Linear Directional Mean tool does produce angles that are compass oriented, and takes into consideration more than just the two end points of the line.  So it provides a fuller analysis of the line direction for complex polylines and populates additional fields that make it possible to identify closed polylines and polylines where the angle between the end points does not really correspond to the overall directional trend of the polyline.  The trig formula is really only accurate for two point lines that fall within the bounds that a Projected Coordinate System has been optimized to cover.  It does not really work very well for polylines with many vertices that have severe changes in directions between the two end points or lines that extend beyond the appropriate bounds of a Projected Coordinate System.

MarkusGeier
New Contributor

You, sir, are my personal hero of the day. Thank you so much for your help.

0 Kudos
TedKowal
Occasional Contributor III

I use Radians for determining Azimuth's and convert it back to 360 degrees....  here is a VB snippet of code I use from an interactive addIn I created.  Me.lng/Me.Lat is the user's selected start point of the line  destination is the lat/lng of the endpoint.  Some Python guru can easily convert this to Python...

Public Function GetAzimuth(destination As LatLng) As Double
  Dim longitudinalDifference = destination.Lng - Me.Lng
  Dim latitudinalDifference = destination.Lat - Me.Lat
  Dim azimuth = (Math.PI * 0.5) - Math.Atan(latitudinalDifference / longitudinalDifference)
  If longitudinalDifference > 0 Then
   Return azimuth
  ElseIf longitudinalDifference < 0 Then
   Return azimuth + Math.PI
  ElseIf latitudinalDifference < 0 Then
   Return Math.PI
  End If
  Return 0.0
End Function


Public Function GetDegreesAzimuth(destination As LatLng) As Double
  Return RadiansToDegreesConversionFactor * GetAzimuth(destination)
End Function


0 Kudos
DanPatterson_Retired
MVP Emeritus

this thread shows the basics of a numpy/python implementation... getting the start and endpoints can be done with FeatureclassToNumPyArray, then distances and angles from a source to a destination(s) is quick

https://community.esri.com/thread/66222#comment-570366

DiegoNegron
New Contributor III

I do want to note that if you have a logitudinalDifference that equals 0 you will generate a zero division error with this code.

0 Kudos