Skip to content

Instantly share code, notes, and snippets.

@RobertSudwarts
Created June 7, 2015 16:18
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save RobertSudwarts/acf8df23a16afdb5837f to your computer and use it in GitHub Desktop.
Save RobertSudwarts/acf8df23a16afdb5837f to your computer and use it in GitHub Desktop.
[python] degrees to cardinal directions
def degrees_to_cardinal(d):
'''
note: this is highly approximate...
'''
dirs = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"]
ix = int((d + 11.25)/22.5)
return dirs[ix % 16]
@roughlycoded
Copy link

Changing this to:
ix = int((d + 11.25)/22.5 - 0.02)
makes it spot on for integer degrees.

@umiphos
Copy link

umiphos commented Oct 12, 2016

Maybe I'm wrong, but what about just adding
ix = int((d)/22.5)
I'm using this one because it didn't appeared to work with this image
https://s-media-cache-ak0.pinimg.com/564x/ff/14/77/ff1477c3a93e44cef33e6ad0ab007b14.jpg

@rezemika
Copy link

rezemika commented Aug 6, 2017

Used in goose-search (here). Thank you!

@Lauszus
Copy link

Lauszus commented Oct 30, 2019

I would say that @umiphos is correct, however you need to round the result instead of casting it to an integer, as it will always be rounded down.

I.e. the code should be:

dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
ix = round(d / (360. / len(dirs)))
return dirs[ix % len(dirs)]

@shahinIman
Copy link

@RobertSudwarts and @Lauszus,
Used in my project, Thank You!

@Pi-DD
Copy link

Pi-DD commented Aug 4, 2020

@RobertSudwarts and @Lauszus,
Thank you! Used for my weather tracking display project!

@leilaher
Copy link

Thanks, @RobertSudwarts, and @Lauszus. Used for my project!

@mattarderne
Copy link

Haven't investigated too carefully but I needed ix to be an int ie

def calculate_bearing(d):
  dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
  ix = int(round(d / (360. / len(dirs))))  <--- int here
  return dirs[ix % len(dirs)]

Thanks

@Lauszus
Copy link

Lauszus commented Jun 5, 2021

@mattarderne this is because the result of round in Python 2 is a float while the returned value is an int in Python 3.

See: https://docs.python.org/2/library/functions.html#round and https://docs.python.org/3/library/functions.html#round.

Python 2:

If ndigits is omitted, it defaults to zero. The result is a floating point number.

Python 3:

If ndigits is omitted or is None, it returns the nearest integer to its input.

@sooswastaken
Copy link

Thank you, I am going to use this is my project

@STG-fisheries
Copy link

Thank you. Will use this in my project.

@AndreLobato
Copy link

In case someone want's to apply for a Numpy Array of angles I've adapted as such...

def degrees_to_cardinal(d):
    '''
    note: this is highly approximate...
    '''
    dirs = np.array(["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
                     "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"], dtype='U')
    ix = np.round(d / (360. / len(dirs))).astype('i')
    return dirs[ix % 16]

@ptcane
Copy link

ptcane commented Jul 5, 2023

I did the following:

DIRECTIONS = [
    'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW',
    'W', 'WNW', 'NW', 'NNW', 'N'
]

x = 155 # anything 0 - 360
cardinal = DIRECTIONS[round(x / 22.5)]

Note the extra N at the end of the list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment