2016-03-29 20 views
3

90°0′0″N 0°0′0″E biçiminde iki koordinat çifti alın ve R = 6371km yarıçapındaki bir küredeki bu noktalar arasındaki mesafeyi hesaplamak istiyorum.Dünyadaki iki koordinat arasındaki uzaklığı hesaplayın

İnternette here, "haversine" ve "kosinüslerin küresel yasası" olmak üzere iki formül buldum ama işe yaramıyorlar. 2*pi*R/4'u döndürmesi gereken 90 derecelik bir açı için, haversin doğru çalışır, ancak kosinler başarısız olur ve 0 döndürür. Daha rastgele koordinatlarla farklı bir nokta, her iki algoritma ile yanlış değerleri döndürür: haversin çok yüksektir ve kosinler çok düşüktür.

Uygulamam yanlış mı yoksa yanlış bir algoritma mı seçtim?

Bunun yerine bu hesaplamaları nasıl yapmalıyım (çiftler yüzey yüzeyine uzaklığı eşler)?

(. Ve evet, ben N/S için kontrol ve E/W yok, ama test koordinatlar kuzey-doğu yarımkürede hepsi değilim biliyorum)

İşte benim Python 3 kod: İşte

import math, re 
R = 6371 
PAT = r'(\d+)°(\d+)′(\d+)″([NSEW])' 

def distance(first, second): 
    def coords_to_rads(s): 
     return [math.radians(int(d) +int(m)/60 +int(s)/3600) \ 
       for d, m, s, nswe in re.findall(PAT, s)] 

    y1, x1 = coords_to_rads(first) 
    y2, x2 = coords_to_rads(second) 
    dx = x1 - x2 
    dy = y1 - y2 

    print("coord string:", first, "|", second) 
    print("coord radians:", y1, x1, "|", y2, x2) 
    print("x/y-distances:", dy, dx) 

    a = math.sin(dx/2)**2 + math.cos(x1) * math.cos(x2) * math.sin(dy/2)**2 
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) 
    haversine = R * c 

    law_of_cosines = math.acos(math.sin(x1) * math.sin(x2) + \ 
           math.cos(x1) * math.cos(x2)) * R 

    print("HS:", round(haversine, 2), "LOC:", round(law_of_cosines, 2)) 

    return haversine 
    #return law_of_cosines 

if __name__ == '__main__': 
    def test(result, correct): 
     print("result: ", result) 
     print("correct:", correct) 

    test(distance("90°0′0″N 0°0′0″E", "0°0′0″N, 0°0′0″E"), 10007.5) 
    test(distance("51°28′48″N 0°0′0″E", "46°12′0″N, 6°9′0″E"), 739.2) 
    test(distance("90°0′0″N 0°0′0″E", "90°0′0″S, 0°0′0″W"), 20015.1) 
    test(distance("33°51′31″S, 151°12′51″E", "40°46′22″N 73°59′3″W"), 15990.2) 

bazı çıktısı:

coord string: 90°0′0″N 0°0′0″E | 0°0′0″N, 0°0′0″E 
coord radians: 1.5707963267948966 0.0 | 0.0 0.0 
x/y-distances: 1.5707963267948966 0.0 
HS: 10007.54 LOC: 0.0 
result: 10007.543398010286 
correct: 10007.5 

coord string: 51°28′48″N 0°0′0″E | 46°12′0″N, 6°9′0″E 
coord radians: 0.8984954989266809 0.0 | 0.8063421144213803 0.10733774899765128 
x/y-distances: 0.09215338450530064 -0.10733774899765128 
HS: 900.57 LOC: 683.85 
result: 900.5669567853056 
correct: 739.2 
+0

İyi soru, ancak bunun olması [codereview.SE] gitmeli acaba ? Çalıştığınız ya da çalışmakta olan bir kod örneğinizin olduğu birçok soruyu burada ve konuyla ilgili olduğu düşünülen konular arasında biliyorum, ancak siteler arasındaki kesin "kesilmeden" emin değilim. –

+0

@DavidZ Anladığım kadarıyla, CR sadece optimizasyon arayan çalışan kod snippet'lerini istiyor. bu yüzden burada yayınladım. Ama bu, SO'dan CR'ye veya arkasından göç eden ilk kişi olmazdı ... –

+0

Bana mantıklı geliyor. Neyse, [Wikipedia] (https://en.wikipedia.org/wiki/Haversine_formula) 'ya karşı bağlandığınız siteyi kontrol ettim ve haversine formülü tanımında bir tutarsızlık var gibi görünüyor. tutarsızlıktır). Buna baktın mı? –

cevap

1

size a senin hesaplanmasında x ve y karışık gibi görünüyor. Enlemin (y) kosinüsünü (x) boylam etmemelisiniz.

Ben senin angular_distance için distance (yani R ile çarpın etmeyin) ve ekleme bazı ek testler değiştirerek bu keşfetti:

test(angular_distance("90°0′0″N 0°0′0″E", "89°0′0″N, 0°0′0″E"), math.radians(1)) 
test(angular_distance("90°0′0″N 0°0′0″E", "80°0′0″N, 0°0′0″E"), math.radians(10)) 
test(angular_distance("90°0′0″N 0°0′0″E", "50°0′0″N, 0°0′0″E"), math.radians(40)) 
test(angular_distance("90°0′0″N 0°0′0″E", "50°0′0″N, 20°0′0″E"), math.radians(40)) 
+0

Teşekkürler, haklısınız. Sadece y1, x1 = coords_to_rads (ilk) ve y2, x2 = coords_to_rads (second) satırlarını değiştirdim ve 'x's ve' y'leri değiştirdim. –

İlgili konular