55#ifndef MATH_QUATERNION_HPP
56#define MATH_QUATERNION_HPP
64#include "utils/Constants.hpp"
65#define ISZERO(a, eps) ((a) > -(eps) && (a) < (eps))
66const RealType tiny = 1.0e-6;
78 template<
typename Real>
79 class Quaternion :
public Vector<Real, 4> {
96 if (
this == &v)
return *
this;
107 Real
w()
const {
return this->data_[0]; }
113 Real&
w() {
return this->data_[0]; }
119 Real
x()
const {
return this->data_[1]; }
125 Real&
x() {
return this->data_[1]; }
131 Real
y()
const {
return this->data_[2]; }
137 Real&
y() {
return this->data_[2]; }
143 Real
z()
const {
return this->data_[3]; }
148 Real&
z() {
return this->data_[3]; }
156 for (
unsigned int i = 0; i < 4; i++) {
157 if (!
equal(this->data_[i], q[i])) {
return false; }
185 void mul(
const Quaternion<Real>& q) {
186 Quaternion<Real> tmp(*
this);
189 (tmp[0] * q[0]) - (tmp[1] * q[1]) - (tmp[2] * q[2]) - (tmp[3] * q[3]);
191 (tmp[0] * q[1]) + (tmp[1] * q[0]) + (tmp[2] * q[3]) - (tmp[3] * q[2]);
193 (tmp[0] * q[2]) + (tmp[2] * q[0]) + (tmp[3] * q[1]) - (tmp[1] * q[3]);
195 (tmp[0] * q[3]) + (tmp[3] * q[0]) + (tmp[1] * q[2]) - (tmp[2] * q[1]);
198 void mul(
const Real& s) {
209 void div(
const Real& s) {
216 Quaternion<Real>& operator*=(
const Quaternion<Real>& q) {
221 Quaternion<Real>& operator*=(
const Real& s) {
226 Quaternion<Real>& operator/=(Quaternion<Real>& q) {
227 *
this *= q.inverse();
231 Quaternion<Real>& operator/=(
const Real& s) {
240 return Quaternion<Real>(
w(), -
x(), -
y(), -
z());
248 return 2.0 * atan2(-sqrt(
x() *
x() +
y() *
y() +
z() *
z()), -
w());
250 return 2.0 * atan2(sqrt(
x() *
x() +
y() *
y() +
z() *
z()),
w());
260 Real half_angle = angle * 0.5;
261 Real sin_a = sin(half_angle);
262 *
this = Quaternion<Real>(cos(half_angle), v.
x() * sin_a, v.
y() * sin_a,
272 Real vl = sqrt(
x() *
x() +
y() *
y() +
z() *
z());
275 axis.
x() =
x() * ivl;
276 axis.
y() =
y() * ivl;
277 axis.
z() =
z() * ivl;
280 angle = 2.0 * atan2(-vl, -
w());
282 angle = 2.0 * atan2(vl,
w());
294 Vector3d c(
cross(from, to));
295 *
this = Quaternion<Real>(
dot(from, to), c.x(), c.y(), c.z());
300 if ((from.
z() * from.
z()) > (from.
x() * from.
x())) {
301 this->data_[0] =
w();
302 this->data_[1] = 0.0;
303 this->data_[2] = from.
z();
304 this->data_[3] = -from.
y();
306 this->data_[0] =
w();
307 this->data_[1] = from.
y();
308 this->data_[2] = -from.
x();
309 this->data_[3] = 0.0;
316 return (Real)2.0 * atan2(q.
z(), q.
w());
319 void RemoveTwist(Quaternion& q) {
320 Real t = ComputeTwist(q);
326 void getTwistSwingAxisAngle(Real& twistAngle, Real& swingAngle,
327 Vector3<Real>& swingAxis) {
328 twistAngle = (Real)2.0 * atan2(
z(),
w());
330 rt.fromAxisAngle(V3Z, twistAngle);
331 rs = *
this * rt.inverse();
333 Real vl = sqrt(rs.x() * rs.x() + rs.y() * rs.y() + rs.z() * rs.z());
336 swingAxis.x() = rs.x() * ivl;
337 swingAxis.y() = rs.y() * ivl;
338 swingAxis.z() = rs.z() * ivl;
341 swingAngle = 2.0 * atan2(-vl, -rs.w());
343 swingAngle = 2.0 * atan2(vl, rs.w());
345 swingAxis = Vector3<Real>(1.0, 0.0, 0.0);
350 Vector3<Real> rotate(
const Vector3<Real>& v) {
351 Quaternion<Real> q(v.x() *
w() + v.z() *
y() - v.y() *
z(),
352 v.y() *
w() + v.x() *
z() - v.z() *
x(),
353 v.z() *
w() + v.y() *
x() - v.x() *
y(),
354 v.x() *
x() + v.y() *
y() + v.z() *
z());
356 return Vector3<Real>(
357 w() * q.x() +
x() * q.w() +
y() * q.z() -
z() * q.y(),
358 w() * q.y() +
y() * q.w() +
z() * q.x() -
x() * q.z(),
359 w() * q.z() +
z() * q.w() +
x() * q.y() -
y() * q.x()) *
363 Quaternion<Real>& align(
const Vector3<Real>& V1,
const Vector3<Real>& V2) {
388 Vector3<Real> Bisector = V1 + V2;
389 Bisector.normalize();
391 Real CosHalfAngle =
dot(V1, Bisector);
393 this->data_[0] = CosHalfAngle;
395 if (CosHalfAngle != (Real)0.0) {
396 Vector3<Real> Cross =
cross(V1, Bisector);
397 this->data_[1] = Cross.x();
398 this->data_[2] = Cross.y();
399 this->data_[3] = Cross.z();
402 if (fabs(V1[0]) >= fabs(V1[1])) {
404 InvLength = (Real)1.0 / sqrt(V1[0] * V1[0] + V1[2] * V1[2]);
406 this->data_[1] = -V1[2] * InvLength;
407 this->data_[2] = (Real)0.0;
408 this->data_[3] = +V1[0] * InvLength;
411 InvLength = (Real)1.0 / sqrt(V1[1] * V1[1] + V1[2] * V1[2]);
413 this->data_[1] = (Real)0.0;
414 this->data_[2] = +V1[2] * InvLength;
415 this->data_[3] = -V1[1] * InvLength;
421 void toTwistSwing(Real& tw, Real& sx, Real& sy) {
424 if (ISZERO(
z(), tiny) && ISZERO(
w(), tiny)) {
425 sx = sy = Constants::PI;
464 Real t = atan2(qz, qw);
466 atan2(sqrt(qx * qx + qy * qy), sqrt(qz * qz + qw * qw));
469 Real
x = 0.0,
y = 0.0, sins = sin(s);
471 if (!ISZERO(sins, tiny)) {
476 y = (-qx * sint + qy * cost) / sins;
477 x = (qx * cost + qy * sint) / sins;
481 sx = (Real)2.0 *
x * s;
482 sy = (Real)2.0 *
y * s;
485 void toSwingTwist(Real& sx, Real& sy, Real& tw) {
489 if (ISZERO(
z(), tiny) && ISZERO(
w(), tiny)) {
490 sx = sy = Constants::PI;
508 Real t = 2.0 * atan2(qz, qw);
510 Real bet = atan2(sqrt(qx * qx + qy * qy), sqrt(qz * qz + qw * qw));
512 Real sinc = ISZERO(bet, tiny) ? 1.0 : sin(bet) / bet;
513 Real singam = sin(gam);
514 Real cosgam = cos(gam);
516 sx = Real((2.0 / sinc) * (cosgam * qx - singam * qy));
517 sy = Real((2.0 / sinc) * (singam * qx + cosgam * qy));
540 rotMat3(0, 0) = w2 + x2 - y2 - z2;
541 rotMat3(0, 1) = 2.0 * (
x() *
y() +
w() *
z());
542 rotMat3(0, 2) = 2.0 * (
x() *
z() -
w() *
y());
544 rotMat3(1, 0) = 2.0 * (
x() *
y() -
w() *
z());
545 rotMat3(1, 1) = w2 - x2 + y2 - z2;
546 rotMat3(1, 2) = 2.0 * (
y() *
z() +
w() *
x());
548 rotMat3(2, 0) = 2.0 * (
x() *
z() +
w() *
y());
549 rotMat3(2, 1) = 2.0 * (
y() *
z() -
w() *
x());
550 rotMat3(2, 2) = w2 - x2 - y2 + z2;
563 template<
typename Real,
unsigned int Dim>
576 template<
typename Real,
unsigned int Dim>
589 template<
typename Real>
603 template<
typename Real>
616 template<
typename Real>
625 inline bool operator==(
const Quaternion<T>& lhs,
const Quaternion<T>& rhs) {
626 return equal(lhs[0], rhs[0]) &&
equal(lhs[1], rhs[1]) &&
627 equal(lhs[2], rhs[2]) &&
equal(lhs[3], rhs[3]);
Quaternion is a sort of a higher-level complex number.
Quaternion(const Vector< Real, 4 > &v)
Constructs and initializes a Quaternion from a Vector<Real,4>.
SquareMatrix< Real, 3 > toRotationMatrix3()
Returns the corresponding rotation matrix (3x3).
Real & z()
Returns the reference of the fourth element of this quaternion.
Quaternion< Real > fromAxisAngle(const Vector3< Real > &axis, const Real &angle)
create a unit quaternion from axis angle representation
void div(Quaternion< Real > &q)
Set the value of this quaternion to the division of itself by another quaternion.
Quaternion< Real > conjugate() const
Returns the conjugate quaternion of this quaternion.
Quaternion(Real w, Real x, Real y, Real z)
Constructs and initializes a Quaternion from w, x, y, z values.
bool operator==(const Quaternion< Real > &q)
Tests if this quaternion is equal to other quaternion.
void toAxisAngle(Vector3< Real > &axis, Real &angle) const
convert a quaternion to axis angle representation, preserve the axis direction and angle from -PI to ...
Real & y()
Returns the reference of the third element of this quaternion.
Real & w()
Returns the reference of the first element of this quaternion.
Quaternion< Real > fromShortestArc(const Vector3d &from, const Vector3d &to)
shortest arc quaternion rotate one vector to another by shortest path.
Quaternion & operator=(const Vector< Real, 4 > &v)
copy assignment
Real & x()
Returns the reference of the second element of this quaternion.
Quaternion< Real > inverse()
Returns the inverse of this quaternion.
Real get_rotation_angle() const
return rotation angle from -PI to PI
void mul(const Quaternion< Real > &q)
Sets the value to the multiplication of itself and another quaternion.
Real & z()
Returns reference of the third element of Vector3.
Real & x()
Returns reference of the first element of Vector3.
Real & y()
Returns reference of the second element of Vector3.
Vector< Real, Dim > & operator=(const Vector< Real, Dim > &v)
copy assignment operator
void normalize()
Normalizes this vector in place.
Real lengthSquare() const
bool isNormalized() const
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
bool equal(const Polynomial< Real > &p1, const Polynomial< Real > &p2)
Tests if two polynomial have the same exponents.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
DynamicRectMatrix< Real > operator*(const DynamicRectMatrix< Real > &m, Real s)
Return the multiplication of scalar and matrix (m * s).
DynamicRectMatrix< Real > operator/(const DynamicRectMatrix< Real > &m, Real s)
Return the scalar division of matrix (m / s).