使用GeoDjango进行3d距离计算
我在用
- python 2.7.12
- Django 1.10.6
- PostgreSQL 9.5.6
- postGIS 2.2.2
第一个问题
我需要使用GeoDjango计算两点之间的距离。当我检查了
文档它说,
GeoQuerySet.distance() 已被弃用,而使用 距离() 从
django.contrib.gis.db.models.functions 。
以下代码可以正常工作:
from django.contrib.gis.db.models.functions import Distance
p1 = Instrument.objects.get(pk=151071000).coordinates
p2 = Instrument.objects.filter(pk=151071008)
for i in p2.annotate(distance=Distance('coordinates', p1)):
print i.distance
print i.distance.__class__
输出:
461.10913945 m
<class 'django.contrib.gis.measure.Distance'>
我的模特:
class Instrument(models.Model):
...
coordinates = gis_models.PointField(null=True, blank=True, dim=3)
但是我只有两点,所以当我尝试不使用 annotate() 使用Distance()时,它比
django.contrib.gis.measure.Distance 返回类
django.contrib.gis.db.models.functions.Distance()的 实例。 () :
p1 = Instrument.objects.get(pk=151071000).coordinates
p2 = Instrument.objects.get(pk=151071008).coordinates
print Distance(p1, p2)
输出:
Distance(Value(SRID=4326;POINT Z (-76.48623600000001 44.260223 0)), GeomValue(SRID=4326;POINT Z (-76.490923 44.262658 0)))
如何获得与使用 anateate() 相同的结果?
第二个问题
我必须计算考虑到深度/高程的3d距离。但是,当我尝试执行此操作时,会收到与2d相同的结果。下面,我将第一个对象的高程更改为200:
p1 = Instrument.objects.get(pk=151071000)
p1.coordinates = 'SRID=4326;POINT Z (-76.48623600000001 44.260223 200)'
p2 = Instrument.objects.filter(pk=151071008)
for i in p2.annotate(distance=Distance('coordinates', p1.coordinates)):
print i.distance
输出:
461.10913945 m
-
让我们分解问题:
- 在Distance类文档中,我们可以阅读以下内容:
接受两个地理字段或表达式,并以 Distance对象的 形式返回它们之间的 距离 。
因此,
Distance(p1, p2)
返回一个Distance
对象。
如果您这样做:p1 = Instrument.objects.get(pk=151071000).coordinates p2 = Instrument.objects.get(pk=151071008).coordinates d = Distance(m=p1.distance(p2)) print d.m
您将获得以米为单位的测量值。
我会坚持的
annotate
解决方案,这似乎更可靠!(意见回应)
Distance
计算两个点之间的2D距离。为了获得3D计算,您需要自己创建一个。
您可以从以下问题了解我的方法:使用纬度经度和海拔(高程)计算两点之间的距离
EDIT 2019:
自从最初的答案以来,我在这里编写了一个问答风格的示例:如何在GeoDjango中计算两个点之间的3D距离(包括海拔高度),该距离使用高度在2个点之间的距离计算要好得多(并且容易出错) 。排序:
我们需要使用Haversine公式或Vicenty公式来计算2个点之间的2D大圆距离,然后将其与2个点之间的高度差(delta)结合起来,以计算它们之间的欧几里得距离,如下所示:
dist = sqrt(great_circle((lat_1, lon_1), (lat-2, lon_2).m**2, (alt_1 - alt_2)**2)
该解决方案假定海拔高度以米为单位,因此也将
great_circle
结果转换为米。
将此留在此处以用于继续注释。
2.Distance
计算两点之间的二维距离。为了获得3D计算,您需要自己创建一个。
您可以从以下问题了解我的方法:使用纬度经度和海拔(高程)计算两点之间的距离-
令polar_point_1 =(long_1,lat_1,alt_1)和polar_point_2 =(long_2,lat_2,alt_2)
-
通过使用以下公式将每个点转换为它的笛卡尔等效项:
x = alt * cos(lat) * sin(long)
y = alt * sin(lat)
z = alt * cos(lat) * cos(long)
并且您将分别拥有p_1 =(x_1,y_1,z_1)和p_2 =(x_2,y_2,z_2)点。
-
最后使用欧几里得公式:
dist = sqrt((x_2-x_1)**2 + (y_2-y_1)**2 + (z_2-z_1)**2)