Wie berechne ich den Begrenzungsrahmen für eine bestimmte Entfernung und Breite / Länge?

13

Ich muss in der Lage sein, einen Begrenzungsrahmen oder -kreis für einen bestimmten WGS84-Breitengrad und WGS84-Längengrad und eine bestimmte Entfernung zu berechnen, habe aber keine Ahnung, wo ich anfangen soll!

Die Entfernung vom Start Lat / Lon würde 10 km oder weniger betragen.

Wäre es jemandem möglich, mir einige Hinweise / Beispiele zu geben, wie man das macht?

nmtoken
quelle
Für Kreise, die keinen der beiden Pole abdecken, finden Sie eine ausführliche Antwort unter gis.stackexchange.com/questions/19221/… . Dies ist jedoch nicht die ganze Geschichte, wie die aktuellen Antworten nahe legen: Sie können Kompromisse zwischen Geschwindigkeit, Genauigkeit und Programmkomplexität eingehen. Beachten Sie auch, dass es beim Festlegen von Begrenzungsrahmen ein "Umlauf" -Problem gibt, wenn Sie in Lat-Lon arbeiten (die Schwierigkeiten treten beim Meridian von + -180 Grad auf). Eine Lösung hierfür finden Sie unter gis.stackexchange.com/questions/17788/… .
whuber
Benötigen Sie wirklich eine Box oder würden 4 Punkte in der Nähe eines bestimmten Punktes ausreichen? Wenn ein Punkt p gegeben ist, finde 4 Punkte d Abstand in den Richtungen NE, SW, SE und NW von p.
Kirk Kuykendall
@ Kirk - Wenn Sie die Koordinaten der 4 Punkte haben, dann haben Sie die Box ...
Martinstöckli
@martinstoeckli richtig, ich hatte nur gehofft, das Problem zu vereinfachen, indem ich nicht visualisieren musste, wie eine auf eine Kugel projizierte Box aussieht. Beachten Sie auch, dass das Problem verallgemeinert werden kann, um zu verdeutlichen, dass die Seiten des Felds nicht auf den gleichen Breiten- / Längengrad fallen müssen (mit anderen Worten, ein gedrehtes Feld).
Kirk Kuykendall
@Kirk - Ahh, wenn du das genau brauchst, dann hast du natürlich recht. Ich denke, die Box ist nur nützlich, um die möglichen Kandidaten schnell zu finden. Um zu überprüfen, ob zwei Punkte innerhalb eines bestimmten Abstands (Kreises) liegen, kann die komplexere Haversinusformel verwendet werden.
Martinstöckli

Antworten:

15

WGS-was? WGS-84? Abhängig davon, welche Genauigkeit Sie benötigen, müssen Sie möglicherweise viel mehr Informationen wissen - ich schätze, deshalb wurden Sie abgelehnt, obwohl sich niemand die Mühe gemacht hat, einen Kommentar zu hinterlassen, in dem angegeben wird, warum.

Hier sind zwei Möglichkeiten:

Ungenau, aber wahrscheinlich "gut genug"

Ein Breitengrad beträgt ungefähr 10001,965729 / 90 Kilometer (Entfernung vom Äquator zum Pol, geteilt durch neunzig Grad) oder 111,113 Kilometer unter Verwendung des Datums WGS-84. Dies ist eine Annäherung aufgrund der Form der Erde und weil sich die Entfernungen ändern, wenn Sie sich den Polen nähern (ein Grund, Breitengrad zu verwenden, nicht Längengrad - schließlich ist der Abstand von einem Längengrad null!). Die Erde ist auch nicht perfekt Kugel. Beides sind Gründe, in meiner zweiten Antwort einen komplexeren projektions- und datumsbasierten Ansatz zu wählen.

10001.965729km = 90 degrees
1km = 90/10001.965729 degrees = 0.0089982311916 degrees
10km = 0.089982311915998 degrees

Hierbei werden Dezimalgrade verwendet, nicht Grad / Minuten / Sekunden.

Ihr Begrenzungsrahmen ist also Ihr Punkt, plus und minus 0,08999 Grad. Alternativ können Sie diese Zahl als Radius verwenden, um einen Begrenzungskreis zu erhalten .

Jede GIS-Person, die dies liest, wird schaudern. Es wird jedoch größtenteils genau sein, je nachdem, wo Sie sich auf der Welt befinden. Für einen Radius von 10 km sollte es in Ordnung sein.

Viel genauer, aber mehr Code

Verwenden Sie eine Projektionsbibliothek und geben Sie Ihr Datum usw. an. Ich empfehle Proj4; Es ist weit verbreitet, so dass Google jede Menge Ergebnisse für Fragen zurückgibt, und es gibt Delphi-Wrapper . Wenn Sie Probleme damit haben, stellen Sie hier eine weitere Frage auf SO - für diese Frage ist sie nicht relevant. Die Proj4-Website enthält Beispiele für die Verwendung der Basis-APIs, und obwohl diese in C vorliegen, sollte sie ziemlich leicht übersetzbar sein. Die API-Referenz ist der beste Ausgangspunkt, gefolgt von den häufig gestellten Fragen .

Ich würde WGS-84 als Basisdatum (Darstellung der Erde) verwenden, es sei denn, Sie kennen ein bestimmtes Datum, das Sie verwenden möchten, oder es wurde zum Erstellen Ihrer Koordinaten verwendet. Es wird häufig verwendet und ist ziemlich genau.

Wenn Ihre Position beispielsweise aus Google Maps stammt, geben Sie eine Mercator-Projektion an. Möglicherweise möchten Sie eine andere Projektion oder beispielsweise UTM-Koordinaten verwendenAnstelle von Breite und Länge, abhängig von der Quelle Ihrer Daten und wenn Sie eine hohe Genauigkeit für einen kleinen lokalen Bereich wünschen. (UTM verfügt über mehrere Zonen, die alle die Verzerrung so ändern, dass sie innerhalb dieser Zone sehr genau ist. Wenn Sie eine Zone für Koordinaten außerhalb dieser Zone verwenden, nimmt die Verzerrung mit zunehmender Entfernung stark zu. Wenn Sie die gesamte Erde von einer projiziert sehen Die UTM-Übersetzungen in einer Zone sind jedoch so gut wie möglich. Die Koordinaten werden in der Regel in Metern und nicht in Grad angegeben, sodass sie für Sie bei einem Bedarf von 10 km möglicherweise nützlicher sind Der Radius von 10 km liegt problemlos innerhalb einer einzelnen Zone, Sie müssen lediglich die geeignete Zone basierend auf Ihrer Mittelkoordinate auswählen. Das einzige schwierige Problem ist, wenn Sie sich einer Grenze nähern: Es ist eine übliche Situation, und es ist in OrdnungBeständig bei der Auswahl der von Ihnen verwendeten Option . Mit Proj4 können Sie auch Projektionen übersetzen, sodass Sie beispielsweise von Ihrem Mercator WGS-84 lat / long zu einer UTM-Zone n oder zu und von zwei UTM-Zonen wechseln können.)

David
quelle
2
Ein Vermesser hat mir einmal erzählt, dass er 1 Grad für seine mentalen Berechnungen verwendet, was ungefähr 108 km entspricht. Geistig sind 10 km ungefähr 0,1 Grad. Da es sich um grobe Näherungen handelt, ist es am besten, sie auf eine signifikante Ziffer (höchstens 2 oder 3) genau zu behandeln, anstatt auf 0,089982311915998, da dies ein Maß an Präzision impliziert.
Stephen Quan
1
Es ist wirklich nicht schwierig, die Grade unter Berücksichtigung des Breitengrads genauer zu berechnen. Da der Computer die Berechnung durchführt, wird mit einer Näherung nichts gewonnen (siehe die erste Funktion in meinem Beispiel).
Martinstöckli
3

Angenommen, Sie möchten eine Abfrage in einer Datenbank durchführen, möchten Sie wahrscheinlich eine schnelle (ungenaue) Suche durchführen und anschließend die Entfernung für die resultierenden Orte genau berechnen. Ist das dein Szenario?

Die folgende Funktion (in PHP leider) berechnet grob die Unterschiede in Breite und Länge. Diese Unterschiede hängen vom Breitengrad Ihres Suchpunkts ab. Verwenden Sie sie (mit einer kleinen Toleranz), um schnell in der Datenbank zu suchen. Die Box kann einfach mit Latitude + -deltaLatitude und Longitude + -deltaLongitude berechnet werden.

deltaLatitude[rad] = distance[m] / earthRadius[m]
deltaLongitude[rad] = distance[m] / (cos(latitude[rad]) * $earthRadius[m])

/**
 * Calculates the deltas in latitude and longitude to use, for a db search
 * around a location in the database.
 * @param float $distance Radius to use for the search [m]
 * @param float $latitude Latitude of the location, we need the angle deltas for [deg decimal]
 * @param float $deltaLatitude Calculated delta in latitude [deg]
 * @param float $deltaLongitude Calculated delta in longitude [deg]
 * @param float $earthRadius Mean earth radius in [m]
 */
public static function angleFromSphericDistance($distance, $latitude,
  &$deltaLatitude, &$deltaLongitude, $earthRadius = 6371000)
{
  $lat = deg2rad($latitude);

  $radiusOnLatitude = cos($lat) * $earthRadius;
  $deltaLatitude = $distance / $earthRadius;
  $deltaLongitude = $distance / $radiusOnLatitude;

  $deltaLatitude = rad2deg($deltaLatitude);
  $deltaLongitude = rad2deg($deltaLongitude);
}

Mit der Haversinus-Formel können Sie Entfernungen auf der Kugel berechnen. Verwenden Sie es für jeden der gefundenen Orte, um die "genaue" Entfernung zu erhalten. Auf diese Weise können Sie testen, ob sich die beiden Orte innerhalb eines bestimmten Radius befinden (ein Kreis anstelle des Kästchens).

/**
 * Calculates the great-circle distance between two points, with
 * the Haversine formula.
 * @param float $latitudeFrom Latitude of start point in [deg decimal]
 * @param float $longitudeFrom Longitude of start point in [deg decimal]
 * @param float $latitudeTo Latitude of target point in [deg decimal]
 * @param float $longitudeTo Longitude of target point in [deg decimal]
 * @param float $earthRadius Mean earth radius in [m]
 * @return float Distance between points in [m] (same as earthRadius)
 */
public static function haversineGreatCircleDistance(
  $latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
{
  // convert from degrees to radians
  $latFrom = deg2rad($latitudeFrom);
  $lonFrom = deg2rad($longitudeFrom);
  $latTo = deg2rad($latitudeTo);
  $lonTo = deg2rad($longitudeTo);

  $latDelta = $latTo - $latFrom;
  $lonDelta = $lonTo - $lonFrom;

  $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
    cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
  return $angle * $earthRadius;
}
martinstoeckli
quelle
3

Um zu testen, ob sich ein Lat / Lon innerhalb oder außerhalb eines Begrenzungskreises befindet, müssen Sie die Entfernung von Ihrem Referenz-Lat / Lon zu dem Lat / Lon-Punkt berechnen, den Sie testen möchten. Da Ihre Entfernung 10 km oder weniger beträgt, würde ich der Einfachheit halber versuchen, die Entfernung mit der Äquirektangularen Näherung anstelle von Haversine zu ermitteln. So ermitteln Sie die Entfernung in km:

x = (lonRef - lon) * cos ( latRef )
y = latRef - lat
distance = EarthRadius * sqrt( x*x + y*y )

Wichtiger Hinweis: Lat / Lon in dieser Formel sind im Bogenmaß und nicht in Grad angegeben. Der typische Wert von EarthRadius ist 6371 km, der die Entfernung in Einheiten von km zurückgibt. Jetzt ist es ein einfacher Test, ob Ihre Distanz innerhalb oder außerhalb des Kreises liegt. Wenn ein Begrenzungskreis funktioniert, würde ich damit einverstanden sein.

Für ein begrenzendes Rechteck würde ich annehmen, dass Sie das Rechteck definieren möchten, indem Sie parallel zum Äquator verlaufen. Ich würde dann die Ecken des Begrenzungsrahmens unter Verwendung von Entfernungs- / Lagerberechnungen berechnen (Lager sind 45 °, 135 °, 225 ° und 315 °). Von dort würde ich annehmen, dass Sie nicht um die Pole sind und einen Punkt im Polygontest verwenden.

TreyA
quelle
2

Unten ist T-SQL-Code, den ich zum Erstellen von Begrenzungsrahmen in SQL Server 2012 verwende. In meinem Fall erhalte ich Dezimalwerte für Lat, Long. Ich benutze dies, um die Anzahl der Zeilen schnell zu begrenzen, bevor ich die SQL- STDistanceFunktion verwende, um zu überprüfen, ob die Ergebnisse tatsächlich innerhalb einer bestimmten Entfernung liegen. Geografiefunktionen sind in SQL Server sehr kostspielig. Durch das Erstellen eines Begrenzungsrahmens kann ich die Anzahl der auszuführenden Vorgänge erheblich reduzieren.

DECLARE @Lat DECIMAL(20, 13) = 35.7862
   ,@Long DECIMAL(20, 13) = -80.3095
   ,@Radius DECIMAL(7, 2) = 5
   ,@Distance DECIMAL(10, 2)
   ,@Earth_Radius INT = 6371000;

SET @Distance = @Radius * 1609.344;

DECLARE @NorthLat DECIMAL(20, 13) = @Lat + DEGREES(@distance / @Earth_Radius)
   ,@SouthLat DECIMAL(20, 13) = @Lat - DEGREES(@distance / @Earth_Radius)
   ,@EastLong DECIMAL(20, 13) = @Long + DEGREES(@distance / @Earth_Radius / COS(RADIANS(@Lat)))
   ,@WestLong DECIMAL(20, 13) = @Long - DEGREES(@distance / @Earth_Radius / COS(RADIANS(@Lat)));

SELECT *
    FROM CustomerPosition AS cp
    WHERE (
            cp.Lat >= @SouthLat
            AND cp.Lat <= @NorthLat )
        AND (
              cp.Long >= @WestLong
              AND cp.Long <= @EastLong )
Vladimir Oselsky
quelle