GPS-Berechnungen mit PHP

Ein Artikel von Ramón Lang, veröffentlicht am 12. März 2023.
Die Lesedauer beträgt ungefähr 6 Minuten.

Es gibt einige programmiertechnische Knackpunkte. Einer davon ist der Umgang mit Koordinaten. Für mathematisch versierte Menschen ist das vermutlich keine besondere Herausforderung. Ich aber weiß höchstens von der Existenz von Begriffen wie Sinus und Kosinus und habe keine Ahnung, was da mathematisch eigentlich geschieht. Dazu kommt natürlich, dass Koordinatensysteme auch ohne Mathematik schon kompliziert sind.

Das ist aber auch nicht verwunderlich. Es gibt internationale und nationale Methoden, um einen Punkt auf der Erde mit Koordinaten zu bestimmen. Und es gibt auch eine digitale Methode. Mit zwei Zahlen lässt sich die Position für digitale Anwendungen bestimmen. Menschen benutzen andere Systeme, damit sie Punkte schneller auf einer Karte finden können und ggf. schon ohne Karte abschätzen können, für welchen Ort eine bestimmte Koordinate bestimmt ist.

Beim Umgang mit Koordinaten müssen außerdem auch Winkel, Erdkrümmung, Erdradius usw. berücksichtigt werden. Das ist ein eigenes Fachgebiet, in das ich mich nicht einarbeiten möchte. Aber trotzdem möchte ich programmiertechnische Methoden zur Verfügung haben, um mit Koordinaten arbeiten zu können. Diese habe ich nun und möchte ich hier teilen:

Wie funktionieren digitale Koordinaten?

Die Bezeichnung „digitale Koordinaten“ kommt übrigens von mir. Eigentlich sind das Dezimalkoordinaten, da es sich um zwei Kommazahlen handelt. Oder auch „decimal degrees“, bzw. DD.

Für den Eiffelturm in Paris gelten beispielsweise folgende Koordinaten:

48.8582602, 2.2944991

Der Wert links (48…) wird als Latitude bezeichnet. Der Wert rechts (2…) wird als Longitude bezeichnet. Es sind Breiten- und Längengrade. Die Zahlen werden durch ein Komma voneinander getrennt und können je nach Punkt auf der Erde auch im Minus liegen. In den folgenden PHP-Variablen steht $lat für die Latitude und $lon für die Longitude.

Distanz berechnen

Eine Distanz zwischen zwei Koordinaten-Punkten zu berechnen konnte ich schon vorher. Da das aber vermutlich eine der häufigsten Anwendungen ist, werde ich sie hier mit aufführen:

function getDistance(
	$lat1, $lon1,
	$lat2, $lon2
) {
	$earth_radius = 6371; // Erdradius in km
	$dLat = deg2rad($lat2 - $lat1);
	$dLon = deg2rad($lon2 - $lon1);
	$a = sin($dLat / 2) * sin($dLat / 2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon / 2) * sin($dLon / 2);
	$c = 2 * asin(sqrt($a));
	$distance = $earth_radius * $c;
	return $distance;
}

Diese Funktion gibt die Distanz zwischen zwei Punkten in Kilometern zurück.

Richtung zwischen zwei Punkten

Wenn zwei Punkte vorliegen, kann die Himmelsrichtung von Punkt 1 Richtung Punkt 2 berechnet werden. Der Rückgabewert dieser Funktion ist ebenfalls eine Kommazahl, mit der man weiter rechnen könnte.

function getBearing(
	$lat1, $lon1,
	$lat2, $lon2
) {
    $dLon = deg2rad($lon2 - $lon1);
    $y = sin($dLon) * cos(deg2rad($lat2));
    $x = cos(deg2rad($lat1)) * sin(deg2rad($lat2)) - sin(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos($dLon);
    $bearing = atan2($y, $x);
    return rad2deg($bearing);
}

Falls man mit diesem Wert keine weiteren Berechnungen durchführen, sondern die Himmelsrichtung von Punkt A Richtung Punkt B ermitteln will, dann kann der Wert noch zusätzlich folgendermaßen weiterverarbeitet werden:

if($bearing < 0) {
    $bearing += 360;
}

Jetzt haben wir einen Wert zwischen 0° und 360°, was gleichzeitig eine Himmelsrichtung darstellt.

Koordinaten zwischen zwei anderen Koordinaten

Mit folgendem Code können wir eine Position zwischen zwei bekannten Koordinaten berechnen. Das kann beispielsweise genau die Mitte sein, oder eine andere Position.

Wichtig ist, dass folgender Code auf die Funktion getBearing() zugreifen können muss. Die Variable $distance enthält die Distanz vom Startpunkt ($lat1/ $lon1).

Ein Beispiel: Wir haben die Koordinaten von Hamburg und von Frankfurt. Nun möchten wir auf dieser Linie die Koordinaten vom Punkt berechnen, der 50km von Hamburg entfernt liegt. Dann ist der Wert $distance = 50.

function getPositionBetween(
	$lat1, $lon1,
	$lat2, $lon2,
	$distance
) {
    $bearing = deg2rad(getBearing($lat1, $lon1, $lat2, $lon2));
    $lat1 = deg2rad($lat1);
    $lon1 = deg2rad($lon1);
    $distance /= 6371;
    $lat2 = asin(sin($lat1) * cos($distance) + cos($lat1) * sin($distance) * cos($bearing));
    $lon2 = $lon1 + atan2(sin($bearing) * sin($distance) * cos($lat1), cos($distance) - sin($lat1) * sin($lat2));
    $lon2 = fmod(($lon2 + 3 * M_PI), (2 * M_PI)) - M_PI; // normalize to -180..+180 degrees
    return array(rad2deg($lat2), rad2deg($lon2));
}

Koordinaten ab nur einem Punkt

Die gleiche Funktion wie gerade eben funktioniert auch, wenn nur ein Punkt vorhanden ist. Dafür muss aber eine Richtung vorgegeben sein. Also 50km ab Hamburg in Richtung Süden.

Dann ist der Wert $distance weiterhin 50 und der Wert $bearing wäre 180, da dieser der Richtung Süden entspricht.

function getPositionAfterPosition(
	$lat1, $lon1,
	$distance, $bearing
) {
    $lat1 = deg2rad($lat1);
    $lon1 = deg2rad($lon1);
    $distance /= 6371; // convert distance to angular distance in radians
    $bearing = deg2rad($bearing);
    $lat2 = asin(sin($lat1) * cos($distance) + cos($lat1) * sin($distance) * cos($bearing));
    $lon2 = $lon1 + atan2(sin($bearing) * sin($distance) * cos($lat1), cos($distance) - sin($lat1) * sin($lat2));
    $lon2 = fmod(($lon2 + 3 * M_PI), (2 * M_PI)) - M_PI; // normalize to -180..+180 degrees
    return array(rad2deg($lat2), rad2deg($lon2));
}

Da gäbe es sicherlich noch mehr, was man berechnen könnte. Aber vorerst war es das von mir. Dass die Funktionen so funktionieren, ist einem sehr langen und intensiven „Gespräch“ mit ChatGPT zu verdanken. Die Vorschläge der KI haben zwar nicht alle auf Anhieb funktioniert, aber gemeinsam sind wir nun zu einem Ziel gekommen.

Bei Fehlern, Vorschlägen und Fragen sind die Kommentare für diesen Artikel offen.

Kommentare zu diesem Artikel

Wie ist Dein Name?

Wie ist Deine E-Mail-Adresse?

Die E-Mail-Adresse wird nicht veröffentlicht.

Was möchtest Du zum Artikel sagen?

Bisher wurden noch keine Kommentare geschrieben.