Winkel zwischen zwei Linen

08/05/2014 12:55 strubelz#1
Ich habe heute ein eher mathematisches Problem (glaube ich), ich habe drei Punkte die durch zwei Linen verbunden sind, ich kenne die Koordinaten aller Punkte und ich möchte wissen wie ich den Winkel zwischen ihnen errechenen kann (in Java).
Hier zu verdeutlichung was ich habe:
[Only registered and activated users can see links. Click Here To Register...]
08/05/2014 13:20 Jeoni#2
Hi,
Es gibt zwei Möglichkeiten.
Einmal mit Vektorrechnung über das Skalarprodukt. Demnach hättest du zwei Vektoren (in dem Fall deine Linien) a und b. Der Winkel zwischen den Vektoren wäre definiert als ß = acos(|a*b| / |a|*|b|).
Beispiel: Gehen deine Linien von (5|5) nach (2|2) und (5|5) nach (5|2) sind deine Vektoren entsprechend a = (5-2 | 5-2) = (3|3) und b = (5-5 | 5 - 2) = (0|3).
|a*b| = 3*0 + 3*3 = 9
|a| = sqrt(3² + 3²) = 4.24
|b| = sqrt(0² + 3²) = 3
|a|*|b| = 12.72
|a*b| / |a|*|b| = 9 / 12.72 = 0.71
acos(0.71) = 44,77°
Entsprechend kann man das natürlich auch im Programm umsetzen. Ich hoffe, du hast das Prinzip verstanden.

Alternativ geht das vermutlich auch (und zwar einfacher) über Dreieckssätze (s. HIER) da rangehen. Da verzichte ich mal auf eine Beispielsrechnung, das sollte auf der Wikipediaseite klar sein und die Schule sollte den Rest getan haben.

Ich wünsche viel Spaß und Erfolg ;)
Mit freundlichen Grüßen
Jeoni
08/05/2014 13:30 strubelz#3
Danke erstmal, deine Rechnung hab ich soweit verstanden, aber ich habe leider erst die 9. Klasse abgeschlossen und da kam sowas noch nicht dran :)

Irgendwie funktioniert es bei mir nicht, ich möchte überprüfen ob ein Punkt in einem Dreieck liegt, dann müsste ja logischerweise die Summe aller Winkel zwischen den Vektoren und die die alle Ecken mit dem Punkt verbinden 360 sein, bei mir sind sie das aber nicht. (Ich habe mir auch schon das ganze Graphisch anzeigen lassen und der Punkt lag im Dreieck)
Mein Code: (x_j und y_j sind die Koordinaten des Punktes)
Code:
	double computeAngle(int x1, int y1, int x2, int y2, int x3, int y3) {
		
		int[] a = new int[]{x1 - x2, y1 - y2};
		int[] b = new int[]{x1 - x3, y1 - y3};
		int ab = a[0]*a[1] + b[0]*b[1];
		double aa = Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2));
		double bb = Math.sqrt(Math.pow(b[0], 2) + Math.pow(b[1], 2));
		double aabb = ab/(aa*bb);
		
		return Math.acos(aabb)*MathUtils.radiansToDegrees;
	}
			double a = computeAngle(x_j, y_j, x2, y2, x1, y1) + computeAngle(x_j, y_j, x3, y3, x1, y1) + computeAngle(x_j, y_j, x2, y2, x3, y3);
			
			if (a == 360) {
				System.out.println(true);
			}
08/05/2014 19:22 Jeoni#4
Code:
int ab = a[0]*a[1] + b[0]*b[1];
Das hier ist falsch. a*b ist hier definiert als a0*b0 + a1*b1 (usw. für höhere Dimensionen).
Müsste also
Code:
int ab = a[0]*b[0] + a[1]*b[1];
lauten.

Mein Code (C):
Code:
double computeAngle(int x1, int y1, int x2, int y2, int x3, int y3) {

	int a[] = {x1 - x2, y1 - y2};
	int b[] = {x1 - x3, y1 - y3};
	int ab = a[0]*b[0] + a[1]*b[1];
	double aa = sqrt((double)(a[0]*a[0] + a[1]*a[1]));
	double bb = sqrt((double)(b[0]*b[0] + b[1]*b[1]));
	double aabb = ab/(aa*bb);

	return acos(aabb)*360.0/(2*3.14159265359);
}

	   int x0 = 5, y0 = 5,
		x1 = 0, y1 = 0,
		x2 = 10, y2 = 10;

	double d = computeAngle(x0, y0, x2, y2, x1, y1)/*a*/ + computeAngle(x1, y1, x2, y2, x0, y0)/*b*/ + computeAngle(x2, y2, x0, y0, x1, y1)/*c*/;
	return 0;
Und eine Abbildung dazu:
[Only registered and activated users can see links. Click Here To Register...]
Die Winkel a, b und c müssen aufaddiert 180° ergeben (das tun sie bei mir auch). Der Rest sollte durch Code und Abbildung verständlich genug sein, nehme ich an ;)
Du kannst das sicherlich auch mit einem Punkt im Dreieck machen, aber ich war zu faul dazu :D

Ich hoffe, dass ich helfen konnte
Jeoni

P.S.: Wenn es in Java eine Vector-Klasse (nicht den Container, sondern den mathematischen Vektor) gibt, dann könnte man diese gegebenenfalls auch nutzen statt alles manuell zu machen. Aber das hier ist ja noch relativ klein, da macht das nicht viel.
08/05/2014 22:11 strubelz#5
So, bei mir funktionierts jetzt auch, ich hab aber gaerade bemerkt, das die Vector2 Klasse von LibGdx eine .angle(Vector2) Methode hat mit der ich einfach den Winkel relativ zum angegebenen Vektor bekommen würde. Einziger Fehler ist, das bei mir anstatt 360° 359,99998° rauskommen, aber das wird wohl nur ein Fehler beim runden oder so sein.
08/06/2014 11:07 Shadow992#6
Quote:
Originally Posted by strubelz View Post
So, bei mir funktionierts jetzt auch, ich hab aber gaerade bemerkt, das die Vector2 Klasse von LibGdx eine .angle(Vector2) Methode hat mit der ich einfach den Winkel relativ zum angegebenen Vektor bekommen würde. Einziger Fehler ist, das bei mir anstatt 360° 359,99998° rauskommen, aber das wird wohl nur ein Fehler beim runden oder so sein.
Genau genommen ist das kein Fehler beim Runden, sondern ein Fehler, der bei Gleitkommazahlen im IEEE Format immer auftaucht. Das Problem dabei ist, dass die Zahl 360 nicht exakt im Computer als Gleitkommazahl (ohne Tricks) oder eine andere Zahl, die für die Berechnung gebraucht wurde darstellbar ist. Das hat das IEEE Format leider so ansich. Wenn du mehr darüber wissdn willst, schau bei Google nach, da gibt es auch ein paar Beispiele wie zu runden ist, wenn soetwas auftaucht.