00001
00011 #include <standard.hpp>
00012 #include <GL/gl.h>
00013 #include "Rotation.hpp"
00014
00015 Rotation::Rotation() : scaledAxis(3)
00016 {
00017
00018 }
00019
00020
00021 void Rotation::setScaledAxis(const GslVector &axis)
00022 {
00023 if (axis.getNumRows() != 3)
00024 throw Error("Rotation::setScaledAxis(): axis param must have 3 elements.");
00025
00026 scaledAxis = axis;
00027 }
00028
00029 void Rotation::setAxisAndAngleRadians(const GslVector &axis, double angle)
00030 {
00031 if (axis.getNumRows() != 3)
00032 throw Error("Rotation::setAxisAndAngleRadians(): axis param must have 3 elements.");
00033 scaledAxis = axis;
00034 scaledAxis *= angle;
00035 }
00036
00037 void Rotation::getAxisAndAngleRadians(GslVector &axis, double &angle) const
00038 {
00039 angle = scaledAxis.getLength();
00040
00041 axis = scaledAxis;
00042 axis /= angle;
00043 }
00044
00045 void axisAngleToRotation (const GslVector &axis, double angle, GslMatrix &r)
00046 {
00047 r.resize(3,3);
00048 r.setToIdentity();
00049
00050 GslMatrix skew(3,3);
00051 skew.setToZero();
00052 skew(0,0) = 0;
00053 skew(0,1) = -axis(2);
00054 skew(0,2) = +axis(1);
00055
00056 skew(1,0) = +axis(2);
00057 skew(1,1) = 0;
00058 skew(1,2) = -axis(0);
00059
00060 skew(2,0) = -axis(1);
00061 skew(2,1) = +axis(0);
00062 skew(2,2) = 0;
00063
00064 r += skew * sin(angle);
00065 r += (skew * skew) * (1-cos(angle));
00066 }
00067
00068
00069 void Rotation::getMatrix(GslMatrix & rotationMatrix)
00070 {
00071 GslVector axis;
00072 double angle;
00073
00074 getAxisAndAngleRadians(axis, angle);
00075 axisAngleToRotation(axis, angle, rotationMatrix);
00076 }
00077
00078 void orthogonalizeMatrix (GslMatrix &m)
00079 {
00080 assert (m.getNumRows() == 3 && m.getNumCols() == 3);
00081
00082 GslMatrix u(3,3), v(3,3);
00083 GslVector s(3);
00084
00085 m.SingularValueDecomposition(u,s,v);
00086 m = u * v.getTranspose();
00087 }
00088
00089 void rotationMatrixToQuaternion (const GslMatrix &m, double &x, double &y, double &z, double &w)
00090 {
00091 double trace = m.getTrace();
00092 if (trace > 0)
00093 {
00094 w = sqrt(trace + 1.) / 2.;
00095 double divisor = 1. / (4. * w);
00096 x = (m(2,1)-m(1,2)) * divisor;
00097 y = (m(0,2)-m(2,0)) * divisor;
00098 z = (m(1,0)-m(0,1)) * divisor;
00099 }
00100 else if (m(0,0) > m(1,1) && m(0,0) > m(2,2))
00101 {
00102 x = sqrt(m(0,0) - m(1,1) - m(2,2) + 1.) * .5;
00103 double divisor = 1. / (4. * x);
00104 y = (m(0,1) + m(1,0)) * divisor;
00105 z = (m(0,2) + m(2,0)) * divisor;
00106 w = (m(2,1) - m(1,2)) * divisor;
00107 }
00108 else if (m(1,1) > m(2,2))
00109 {
00110 y = sqrt(m(1,1) - m(0,0) - m(2,2) + 1.) * .5;
00111 double divisor = 1. / (4. * y);
00112 x = (m(0,1) + m(1,0)) * divisor;
00113 w = (m(0,2) - m(2,0)) * divisor;
00114 z = (m(1,2) + m(2,1)) * divisor;
00115 }
00116 else
00117 {
00118 z = sqrt(m(2,2) - m(0,0) - m(1,1) + 1.) * .5;
00119 double divisor = 1. / (4. * z);
00120 w = (m(1,0) - m(0,1)) * divisor;
00121 x = (m(0,2) + m(2,0)) * divisor;
00122 y = (m(1,2) + m(2,1)) * divisor;
00123 }
00124 }
00125
00126 void quaternionToAxisAngle (double x, double y, double z, double w, GslVector &axis, double &angle)
00127 {
00128 if (fabs(w) < 1)
00129 {
00130 angle = 2.*acos(w);
00131 double divisor = 1./sqrt(1.-w*w);
00132 axis(0) = x*divisor;
00133 axis(1) = y*divisor;
00134 axis(2) = z*divisor;
00135 }
00136 else
00137 {
00138 axis.setToZero();
00139 axis(0) = 1;
00140 angle = 0;
00141 }
00142 }
00143
00144
00145 void Rotation::setMatrix(GslMatrix rotationMatrix)
00146 {
00147 if (rotationMatrix.getNumRows() != 3 ||
00148 rotationMatrix.getNumCols() != 3)
00149 {
00150 throw Error("Rotation::setMatrix(): rotationMatrix param must be 3x3.");
00151 }
00152
00153
00154
00155 orthogonalizeMatrix (rotationMatrix);
00156
00157
00158
00159
00160
00161 double angle;
00162 double x,y,z,w;
00163 rotationMatrixToQuaternion(rotationMatrix, x, y, z, w);
00164 quaternionToAxisAngle(x,y,z,w,scaledAxis,angle);
00165 scaledAxis *= angle;
00166 }