webentwicklung-frage-antwort-db.com.de

Abrufen der Entfernung zwischen zwei Punkten basierend auf dem Breitengrad / Längengrad

Ich habe versucht, diese Formel zu implementieren: http://andrew.hedges.name/experiments/haversine/ Das Aplet ist gut für die beiden Punkte, die ich teste:

enter image description here

Mein Code funktioniert jedoch nicht.

from math import sin, cos, sqrt, atan2

R = 6373.0

lat1 = 52.2296756
lon1 = 21.0122287
lat2 = 52.406374
lon2 = 16.9251681

dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))**2 + cos(lat1) * cos(lat2) * (sin(dlon/2))**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
distance = R * c

print "Result", distance
print "Should be", 278.546

Die zurückgegebene Entfernung beträgt 5447.05546147 . Warum?

110
gwaramadze

Bearbeiten: Nur als Hinweis: Wenn Sie nur eine schnelle und einfache Methode zum Ermitteln des Abstands zwischen zwei Punkten benötigen, empfehle ich nachdrücklich die in beschriebene Vorgehensweise Kurts Antwort unten, anstatt Haversine erneut zu implementieren - siehe seinen Beitrag zur Begründung.

Diese Antwort konzentriert sich nur auf die Beantwortung des Fehlers, auf den das OP gestoßen ist.


Dies liegt daran, dass in Python alle Triggerfunktionen verwenden Sie das Bogenmaß , nicht Grad.

Sie können die Zahlen entweder manuell in Bogenmaß umrechnen oder die Funktion radians aus dem Mathematikmodul verwenden:

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

# approximate radius of earth in km
R = 6373.0

lat1 = radians(52.2296756)
lon1 = radians(21.0122287)
lat2 = radians(52.406374)
lon2 = radians(16.9251681)

dlon = lon2 - lon1
dlat = lat2 - lat1

a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
c = 2 * atan2(sqrt(a), sqrt(1 - a))

distance = R * c

print("Result:", distance)
print("Should be:", 278.546, "km")

Die Entfernung gibt nun den korrekten Wert von 278.545589351 Km zurück.

163
Michael0x2a

Update: 04/2018: Beachten Sie, dass Vincenty distance seit der GeoPy-Version veraltet ist 1.1 - Sie sollten geopy.distance.distance verwenden () stattdessen!


Die obigen Antworten basieren auf der Haversine-Formel , die annimmt, dass die Erde eine Kugel ist, was zu Fehlern von bis zu 0,5% führt (gemäß help(geopy.distance)). Vincenty distance verwendet genauere ellipsoidale Modelle wie WGS-84 und ist in geopy implementiert. Zum Beispiel,

import geopy.distance

coords_1 = (52.2296756, 21.0122287)
coords_2 = (52.406374, 16.9251681)

print geopy.distance.vincenty(coords_1, coords_2).km

druckt den Abstand von 279.352901604 Kilometer mit dem Standardellipsoid WGS-84. (Sie können auch .miles oder eine von mehreren anderen Entfernungseinheiten).

163
Kurt Peek

Für Leute (wie ich), die über eine Suchmaschine hierher kommen und nur nach einer Lösung suchen, die sofort funktioniert, empfehle ich die Installation von mpu . Installiere es über pip install mpu --user und benutze es so, um den Haversinusabstand zu erhalten:

import mpu

# Point one
lat1 = 52.2296756
lon1 = 21.0122287

# Point two
lat2 = 52.406374
lon2 = 16.9251681

# What you were looking for
dist = mpu.haversine_distance((lat1, lon1), (lat2, lon2))
print(dist)  # gives 278.45817507541943.

Ein alternatives Paket ist gpxpy .

Wenn Sie keine Abhängigkeiten möchten, können Sie Folgendes verwenden:

import math


def distance(Origin, destination):
    """
    Calculate the Haversine distance.

    Parameters
    ----------
    Origin : Tuple of float
        (lat, long)
    destination : Tuple of float
        (lat, long)

    Returns
    -------
    distance_in_km : float

    Examples
    --------
    >>> Origin = (48.1372, 11.5756)  # Munich
    >>> destination = (52.5186, 13.4083)  # Berlin
    >>> round(distance(Origin, destination), 1)
    504.2
    """
    lat1, lon1 = Origin
    lat2, lon2 = destination
    radius = 6371  # km

    dlat = math.radians(lat2 - lat1)
    dlon = math.radians(lon2 - lon1)
    a = (math.sin(dlat / 2) * math.sin(dlat / 2) +
         math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
         math.sin(dlon / 2) * math.sin(dlon / 2))
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    d = radius * c

    return d


if __== '__main__':
    import doctest
    doctest.testmod()
69
Martin Thoma

Ich bin zu einer viel einfacheren und stabileren Lösung gekommen, die geodesic aus geopy -Paket verwendet, da Sie es höchstwahrscheinlich sowieso in Ihrem Projekt verwenden werden, sodass keine zusätzliche Paketinstallation erforderlich ist.

Hier ist meine Lösung:

from geopy.distance import geodesic


Origin = (30.172705, 31.526725)  # (latitude, longitude) don't confuse
dist = (30.288281, 31.732326)

print(geodesic(Origin, dist).meters)  # 23576.805481751613
print(geodesic(Origin, dist).kilometers)  # 23.576805481751613
print(geodesic(Origin, dist).miles)  # 14.64994773134371

geopy

2
Ramy Mohamed
import numpy as np


def Haversine(lat1,lon1,lat2,lon2, **kwarg):
    """
    This uses the ‘haversine’ formula to calculate the great-circle distance between two points – that is, 
    the shortest distance over the earth’s surface – giving an ‘as-the-crow-flies’ distance between the points 
    (ignoring any hills they fly over, of course!).
    Haversine
    formula:    a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)
    c = 2 ⋅ atan2( √a, √(1−a) )
    d = R ⋅ c
    where   φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km);
    note that angles need to be in radians to pass to trig functions!
    """
    R = 6371.0088
    lat1,lon1,lat2,lon2 = map(np.radians, [lat1,lon1,lat2,lon2])

    dlat = lat2 - lat1
    dlon = lon2 - lon1
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2) **2
    c = 2 * np.arctan2(a**0.5, (1-a)**0.5)
    d = R * c
    return round(d,4)
0
Sudhirln92