vide_public/external/healpix/cxxsupport/rotmatrix.cc
2012-10-30 13:56:48 -04:00

177 lines
4.7 KiB
C++

/*
* This file is part of libcxxsupport.
*
* libcxxsupport is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* libcxxsupport is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libcxxsupport; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
* and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
* (DLR).
*/
/*
* Class for rotation transforms in 3D space
*
* Copyright (C) 2003 Max-Planck-Society
* Author: Martin Reinecke
*/
#include "rotmatrix.h"
#include "vec3.h"
#include "lsconstants.h"
#include <algorithm>
using namespace std;
rotmatrix::rotmatrix (const vec3 &a, const vec3 &b, const vec3 &c)
{
entry[0][0]=a.x; entry[0][1]=b.x; entry[0][2]=c.x;
entry[1][0]=a.y; entry[1][1]=b.y; entry[1][2]=c.y;
entry[2][0]=a.z; entry[2][1]=b.z; entry[2][2]=c.z;
}
void rotmatrix::SetToIdentity ()
{
entry[0][0] = entry[1][1] = entry[2][2] = 1.;
entry[0][1] = entry[1][0] = entry[0][2] =
entry[2][0] = entry[1][2] = entry[2][1] = 0.;
}
void rotmatrix::SetToZero ()
{
for (int m=0; m<3; ++m)
entry[m][0] = entry[m][1] = entry[m][2] = 0;
}
void rotmatrix::Transpose ()
{
swap(entry[0][1], entry[1][0]);
swap(entry[0][2], entry[2][0]);
swap(entry[1][2], entry[2][1]);
}
void rotmatrix::toAxisAngle (vec3 &axis, double &angle) const
{
double c2 = entry[0][0] + entry[1][1] + entry[2][2] - 1;
axis.x = entry[2][1] - entry[1][2];
axis.y = entry[0][2] - entry[2][0];
axis.z = entry[1][0] - entry[0][1];
double s2 = axis.Length();
if (s2>0)
{
angle = atan2(s2,c2);
axis *= 1/s2;
return;
}
if (c2>=2) // angle is 0
{
axis = vec3(1,0,0);
angle = 0;
return;
}
angle = pi;
int choice = 0; // assume entry[0][0] is the largest
if ((entry[1][1]>entry[0][0]) && (entry[1][1]>entry[2][2])) choice=1;
if ((entry[2][2]>entry[0][0]) && (entry[2][2]>entry[1][1])) choice=2;
if (choice==0)
{
axis.x = 0.5*sqrt(entry[0][0]-entry[1][1]-entry[2][2]+1);
double half_inv = 0.5/axis.x;
axis.y = half_inv*entry[0][1];
axis.z = half_inv*entry[0][2];
return;
}
if (choice==1)
{
axis.y = 0.5*sqrt(entry[1][1]-entry[0][0]-entry[2][2]+1);
double half_inv = 0.5/axis.y;
axis.x = half_inv*entry[0][1];
axis.z = half_inv*entry[1][2];
return;
}
axis.z = 0.5*sqrt(entry[2][2]-entry[0][0]-entry[1][1]+1);
double half_inv = 0.5/axis.z;
axis.x = half_inv*entry[0][2];
axis.y = half_inv*entry[1][2];
}
void rotmatrix::Make_CPAC_Euler_Matrix
(double alpha, double beta, double gamma)
{
double ca=cos(alpha), cb=cos(beta), cg=cos(gamma);
double sa=sin(alpha), sb=sin(beta), sg=sin(gamma);
entry[0][0]= ca*cb*cg-sa*sg; entry[0][1]=-ca*cb*sg-sa*cg; entry[0][2]= ca*sb;
entry[1][0]= sa*cb*cg+ca*sg; entry[1][1]=-sa*cb*sg+ca*cg; entry[1][2]= sa*sb;
entry[2][0]=-sb*cg; entry[2][1]= sb*sg; entry[2][2]= cb;
}
void rotmatrix::Extract_CPAC_Euler_Angles
(double &alpha, double &beta, double &gamma) const
{
double cb = entry[2][2];
double sb = sqrt(entry[0][2]*entry[0][2] + entry[1][2]*entry[1][2]);
beta=atan2(sb,cb);
if (abs(sb)<=1e-6)
{
alpha=0;
if (cb>0)
gamma=atan2(entry[1][0],entry[0][0]);
else
gamma=atan2(entry[0][1],-entry[0][0]);
}
else
{
alpha=atan2(entry[1][2],entry[0][2]);
gamma=atan2(entry[2][1],-entry[2][0]);
}
}
rotmatrix operator* (const rotmatrix &a, const rotmatrix &b)
{
rotmatrix res;
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
res.entry[i][j] = a.entry[i][0] * b.entry[0][j]
+ a.entry[i][1] * b.entry[1][j]
+ a.entry[i][2] * b.entry[2][j];
return res;
}
void TransposeTimes (const rotmatrix &a, const rotmatrix &b, rotmatrix &res)
{
for (int i=0; i<3; ++i)
for (int j=0; j<3; ++j)
res.entry[i][j] = a.entry[0][i] * b.entry[0][j]
+ a.entry[1][i] * b.entry[1][j]
+ a.entry[2][i] * b.entry[2][j];
}
ostream &operator<< (ostream &os, const rotmatrix &mat)
{
for (int i=0;i<3;++i)
os << mat.entry[i][0] << ' '
<< mat.entry[i][1] << ' '
<< mat.entry[i][2] << endl;
return os;
}