In dit artikel vind je de omzetting van een willekeurige rotatiematrix naar de Euler hoeken die je zoekt:
https://www.gregslabaugh.net/publications/euler.pdf
Voordat we die kunnen gebruiken moeten we eerst die rotatiematrix M bepalen van de rotatie die wij uitvoeren.
Kies een assenstelset met de oorsprong O in het zwaartepunt van de dodecaeder.
Alle 20 hoekpunten liggen dan op een bol met middelpunt O en een straal R.
In dit plaatje is A zo'n hoekpunt:
We zoeken dan de rotaties om de as OA, met een rotatiehoek
\(\rho\), met
\(\rho = 120^\circ\) en
\(\rho = 240^\circ = -120^\circ\) in het bijzonder.
Hiervoor kunnen we de basisrotaties om de x-, y- en z-as gebruiken zoals gegeven op pagina 1 van bovenstaand artikel:
Als A = [xa, ya, za], dan is P de loodrechte projectie van A op het x-y-vlak: P = [xa, ya, 0].
We roteren eerst alles om de z-as, zodanig dat P op de positieve x-as komt te liggen: rotatiematrix
\(R_{z,-\lambda}\), met
\(\lambda\) te bepalen uit xa en ya.
Dan roteren we alles om de y-as, waarbij OA op de z-as komt te liggen:
\(R_{y, - \mu }\), met
\(\mu\) te bepalen uit za en straal R (=|OA|).
Dan kunnen we onze rotatie uitvoeren: een hoek van
\(\rho\) om de z-as:
\(R_{z, \rho}\)
En tenslotte moeten we alles weer terugdraaien, zodat A weer op zijn oorspronkelijke plaats komt te liggen:
eerst
\(R_{y, \mu }\), dan
\(R_{z,\lambda}\)
Onze matrix M wordt dan het product van deze 5 matrices:
\(M = R_{z,\lambda} \cdot R_{y, \mu } \cdot R_{z, \rho} \cdot R_{y, - \mu } \cdot R_{z,-\lambda}\)
Mocht jouw programma niet kunnen rekenen met matrices, dan is hier het resultaat:
Als
\(M = \begin{bmatrix} m_{1,1} & m_{1,2} & m_{1,3}\\ m_{2,1} & m_{2,2} & m_{2,3}\\ m_{3,1} & m_{3,2} & m_{3,3} \end{bmatrix}\)
dan is
\(m_{1,1} = (\cos(\rho)*\cos(\mu)^2 + \sin(\mu)^2)*\cos(\lambda)^2 + \cos(\rho)*\sin(\lambda)^2;\)
\(m_{1,2} = (\cos(\rho)*\cos(\mu)^2 + \sin(\mu)^2 - \cos(\rho))*\sin(\lambda)*\cos(\lambda) - \sin(\rho)*\cos(\mu);\)
\(m_{1,3} = (1 - \cos(\rho))*\sin(\mu)*\cos(\mu)*\cos(\lambda) + \sin(\rho)*\sin(\mu)*\sin(\lambda);\)
\(m_{2,1} = \sin(\rho)*\cos(\mu) + (\cos(\rho)*\cos(\mu)^2 + \sin(\mu)^2 - \cos(\rho))*\sin(\lambda)*\cos(\lambda);\)
\(m_{2,2} = \cos(\rho)*\cos(\lambda)^2 + (\cos(\rho)*\cos(\mu)^2 + \sin(\mu)^2)*\sin(\lambda)^2;\)
\(m_{2,3} = (1 - \cos(\rho))*\sin(\mu)*\cos(\mu)*\sin(\lambda) - \sin(\rho)*\sin(\mu)*\cos(\lambda);\)
\(m_{3,1} = (1 - \cos(\rho))*\sin(\mu)*\cos(\mu)*\cos(\lambda) - \sin(\rho)*\sin(\mu)*\sin(\lambda);\)
\(m_{3,2} = \sin(\rho)*\sin(\mu)*\cos(\lambda) + (1 - \cos(\rho))*\sin(\mu)*\cos(\mu)*\sin(\lambda);\)
\(m_{3,3} = \cos(\mu)^2 + \cos(\rho)*\sin(\mu)^2;\)
Nu we M kennen, kunnen we het algoritme in bovenstaand artikel (pag. 5, Figure 1) gebruiken om de Euler hoeken te bepalen.
Voorbeeld:
Neem de figuur van
https://en.wikipedia.org/wiki/Regular_d ... oordinates:
De coordinaten van een aantal hoekpunten zijn:
Code: Selecteer alles
A = [ 0.618, 0, 1.618 ]
B = [-0.618, 0, 1.618 ]
C = [ 1, -1, 1 ]
D = [ 1, 1, 1 ]
E = [ 1.618, 0.618, 0 ]
F = [ 0, 1.618, 0.618 ]
Willen we deze dodecaeder roteren om as OA over
\(\rho = 120^\circ\), dan krijgen we:
\(M = \begin{bmatrix} -0.30901699437494742410 & -0.80901699437494742410 & 0.50000000000000000000\\ 0.80901699437494742410 & -0.50000000000000000000 & -0.30901699437494742410\\ 0.50000000000000000000 & 0.30901699437494742410 & 0.80901699437494742410\end{bmatrix}\)
en dit levert 2 mogelijkheden voor de Euler-hoeken (beide eerst roteren om de x-as, dan om de y-as, dan om de z-as):
\(\psi_1 = 20.905157447889299033\)
\(\theta_1 = -30.000000000000000000\)
\(\phi_1 = 110.90515744788929903\)
\(\psi_2 = -159.09484255211070097\)
\(\theta_2 = 210.00000000000000000\)
\(\phi_2 = -69.094842552110700967\)
Ter controle:
\(B = [-0.61803398874989484820, 0, 1.6180339887498948482]\)
B wordt afgebeeld op
\(M \cdot B = C = [1.0000000000000000000, -1.0000000000000000000, 1.0000000000000000000]\)
B 2 keer roteren geeft
\(M^2 \cdot B = D = [1.0000000000000000000, 1.0000000000000000000, 1.0000000000000000000]\)
B 3 keer roteren geeft
\(M^3 \cdot B = B = [-0.61803398874989484820, -1.3943356759474202090\cdot 10^{-38}, 1.6180339887498948482]\)
Zoals verwacht keert B na 3 rotaties (binnen de machineprecisie) weer terug op zijn oude positie.
Eveneens geldt dat
\(R_{z,\phi_1} \cdot R_{y,\theta_1} \cdot R_{x,\psi_1} = M\)
en
\(R_{z,\phi_2} \cdot R_{y,\theta_2} \cdot R_{x,\psi_2} = M\)
Hier nog wat code die je mogelijk kan gebruiken:
Code: Selecteer alles
\\------------------------------------------------------------
\\ HULPFUNCTIES:
\\------------------------------------------------------------
\\ afstand tussen punten P en Q:
dist(P,Q)={
sqrt((P[1]-Q[1])^2 + (P[2]-Q[2])^2 + (P[3]-Q[3])^2)
}
\\ bepaal de hoek die vector [x, y] maakt met positieve x-as:
\\ resultaat: -pi < hoek <= pi
atan2(y,x)={
if(x==0,
if(y==0, return(0));
if(y>0,
return(Pi/2);
,\\else: y<0:
return(-Pi/2);
);
);
if(x<0,
if(y>=0,
return(Pi+atan(y/x));
,\\else: y<0:
return(-Pi+atan(y/x));
);
,\\else: x>0:
return(atan(y/x));
);
}
\\------------------------------------------------------------
\\ MAAK DE ROTATIEMATRIX M VOOR ROTATIE rho OM ROTATIEAS OA:
\\------------------------------------------------------------
makematM(A, rho)={
local(lambda, R, mu, cr, sr, sL, cL, sM, cM); \\ locale variabelen
\\ bepaal de hoeken van de rotatie-as:
lambda=atan2(A[2],A[1]);
R=dist([0,0,0], A);
mu=acos(A[3]/R);
\\ goniometrische waarden:
sr=sin(rho);
cr=cos(rho);
sL=sin(lambda);
cL=cos(lambda);
sM=sin(mu);
cM=cos(mu);
\\ bepaal rotatiematrix M:
M=matrix(3,3);
M[1,1] = (cr*cM^2 + sM^2)*cL^2 + cr*sL^2;
M[1,2] = (cr*cM^2 + sM^2 - cr)*sL*cL - sr*cM;
M[1,3] = (1 - cr)*sM*cM*cL + sr*sM*sL;
M[2,1] = sr*cM + (cr*cM^2 + sM^2 - cr)*sL*cL;
M[2,2] = cr*cL^2 + (cr*cM^2 + sM^2)*sL^2;
M[2,3] = (1 - cr)*sM*cM*sL - sr*sM*cL;
M[3,1] = (1 - cr)*sM*cM*cL - sr*sM*sL;
M[3,2] = sr*sM*cL + (1 - cr)*sM*cM*sL;
M[3,3] = cM^2 + cr*sM^2;
}
\\------------------------------------------------------------
\\ BEPAAL DE EULER HOEKEN VOOR MATRIX M:
\\------------------------------------------------------------
eulerangles()={
if(M[3,1]!=1 && M[3,1]!=-1,
numsol=2; \\ aantal oplossingen = 2
tt1=-asin(M[3,1]);
tt2=Pi-tt1;
ps1=atan2(M[3,2]/cos(tt1), M[3,3]/cos(tt1));
ps2=atan2(M[3,2]/cos(tt2), M[3,3]/cos(tt2));
ph1=atan2(M[2,1]/cos(tt1), M[1,1]/cos(tt1));
ph2=atan2(M[2,1]/cos(tt2), M[1,1]/cos(tt2));
, \\else:
numsol=1; \\ aantal oplossingen = 1
ph1=0;
if(M[3,1]==-1,
tt1=Pi/2;
ps1=ph1+atan2(M[1,2], M[1,3]);
,\\else:
tt1=-Pi/2;
ps1=-ph1+atan2(-M[1,2], -M[1,3]);
);
);
return(numsol);
}
\\------------------------------------------------------------
\\ TOON DE EULER HOEKEN (deg==1 <=> IN GRADEN):
\\------------------------------------------------------------
printeuler(deg)={
eulerangles(); \\ bereken de Euler hoeken
if(deg==0,
c=1; \\ hoeken in radialen
, \\else:
c=180.0/Pi; \\ hoeken in graden
);
if(abs(ps1)<1.E-36, ps1=0);
if(abs(tt1)<1.E-36, tt1=0);
if(abs(ph1)<1.E-36, ph1=0);
print("---------------------------------------------------");
print("Rx: ps1 = ", ps1*c);
print("Ry: tt1 = ", tt1*c);
print("Rz: ph1 = ", ph1*c);
print("---------------------------------------------------");
if(numsol>1,
if(abs(ps2)<1.E-36, ps2=0);
if(abs(tt2)<1.E-36, tt2=0);
if(abs(ph2)<1.E-36, ph2=0);
print("Rx: ps2 = ", ps2*c);
print("Ry: tt2 = ", tt2*c);
print("Rz: ph2 = ", ph2*c);
print("---------------------------------------------------");
);
}
\\------------------------------------------------------------
\\ CHECK: Rz * Ry * Rx = M ?
\\------------------------------------------------------------
checkrot()={
Rx=[1,0,0; 0,cos(ps1),-sin(ps1); 0,sin(ps1),cos(ps1)];
Ry=[cos(tt1),0,sin(tt1); 0,1,0; -sin(tt1) ,0,cos(tt1)];
Rz=[cos(ph1),-sin(ph1),0; sin(ph1),cos(ph1),0; 0,0,1];
Rz*Ry*Rx
}
checkrot2()={
Rx=[1,0,0; 0,cos(ps2),-sin(ps2); 0,sin(ps2),cos(ps2)];
Ry=[cos(tt2),0,sin(tt2); 0,1,0; -sin(tt2) ,0,cos(tt2)];
Rz=[cos(ph2),-sin(ph2),0; sin(ph2),cos(ph2),0; 0,0,1];
Rz*Ry*Rx
}
\\------------------------------------------------------------
\\ MAIN PROGRAM:
\\------------------------------------------------------------
\\ MAIN:
{
gr=(1+sqrt(5))/2; \\ definieer: gr = golden ratio
A=[1/gr,0,gr];
B=[-1/gr,0,gr];
\\ maak rotatiematrix M voor rotatie om OA, over 120 graden:
makematM(A,120*Pi/180);
\\ toon de Euler hoeken in graden:
printeuler(1);
\\ toon punt B na 0, 1, 2 resp. 3 rotaties M:
print(" B = ", B);
print(" M * B = ", M*B~);
print("M^2 * B = ", M^2*B~);
print("M^3 * B = ", M^3*B~);
}
Kom je hiermee verder?