Django - 我怎样才能找到两个位置之间的距离?

JPC*_*JPC 9 python django google-maps geodjango

我有一些用户在我的Django应用程序中注册,我想简单地能够根据他们的邮政编码找出两个用户之间的距离,然后根据该列表对列表进行排序.我想这个功能没有内置到Django中.我正在寻找一些选项,偶然发现了geodjango,这似乎可能对我的需求有些过分.

Joh*_*hin 18

这是对@Sven Marnach(目前接受的)答案中发布的代码的重大评论.

来自zip项目网站的原始代码,由我编辑的缩进:

from math import *
def calcDist(lat_A, long_A, lat_B, long_B):
    distance = (sin(radians(lat_A)) *
        sin(radians(lat_B)) +
        cos(radians(lat_A)) *
        cos(radians(lat_B)) *
        cos(radians(long_A - long_B)))
    distance = (degrees(acos(distance))) * 69.09
    return distance
Run Code Online (Sandbox Code Playgroud)

代码发布者Sven:

from math import sin, cos, radians, degrees

def calc_dist(lat_a, long_a, lat_b, long_b):
    lat_a = radians(lat_a)
    lat_b = radians(lat_b)
    distance = (sin(lat_a) * sin(lat_b) +
                cos(lat_a) * cos(lat_b) * cos(long_a - long_b))
    return degrees(acos(distance)) * 69.09
Run Code Online (Sandbox Code Playgroud)

问题1:不会运行:需要导入acos

问题2:错误的答案:需要将经度差转换为倒数第二行的弧度

问题3:变量名称"距离"是一个极端的用词不当.该数量实际上是从地球中心到输入点的两条线之间的角度的cos.更改为"cos_x"

问题4:没有必要将角度x转换为度数.只需将x乘以所选单位的地球半径(km,nm或"statute miles")

解决了所有这些问题后,我们得到:

from math import sin, cos, radians, acos

# http://en.wikipedia.org/wiki/Earth_radius
# """For Earth, the mean radius is 6,371.009 km (˜3,958.761 mi; ˜3,440.069 nmi)"""
EARTH_RADIUS_IN_MILES = 3958.761

def calc_dist_fixed(lat_a, long_a, lat_b, long_b):
    """all angles in degrees, result in miles"""
    lat_a = radians(lat_a)
    lat_b = radians(lat_b)
    delta_long = radians(long_a - long_b)
    cos_x = (
        sin(lat_a) * sin(lat_b) +
        cos(lat_a) * cos(lat_b) * cos(delta_long)
        )
    return acos(cos_x) * EARTH_RADIUS_IN_MILES
Run Code Online (Sandbox Code Playgroud)

注意:在解决问题1和2之后,这是通常实现的"余弦球面定律".对于诸如"两个美国邮政编码之间的距离"之类的应用程序是可以的.

警告1:对于从前门到街道的小距离来说这是不精确的,以至于如果两点相同,它可以给出非零距离或引发异常(cos_x> 1.0); 这种情况可以是特殊的.

警告2:如果两个点是对映点(直线路径穿过地球中心),它可以引发异常(cos_x <-1.0).任何担心这一点的人都可以在做acos之前检查cos_x(cos_x).

例:

SFO(37.676,-122.433)到纽约(40.733,-73.917)

calcDist - > 2570.7758043869976
calc_dist - > 5038.599866130089
calc_dist_fixed - > 2570.9028268899356

美国政府网站(http://www.nhc.noaa.gov/gccalc.shtml) - > 2569

这个网站(http://www.timeanddate.com/worldclock/distanceresult.html?p1=179&p2=224),我从中获得了SFO和NYC坐标, - > 2577


Sve*_*ach 6

根据tcarobruce的建议,以上是我的上述评论作为答案:

邮政编码数据库项目具有纬度和美国邮政编码的经度的数据库,无论是作为SQL或CSV.他们还提供了以下距离计算代码(由我编辑的slighlty):

from math import sin, cos, radians, degrees, acos

def calc_dist(lat_a, long_a, lat_b, long_b):
    lat_a = radians(lat_a)
    lat_b = radians(lat_b)
    long_diff = radians(long_a - long_b)
    distance = (sin(lat_a) * sin(lat_b) +
                cos(lat_a) * cos(lat_b) * cos(long_diff))
    return degrees(acos(distance)) * 69.09
Run Code Online (Sandbox Code Playgroud)

请注意,结果以法定里程给出.

编辑:John Machin的更正.