24 #include "quaternion.h"
28 using namespace qglviewer;
37 const double epsilon = 1E-10f;
42 if ((fromSqNorm < epsilon) || (toSqNorm < epsilon))
49 Vec axis = cross(from, to);
53 if (axisSqNorm < epsilon)
56 double angle = asin(sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
61 setAxisAngle(axis, angle);
70 return inverse().rotate(v);
78 const double q00 = 2.0l * q[0] * q[0];
79 const double q11 = 2.0l * q[1] * q[1];
80 const double q22 = 2.0l * q[2] * q[2];
82 const double q01 = 2.0l * q[0] * q[1];
83 const double q02 = 2.0l * q[0] * q[2];
84 const double q03 = 2.0l * q[0] * q[3];
86 const double q12 = 2.0l * q[1] * q[2];
87 const double q13 = 2.0l * q[1] * q[3];
89 const double q23 = 2.0l * q[2] * q[3];
91 return Vec((1.0 - q11 - q22)*v[0] + ( q01 - q23)*v[1] + ( q02 + q13)*v[2],
92 ( q01 + q23)*v[0] + (1.0 - q22 - q00)*v[1] + ( q12 - q03)*v[2],
93 ( q02 - q13)*v[0] + ( q12 + q03)*v[1] + (1.0 - q11 - q00)*v[2] );
104 void Quaternion::setFromRotationMatrix(
const double m[3][3])
107 const double onePlusTrace = 1.0 + m[0][0] + m[1][1] + m[2][2];
109 if (onePlusTrace > 1E-5)
112 const double s = sqrt(onePlusTrace) * 2.0;
113 q[0] = (m[2][1] - m[1][2]) / s;
114 q[1] = (m[0][2] - m[2][0]) / s;
115 q[2] = (m[1][0] - m[0][1]) / s;
121 if ((m[0][0] > m[1][1])&(m[0][0] > m[2][2]))
123 const double s = sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]) * 2.0;
125 q[1] = (m[0][1] + m[1][0]) / s;
126 q[2] = (m[0][2] + m[2][0]) / s;
127 q[3] = (m[1][2] - m[2][1]) / s;
130 if (m[1][1] > m[2][2])
132 const double s = sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]) * 2.0;
133 q[0] = (m[0][1] + m[1][0]) / s;
135 q[2] = (m[1][2] + m[2][1]) / s;
136 q[3] = (m[0][2] - m[2][0]) / s;
140 const double s = sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]) * 2.0;
141 q[0] = (m[0][2] + m[2][0]) / s;
142 q[1] = (m[1][2] + m[2][1]) / s;
144 q[3] = (m[0][1] - m[1][0]) / s;
151 void Quaternion::setFromRotationMatrix(
const float m[3][3])
153 qWarning(
"setFromRotationMatrix now waits for a double[3][3] parameter");
156 for (
int i=0; i<3; ++i)
157 for (
int j=0; j<3; ++j)
158 mat[i][j] =
double(m[i][j]);
160 setFromRotationMatrix(mat);
163 void Quaternion::setFromRotatedBase(
const Vec& X,
const Vec& Y,
const Vec& Z)
165 qWarning(
"setFromRotatedBase is deprecated, use setFromRotatedBasis instead");
166 setFromRotatedBasis(X,Y,Z);
185 double normX = X.
norm();
186 double normY = Y.
norm();
187 double normZ = Z.
norm();
189 for (
int i=0; i<3; ++i)
191 m[i][0] = X[i] / normX;
192 m[i][1] = Y[i] / normY;
193 m[i][2] = Z[i] / normZ;
196 setFromRotationMatrix(m);
203 angle = 2.0*acos(q[3]);
204 axis =
Vec(q[0], q[1], q[2]);
205 const double sinus = axis.
norm();
211 angle = 2.0*M_PI - angle;
221 Vec res =
Vec(q[0], q[1], q[2]);
222 const double sinus = res.
norm();
225 return (acos(q[3]) <= M_PI/2.0) ? res : -res;
236 const double angle = 2.0 * acos(q[3]);
237 return (angle <= M_PI) ? angle : 2.0*M_PI - angle;
258 QDomElement de = document.createElement(name);
259 de.setAttribute(
"q0", QString::number(q[0]));
260 de.setAttribute(
"q1", QString::number(q[1]));
261 de.setAttribute(
"q2", QString::number(q[2]));
262 de.setAttribute(
"q3", QString::number(q[3]));
288 QStringList attribute;
289 attribute <<
"q0" <<
"q1" <<
"q2" <<
"q3";
290 #if QT_VERSION >= 0x040000
291 for (
int i=0; i<attribute.size(); ++i)
293 for (
unsigned int i=0; i<attribute.count(); ++i)
295 q[i] = DomUtils::doubleFromDom(element, attribute[i], ((i<3)?0.0f:1.0f));
312 static GLdouble m[4][4];
314 return (
const GLdouble*)(m);
323 const double q00 = 2.0l * q[0] * q[0];
324 const double q11 = 2.0l * q[1] * q[1];
325 const double q22 = 2.0l * q[2] * q[2];
327 const double q01 = 2.0l * q[0] * q[1];
328 const double q02 = 2.0l * q[0] * q[2];
329 const double q03 = 2.0l * q[0] * q[3];
331 const double q12 = 2.0l * q[1] * q[2];
332 const double q13 = 2.0l * q[1] * q[3];
334 const double q23 = 2.0l * q[2] * q[3];
336 m[0][0] = 1.0l - q11 - q22;
341 m[1][1] = 1.0l - q22 - q00;
346 m[2][2] = 1.0l - q11 - q00;
361 static GLdouble mat[4][4];
364 for (
int i=0; i<4; ++i)
365 for (
int j=0; j<4; ++j)
366 m[count++] = mat[i][j];
377 static GLdouble mat[4][4];
379 for (
int i=0; i<3; ++i)
380 for (
int j=0; j<3; ++j)
395 static GLdouble m[4][4];
397 return (
const GLdouble*)(m);
406 inverse().getMatrix(m);
412 inverse().getMatrix(m);
421 static GLdouble mat[4][4];
422 getInverseMatrix(mat);
423 for (
int i=0; i<3; ++i)
424 for (
int j=0; j<3; ++j)
443 if ((1.0 - fabs(cosAngle)) < 0.01)
451 double angle = acos(fabs(cosAngle));
452 double sinAngle = sin(angle);
453 c1 = sin(angle * (1.0 - t)) / sinAngle;
454 c2 = sin(angle * t) / sinAngle;
458 if (allowFlip && (cosAngle < 0.0))
461 return Quaternion(c1*a[0] + c2*b[0], c1*a[1] + c2*b[1], c1*a[2] + c2*b[2], c1*a[3] + c2*b[3]);
481 double len = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
487 double coef = acos(q[3]) / len;
488 return Quaternion(q[0]*coef, q[1]*coef, q[2]*coef, 0.0);
495 double theta = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
498 return Quaternion(q[0], q[1], q[2], cos(theta));
501 double coef = sin(theta) / theta;
502 return Quaternion(q[0]*coef, q[1]*coef, q[2]*coef, cos(theta));
522 for (
int i=0; i<4; ++i)
523 e.q[i] = -0.25 * (l1.q[i] + l2.q[i]);
524 e = center*(e.
exp());
532 ostream& operator<<(ostream& o,
const Quaternion& Q)
534 return o << Q[0] <<
'\t' << Q[1] <<
'\t' << Q[2] <<
'\t' << Q[3];
550 double seed = rand()/(double)RAND_MAX;
551 double r1 = sqrt(1.0 - seed);
552 double r2 = sqrt(seed);
553 double t1 = 2.0 * M_PI * (rand()/(double)RAND_MAX);
554 double t2 = 2.0 * M_PI * (rand()/(double)RAND_MAX);
555 return Quaternion(sin(t1)*r1, cos(t1)*r1, sin(t2)*r2, cos(t2)*r2);