Skip to content

Instantly share code, notes, and snippets.

@jeromer
Last active February 21, 2024 13:31
Show Gist options
  • Save jeromer/2005586 to your computer and use it in GitHub Desktop.
Save jeromer/2005586 to your computer and use it in GitHub Desktop.
compass bearing between two points in Python
# LICENSE: public domain
def calculate_initial_compass_bearing(pointA, pointB):
"""
Calculates the bearing between two points.
The formulae used is the following:
θ = atan2(sin(Δlong).cos(lat2),
cos(lat1).sin(lat2) − sin(lat1).cos(lat2).cos(Δlong))
:Parameters:
- `pointA: The tuple representing the latitude/longitude for the
first point. Latitude and longitude must be in decimal degrees
- `pointB: The tuple representing the latitude/longitude for the
second point. Latitude and longitude must be in decimal degrees
:Returns:
The bearing in degrees
:Returns Type:
float
"""
if (type(pointA) != tuple) or (type(pointB) != tuple):
raise TypeError("Only tuples are supported as arguments")
lat1 = math.radians(pointA[0])
lat2 = math.radians(pointB[0])
diffLong = math.radians(pointB[1] - pointA[1])
x = math.sin(diffLong) * math.cos(lat2)
y = math.cos(lat1) * math.sin(lat2) - (math.sin(lat1)
* math.cos(lat2) * math.cos(diffLong))
initial_bearing = math.atan2(x, y)
# Now we have the initial bearing but math.atan2 return values
# from -180° to + 180° which is not what we want for a compass bearing
# The solution is to normalize the initial bearing as shown below
initial_bearing = math.degrees(initial_bearing)
compass_bearing = (initial_bearing + 360) % 360
return compass_bearing
@deltaoui
Copy link

up !

@fredvollmer
Copy link

Very nice, especially all the explanation. Thank you!

@dali5
Copy link

dali5 commented Jul 19, 2017

thank you

@mapcloud
Copy link

Thank you for sharing!

@minderx
Copy link

minderx commented Aug 25, 2017

great

@glaucomunsberg
Copy link

Great!!

@echocodepy
Copy link

awesome work man

@ocean86
Copy link

ocean86 commented Nov 20, 2017

Thanks!

@zaarcvon
Copy link

zaarcvon commented Feb 9, 2018

Thank you for sharing!

@blackgis
Copy link

blackgis commented Feb 22, 2018

I have an issue with that, the output is different then expected: A = (-73.933781942,40.7062912231)
B = (-73.93390547,40.7062643692)
bearing is 183.44288775507985 but it should be nearly 270
when BA: bearing is 3.4429135601084795 but it should be almost 90
could it be that there is a wired 90 degree changing required somewhere?
bearing issue

Update yes @schicks you are right, i messed up the x and y and i wasn't aware that i can use the wgs84 coordinates without transforming to a 2D
Now it gives back 253.99863197083152 what is expected

@schicks
Copy link

schicks commented Feb 27, 2018

@blackgis, I think you may have the arguments a little messed up. They should be (lat, lon), not (lon, lat).

@lionsterben
Copy link

thank you!

@Amytipple
Copy link

Thanks!

@Gurpmond
Copy link

Gurpmond commented Jun 27, 2018

import math
lat1 = math.radians(float(input("Lattitude1:")))
lat2 = math.radians(float(input("Lattitude2:")))
long1 = math.radians(float(input("Longitude1:")))
long2 = math.radians(float(input("Longitude2:")))
longdifference = math.radians(float(long2-long1))
x = math.sin(longdifference) * math.cos(lat2)
y = math.cos(lat1) * math.sin(lat2) - (math.sin(lat1)* math.cos(lat2) * math.cos(longdifference))
initial_bearing = math.atan2(x, y)
initial_bearing = math.degrees(initial_bearing)
compass_bearing = (initial_bearing + 360) % 360
print(initial_bearing, "°")

Output:
Lattitude1:47.5606
Lattitude2:47.594719
Longitude1:-52.743099
Longitude2:-52.685001

Result: 1.1481674985452277 ° this should be 49°, why i am getting wrong value ?

@tboutaour
Copy link

Great work! It's what I looking for. Thank you

@nikisix
Copy link

nikisix commented Aug 22, 2019

Good job!

@Mantej-Singh
Copy link

Thanks for this method, really helped me in a project

@gpayne007
Copy link

Thank you!

@ErPraveenSingh
Copy link

Thanks for providing a good option. It is a really helpful for us.

@neeveermoree
Copy link

Dude, I want to have kids from you <3. Excellent work!!!

@gmazet
Copy link

gmazet commented Feb 16, 2021

Much faster than importing obspy.geodetics.gps2dist_azimuth
Thanks a lot

@GAnagno
Copy link

GAnagno commented Jun 7, 2021

Great work! Thanks very much 👍

@tobixen
Copy link

tobixen commented Jun 24, 2021

This is good enough for me, though I think the algorithm is a bit simplified. It will probably give inaccurate results when used over long distances or when one is close to the poles. I find it strange that there isn't anything easily available through the geopy library.

@dsecuma
Copy link

dsecuma commented Jul 15, 2021

Excellent work

@normanheckscher
Copy link

Thanks. Fixed my problem with this one.

@HCaspari
Copy link

HCaspari commented Mar 6, 2023

Thank you this worked 👯

@BritishTechGuru
Copy link

I like this. I'll combine this with Vincenty's formula to return bearing and distance.

@av01d
Copy link

av01d commented Feb 21, 2024

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