Eine Drehung, die einen Anfangspunkt in einen Endpunkt
überführt und die
durch den Punkt
gehende Drehachse
hat, kann wie folgt ausgeführt werden.
| (1.24) |
von links nach rechts dargestellt wird zunächst die Drehachse in den Ursprung verschoben, dann die Drehung
ausgeführt und dann alles wieder um die ursprüngliche Strecke zurckgeschoben. Bleibt nur noch die Bestimmung der
Matrixelemente von M und die Aufgabe ist allgemein gelöst.
Der zu
| (1.25) |
| (1.26) |
und es gilt:
void mbld(double *V_1 ,double *V_2 ,double *M_A){ //feldpointer Drehmatrix A (9 Elemente!)
double ca, sa, cb, sb, cd, sd, cx, cy, cz, vb, DV, Rx, Ry, Rz, temp1, temp2;
//******** Kreuzprodukt der beiden Vektoren ist Drehachse *****************
Rx = *(V_1+1) * *(V_2+2) - *(V_1+2) * *(V_2+1);// y1 * z2 - y2 * z1
Ry = *(V_1+2) * *(V_2) - *(V_1) * *(V_2+2);// z1 * x2 - z2 * x1
Rz = *(V_1) * *(V_2+1) - *(V_1+1) * *(V_2) ;// x1 * y2 - x2 * y1
if(Ry == 0 && Rz == 0){Rz = 1;};
//'******** Winkel zwischen beiden Vektoren ist Drehwinkel um diese Achse **
temp1 = *(V_1) * *(V_2) + *(V_1+1) * *(V_2+1) + *(V_1+2) * *(V_2+2) ;
temp2 = sqrt(*(V_1) * *(V_1) + *(V_1+1) * *(V_1+1) + *(V_1+2) * *(V_1+2))
* sqrt(*(V_2) * *(V_2) + *(V_2+1) **(V_2+1) + *(V_2+2) * *(V_2+2)) ; // 'Betraege multipliziert
cd = temp1 / temp2 ; // 'Cosinus des Drehwinkels
sd = sqrt(fabs(1.0 - cd * cd)) ; // 'Sinus des Drehwinkels
//'******** Im Folgenden Bestimmung der Drehachse **********
vb = sqrt(Rx *Rx + Ry *Ry + Rz *Rz);
cx = Rx / vb ; cy = Ry / vb ; cz = Rz / vb ; // 'Richtungscosinus und sinus der Drehachse
DV = sqrt(cy * cy + cz *cz);
ca = cz / DV; sa = cy / DV; cb = DV; sb = cx ; // 'Cosinusterme zur Drehung um x und y Achse
//'**** Matrixelemente Drehung von Vektor x1,y1,z2 in den Vektor x2,y2,z2 **
temp1 = sa * cb * sb * (1 - cd); temp2 = ca * cb * sd;
*(M_A+1) = temp1 - temp2;
*(M_A+3) = temp1 + temp2;
temp1 = ca * sa * cb * cb * (1 - cd);
temp2 = sb * sd;
*(M_A+5) = temp1 - temp2; *(M_A+7) = temp1 + temp2;
temp1 = ca * cb * sb * (1 - cd);
temp2 = sa * cb * sd;
*(M_A+6) = temp1 - temp2; *(M_A+2) = temp1 + temp2;
*(M_A+0) = cb * cb * cd + sb *sb;
*(M_A+4) = ca * ca * cd + sa * sa * sb * sb * cd + sa * sa * cb * cb;
*(M_A+8) = sa * sa * cd + ca * ca * sb * sb * cd + ca * ca * cb * cb;
};
Und folgende Routine stellt die Determinante auf 1.
void mdet1(double *MP){
if(*(MP+1) * *(MP+3) - *(MP) * *(MP+4) != 0)
{
*(MP+8) =
( *(MP+1) * *(MP+5) * *(MP+6) + *(MP+2) * *(MP+3) * *(MP+7)
- *(MP+2) * *(MP+4) * *(MP+6) - *(MP) * *(MP+5) * *(MP+7) - 1.0)
/ (*(MP+1) * *(MP+3) - *(MP) * *(MP+4));
}};
Damit haben wir die Mathematik zusammen, um eine aus dreidimensionalen Koordinaten bestendende Geometrie am Bildschirm zu drehen. Eingegebene Eckpunkte werden in einer Liste gespeichert. Aus Mausaktionen werden die Elemente der Drehmatrix bestimmt und die Determinante anschließend zu 1 gemacht. Über eine Matrixmultiplikation wird eine, nun gedrehte, Kopie der
Liste von Eckpunkten geschrieben. Von dieser Kopie werden dann 2 der 3 Dimensionen am Bildschirm ausgegeben. Vorteil des Verfahrens ist, daß wir stets die unveränderte Datenbasis verwenden und sich damit keine Rundungsfehler aufsummieren.
Die unveränderte Datenbasis kann im Original manipuliert oder gespeichert werden.