Math-SO3
view release on metacpan or search on metacpan
# Note that this trick does not work with an angle of 180 degrees;
# here, we take an arbitrary vector and its rotated image and compute the
# normalized sum. Take a different vector if norm is zero. There are
# cases when we must do this three times.
#
# XXX have to put a bit more thought into this. Does it really work that way,
# or did I still miss a point?
void
turning_angle_and_dir(...)
PPCODE:
{
double angle, *dir, v2[3], v3[3], norm;
char *cdir;
if( (items!=1 && items != 2)
|| SvTYPE(SvRV(ST(0)))!=SVt_PVMG
|| 0==(cdir=alloca(1+3*sizeof(double))))
{
croak(croak_turning_angle_and_dir);
}
# (1) Determine q (theta) from [2][2] element.
# (2) Determine r (psi) from [0][2] and [1][2] elements. If theta=0, we can also set psi=0.
# (Since all that remains is a z-rotation or z-rotation with 180deg x-rotation,
# both characterized by a single angle)
# (3) Do some math to determine phi from [1][0] and [1][1] elements if theta=0,
# otherwise use [2][0] and [2][1] elements.
void
euler_angles_zxz(...)
PPCODE:
{
if( (items!=1 && items!=2)
|| SvTYPE(SvRV(ST(0)))!=SVt_PVMG)
{
croak(croak_euler_angles_zxz);
}
else
{
int i;
double phi, theta, psi, cos_theta, sin_theta, cos_psi, sin_psi, sin_phi, cos_phi;
# [0][0]: cos r cos -h - sin r sin -h => cos (r-h)
# [0][2]: sin r cos -h + cos r sin -h => sin (r-h)
#
# Heading does not make sense for an airplane going straight up or straight down.
# Therefore, we take this last angle to be all roll.
#
# => heading=0, roll=atan2(sin_roll, cos_roll)
void
euler_angles_yxz(...)
PPCODE:
{
int i;
double heading, pitch, roll, cos_heading, cos_pitch, cos_roll, sin_heading, sin_pitch, sin_roll;
Math__SO3 so3;
if( (items!=1 && items!=2)
|| SvTYPE(SvRV(ST(0)))!=SVt_PVMG)
{
croak(croak_euler_angles_zxz);
}
( run in 0.819 second using v1.01-cache-2.11-cpan-5511b514fd6 )