Erhalten Sie Lat / Long bei aktuellem Punkt, Abstand und Peilung


75

Bei einem vorhandenen Punkt in Lat / Long, Entfernung in (in KM) und Peilung (in Grad umgerechnet in Bogenmaß) möchte ich das neue Lat / Long berechnen. Diese Seite taucht immer wieder auf, aber ich kann die Formel einfach nicht für mich arbeiten lassen.

Die Formeln unter dem obigen Link sind:

lat2 = asin(sin(lat1)*cos(d/R) + cos(lat1)*sin(d/R)*cos(θ))

lon2 = lon1 + atan2(sin(θ)*sin(d/R)*cos(lat1), cos(d/R)−sin(lat1)*sin(lat2))

Die obige Formel gilt für MSExcel, wobei

asin          = arc sin()   
d             = distance (in any unit)   
R             = Radius of the earth (in the same unit as above)  
and hence d/r = is the angular distance (in radians)  
atan2(a,b)    = arc tan(b/a)  
θ is the bearing (in radians, clockwise from north);  

Hier ist der Code, den ich in Python habe.

import math

R = 6378.1 #Radius of the Earth
brng = 1.57 #Bearing is 90 degrees converted to radians.
d = 15 #Distance in km

#lat2  52.20444 - the lat result I'm hoping for
#lon2  0.36056 - the long result I'm hoping for.

lat1 = 52.20472 * (math.pi * 180) #Current lat point converted to radians
lon1 = 0.14056 * (math.pi * 180) #Current long point converted to radians

lat2 = math.asin( math.sin(lat1)*math.cos(d/R) +
             math.cos(lat1)*math.sin(d/R)*math.cos(brng))

lon2 = lon1 + math.atan2(math.sin(brng)*math.sin(d/R)*math.cos(lat1),
                     math.cos(d/R)-math.sin(lat1)*math.sin(lat2))

print(lat2)
print(lon2)

Ich bekomme

lat2 = 0.472492248844 
lon2 = 79.4821662373

@ GWW Ich bekam eine Antwort, die keinen Sinn ergab. Der Grund, warum es keinen Sinn ergab, weil ich die Antworten nicht wieder in Grad umwandelte. Code geändert und als Bearbeitung in den ursprünglichen Beitrag aufgenommen.
David M

6
Sie sollten Ihre Bearbeitung einfach als Antwort einreichen und diese Antwort akzeptieren, um klarer zu machen, dass Sie Ihr eigenes Problem gelöst haben. Andernfalls wird SO Sie dafür bestrafen, dass Sie eine Frage ungelöst lassen, wodurch es etwas wahrscheinlicher wird, dass zukünftige Benutzer sich nicht die Mühe machen, Ihre Fragen zu beantworten.
Cerin

Sie erhalten eine bessere Präzision und bessere Ergebnisse, wenn Sie numpy Objekte verwenden.
Mike Pennington

@Cerin - danke für den Rat.
David M

sollte das nicht "lat1 = 52.20472 * (math.pi * / 180)" sein?
Tushar Seth

Antworten:


86

Muss Antworten vom Bogenmaß zurück in Grad konvertieren. Arbeitscode unten:

import math

R = 6378.1 #Radius of the Earth
brng = 1.57 #Bearing is 90 degrees converted to radians.
d = 15 #Distance in km

#lat2  52.20444 - the lat result I'm hoping for
#lon2  0.36056 - the long result I'm hoping for.

lat1 = math.radians(52.20472) #Current lat point converted to radians
lon1 = math.radians(0.14056) #Current long point converted to radians

lat2 = math.asin( math.sin(lat1)*math.cos(d/R) +
     math.cos(lat1)*math.sin(d/R)*math.cos(brng))

lon2 = lon1 + math.atan2(math.sin(brng)*math.sin(d/R)*math.cos(lat1),
             math.cos(d/R)-math.sin(lat1)*math.sin(lat2))

lat2 = math.degrees(lat2)
lon2 = math.degrees(lon2)

print(lat2)
print(lon2)

das gleiche ergebnis auch für mich
boden


Ich habe festgestellt, dass wenn der ursprüngliche Breitengrad 0 ist, der ursprüngliche Längengrad -179 ist, die Peilung 270 Grad (1,5 pi Radiant) beträgt und die Entfernung 1500 km beträgt, der resultierende Längengrad -192,4 beträgt, was auf einer Karte nicht vorhanden ist.
JVE999


Ich habe die Code-Ausgabe validiert mit: fcc.gov/media/radio/find-terminal-coordinates
Michael Behrens

33

Die Geopy- Bibliothek unterstützt dies:

import geopy
from geopy.distance import VincentyDistance

# given: lat1, lon1, b = bearing in degrees, d = distance in kilometers

origin = geopy.Point(lat1, lon1)
destination = VincentyDistance(kilometers=d).destination(origin, b)

lat2, lon2 = destination.latitude, destination.longitude

Gefunden über https://stackoverflow.com/a/4531227/37610


Diese Bibliothek hat einige Entfernungsprobleme, die darauf warten, gelöst zu werden: github.com/geopy/geopy/pull/144
Justin Poehnelt

14

Diese Frage ist als direktes Problem bei der Untersuchung der Geodäsie bekannt .

Dies ist in der Tat eine sehr beliebte Frage, die ständig Verwirrung stiftet. Der Grund ist, dass die meisten Menschen nach einer einfachen und direkten Antwort suchen. Aber es gibt keine, weil die meisten Leute, die diese Frage stellen, nicht genügend Informationen liefern, einfach weil sie nicht wissen, dass:

  1. Die Erde ist keine perfekte Kugel, da sie durch ihre Pole abgeflacht / komprimiert wird
  2. Wegen (1) hat die Erde keinen konstanten Radius R. Siehe hier .
  3. Die Erde ist nicht perfekt glatt (Höhenunterschiede) usw.
  4. Aufgrund der Bewegung der tektonischen Platte kann sich die Lat / Lon-Position eines geografischen Punkts jedes Jahr um mindestens einige Millimeter ändern.

Daher werden in den verschiedenen geometrischen Modellen viele verschiedene Annahmen verwendet, die je nach erforderlicher Genauigkeit unterschiedlich gelten. Um die Frage zu beantworten, müssen Sie überlegen, mit welcher Genauigkeit Sie Ihr Ergebnis erzielen möchten.

Einige Beispiele:

  • Ich suche nur für einen ungefähren Standort auf die nächsten paar Kilometer für kleine ( < 100 km) Entfernung von in latitudeszwischen 0-70 deg N | S . (Die Erde ist ein flaches Modell.)
  • Ich möchte eine Antwort, die überall auf der Welt gut ist, aber nur auf wenige Meter genau
  • Ich möchte eine super genaue Positionierung, die bis auf atomare Skalen von nanometers[nm] gültig ist .
  • Ich möchte Antworten, die sehr schnell und einfach zu berechnen und nicht rechenintensiv sind.

Sie haben also viele Möglichkeiten, welchen Algorithmus Sie verwenden möchten. Darüber hinaus verfügt jede Programmiersprache über eine eigene Implementierung oder ein eigenes "Paket", multipliziert mit der Anzahl der Modelle und den spezifischen Anforderungen der Modellentwickler. Für alle praktischen Zwecke lohnt es sich, jede andere Sprache außer sich zu lassen javascript, da sie von Natur aus dem Pseudocode sehr ähnlich ist. Somit kann es mit minimalen Änderungen leicht in jede andere Sprache konvertiert werden.

Dann sind die Hauptmodelle:

  • Euclidian/Flat earth model: gut für sehr kurze Strecken unter ~ 10 km
  • Spherical model: gut für große Längsabstände, aber mit geringem Breitengradunterschied. Beliebtes Modell:
    • Haversine : Meter Genauigkeit auf [km] Waagen, sehr einfachen Code.
  • Ellipsoidal models: Am genauesten bei jedem Lat / Lon und jeder Entfernung, aber immer noch eine numerische Annäherung, die davon abhängt, welche Genauigkeit Sie benötigen. Einige beliebte Modelle sind:
    • Lambert : ~ 10 Meter Präzision über 1000 km .
    • Paul D.Thomas : Andoyer-Lambert-Näherung
    • Vincenty : Millimetergenauigkeit und Recheneffizienz
    • Kerney : Nanometer - Präzision

Verweise:


13

Möglicherweise ist die Beantwortung etwas spät, aber nach dem Testen der anderen Antworten scheint es, dass sie nicht richtig funktionieren. Hier ist ein PHP-Code, den wir für unser System verwenden. In alle Richtungen arbeiten.

PHP-Code:

lat1 = Breitengrad des Startpunkts in Grad

long1 = Länge des Startpunkts in Grad

d = Entfernung in km

Winkel = Peilung in Grad

function get_gps_distance($lat1,$long1,$d,$angle)
{
    # Earth Radious in KM
    $R = 6378.14;

    # Degree to Radian
    $latitude1 = $lat1 * (M_PI/180);
    $longitude1 = $long1 * (M_PI/180);
    $brng = $angle * (M_PI/180);

    $latitude2 = asin(sin($latitude1)*cos($d/$R) + cos($latitude1)*sin($d/$R)*cos($brng));
    $longitude2 = $longitude1 + atan2(sin($brng)*sin($d/$R)*cos($latitude1),cos($d/$R)-sin($latitude1)*sin($latitude2));

    # back to degrees
    $latitude2 = $latitude2 * (180/M_PI);
    $longitude2 = $longitude2 * (180/M_PI);

    # 6 decimal for Leaflet and other system compatibility
   $lat2 = round ($latitude2,6);
   $long2 = round ($longitude2,6);

   // Push in array and get back
   $tab[0] = $lat2;
   $tab[1] = $long2;
   return $tab;
 }

1
Sieht gut aus, aber ich denke, der Anforderer möchte etwas in Python haben. Falsch?
user2360915

kann besser benannt get_gps_coordoder ähnlich sein. Du bekommst nicht die Distanz, das gibst du der Funk. Aber danke dafür, es ist genau das, wonach ich gesucht habe. Viele Suchvorgänge geben den berechneten Abstand zwischen Koordinaten zurück (falsch positive Ergebnisse). Vielen Dank!
Dev Null

Genial! Vielen Dank für Ihren Beitrag!
Jkamizato

1
6,378.14 kmscheint der maximale Radius der Erde zu sein. Der Durchschnitt liegt bei ungefähr 6,371.0 km, was genauere Berechnungen ermöglichen kann.
JVE999

7

Ich habe die Antwort von Brad auf die Antwort von Vanilla JS portiert, ohne Abhängigkeit von Bing-Karten

https://jsfiddle.net/kodisha/8a3hcjtd/

    // ----------------------------------------
    // Calculate new Lat/Lng from original points
    // on a distance and bearing (angle)
    // ----------------------------------------
    let llFromDistance = function(latitude, longitude, distance, bearing) {
      // taken from: https://stackoverflow.com/a/46410871/13549 
      // distance in KM, bearing in degrees
    
      const R = 6378.1; // Radius of the Earth
      const brng = bearing * Math.PI / 180; // Convert bearing to radian
      let lat = latitude * Math.PI / 180; // Current coords to radians
      let lon = longitude * Math.PI / 180;
    
      // Do the math magic
      lat = Math.asin(Math.sin(lat) * Math.cos(distance / R) + Math.cos(lat) * Math.sin(distance / R) * Math.cos(brng));
      lon += Math.atan2(Math.sin(brng) * Math.sin(distance / R) * Math.cos(lat), Math.cos(distance / R) - Math.sin(lat) * Math.sin(lat));
    
      // Coords back to degrees and return
      return [(lat * 180 / Math.PI), (lon * 180 / Math.PI)];
    
    }
    
    let pointsOnMapCircle = function(latitude, longitude, distance, numPoints) {
      const points = [];
      for (let i = 0; i <= numPoints - 1; i++) {
        const bearing = Math.round((360 / numPoints) * i);
        console.log(bearing, i);
        const newPoints = llFromDistance(latitude, longitude, distance, bearing);
        points.push(newPoints);
      }
      return points;
    }
    
    const points = pointsOnMapCircle(41.890242042122836, 12.492358982563019, 0.2, 8);
    let geoJSON = {
      "type": "FeatureCollection",
      "features": []
    };
    points.forEach((p) => {
      geoJSON.features.push({
        "type": "Feature",
        "properties": {},
        "geometry": {
          "type": "Point",
          "coordinates": [
            p[1],
            p[0]
          ]
        }
      });
    });
    
    document.getElementById('res').innerHTML = JSON.stringify(geoJSON, true, 2);

Außerdem habe ich den geoJSONExport hinzugefügt , sodass Sie das resultierende geoJSON einfach in Folgendes einfügen können: http://geojson.io/#map=17/41.89017/12.49171um die Ergebnisse sofort anzuzeigen .

Ergebnis: geoJSON Screenshot


Die Karte des Geojson ist sehr hilfreich für mich, um einen Ort in einer Karte
anzuvisieren

Danke @kodisha, deine Geige hilft mir sehr!
Douglas Schmidt

5

Schneller Weg mit Geopy

from geopy import distance
#distance.distance(unit=15).destination((lat,lon),bering) 
#Exemples
distance.distance(nautical=15).destination((-24,-42),90) 
distance.distance(miles=15).destination((-24,-42),90)
distance.distance(kilometers=15).destination((-24,-42),90) 

2
Ohne Angabe der Berechnungsmethode ist die Antwort grundsätzlich nutzlos.
not2qubit

1
@ not2qubit Ob @ plinio-bueno-andrade-silva sich bewusst war oder nicht, geopy.distance.distance currently uses geodesic. geopy Und genauer gesagt, das standardmäßig verwendete Ellipsoidmodell ist das WGS-84-Ellipsoid, "das global genaueste".
Hlongmore

3

lon1 und lat1 in Grad

brng = Peilung im Bogenmaß

d = Entfernung in km

R = Radius der Erde in km

lat2 = math.degrees((d/R) * math.cos(brng)) + lat1
long2 = math.degrees((d/(R*math.sin(math.radians(lat2)))) * math.sin(brng)) + long1

Ich habe Ihren und meinen Algorithmus in PHP implementiert und verglichen. Diese Version lief in etwa 50% der Fälle. Die generierten Ergebnisse waren identisch, daher scheint es mathematisch äquivalent zu sein.

Ich habe den obigen Python-Code nicht getestet, daher kann es zu Syntaxfehlern kommen.


Funktioniert nicht. Von Nord nach Süd ist das Ergebnis korrekt, aber in "Ost-West" -Richtung falsch.
Peter

1

Ebenfalls spät, aber für diejenigen, die dies möglicherweise finden, erhalten Sie mit der geographiclib- Bibliothek genauere Ergebnisse . In den geodätischen Problembeschreibungen und den JavaScript-Beispielen finden Sie eine einfache Einführung in die Beantwortung der Themenfrage sowie in viele andere. Implementierungen in verschiedenen Sprachen, einschließlich Python. Weitaus besser als das Codieren Ihrer eigenen, wenn Sie Wert auf Genauigkeit legen. besser als VincentyDistance in der früheren Empfehlung "Bibliothek verwenden". In der Dokumentation heißt es: "Der Schwerpunkt liegt auf der Rückgabe genauer Ergebnisse mit Fehlern nahe der Abrundung (ca. 5–15 Nanometer)."


1

Tauschen Sie einfach die Werte in der Funktion atan2 (y, x) aus. Nicht atan2 (x, y)!


1

Ich habe den Python nach Javascript portiert. Dies gibt ein Bing Maps- LocationObjekt zurück, das Sie nach Belieben ändern können.

getLocationXDistanceFromLocation: function(latitude, longitude, distance, bearing) {
    // distance in KM, bearing in degrees

    var R = 6378.1,                         // Radius of the Earth
        brng = Math.radians(bearing)       // Convert bearing to radian
        lat = Math.radians(latitude),       // Current coords to radians
        lon = Math.radians(longitude);

    // Do the math magic
    lat = Math.asin(Math.sin(lat) * Math.cos(distance / R) + Math.cos(lat) * Math.sin(distance / R) * Math.cos(brng));
    lon += Math.atan2(Math.sin(brng) * Math.sin(distance / R) * Math.cos(lat), Math.cos(distance/R)-Math.sin(lat)*Math.sin(lat));

    // Coords back to degrees and return
    return new Microsoft.Maps.Location(Math.degrees(lat), Math.degrees(lon));

},

Bitte geben Sie den Funktionscode ein, einschließlich dessen, was ausgeführt werden muss. Dh dies scheint von Microsoft.Maps abhängig zu sein. Wo finde / wie installiere ich das?
not2qubit

Sie würden Bing (Microsoft) Maps nur verwenden, wenn Ihr Programm Bing Maps verwendet. Nehmen Sie einfach die Math.degrees(lat)und Math.degrees(lon)Werte und mit ihnen tun , was Sie für Ihre Anwendung benötigen.
Brad Mathews

0

Hier ist eine PHP-Version, die auf Ed Williams Aviation Formulary basiert. Der Modul wird in PHP etwas anders gehandhabt. Das funktioniert bei mir.

function get_new_waypoint ( $lat, $lon, $radial, $magvar, $range )
{

   // $range in nm.
   // $radial is heading to or bearing from    
   // $magvar for local area.

   $range = $range * pi() /(180*60);
   $radial = $radial - $magvar ;

   if ( $radial < 1 )
     {
        $radial = 360 + $radial - $magvar; 
     }
   $radial =  deg2rad($radial);
   $tmp_lat = deg2rad($lat);
   $tmp_lon = deg2rad($lon);
   $new_lat = asin(sin($tmp_lat)* cos($range) + cos($tmp_lat) * sin($range) * cos($radial));
   $new_lat = rad2deg($new_lat);
   $new_lon = $tmp_lon - asin(sin($radial) * sin($range)/cos($new_lat))+ pi() % 2 * pi() -  pi();
   $new_lon = rad2deg($new_lon);

   return $new_lat." ".$new_lon;

}

Können Sie einige der Variablen erklären? $ range und $ magvar könnten etwas mehr Exposition für Anfänger wie (ich :)
Tommie C.

Bitte lesen Sie meine Antwort und den Link zu der verwendeten Formel und zu der Genauigkeit, die wir erwarten können.
not2qubit

0

Ich habe die Antwort von @David M auf Java portiert, wenn jemand dies wollte ... Ich erhalte ein etwas anderes Ergebnis von 52.20462299620793, 0.360433887489931

    double R = 6378.1;  //Radius of the Earth
    double brng = 1.57;  //Bearing is 90 degrees converted to radians.
    double d = 15;  //Distance in km

    double lat2 = 52.20444; // - the lat result I'm hoping for
    double lon2 = 0.36056; // - the long result I'm hoping for.

    double lat1 = Math.toRadians(52.20472); //Current lat point converted to radians
    double lon1 = Math.toRadians(0.14056); //Current long point converted to radians

    lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
            Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng));

    lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1),
            Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));

    lat2 = Math.toDegrees(lat2);
    lon2 = Math.toDegrees(lon2);

    System.out.println(lat2 + ", " + lon2);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.