Recently, I needed to calculate the compass direction (i.e. North, South West etc) between two points.

At first, this seemed like a simple task as visually for humans it's very easy...but figuring out how to get it calculated took me a little longer than I'd hoped!

I'll managed to finally crack it, so can run through my code here.

Let's visualise two simple points on a 2D grid, each with an x and y coordinate

In this first scenario, the blue dot is the origin located at (2,3) and the red dot is the destination located at (7,7).

Straight away, we know we'd need to travel North East, but let's get Python to figure it out instead!

Firstly, let's specify these points:

destination_x = 7

origin_x = 2

destination_y = 7

origin_y = 3

Then, let's calculate the distance between the points along the x axis and the y axis:

deltaX = destination_x - origin_x

deltaY = destination_y - origin_y

Now, into some maths:

degrees_temp = math.atan2(deltaX, deltaY)/math.pi*180

math.atan2 is a function that returns the arc tangent of two numbers x and y. Think back to trigonometry at high school and you might remeber working out the tan(opposite/adjacent) to find the angle between them. This is precisely that!

This returns a value in radians. Radians are a unit of measurement of angles equal to about 57.3 degrees (or 360 / 2pi), equivalent to the angle subtended at the centre of a circle by an arc equal in length to the radius.

To convert this to degrees, we divide the result by pi*180.

This is all well and good for angles between 0 and 180 degrees, but for angles between 180 and 360 degrees it returns a negative number of degrees, i.e. it works back from 0 instead of carrying on around in a clockwise direction.

To counter this, I added an if statement:

if degrees_temp < 0:

degrees_final = 360 + degrees_temp

else:

degrees_final = degrees_temp

So now we have the precise number of degrees between the two points, but how to we summarise that down to a compass value of North East, or South West etc?

Let's create a list, containing the brackets we want:

compass_brackets = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"]

Note: We include North twice to counter it being on either side of 0

And then, create a 'score' that will fit our degree value into one of those brackets

compass_lookup = round(degrees_final / 45)

Each bracket is 45 degrees, hence dividing by 45

Now, if we lookup our value in our directions list, it should return us our direction

compass_brackets[compass_lookup]

>>> 'NE'

Full Function Code:

def direction_lookup(destination_x, origin_x, destination_y, origin_y):

deltaX = destination_x - origin_x

deltaY = destination_y - origin_y

degrees_temp = math.atan2(deltaX, deltaY)/math.pi*180

if degrees_temp < 0:

degrees_final = 360 + degrees_temp

else:

degrees_final = degrees_temp

compass_brackets = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"]

compass_lookup = round(degrees_final / 45)

return compass_brackets[compass_lookup], degrees_final

direction_lookup(7,2,7,3)

>>> ('NE', 51.340191745909905)

To test it, let's reverse the origin and destination (i.e. we now want to go from the red dot to the blue dot)

direction_lookup(7,2,7,3)

>>> ('SW', 231.3401917459099)

It works!

I hope that's helpful. If you have any suggestions/improvements/comments - feel free to get in touch.