Wie berechne ich die Entfernung zwischen zwei GPS-Koordinaten (unter Verwendung von Breitengrad und Längengrad)?
Antworten
Zu viele Anzeigen?I. In Bezug auf die Methode "Breadcrumbs"
- Der Erdradius ist unterschiedlich bei unterschiedlichen Breitengraden. Dies muss im Haversine-Algorithmus berücksichtigt werden.
- Beachten Sie die Änderung des Kurses, die gerade Linien in Bögen verwandelt (die länger sind).
- Die Berücksichtigung von Geschwindigkeitsänderungen verwandelt Bögen in Spiralen (die länger oder kürzer sind als Bögen).
- Änderungen in der Höhe verwandeln flache Spiralen in 3D-Spiralen (die wiederum länger sind). Dies ist besonders wichtig für hügelige Gebiete.
Im Folgenden finden Sie die Funktion in C, die #1 und #2 berücksichtigt:
double calcDistanceByHaversine(double rLat1, double rLon1, double rHeading1,
double rLat2, double rLon2, double rHeading2){
double rDLatRad = 0.0;
double rDLonRad = 0.0;
double rLat1Rad = 0.0;
double rLat2Rad = 0.0;
double a = 0.0;
double c = 0.0;
double rResult = 0.0;
double rEarthRadius = 0.0;
double rDHeading = 0.0;
double rDHeadingRad = 0.0;
if ((rLat1 < -90.0) || (rLat1 > 90.0) || (rLat2 < -90.0) || (rLat2 > 90.0)
|| (rLon1 < -180.0) || (rLon1 > 180.0) || (rLon2 < -180.0)
|| (rLon2 > 180.0)) {
return -1;
};
rDLatRad = (rLat2 - rLat1) * DEGREE_TO_RADIANS;
rDLonRad = (rLon2 - rLon1) * DEGREE_TO_RADIANS;
rLat1Rad = rLat1 * DEGREE_TO_RADIANS;
rLat2Rad = rLat2 * DEGREE_TO_RADIANS;
a = sin(rDLatRad / 2) * sin(rDLatRad / 2) + sin(rDLonRad / 2) * sin(
rDLonRad / 2) * cos(rLat1Rad) * cos(rLat2Rad);
if (a == 0.0) {
return 0.0;
}
c = 2 * atan2(sqrt(a), sqrt(1 - a));
rEarthRadius = 6378.1370 - (21.3847 * 90.0 / ((fabs(rLat1) + fabs(rLat2))
/ 2.0));
rResult = rEarthRadius * c;
// Korrektur von Sehne zu Bogen basierend auf Kursänderungen. Wichtig für Strecken mit vielen Kurven und Wendungen
if ((rHeading1 >= 0.0) && (rHeading1 < 360.0) && (rHeading2 >= 0.0)
&& (rHeading2 < 360.0)) {
rDHeading = fabs(rHeading1 - rHeading2);
if (rDHeading > 180.0) {
rDHeading -= 180.0;
}
rDHeadingRad = rDHeading * DEGREE_TO_RADIANS;
if (rDHeading > 5.0) {
rResult = rResult * (rDHeadingRad / (2.0 * sin(rDHeadingRad / 2)));
} else {
rResult = rResult / cos(rDHeadingRad);
}
}
return rResult;
}
II. Es gibt einen einfacheren Weg, der ziemlich gute Ergebnisse liefert.
Mit durchschnittlicher Geschwindigkeit.
Strecke = Durchschnittsgeschwindigkeit * Fahrzeit
Da die GPS-Geschwindigkeit durch den Dopplereffekt erkannt wird und nicht direkt mit [Lon,Lat] in Verbindung steht, kann sie zumindest als sekundäre (Backup- oder Korrektur-) Methode für die Abstandsberechnung in Betracht gezogen werden.
Eine T-SQL-Funktion, die ich verwende, um Datensätze nach Entfernung für ein Zentrum auszuwählen
Create Function [dbo].[DistanceInMiles]
( @fromLatitude float ,
@fromLongitude float ,
@toLatitude float,
@toLongitude float
)
returns float
AS
BEGIN
declare @distance float
select @distance = cast((3963 * ACOS(round(COS(RADIANS(90-@fromLatitude))*COS(RADIANS(90-@toLatitude))+
SIN(RADIANS(90-@fromLatitude))*SIN(RADIANS(90-@toLatitude))*COS(RADIANS(@fromLongitude-@toLongitude)),15))
)as float)
return round(@distance,1)
END
Wenn Sie etwas genaueres benötigen, dann schauen Sie sich hier an.
Die Vincenty-Formeln sind zwei verwandte iterative Methoden, die in der Geodäsie verwendet werden, um den Abstand zwischen zwei Punkten auf der Oberfläche eines Spheroids zu berechnen, entwickelt von Thaddeus Vincenty (1975a). Sie basieren auf der Annahme, dass die Form der Erde ein abgeflachtes Spheroid ist, und sind daher genauer als Methoden wie die Großkreisdistanz, die von einer sphärischen Erde ausgehen.
Die erste (direkte) Methode berechnet die Position eines Punktes, der einen gegebenen Abstand und Azimut (Richtung) von einem anderen Punkt hat. Die zweite (umgekehrte) Methode berechnet den geografischen Abstand und Azimut zwischen zwei gegebenen Punkten. Sie wurden in der Geodäsie weit verbreitet eingesetzt, da sie auf dem Erdellipsoid eine Genauigkeit von 0,5 mm (0,020) haben.
Wenn Sie .NET verwenden, erfinden Sie das Rad nicht neu. Siehe System.Device.Location. Dank an fnx in den Kommentaren in einer anderen Antwort.
using System.Device.Location;
double lat1 = 45.421527862548828D;
double long1 = -75.697189331054688D;
double lat2 = 53.64135D;
double long2 = -113.59273D;
GeoCoordinate geo1 = new GeoCoordinate(lat1, long1);
GeoCoordinate geo2 = new GeoCoordinate(lat2, long2);
double distance = geo1.GetDistanceTo(geo2);
Hier ist die Swift-Implementierung aus der Antwort
func degreesToRadians(degrees: Double) -> Double {
return degrees * Double.pi / 180
}
func distanceInKmBetweenEarthCoordinates(lat1: Double, lon1: Double, lat2: Double, lon2: Double) -> Double {
let earthRadiusKm: Double = 6371
let dLat = degreesToRadians(degrees: lat2 - lat1)
let dLon = degreesToRadians(degrees: lon2 - lon1)
let lat1 = degreesToRadians(degrees: lat1)
let lat2 = degreesToRadians(degrees: lat2)
let a = sin(dLat/2) * sin(dLat/2) +
sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2)
let c = 2 * atan2(sqrt(a), sqrt(1 - a))
return earthRadiusKm * c
}
3 Stimmen
Dieser Algorithmus ist als die Großkreisdistanz bekannt.
0 Stimmen
@GregHewgill, der erste Satz dieses Artikels besagt "Dieser Artikel handelt von der kürzesten Entfernung auf einer Kugel." Also offensichtlich nicht anwendbar auf GPS-Koordinaten.