当给定每端点的纬度和经度时,我有一个短函数来计算线的中点。简单来说,当经度大于-90度或小于90度时,它可以正常工作。对于地球的另一半,它提供了一些随机的结果。
该代码是http://www.movable-type.co.uk/scripts/latlong.html提供的javascript的python转换,似乎符合更正的版本here和here。与两个stackoverflow版本进行比较时,我承认我不用C#或Java编写代码,但我无法发现我的错误。
代码如下:
#!/usr/bin/python
import math
def midpoint(p1, p2):
lat1, lat2 = math.radians(p1[0]), math.radians(p2[0])
lon1, lon2 = math.radians(p1[1]), math.radians(p2[1])
dlon = lon2 - lon1
dx = math.cos(lat2) * math.cos(dlon)
dy = math.cos(lat2) * math.sin(dlon)
lat3 = math.atan2(math.sin(lat1) + math.sin(lat2), math.sqrt((math.cos(lat1) + dx) * (math.cos(lat1) + dx) + dy * dy))
lon3 = lon1 + math.atan2(dy, math.cos(lat1) + dx)
return(math.degrees(lat3), math.degrees(lon3))
p1 = (6.4, 45)
p2 = (7.3, 43.5)
print "Correct:", midpoint(p1, p2)
p1 = (95.5,41.4)
p2 = (96.3,41.8)
print "Wrong:", midpoint(p1, p2)
有什么建议吗?
答案 0 :(得分:4)
将您的arg设置代码替换为:
lat1, lon1 = p1
lat2, lon2 = p2
assert -90 <= lat1 <= 90
assert -90 <= lat2 <= 90
assert -180 <= lon1 <= 180
assert -180 <= lon2 <= 180
lat1, lon1, lat2, lon2 = map(math.radians, (lat1, lon1, lat2, lon2))
再次运行您的代码。
更新关于纬度/经度计算的一些有希望的一般性建议:
中点例程的最后一部分可以有效地改变,以避免长途使用的潜在问题:
lon3 = lon1 + math.atan2(dy, math.cos(lat1) + dx)
# replacement code follows:
lon3d = math.degrees(lon3)
if lon3d < -180:
print "oops1", lon3d
lon3d += 360
elif lon3d > 180:
print "oops2", lon3d
lon3d -= 360
return(math.degrees(lat3), lon3d)
例如,找到奥克兰,新西兰(-36.9,174.8)和帕皮提,大溪地(-17.5,-149.5)之间的中点,在获得有效答案oops2 194.270430902
<的途中产生(-28.355951246746923, -165.72956909809082)
/ p>
答案 1 :(得分:1)
首先,道歉,我要留下另一个答案。我对该答案中提到的问题有一个解决方案,涉及如何找到日期线两侧的两点的中点。我想简单地在现有答案中添加评论,但我没有这样做的声誉。
通过查看http://www.movable-type.co.uk/scripts/latlong.html处为该工具提供支持的Javascript文件,找到了该解决方案。我正在使用shapely.geometry.Point。如果你不想安装这个软件包,那么使用元组代码就可以了。
def midpoint(pointA, pointB):
lonA = math.radians(pointA.x)
lonB = math.radians(pointB.x)
latA = math.radians(pointA.y)
latB = math.radians(pointB.y)
dLon = lonB - lonA
Bx = math.cos(latB) * math.cos(dLon)
By = math.cos(latB) * math.sin(dLon)
latC = math.atan2(math.sin(latA) + math.sin(latB),
math.sqrt((math.cos(latA) + Bx) * (math.cos(latA) + Bx) + By * By))
lonC = lonA + math.atan2(By, math.cos(latA) + Bx)
lonC = (lonC + 3 * math.pi) % (2 * math.pi) - math.pi
return Point(math.degrees(lonC), math.degrees(latC))
我希望这是有帮助的,不应被视为不恰当的看法,因为它是对前一个答案中提出的问题的回答。
答案 2 :(得分:0)
不能直接回答&gt; 90问题,但它在我的情况下有所帮助,所以我把它留在这里以防它可以帮助其他人。
我只需要将中点放在带有纬度的地图中,长度为度。我没有使用转换为弧度,并且通过使用简单的欧几里德距离在地图中正确地描绘了它。示例功能:
def midpoint_euclidean(x1,y1,x2,y2):
dist_x = abs(x1-x2) / 2.
dist_y = abs(y1-y2) / 2.
res_x = x1 - dist_x if x1 > x2 else x2 - dist_x
res_y = y1 - dist_y if y1 > y2 else y2 - dist_y
return res_x, res_y