• Willkommen im Geoclub - dem größten deutschsprachigen Geocaching-Forum. Registriere dich kostenlos, um alle Inhalte zu sehen und neue Beiträge zu erstellen.

Winkel zwischen zwei Strecken berechnen

hugobalder

Geonewbie
Hallo!
Ich habe ein Problem und hoffe, dass ihr mir helfen könnt! Ich habe schon einige Foren und so gut wie alle Google-Treffer abgegrast, aber ich finde den Fehler irgendwie nicht...

Hintergrund:
Ich möchte eine OpenSource App schreiben, bei der ich eine Adresse eingeben und dann einfach ein Pfeil immer in Richtung Ziel zeigt. Das klappt auch alles soweit ganz gut, ich habe die Zielposition (Z), die aktuelle Position(A) und die letzte Position(B) (1sek her) als Lat/Lon Koordinaten.

Das Problem:
Damit ich weiß um wieviel Grad ich den Pfeil in meiner Animation drehen muss, brauche ich den Winkel zwischen der Strecke A-B und A-Z.

Meine bisherigen Ansätze:
Als erstes habe ich gehofft, dass ich es mir einfach machen kann und habe die Koordinaten einfach in Kartesische Koordinaten
Code:
xz = R * Math.cos(lat) * Math.cos(lon);
yz = R * Math.cos(lat) * Math.sin(lon);
umgerechnet und dann Trigonometrisch die Winkel bestimmt. Da Zeigt der Pfeil aber leider nicht in die richtige Richtung.

Anschließend habe ich es mit folgender Formel versucht:
Code:
Δφ = ln( tan( latB / 2 + π / 4 ) / tan( latA / 2 + π / 4) )
Damit berechne ich den Winkel zwischen der Strecke A-B und dem Nordpol.
Aber leider komme ich von dieser Rechnung nicht auf den Winkel zwische A-B und A-Z.

Hat jemand von euch einen Tip für mich? Bin ich auf dem richtigen Weg? Oder muss ich andere Formeln nutzen?

Falls hier jemand ist, der Lust hat mir zu helfen, dann werde ich natürlich nochmal ein wenig ausführlicher schreiben, aber ich wollte den Startpost nicht gleich abschreckend lang machen... :)
Vielen Dank!
 

moenk

Administrator
Teammitglied
Grundsätzlich rechne mal so, dass Du immer mit 0 Grad auf Nord arbeitest. Also nicht wie in der Mathematik üblich, sondern wie in der Geodäsie. Der Winkel den Du suchst ist dann die Differenz zwischen den Winkeln (berechnen über Tangens, aber Vorzeichenfalle beachten!) bezogen auf Nord.
 
OP
H

hugobalder

Geonewbie
Hallo!
Erstmal vielen Dank für die schnelle Antwort!

Ich habe, beim kartesischen Ansatz, schon den Nullpunkt auf Norden gesetzt und die Drehrichtung geändert. Leider zeigt der Pfeil immer noch in die falsche Richtung. Es wird zwar erkannt, wenn ich mich um 180° drehe und in die entgegengesetzte Richtung laufe, aber kleinere Abweichungen (ca.20°) werden von der Berechnung noch ignoriert.
Ich habe aber statt des Tangens mit dem Kosinussatz gearbeitet, da ich mit Tangens (Ankathete / Gegenkathete) doch nur rechnen kann, wenn es sich um ein rechtwinkliges Dreieck handelt?

Hier mal mein Weg:

Code:
//Winkelberchnung, kartesisch. Mit Hinweis von http://stackoverflow.com/questions/6745131/how-can-we-find-the-angle-between-two-locations-defined-by-latitude-or-longitude
		//Demnach ist der Nullpunkt bei der trigonometrischen Berechnung im Osten und geht gegen den Uhrzeigersinn. Daher Ergebnis + 90° und das Vorzeichen invertieren.
		
		//1. Die Kartesischen Koordinaten der einzelnen Punkte
		
		double xz = R * Math.cos(lat) * Math.cos(lon);
		double yz = R * Math.cos(lat) * Math.sin(lon);
		double x1 = R * Math.cos(pos1lat) * Math.cos(pos1lon);
		double y1 = R * Math.cos(pos1lat) * Math.sin(pos1lon);
		double x2 = R * Math.cos(pos2lat) * Math.cos(pos2lon);
		double y2 = R * Math.cos(pos2lat) * Math.sin(pos2lon);
		
		//2. Strecke Pos1 -- Ziel
		double az1 = Math.abs(yz-y1);
		double bz1 = Math.abs(xz-x1);
		double cz1 = Math.sqrt((az1*az1)+(bz1*bz1));
		
		//3. Strecke Pos2 -- Ziel
		double az2 = Math.abs(yz-y2);
		double bz2 = Math.abs(xz-x2);
		double cz2 = Math.sqrt((az2*az2)+(bz2*bz2));
		
		//4. Strecke Pos1 -- Pos2
		
		double a12 = Math.abs(y1-y2);
		double b12 = Math.abs(x1-x2);
		double c12 = Math.sqrt((a12*a12)+(b12*b12));
		
		//5. Winkel zwischen Strecke Pos1 -- Pos2 und Pos2 -- Ziel

		double cosalpha = (( (cz2*cz2) + (c12*c12) - (cz1*cz1) ) / (2 * cz2 * c12 ) );
		double rad = Math.acos(cosalpha);
		win = Math.toDegrees(rad);
		win = (win - 90) * (-1);

Habe ich vielleicht schon bei der Berechnung einen Fehler gemacht_
 

moenk

Administrator
Teammitglied
Mir scheint der ganze Ansatz etwas kompliziert. Kannst Du das nicht einfach mit sphärischer Geometrie rechnen?
http://de.wikipedia.org/wiki/Orthodrome
http://de.wikipedia.org/wiki/Loxodrome
 
OP
H

hugobalder

Geonewbie
Super!
Das scheint ja genau das zu sein, was mir gefehlt hat... Dadurch wird die Rechnung hoffentlich wesentlich einfacher. Ich werde das nächste Woche mal ausprobieren und dann melde ich mich nochmal.

Vielen Dank erstmal!
 
OP
H

hugobalder

Geonewbie
EDIT: Oh man...
nochmal alles kurz zurück.
Kein wunder, dass der Winkel so klein ist bei mir... ich habe den "arcos" vergessen...
:kopfwand: :kopfwand: :kopfwand:
Ich ändere das und melde mich dann nochmal...



Hmm, das hat leider noch nicht so geklappt wie ich mir das Vorgestellt habe. Ich habe die Wikipedia Artikel so verstanden, dass ich mit der Formel aus dem Orthodrome Artikel:
file.php
Den Winkel zwischen der Strecke am Punkt 1 und dem geographischen Norden ausrechnen kann.
Dann müsste ich ja eigentlich diese Winkel berechnen können:
file.php

Dann wollte ich also den Differenzwinkel zwischen den beiden Strecken ausrechnen. Da ich von Pos2 zu Pos1 laufe, also in der Richtung meine 0Grad sind, muss ich den Pfeil um 180 - (alpha - beta) drehen. Dachte ich.
Aber der berechnete Winkel stimmt nicht, scheinbar ist er immer sehr klein und ändert sich nicht so wie er sollte. Wenn ich mich zum Beispiel um 90 Grad drehe, dreht der Pfeil maximal 5-10 Grad.

Irgendwo muss da also ein Denkfehler sein, aber ich finde ihn nicht...
Hat da vielleicht noch jemand eine Idee?
Danke!

Hier nochmal mein Code:
Code:
double zwischen  = Math.cos(pos1lat) * Math.sin(pos2lat) - Math.cos(pos1lon - pos2lon) * Math.cos(pos2lat) * Math.sin(pos1lat);
		double zwischen1 = Math.cos(pos1lon - pos2lon) * Math.cos(pos1lat) * Math.cos(pos2lat) + Math.sin(pos1lat) * Math.sin(pos2lat);
		
		alpha = (
				zwischen / Math.sqrt(1-(zwischen1 * zwischen1))
				);
		
		//Winkel beta, zwischen Punkt1 -- Ziel und dem Nordpol
		double zwischen2 = Math.cos(pos1lat) * Math.sin(lat) - Math.cos(pos1lon - lon) * Math.cos(lat) * Math.sin(lat);
		double zwischen3 = Math.cos(pos1lon - lon) * Math.cos(pos1lat) * Math.cos(lat) + Math.sin(pos1lat) * Math.sin(lat);
		
		beta = (
				zwischen2 / Math.sqrt(1-(zwischen3 * zwischen3))
				);
		
		double anz = 180 - (alpha -beta);
		win = Math.toDegrees(anz);
 

Anhänge

  • winkel_rechnung.jpg
    winkel_rechnung.jpg
    16,3 KB · Aufrufe: 3.166
  • winkel_klein.jpg
    winkel_klein.jpg
    10,8 KB · Aufrufe: 3.166
OP
H

hugobalder

Geonewbie
So, ich habe jetzt noch einmal eine ganze Weile rumprobiert und auch noch ein zwei Fehler gefunden, aber trotzdem funktioniert das ganze noch nicht so, wie es soll. Anscheinend habe ich die Formeln doch nicht richtig verstanden. Ich dachte mit:
file.php


kann ich den Winkel zwischen der Strecke PunktA--PunktB und dem geographischen Norden ausrechnen.
Dann müsste ich ja eigentlich die Winkel Alpha und Beta berechnen können:
file.php


Dann wollte ich also den Differenzwinkel zwischen den beiden Strecken ausrechnen. Dachte ich.
Aber der berechnete Winkel stimmt nicht, scheinbar ist er immer sehr klein und ändert sich nicht so wie er sollte. Wenn ich mich zum Beispiel um 90 Grad drehe, dreht der Pfeil maximal 10-15 Grad.

Irgendwo muss da also ein Denkfehler sein, aber ich finde ihn nicht...
Hat da vielleicht noch jemand eine Idee?
Danke!

Hier nochmal mein Code:
Code:
//Winkel alpha, zwischen Punkt1 -- Punkt2 und dem Nordpol

double zwischen  = Math.cos(pos1lat) * Math.sin(pos2lat) - Math.cos(pos1lon - pos2lon) * Math.cos(pos2lat) * Math.sin(pos1lat);

double zwischen1 = Math.cos(pos1lon - pos2lon) * Math.cos(pos1lat) * Math.cos(pos2lat) + Math.sin(pos1lat) * Math.sin(pos2lat);
		
		alpha = Math.acos(
				zwischen / Math.sqrt(1-(zwischen1 * zwischen1))
				);
		
//Winkel beta, zwischen Punkt1 -- Ziel und dem Nordpol

double zwischen2 = Math.cos(pos1lat) * Math.sin(lat) - Math.cos(pos1lon - lon) * Math.cos(lat) * Math.sin(lat);

double zwischen3 = Math.cos(pos1lon - lon) * Math.cos(pos1lat) * Math.cos(lat) + Math.sin(pos1lat) * Math.sin(lat);
		
		beta = Math.acos(
				zwischen2 / Math.sqrt(1-(zwischen3 * zwischen3))
				);
		
	double anz = Math.PI - (alpha -beta);
	win = Math.toDegrees(anz);
//win ist dann der auszugebene Winkel...
 
Oben