great.py

Created by tlake

Created on August 15, 2020

3.67 KB

Computer great circle distance between two cities whose coordinates are known


from math import *

# distance using Meeus approximation
def distance( lat1, lon1, lat2, lon2 ) :

    F = (lat1 + lat2)/2.0
    G = (lat1 - lat2)/2.0
    L = (lon1 - lon2)/2.0

    sinG2 = sin(G)**2
    cosG2 = cos(G)**2
    sinF2 = sin(F)**2
    cosF2 = cos(F)**2
    sinL2 = sin(L)**2
    cosL2 = cos(L)**2

    S = sinG2*cosL2 + cosF2*sinL2
    C = cosG2*cosL2 + sinF2*sinL2

    w = atan(sqrt(S/C))
    R = sqrt(S*C)/w

    a = 6378.137            # WGS-84 equatorial radius
    f = 1.0/298.257223563   # WGS-84 ellipsoid flattening factor

    D = 2*w*a
    H1 = (3*R - 1)/(2*C)
    H2 = (3*R + 1)/(2*S)

    dist = D*(1 + f*H1*sinF2*cosG2 - f*H2*cosF2*sinG2)

    return round(100*dist)/100.0


# course using spherical trigonometry
# does not work if one latitude is polar!!!
def course( lat1, lon1, lat2, lon2 ):

    L    = lon2 - lon1
    cosD = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(L)  
    D    = acos(cosD)
    cosC = (sin(lat2) - cosD*sin(lat1))/(sin(D)*cos(lat1))

# numerical error can result in |cosC| slightly > 1.0 
    if cosC > 1.0:
        cosC = 1.0

    if cosC < -1.0:
        cosC = -1.0

    C = 180.0*acos(cosC)/pi

    if sin(L) < 0.0:
        C = 360.0 - C


    return round(100*C)/100.0


# convert to radians
def latitude( sgn, deg, min, sec ):

    lat = 0

    if (0.0 <= sec) and (sec < 60.0):
        lat = lat + sec/3600.0
    else:
        print("check latitude seconds!") 


    if (0.0 <= min) and (min < 60.0):
        lat = lat + min/60.0
    else:
        print("check latitude minutes!")

    
    if (0.0 <= deg) and (deg <= 90.0):
        lat = lat + deg
    else:
        print("check latitude degrees!")


    if (0.0 <= lat) and (lat <= 90.0):
        lat = pi*lat/180.0
    else:
        print("latitude range error!")


    assert (sgn == +1) or (sgn == -1)
    return sgn*lat


# convert to radians
def longitude( sgn, deg, min, sec ):

    lon = 0

    if (0.0 <= sec) and (sec < 60.0):
        lon = lon + sec / 3600.0
    else:
        print("check longitude seconds!")

    
    if (0.0 <= min) and (min < 60.0):
        lon = lon + min / 60.0
    else:
        print("check longitude minutes!")


    if (0.0 <= deg) and (deg <= 180.0):
        lon = lon + deg
    else:
        print("check longitude degrees!")


    if (0.0 <= lon) and (lon <= 180.0):
        lon = pi * lon / 180.0
    else:
        print("longitude range error!")


    assert (sgn == +1) or (sgn == -1)
    return sgn*lon


# Sydney, AS     33°53' S  151°13' E
lat1 = latitude(  -1,  33, 53, 0 )
lon1 = longitude( +1, 151, 13, 0 )

# London, UK,    51°30' N    0°07' W
lat2 = latitude(  +1, 51, 30, 0 )
lon2 = longitude( -1,  0,  7, 0 )

# Boston, MA US  42°21' N   71°04' W
lat3 = latitude(  +1, 42, 21, 0 )
lon3 = longitude( -1, 71,  4, 0 )

# Tokyo, JA,     35°41' N  139°45' E
lat4 = latitude(  +1,  35, 41, 0 )
lon4 = longitude( +1, 139, 45, 0 )

print("Sydney, AS to London, UK")
dist = distance(lat1, lon1, lat2, lon2)
crse = course(lat1, lon1, lat2, lon2)
print("distance = %8.2f  kilometers" %(dist))
print("heading  = %8.2f° true (initially)\n" %(crse))

print("London, UK to Boston, MA US")
dist = distance(lat2, lon2, lat3, lon3)
crse = course(lat2, lon2, lat3, lon3)
print("distance = %8.2f  kilometers" %(dist))
print("heading  = %8.2f° true (initially)\n" %(crse))

print("Boston, MA US to Tokyo, JA")
dist = distance(lat3, lon3, lat4, lon4)
crse = course(lat3, lon3, lat4, lon4)
print("distance = %8.2f  kilometers" %(dist))
print("heading  = %8.2f° true (initially)\n" %(crse))

print("Tokyo, JA to Sydney, AS")
dist = distance(lat4, lon4, lat1, lon1)
crse = course(lat4, lon4, lat1, lon1)
print("distance = %8.2f  kilometers" %(dist))
print("heading  = %8.2f° true (initially)\n" %(crse))

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.