OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Quaternion.cpp
Go to the documentation of this file.
2 #include "AppTypes/Tenzor.h"
3 #include "Physics/Physics.h"
6 
7 namespace {
8  Vector_t normalize(const Vector_t & vec)
9  {
10  double length = std::sqrt(dot(vec, vec));
11 
12 #ifndef NOPAssert
13  if (length < 1e-12)
14  throw GeneralClassicException("normalize()",
15  "length of vector less than 1e-12");
16 #endif
17 
18  return vec / length;
19  }
20 }
21 
23  Vektor<double, 4>(0.0)
24 {
25  (*this)(0) = std::sqrt(std::max(0.0, 1 + M(0, 0) + M(1, 1) + M(2, 2))) / 2;
26  (*this)(1) = std::sqrt(std::max(0.0, 1 + M(0, 0) - M(1, 1) - M(2, 2))) / 2;
27  (*this)(2) = std::sqrt(std::max(0.0, 1 - M(0, 0) + M(1, 1) - M(2, 2))) / 2;
28  (*this)(3) = std::sqrt(std::max(0.0, 1 - M(0, 0) - M(1, 1) + M(2, 2))) / 2;
29  (*this)(1) = std::abs(M(2, 1) - M(1, 2)) > 0? std::copysign((*this)(1), M(2, 1) - M(1, 2)): 0.0;
30  (*this)(2) = std::abs(M(0, 2) - M(2, 0)) > 0? std::copysign((*this)(2), M(0, 2) - M(2, 0)): 0.0;
31  (*this)(3) = std::abs(M(1, 0) - M(0, 1)) > 0? std::copysign((*this)(3), M(1, 0) - M(0, 1)): 0.0;
32 }
33 
35 {
36  const double tol = 1e-12;
37 
38  u = normalize(u);
39  ref = normalize(ref);
40 
41  Vector_t axis = cross(u, ref);
42  double normAxis = std::sqrt(dot(axis,axis));
43 
44  if (normAxis < tol) {
45  if (std::abs(dot(u, ref) - 1.0) < tol) {
46  return Quaternion(1.0, Vector_t(0.0));
47  }
48  // vectors are parallel or antiparallel
49  do { // find any vector in plane with ref as normal
50  double u = IpplRandom();
51  double v = 2 * Physics::pi * IpplRandom();
52  axis(0) = std::sqrt(1 - u*u) * std::cos(v);
53  axis(1) = std::sqrt(1 - u*u) * std::sin(v);
54  axis(2) = u;
55  } while(std::abs(dot(axis, ref)) > 0.9);
56 
57  axis -= dot(axis, ref) * ref;
58  axis = normalize(axis);
59 
60  return Quaternion(0, axis);
61  }
62 
63  axis /= normAxis;
64 
65  double cosAngle = sqrt(0.5 * (1 + dot(u, ref)));
66  double sinAngle = sqrt(1 - cosAngle * cosAngle);
67 
68  return Quaternion(cosAngle, sinAngle * axis);
69 }
70 
71 Quaternion Quaternion::operator*(const double & d) const
72 {
73  Quaternion result(d * this->real(), d * this->imag());
74 
75  return result;
76 }
77 
79 {
80  Quaternion result(*this);
81  return result *= other;
82 }
83 
85 {
86  Vector_t imagThis = this->imag();
87  Vector_t imagOther = other.imag();
88 
89  *this = Quaternion((*this)(0) * other(0) - dot(imagThis, imagOther),
90  (*this)(0) * imagOther + other(0) * imagThis + cross(imagThis, imagOther));
91 
92  return *this;
93 }
94 
95 Quaternion Quaternion::operator/(const double & d) const
96 {
97  Quaternion result(this->real() / d, this->imag() / d);
98 
99  return result;
100 }
101 
103 {
104 #ifndef NOPAssert
105  if (this->Norm() < 1e-12)
106  throw GeneralClassicException("Quaternion::normalize()",
107  "length of quaternion less than 1e-12");
108 #endif
109 
110  (*this) /= this->length();
111 
112  return (*this);
113 }
114 
116 {
117  Quaternion returnValue = conjugate();
118 
119  return returnValue.normalize();
120 }
121 
123 {
124 #ifndef NOPAssert
125  if (!this->isUnit())
126  throw GeneralClassicException("Quaternion::rotate()",
127  "quaternion isn't unit quaternion. Norm: " + std::to_string(this->Norm()));
128 #endif
129 
130  Quaternion quat(vec);
131 
132  return ((*this) * (quat * (*this).conjugate())).imag();
133 }
134 
136 {
137  Quaternion rot(*this);
138  rot.normalize();
139  Tenzor<double, 3> mat(1 - 2 * (rot(2) * rot(2) + rot(3) * rot(3)),
140  2 * (-rot(0) * rot(3) + rot(1) * rot(2)),
141  2 * (rot(0) * rot(2) + rot(1) * rot(3)),
142  2 * (rot(0) * rot(3) + rot(1) * rot(2)),
143  1 - 2 * (rot(1) * rot(1) + rot(3) * rot(3)),
144  2 * (-rot(0) * rot(1) + rot(2) * rot(3)),
145  2 * (-rot(0) * rot(2) + rot(1) * rot(3)),
146  2 * (rot(0) * rot(1) + rot(2) * rot(3)),
147  1 - 2 * (rot(1) * rot(1) + rot(2) * rot(2)));
148 
149  return mat;
150 }
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
Quaternion getQuaternion(Vector_t u, Vector_t ref)
Definition: Quaternion.cpp:34
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
Definition: Vector3D.cpp:111
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
RandomNumberGen IpplRandom
constexpr double e
The value of.
Definition: Physics.h:39
constexpr double pi
The value of.
Definition: Physics.h:30
Quaternion & normalize()
Definition: Quaternion.cpp:102
Vector_t rotate(const Vector_t &) const
Definition: Quaternion.cpp:122
double real() const
Definition: Quaternion.h:113
Quaternion conjugate() const
Definition: Quaternion.h:105
Quaternion inverse() const
Definition: Quaternion.cpp:115
Tenzor< double, 3 > getRotationMatrix() const
Definition: Quaternion.cpp:135
Quaternion & operator*=(const Quaternion &)
Definition: Quaternion.cpp:84
Quaternion operator/(const double &) const
Definition: Quaternion.cpp:95
Vector_t imag() const
Definition: Quaternion.h:119
bool isUnit() const
Definition: Quaternion.h:87
Quaternion operator*(const double &) const
Definition: Quaternion.cpp:71
double length() const
Definition: Quaternion.h:81
double Norm() const
Definition: Quaternion.h:75
Definition: Vec.h:22
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6