I have a FC with a column for NEAR_ANGLE from the output of the NEAR tool. The angle is displayed in degrees (i.e. -154.67687) which is fine. I am trying to create a column, HEADING, that reads this degree value and converts it to either a "North, North-east, South, South-west... etc. whichever direction the near object happens to be from my point.

i.e. If value is between 0 and 90 then East, or if value is between -180 and -90 then South-west

I've searched and tried several examples but none work for me.



1 Answer 1


A while ago, I wrote this Python function that returns 'E', 'NE', 'N', etc. based on the overall direction of a line geometry (i.e. the direction from its starting coordinates to its ending coordinates).

def determine_arc_bearing(line_geom):
    ''' Determines the cardinal direction of a single arc, determined from its
        two endpoints. The angle is determined by the atan2() function, and
        after some numeric manipulation is then used to select the correct
        cardinal direction from an ordered list of possibilities. '''
    from math import atan2, degrees, floor
    x1 = line_geom.firstPoint.X
    y1 = line_geom.firstPoint.Y
    x2 = line_geom.lastPoint.X
    y2 = line_geom.lastPoint.Y
    xdiff = x2 - x1
    ydiff = y2 - y1
    angle = degrees(atan2(ydiff, xdiff))
    index = int(floor(((angle + 22.5) % 360) / 45))
    cardinal_dirs = ('E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE')  # Order here is critical
    bearing = cardinal_dirs[index]
    return bearing

You can adapt the code after the coordinate calculations to suit your own needs. The key part are the 3 lines at the end that calculate index, cardinal_dirs and bearing. You could use a stripped-down version of this function that accepts your NEAR_ANGLE field as the argument in your pre-logic script code:

def determine_heading(angle):
    from math import floor
    index = int(floor(((angle + 22.5) % 360) / 45))
    cardinal_dirs = ('N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW')  # Order here is critical
    bearing = cardinal_dirs[index]
    return bearing

And then the expressions for actually calculating HEADING =

  • Would this work if the two locations were two separate points instead of a line feature?
    – Carl Ross
    Aug 28, 2017 at 17:57
  • I have an X field for the starting point....From_X and a Y field ... From_Y. The near object 's fields are X..NEAR_X and Y ..NEAR_Y
    – Carl Ross
    Aug 28, 2017 at 18:00
  • @CarlRoss yes, you could modify the function to accept four fields as arguments (instead of one line geometry argument) and use those to set the x1 (From_X), y1 (From_Y), x2 (NEAR_X) and y2 (NEAR_Y) values. If you do it that way, the math should work as-is.
    – nmpeterson
    Aug 28, 2017 at 18:05
  • @CarlRoss I should add that this will not work well if your X/Y coordinates are unprojected (i.e. in decimal degrees). This is Euclidean math that works well with the assumption of a flat plane, but is unreliable for curved surfaces, which is what decimal degrees represent.
    – nmpeterson
    Aug 28, 2017 at 18:08
  • Forgive me. Im relatively new to this. I do have an angle that is being produced by running the NEAR tool. For example, the output of the angle is -150.265648. Im assuming that this is the angle from my starting point to the near point. Being new and slightly naive, I thought that maybe I could just insert code into the calculator that would take this angle , and return a string depending on which two angles (settings) it fell between. If it was between zero and 90, then return Northeast...and so on. Im way off here aren't I?
    – Carl Ross
    Aug 28, 2017 at 18:15

Not the answer you're looking for? Browse other questions tagged or ask your own question.