Haversine Formula in Python (Bearing and Distance between two GPS points)

后端 未结 10 1586
死守一世寂寞
死守一世寂寞 2020-11-22 09:47

Problem

I would like to know how to get the distance and bearing between 2 GPS points. I have researched on the haversine formula. Someone told me

相关标签:
10条回答
  • 2020-11-22 10:13

    The Y in atan2 is, by default, the first parameter. Here is the documentation. You will need to switch your inputs to get the correct bearing angle.

    bearing = atan2(sin(lon2-lon1)*cos(lat2), cos(lat1)*sin(lat2)in(lat1)*cos(lat2)*cos(lon2-lon1))
    bearing = degrees(bearing)
    bearing = (bearing + 360) % 360
    
    0 讨论(0)
  • 2020-11-22 10:17

    The bearing calculation is incorrect, you need to swap the inputs to atan2.

        bearing = atan2(sin(long2-long1)*cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(long2-long1))
        bearing = degrees(bearing)
        bearing = (bearing + 360) % 360
    

    This will give you the correct bearing.

    0 讨论(0)
  • 2020-11-22 10:18

    There is also a vectorized implementation, which allows to use 4 numpy arrays instead of scalar values for coordinates:

    def distance(s_lat, s_lng, e_lat, e_lng):
    
       # approximate radius of earth in km
       R = 6373.0
    
       s_lat = s_lat*np.pi/180.0                      
       s_lng = np.deg2rad(s_lng)     
       e_lat = np.deg2rad(e_lat)                       
       e_lng = np.deg2rad(e_lng)  
    
       d = np.sin((e_lat - s_lat)/2)**2 + np.cos(s_lat)*np.cos(e_lat) * np.sin((e_lng - s_lng)/2)**2
    
       return 2 * R * np.arcsin(np.sqrt(d))
    
    0 讨论(0)
  • 2020-11-22 10:18

    Here are two functions to calculate distance and bearing, which are based on the code in previous messages and https://gist.github.com/jeromer/2005586 (added tuple type for geographical points in lat, lon format for both functions for clarity). I tested both functions and they seem to work right.

    #coding:UTF-8
    from math import radians, cos, sin, asin, sqrt, atan2, degrees
    
    def haversine(pointA, pointB):
    
        if (type(pointA) != tuple) or (type(pointB) != tuple):
            raise TypeError("Only tuples are supported as arguments")
    
        lat1 = pointA[0]
        lon1 = pointA[1]
    
        lat2 = pointB[0]
        lon2 = pointB[1]
    
        # convert decimal degrees to radians 
        lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2]) 
    
        # haversine formula 
        dlon = lon2 - lon1 
        dlat = lat2 - lat1 
        a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
        c = 2 * asin(sqrt(a)) 
        r = 6371 # Radius of earth in kilometers. Use 3956 for miles
        return c * r
    
    
    def initial_bearing(pointA, pointB):
    
        if (type(pointA) != tuple) or (type(pointB) != tuple):
            raise TypeError("Only tuples are supported as arguments")
    
        lat1 = radians(pointA[0])
        lat2 = radians(pointB[0])
    
        diffLong = radians(pointB[1] - pointA[1])
    
        x = sin(diffLong) * cos(lat2)
        y = cos(lat1) * sin(lat2) - (sin(lat1)
                * cos(lat2) * cos(diffLong))
    
        initial_bearing = 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 = degrees(initial_bearing)
        compass_bearing = (initial_bearing + 360) % 360
    
        return compass_bearing
    
    pA = (46.2038,6.1530)
    pB = (46.449, 30.690)
    
    print haversine(pA, pB)
    
    print initial_bearing(pA, pB)
    
    0 讨论(0)
  • 2020-11-22 10:25

    Most of these answers are "rounding" the radius of the earth. If you check these against other distance calculators (such as geopy), these functions will be off.

    This works well:

    from math import radians, cos, sin, asin, sqrt
    
    def haversine(lat1, lon1, lat2, lon2):
    
          R = 3959.87433 # this is in miles.  For Earth radius in kilometers use 6372.8 km
    
          dLat = radians(lat2 - lat1)
          dLon = radians(lon2 - lon1)
          lat1 = radians(lat1)
          lat2 = radians(lat2)
    
          a = sin(dLat/2)**2 + cos(lat1)*cos(lat2)*sin(dLon/2)**2
          c = 2*asin(sqrt(a))
    
          return R * c
    
    # Usage
    lon1 = -103.548851
    lat1 = 32.0004311
    lon2 = -103.6041946
    lat2 = 33.374939
    
    print(haversine(lat1, lon1, lat2, lon2))
    
    0 讨论(0)
  • 2020-11-22 10:25

    Refer to this link :https://gis.stackexchange.com/questions/84885/whats-the-difference-between-vincenty-and-great-circle-distance-calculations

    this actually gives two ways of getting distance. They are Haversine and Vincentys. From my research I came to know that Vincentys is relatively accurate. Also use import statement to make the implementation.

    0 讨论(0)
提交回复
热议问题