2012-01-13 201 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