Hallo zusammen!
Ich stehe hier gerade nicht unbedingt vor einem formeltechnischen/mathematischen,
dafür aber vielleicht vor einem Verständnisproblem was die Präzision von float
und double anbelangt.
Ich versuche den Winkel zwischen 2 Punkten respektive einer
Strecke im 2-dimensionalen zu berechnen. Die Richtung (0,-1) stellt dabei 0
Grad dar (oben/Norden), im Uhrzeigersinn geht es dann in positive Richtung.
Siehe hierzu erst das Bild und danach folgenden Code:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// Winkel der Strecke CB; 0° in negativer y-Richtung (Ausrichtung nach oben/Norden);
// vorwärts im Uhrzeigersinn
float WinkelDerLinie(const Vector2D& C, const Vector2D& B)
{
// Punkt A := (C.x, C.y - 1)
// -> Liegt auf der Y-Achse 1 über Punkt C => |AC| = b = 1
// Formel: c² = a² + b² - 2ab * cos(gamma)
const Vector2D CB = B - C;
const float a_square = CB.x * CB.x + CB.y * CB.y;
const Vector2D AB = B - Vector2D(C.x, C.y - 1);
const float c_square = AB.x * AB.x + AB.y * AB.y;
// Ausdruck für den ArcCos
float tmpVal = (a_square + 1 - c_square) / (2 * sqrtf(a_square));
/** EHER UNELEGANTE LÖSUNG: **/
// Verhinderung von Werten > 1 und < -1
if (tmpVal > 1)
tmpVal = 1.0f;
else if (tmpVal < -1)
tmpVal = -1.0f;
// Wenn Punkt B links von C liegt (entlang der x-Achse),
// dann Ergebnis von 2 * pi abziehen
if (B.x < C.x)
return CONST_2PI - acosf(tmpVal);
else
return acosf(tmpVal);
}
|
Nun habe ich das Problem, dass ich bei 180° bzw. pi ein -1.#IND
bekomme. Inzwischen bin ich soweit, dass ich weiß, dass die Funktion acos()
hier einen Wert entweder >1 oder <-1 bekommt, was zu obigem return-Wert
führt. Dieses Problem habe ich bisher (auf wahrscheinlich unelegante Weise) mit
if-Abfragen gelöst. Möchte Euch daher einmal fragen, ob Euch dazu etwas besseres,
wie zum Beispiel eine bessere Formel oder ein besserer Umgang mit float oder
double einfällt. Vielen Dank!