Python中的Haversine公式(两个GPS点之间的方位和距离)
问题
我想知道如何获得2个GPS点之间的距离和方位 。 我研究了半胱氨酸的配方。 有人告诉我,我也可以使用相同的数据find方位。
编辑
一切工作正常,但轴承还不正常。 轴承输出负值,但应在0 – 360度之间。 设定的数据应该是水平轴承96.02166666666666
并且是:
Start point: 53.32055555555556 , -1.7297222222222221 Bearing: 96.02166666666666 Distance: 2 km Destination point: 53.31861111111111, -1.6997222222222223 Final bearing: 96.04555555555555
这是我的新代码:
from math import * Aaltitude = 2000 Oppsite = 20000 lat1 = 53.32055555555556 lat2 = 53.31861111111111 lon1 = -1.7297222222222221 lon2 = -1.6997222222222223 lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 c = 2 * atan2(sqrt(a), sqrt(1-a)) Base = 6371 * c Bearing =atan2(cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2)) Bearing = degrees(Bearing) print "" print "" print "--------------------" print "Horizontal Distance:" print Base print "--------------------" print "Bearing:" print Bearing print "--------------------" Base2 = Base * 1000 distance = Base * 2 + Oppsite * 2 / 2 Caltitude = Oppsite - Aaltitude a = Oppsite/Base b = atan(a) c = degrees(b) distance = distance / 1000 print "The degree of vertical angle is:" print c print "--------------------" print "The distance between the Balloon GPS and the Antenna GPS is:" print distance print "--------------------"
这是一个Python版本:
from math import radians, cos, sin, asin, sqrt def haversine(lon1, lat1, lon2, lat2): """ Calculate the great circle distance between two points on the earth (specified in decimal degrees) """ # convert decimal degrees to radians lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) # 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
方位计算不正确,您需要将input交换到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
这会给你正确的方位。
python中的一些实现:
您可以通过添加360°来解决负面的轴承问题。 不幸的是,这可能导致正向轴承的轴承大于360°。 这是模运算符的一个很好的候选者,所以总的来说你应该添加这条线
Bearing = (Bearing + 360) % 360
在你的方法结束。
我没有python翻译,但她是你需要的公式。
您可以尝试以下方法:
from haversine import haversine haversine((45.7597, 4.8422),(48.8567, 2.3508),miles = True) 243.71209416020253
atan2中的Y默认是第一个参数。 这里是文档 。 您需要切换input以获得正确的方位angular。
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
请参阅以下链接: https : //gis.stackexchange.com/questions/84885/whats-the-difference-between-vincenty-and-great-circle-distance-calculations
这实际上给出了两种获得距离的方法。 他们是Haversine和Vincentys。 从我的研究中,我知道Vincentys是相对准确的。 也使用import语句来实现。
这些答案中的大部分是“四舍五入”地球的半径。 如果您对其他距离计算器(如geopy)进行检查,这些function将closures。
这很好:
lon1 = -103.548851 lat1 = 32.0004311 lon2 = -103.6041946 lat2 = 33.374939 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 print(haversine(lat1, lon1, lat2, lon2))
以下是计算距离和方位的两个函数,它们基于前面的消息和https://gist.github.com/jeromer/2005586中的代码(对于两个函数,为了清晰起见,添加了纬度为纬度的地理点的元组types)。; 我testing了这两个function,他们似乎工作正确。
#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)