52#ifndef MATH_QUATERNION_HPP
53#define MATH_QUATERNION_HPP
61#include "utils/Constants.hpp"
62#define ISZERO(a, eps) ((a) > -(eps) && (a) < (eps))
63const RealType tiny = 1.0e-6;
75 template<
typename Real>
93 if (
this == &v)
return *
this;
104 Real
w()
const {
return this->data_[0]; }
110 Real&
w() {
return this->data_[0]; }
116 Real
x()
const {
return this->data_[1]; }
122 Real&
x() {
return this->data_[1]; }
128 Real
y()
const {
return this->data_[2]; }
134 Real&
y() {
return this->data_[2]; }
140 Real
z()
const {
return this->data_[3]; }
145 Real&
z() {
return this->data_[3]; }
153 for (
unsigned int i = 0; i < 4; i++) {
154 if (!
equal(this->data_[i], q[i])) {
return false; }
186 (tmp[0] * q[0]) - (tmp[1] * q[1]) - (tmp[2] * q[2]) - (tmp[3] * q[3]);
188 (tmp[0] * q[1]) + (tmp[1] * q[0]) + (tmp[2] * q[3]) - (tmp[3] * q[2]);
190 (tmp[0] * q[2]) + (tmp[2] * q[0]) + (tmp[3] * q[1]) - (tmp[1] * q[3]);
192 (tmp[0] * q[3]) + (tmp[3] * q[0]) + (tmp[1] * q[2]) - (tmp[2] * q[1]);
195 void mul(
const Real& s) {
206 void div(
const Real& s) {
213 Quaternion<Real>& operator*=(
const Quaternion<Real>& q) {
218 Quaternion<Real>& operator*=(
const Real& s) {
223 Quaternion<Real>& operator/=(Quaternion<Real>& q) {
224 *
this *= q.inverse();
228 Quaternion<Real>& operator/=(
const Real& s) {
245 return 2.0 * atan2(-sqrt(
x() *
x() +
y() *
y() +
z() *
z()), -
w());
247 return 2.0 * atan2(sqrt(
x() *
x() +
y() *
y() +
z() *
z()),
w());
257 Real half_angle = angle * 0.5;
258 Real sin_a = sin(half_angle);
269 Real vl = sqrt(
x() *
x() +
y() *
y() +
z() *
z());
272 axis.
x() =
x() * ivl;
273 axis.
y() =
y() * ivl;
274 axis.
z() =
z() * ivl;
277 angle = 2.0 * atan2(-vl, -
w());
279 angle = 2.0 * atan2(vl,
w());
297 if ((from.
z() * from.
z()) > (from.
x() * from.
x())) {
298 this->data_[0] =
w();
299 this->data_[1] = 0.0;
300 this->data_[2] = from.
z();
301 this->data_[3] = -from.
y();
303 this->data_[0] =
w();
304 this->data_[1] = from.
y();
305 this->data_[2] = -from.
x();
306 this->data_[3] = 0.0;
313 return (Real)2.0 * atan2(q.
z(), q.
w());
316 void RemoveTwist(Quaternion& q) {
317 Real t = ComputeTwist(q);
323 void getTwistSwingAxisAngle(Real& twistAngle, Real& swingAngle,
324 Vector3<Real>& swingAxis) {
325 twistAngle = (Real)2.0 * atan2(
z(),
w());
327 rt.fromAxisAngle(V3Z, twistAngle);
328 rs = *
this * rt.inverse();
330 Real vl = sqrt(rs.x() * rs.x() + rs.y() * rs.y() + rs.z() * rs.z());
333 swingAxis.x() = rs.x() * ivl;
334 swingAxis.y() = rs.y() * ivl;
335 swingAxis.z() = rs.z() * ivl;
338 swingAngle = 2.0 * atan2(-vl, -rs.w());
340 swingAngle = 2.0 * atan2(vl, rs.w());
342 swingAxis = Vector3<Real>(1.0, 0.0, 0.0);
347 Vector3<Real> rotate(
const Vector3<Real>& v) {
348 Quaternion<Real> q(v.x() *
w() + v.z() *
y() - v.y() *
z(),
349 v.y() *
w() + v.x() *
z() - v.z() *
x(),
350 v.z() *
w() + v.y() *
x() - v.x() *
y(),
351 v.x() *
x() + v.y() *
y() + v.z() *
z());
353 return Vector3<Real>(
354 w() * q.x() +
x() * q.w() +
y() * q.z() -
z() * q.y(),
355 w() * q.y() +
y() * q.w() +
z() * q.x() -
x() * q.z(),
356 w() * q.z() +
z() * q.w() +
x() * q.y() -
y() * q.x()) *
360 Quaternion<Real>& align(
const Vector3<Real>& V1,
const Vector3<Real>& V2) {
385 Vector3<Real> Bisector = V1 + V2;
386 Bisector.normalize();
388 Real CosHalfAngle =
dot(V1, Bisector);
390 this->data_[0] = CosHalfAngle;
392 if (CosHalfAngle != (Real)0.0) {
393 Vector3<Real> Cross =
cross(V1, Bisector);
394 this->data_[1] = Cross.x();
395 this->data_[2] = Cross.y();
396 this->data_[3] = Cross.z();
399 if (fabs(V1[0]) >= fabs(V1[1])) {
401 InvLength = (Real)1.0 / sqrt(V1[0] * V1[0] + V1[2] * V1[2]);
403 this->data_[1] = -V1[2] * InvLength;
404 this->data_[2] = (Real)0.0;
405 this->data_[3] = +V1[0] * InvLength;
408 InvLength = (Real)1.0 / sqrt(V1[1] * V1[1] + V1[2] * V1[2]);
410 this->data_[1] = (Real)0.0;
411 this->data_[2] = +V1[2] * InvLength;
412 this->data_[3] = -V1[1] * InvLength;
418 void toTwistSwing(Real& tw, Real& sx, Real& sy) {
421 if (ISZERO(
z(), tiny) && ISZERO(
w(), tiny)) {
422 sx = sy = Constants::PI;
461 Real t = atan2(qz, qw);
463 atan2(sqrt(qx * qx + qy * qy), sqrt(qz * qz + qw * qw));
466 Real
x = 0.0,
y = 0.0, sins = sin(s);
468 if (!ISZERO(sins, tiny)) {
473 y = (-qx * sint + qy * cost) / sins;
474 x = (qx * cost + qy * sint) / sins;
478 sx = (Real)2.0 *
x * s;
479 sy = (Real)2.0 *
y * s;
482 void toSwingTwist(Real& sx, Real& sy, Real& tw) {
486 if (ISZERO(
z(), tiny) && ISZERO(
w(), tiny)) {
487 sx = sy = Constants::PI;
505 Real t = 2.0 * atan2(qz, qw);
507 Real bet = atan2(sqrt(qx * qx + qy * qy), sqrt(qz * qz + qw * qw));
509 Real sinc = ISZERO(bet, tiny) ? 1.0 : sin(bet) / bet;
510 Real singam = sin(gam);
511 Real cosgam = cos(gam);
513 sx = Real((2.0 / sinc) * (cosgam * qx - singam * qy));
514 sy = Real((2.0 / sinc) * (singam * qx + cosgam * qy));
537 rotMat3(0, 0) = w2 + x2 - y2 - z2;
538 rotMat3(0, 1) = 2.0 * (
x() *
y() +
w() *
z());
539 rotMat3(0, 2) = 2.0 * (
x() *
z() -
w() *
y());
541 rotMat3(1, 0) = 2.0 * (
x() *
y() -
w() *
z());
542 rotMat3(1, 1) = w2 - x2 + y2 - z2;
543 rotMat3(1, 2) = 2.0 * (
y() *
z() +
w() *
x());
545 rotMat3(2, 0) = 2.0 * (
x() *
z() +
w() *
y());
546 rotMat3(2, 1) = 2.0 * (
y() *
z() -
w() *
x());
547 rotMat3(2, 2) = w2 - x2 - y2 + z2;
560 template<
typename Real,
unsigned int Dim>
573 template<
typename Real,
unsigned int Dim>
586 template<
typename Real>
600 template<
typename Real>
613 template<
typename Real>
622 inline bool operator==(
const Quaternion<T>& lhs,
const Quaternion<T>& rhs) {
623 return equal(lhs[0], rhs[0]) &&
equal(lhs[1], rhs[1]) &&
624 equal(lhs[2], rhs[2]) &&
equal(lhs[3], rhs[3]);
627 using Quat4d = Quaternion<RealType>;
Quaternion is a sort of a higher-level complex number.
Real x() const
Returns the value of the first element of this quaternion.
Real z() const
Returns the value of the fourth element of this quaternion.
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.
Real w() const
Returns the value of the first element 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
Real y() const
Returns the value of the thirf element of this quaternion.
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.
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).