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.