如何使用GeoDjango计算两点之间的实际距离?

7
from django.contrib.gis.geos import Point

p1 = Point(36.74851779201058, -6.429006806692149, srid=4326)
p2 = Point(37.03254161520977, -8.98366068931684, srid=4326)
p1.distance(p2)
Out: 2.5703941316759376

但这个浮点数的单位是什么?

如果你计算这个距离,它是229.88千米。你也可以使用geopy得到相同的结果:

from geopy.distance import distance
distance(p1, p2)
Out: Distance(229.883275249)
distance(p1, p2).km
Out: 229.88327524944066

我读到过这样的内容,如果你把之前的数字除以111,就可以得到(so so)。

(2.5703941316759376 / 111) * 10000
Out: 231.5670388897241  # kilometers

是否有办法仅使用GeoDjango获取真实距离?或者我应该使用geopy?


1
根据这里的讨论,你应该首先使用球形墨卡托(他们正在使用geodjango)转换你的点。很抱歉我不能提供更好的帮助,我对地理定位不是很熟悉。 - Daniel Kravetz Malabud
如果我转换这些点的结果是:288735.5781466976(288.73公里),误差为20%。这太多了。 - Goin
3个回答

7
通常,所有空间计算都会在与输入相同的坐标系中产生结果。在您的情况下,您应该寻求使用SRID 4326进行计算,该坐标系是经度/纬度极角,以度为单位从本初子午线和赤道测量的。
因此,GeoDjango的距离计算(如果我理解正确)是两个坐标对之间的欧几里德距离。您正在寻找大圆距离(其中您除以111只是一个粗略的近似,在某些纬度范围内仅接近实际的大圆距离)。
geopy应该隐式地使用SRID 4326的大圆距离,从而产生正确的结果。
现在您有几个不同的选择:
A:自己实现大圆
搜索haversine公式,您可以输入两对纬度/经度坐标,并获得实际大圆距离的良好近似值。但是,这取决于所使用的墨卡托逼近--请记住,地球不是一个球体。您可能会在极点附近遇到问题。
B:转换为度量(本地)坐标系
如果您将两个位置转换为以米为单位的另一个坐标系,则计算欧几里德距离将产生正确的结果。但是,这种坐标系(称为平面系统)对于地球上的各个区域是不同的。有不同的投影用于不同的国家,因为将地球的不规则曲面近似为平面是错误的--尤其是对于其表面上的任何位置都不是唯一的错误。
仅当您希望在其中计算距离的所有点都位于同一地理区域时,才适用此选项。
C:使用库进行此操作
使用geopy或shapely或任何其他合格的库,可以基于给定点的SRID计算实际的大圆距离。请记住,所有坐标仅是由于地球的不规则性而产生的近似值。

谢谢!你认为最好的解决方案是什么?对我来说,如果B方案有一点错误,我知道我总会得到一个错误。但是如果我应用B方案(转换为度量(本地)坐标系),我会得到20%的误差(请参见我的其他评论:“如果我转换点的结果是:288735.5781466976(288.73公里),误差为20%。这太多了。”)。所以我认为最好的解决方案是C。请告诉我你的意见。 - Goin
球形墨卡托投影(SRID 900913)在接近极点的点越近,误差就越大。只需在 Google 地图上查看南极洲或格陵兰岛的大小即可了解此情况。此外,您可能需要参考以下链接:http://gis.stackexchange.com/questions/31681/distances-and-areas-in-google-projection -- 总之,您应该毫不犹豫地选择 选项 C - jbndlr

3
据我所知,GeoDjango不支持计算实际距离,它只能在几何上计算距离。因此,我认为您应该像我的项目一样使用geopy。
from geopy.distance import vincenty

distance = vincenty((lat1, lon1), (lat2, lon2)).kilometers

这将给出正确的公里距离。

如需更多信息,请查看 geopy 文档。

http://geopy.readthedocs.io/en/latest/


谢谢!但我更喜欢使用geopy.distance库中的distance函数: from geopy.distance import distance; distance(p1, p2) - Goin

1

有一个在线解决方案,既可以解释GeoDjango最初是如何进行距离计算的(基本上没有使用任何标准单位),也可以将其转换为以更有用的单位返回距离的形式 - 代码与您已经在做的非常相似,只是在检索距离之前对每个点使用了一个变换。以下链接可能对您有用:

https://coderwall.com/p/k1gg1a/distance-calculation-in-geodjango


如果我转换这些点,结果是:288735.5781466976(288.73公里),误差达到了20%。这太大了。 - Goin
是的,我认为你可能会被困在这里——从今天更多的阅读中得知,人们似乎会退回到geopy或postgis作为解决方案,而不是仅仅在GeoDjango周围进行黑客攻击。当然,如果你不想使用它们中的任何一个,你也可以使用数学方法。 - Rob Wilkins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接