Veranschaulicht man sich das Problem graphisch, so fällt auf, dass sich bei der Bewegung eigentlich nur der Winkel (Drehwinkel) zwischen dem Ortsvektor und der x-Achse ändert. Die Länge des Ortsvektors (sein Betrag) dagegen bleibt konstant. Was liegt also näher, als die Umlaufbahn der Erde als Funktion ihres Drehwinkels zu beschreiben. Man spricht in diesem Zusammenhang von einer zweidimensionalen Polarkoordinatendarstellung.
Polarkoordinaten können natürlich auch für den dreidimensionalen Raum definiert werden. Ihre Verwendung bietet sich, wie im ersten Beispiel beschrieben, bei der Positionsangabe von Städten auf einer Weltkarte an oder bei der Positionierung von Hintergrundnebeln und Galaxien in einem Weltraumspiel. Die nachfolgende Abbildung veranschaulicht eine mögliche Definition der dreidimensionalen Polarkoordinatendarstellung:
Hier nun der Zusammenhang zwischen den Polarwinkeln und den kartesischen Koordinaten:
Hinweis:
Setzt man jetzt für den Vertikalwinkel 90° ein, zeigt der Ortsvektor immer in die positive y-Richtung.
Ist der Vertikalwinkel gleich 0° und der Horizontalwinkel gleich 90°, zeigt der Ortsvektor in die positive x-Richtung.
Ist der Vertikalwinkel gleich 0° und der Horizontalwinkel gleich 180°, zeigt der Ortsvektor in die negative z-Richtung.
In der täglichen Programmierpraxis ergibt sich oftmals das Problem, dass für einen gegebenen Richtungsvektor (Einheitsvektor) die zugehörigen Polarwinkel berechnet werden müssen. Ein Beispiel hierfür wäre eine Explosion. Man kennt die Bewegungsrichtung der einzelnen Trümmerteile und benötigt für die effektvolle Darstellung von Rauch- und Brandspuren (Billboards) die zugehörigen Polarwinkel. Im Weltraum-Echtzeitstrategiespiel „Haegemonia“ wurde dies sehr eindrucksvoll umgesetzt.
Die nachfolgende CalculatePolarCoordinates()-Funktion berechnet nun nicht nur die einzelnen Polarwinkel, sondern liefert dem Programmierer darüber hinaus auch die zugehörigen Sinus- und Kosinuswerte.
inline void CalculatePolarCoordinates(D3DXVECTOR3* pDirection,
float &DirectionVerticalAngle,
float &DirectionSinVerticalAngle,
float &DirectionCosVerticalAngle,
float &DirectionHorizontalAngle,
float &DirectionSinHorizontalAngle,
float &DirectionCosHorizontalAngle)
{
// Berechnung der Polarkoordinatenwinkel:
DirectionSinVerticalAngle = pDirection->y;
if(fabs(DirectionSinVerticalAngle) > 0.999f) // 90°
{
DirectionCosVerticalAngle = 0.0f;
DirectionCosHorizontalAngle = 1.0f;
DirectionSinHorizontalAngle = 0.0f;
return;
}
else
{
// Vertikalwinkel berechnen:
DirectionVerticalAngle = asinf(DirectionSinVerticalAngle);
DirectionCosVerticalAngle = cosf(DirectionVerticalAngle);
// Horizontalwinkel berechnen:
DirectionCosHorizontalAngle = pDirection->z/
DirectionCosVerticalAngle;
DirectionHorizontalAngle = acosf(DirectionCosHorizontalAngle);
if(pDirection->x < 0.0f)
DirectionHorizontalAngle = 6.283185308f-DirectionHorizontalAngle;
DirectionSinHorizontalAngle = sinf(DirectionHorizontalAngle);
return;
}
}
float &DirectionVerticalAngle,
float &DirectionSinVerticalAngle,
float &DirectionCosVerticalAngle,
float &DirectionHorizontalAngle,
float &DirectionSinHorizontalAngle,
float &DirectionCosHorizontalAngle)
{
// Berechnung der Polarkoordinatenwinkel:
DirectionSinVerticalAngle = pDirection->y;
if(fabs(DirectionSinVerticalAngle) > 0.999f) // 90°
{
DirectionCosVerticalAngle = 0.0f;
DirectionCosHorizontalAngle = 1.0f;
DirectionSinHorizontalAngle = 0.0f;
return;
}
else
{
// Vertikalwinkel berechnen:
DirectionVerticalAngle = asinf(DirectionSinVerticalAngle);
DirectionCosVerticalAngle = cosf(DirectionVerticalAngle);
// Horizontalwinkel berechnen:
DirectionCosHorizontalAngle = pDirection->z/
DirectionCosVerticalAngle;
DirectionHorizontalAngle = acosf(DirectionCosHorizontalAngle);
if(pDirection->x < 0.0f)
DirectionHorizontalAngle = 6.283185308f-DirectionHorizontalAngle;
DirectionSinHorizontalAngle = sinf(DirectionHorizontalAngle);
return;
}
}