2012-01-13 155 views
8

我正在设置一个小程序,从用户获取2个地理坐标,然后计算它们之间的距离(考虑到地球曲率)。所以我查了一下维基百科公式是here需要帮助计算地理距离

我基本建立我的Python功能基于这一点,这是我想出了:

def geocalc(start_lat, start_long, end_lat, end_long): 
    start_lat = math.radians(start_lat) 
    start_long = math.radians(start_long) 
    end_lat = math.radians(end_long) 
    end_long = math.radians(end_long) 

    d_lat = start_lat - end_lat 
    d_long = start_long - end_long 

    EARTH_R = 6372.8 

    c = math.atan((math.sqrt((math.cos(end_lat)*d_long)**2 +((math.cos(start_lat)*math.sin(end_lat)) - (math.sin(start_lat)*math.cos(end_lat)*math.cos(d_long)))**2))/((math.sin(start_lat)*math.sin(end_lat)) + (math.cos(start_lat)*math.cos(end_lat)*math.cos(d_long)))) 

    return EARTH_R*c 

的问题是,出来的结果真的不准确的。我是python的新手,所以一些帮助或建议将不胜感激!

+2

请给一个具体的例子(输入,预期的输出,实际输出)。 – 2012-01-13 23:56:31

+0

我输入了这些坐标(-6.508,55.071)和(-8.886,51.622)。 预计产量为414Km。实际结果是6473公里 – Darkphenom 2012-01-14 00:19:11

+0

我认为这不是不准确,这是错误的。<不准确可能是420公里 – hochl 2012-01-14 01:33:24

回答

10

你有4个或5或6个问题:

(1)end_lat = math.radians(end_long)应该是end_lat = math.radians(end_lat)

(2)你缺少一些东西的人已经提到的,最有可能是因为

(3)你的代码是难以辨认(线太长了,多余的括号,17种无意义的情况下,“数学”。)

(4)你没有注意到维基百科的文章中的言论有关使用atan2()

(5)进入你的坐标时,您可能已经交换纬度和经度

(6)delta(latitude)不必要计算;它不会出现在式

在全部放在一起:

from math import radians, sqrt, sin, cos, atan2 

def geocalc(lat1, lon1, lat2, lon2): 
    lat1 = radians(lat1) 
    lon1 = radians(lon1) 
    lat2 = radians(lat2) 
    lon2 = radians(lon2) 

    dlon = lon1 - lon2 

    EARTH_R = 6372.8 

    y = sqrt(
     (cos(lat2) * sin(dlon)) ** 2 
     + (cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)) ** 2 
     ) 
    x = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(dlon) 
    c = atan2(y, x) 
    return EARTH_R * c 



>>> geocalc(36.12, -86.67, 33.94, -118.40) 
2887.2599506071115 
>>> geocalc(-6.508, 55.071, -8.886, 51.622) 
463.09798886300376 
>>> geocalc(55.071, -6.508, 51.622, -8.886) 
414.7830891822618 
+0

感谢您指出所有这些问题。它看起来比我做的和它的工作更清洁! – Darkphenom 2012-01-14 11:01:20

4

您可以使用对距离计算内置功能geopy模块,向下滚动到下面链接中“计算距离”: https://pypi.python.org/pypi/geopy

+0

这是一个很好的建议,但如果你可以包括一些关于如何实现OP的目标的代码,你的回答会更好。 – MERose 2015-06-08 11:14:48

3

我想你错过了math.sin(d_long)朝开始,也许应该是这样的:

c = math.atan((math.sqrt((math.cos(end_lat)*math.sin(d_long))**2 +((math.cos(start_lat)*math.sin(end_lat)) - (math.sin(start_lat)*math.cos(end_lat)*math.cos(d_long)))**2))/((math.sin(start_lat)*math.sin(end_lat)) + (math.cos(start_lat)*math.cos(end_lat)*math.cos(d_long)))) 
+0

你在那里是正确的。但是,我仍然得到完全错误的答案。 – Darkphenom 2012-01-14 00:12:30

4

此作品(打印˚F返回2887.26公里按照工作实例@http://en.wikipedia.org/wiki/Great-circle_distance):

import math 

def geocalc(start_lat, start_long, end_lat, end_long): 

    start_lat = math.radians(start_lat) 
    start_long = math.radians(start_long) 
    end_lat = math.radians(end_lat) 
    end_long = math.radians(end_long) 

    d_lat = math.fabs(start_lat - end_lat) 
    d_long = math.fabs(start_long - end_long) 

    EARTH_R = 6372.8 

    y = ((math.sin(start_lat)*math.sin(end_lat)) + (math.cos(start_lat)*math.cos(end_lat)*math.cos(d_long))) 

    x = math.sqrt((math.cos(end_lat)*math.sin(d_long))**2 + ((math.cos(start_lat)*math.sin(end_lat)) - (math.sin(start_lat)*math.cos(end_lat)*math.cos(d_long)))**2) 

    c = math.atan(x/y) 

    return EARTH_R*c 

f = geocalc(36.12, -86.67, 33.94, -118.40) 
print f 

注意这条线在你的提交:end_lat = math.radians(end_long)

+0

你不需要'fabs()',因为'cos(-x)== cos(x)' – 2012-01-14 02:38:58

+0

-1因为你使用'atan'而不是'atan2',所以这可能会变得非常糟糕。例如:从45度到45度的正南方向是10010公里(正常),但是从45.1度到-45.1度(稍长的距离)会产生9988公里的减幅。从北极到南极的旅行产生了零公里! – 2012-01-14 04:36:17

+0

@JohnMachin关于fabs()的评论你对这个特定的实现是正确的,但是当教授delta的概念时,绝对值的使用是正确的,而不是简单的减法。 – sgallen 2012-01-14 13:44:53