使用GeoDjango进行3d距离计算 [英] 3d distance calculations with GeoDjango

查看:109
本文介绍了使用GeoDjango进行3d距离计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用

  • python 2.7.12
  • django 1.10.6
  • postgreSQL 9.5.6
  • postGIS 2.2.2

第一个问题

我需要使用GeoDjango计算两个点之间的距离.当我查看文档时,它说<不推荐使用em> GeoQuerySet.distance(),而是使用 django.contrib.gis.db.models.functions 中的 Distance().

I need to use GeoDjango to calculate distance between two points. When I checked the documentation it says that GeoQuerySet.distance() is deprecated and instead use Distance() from django.contrib.gis.db.models.functions.

以下代码可以正常工作:

The following code works OK:

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.db.models.functions.Distance的实例. () django.contrib.gis.measure.Distance():

But I have only two points so when I try to use Distance() without annotate() it returns instance of class django.contrib.gis.db.models.functions.Distance() rathen than django.contrib.gis.measure.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)))

我如何获得与使用 annotate()相同的结果?

How do I receive the same result as with using annotate()?

第二个问题

我必须计算考虑到深度/高程的3d距离.但是,当我尝试执行此操作时,会收到与2d相同的结果.下面,我在第一个对象中将海拔高度更改为200:

I have to calculate 3d distance that is taking into account depth/elevation. But when I try to do it I receive the same result as with 2d. Below I changed elevation to 200 in the first object:

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

推荐答案

让我们分解一下问题:

  1. 距离类文档,我们可以阅读以下内容:

  1. In the Distance class documentation, we can read the following:

接受两个地理字段或表达式,并以 Distance object (距离对象)的形式返回它们之间的距离.

Accepts two geographic fields or expressions and returns the distance between them, as a Distance object.

因此,Distance(p1, p2)返回 Distance对象.
如果您这样做:

So the Distance(p1, p2) returns a Distance object.
If you do:

p1 = Instrument.objects.get(pk=151071000).coordinates
p2 = Instrument.objects.get(pk=151071008).coordinates
d = Distance(m=p1.distance(p2))
print d.m

您将获得以米为单位的测量值.

You will get the measurement in meters.

我会坚持使用annotate解决方案,这似乎更可靠! (意见回应)

I would stick with the annotate solution, which seems more solid! (opinionated response)


  1. Distance计算两个点之间的2D距离.为了进行3D计算,您需要自己创建一个.
    您可以从以下问题看我的方法:

  1. Distance calculates the 2D distance between two points. In order to get a 3D calculation, you need to create one yourself.
    You can have a look at my method from this question: Calculating distance between two points using latitude longitude and altitude (elevation)

编辑2019:自初始答案以来,我在此处撰写了一个问答风格示例:

EDIT 2019: Since the initial answer I have composed a Q&A style example here: How to calculate 3D distance (including altitude) between two points in GeoDjango that uses a far better (and less calculation error-prone) distance calculation between 2 points with altitude.

排序:

我们需要计算两个点之间的2D 大圆距离 Haversine公式

We need to calculate the 2D great-circle distance between 2 points using either the Haversine formula or the Vicenty formula and then we can combine it with the difference (delta) in altitude between the 2 points to calculate the Euclidean distance between them as follows:

dist = sqrt(great_circle((lat_1, lon_1), (lat-2, lon_2).m**2, (alt_1 - alt_2)**2)

该解决方案假定海拔高度以米为单位,因此也将great_circle的结果转换为米.

The solution assumes that the altitude is in meters and thus converts the great_circle's result into meters as well.


出于评论继续的目的,将其留在此处.

2.Distance计算两点之间的2D距离.为了获得3D计算,您需要自己创建一个.
您可以从以下问题看我的方法:

2. Distance calculates the 2D distance between two points. In order to get a 3D calculation, you need to create one yourself.
You can have a look at my method from this question: Calculating distance between two points using latitude longitude and altitude (elevation)

  • 让polar_point_1 =(long_1,lat_1,alt_1)和polar_point_2 = (long_2,lat_2,alt_2)

  • Let polar_point_1 = (long_1, lat_1, alt_1) and polar_point_2 = (long_2, lat_2, alt_2)

利用此将每个点转换为等效的笛卡尔 公式:

Translate each point to it's Cartesian equivalent by utilizing this formula:

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)点.

and you will have p_1 = (x_1, y_1, z_1) and p_2 = (x_2, y_2, z_2) points respectively.

最后使用欧几里得公式:

Finally use the Euclidean formula:

dist = sqrt((x_2-x_1)**2 + (y_2-y_1)**2 + (z_2-z_1)**2)

这篇关于使用GeoDjango进行3d距离计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆