opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
qua.h
Go to the documentation of this file.
1#pragma once
2
10
11#include <cstddef>
12#include <ostream>
13#include <sstream>
14#include <string>
15#include <tuple>
16#include <utility>
17
18namespace osc
19{
20 // a 3D (4-element) quaternion: usually used to represent rotations
21 template<typename T>
22 struct Qua {
23 using value_type = T;
26 using reference = T&;
27 using const_reference = const T&;
28 using pointer = T*;
29 using const_pointer = const T*;
30 using iterator = T*;
31 using const_iterator = const T*;
32 using type = Qua<T>;
33
34 static constexpr Qua<T> wxyz(T w, T x, T y, T z) { return Qua<T>(w, x, y, z); }
35
36 // default-constructs a `Qua` with an identity transform
37 constexpr Qua() = default;
38
39 // constructs a `Qua` with `w = s` and the xyz of `v`
40 constexpr Qua(T s, const Vector<T, 3>& v) :
41 w{s}, x{v.x()}, y{v.y()}, z{v.z()}
42 {}
43
44 // constructs a `Qua` from its wxyz components
45 constexpr Qua(T w_, T x_, T y_, T z_) :
46 w{w_}, x{x_}, y{y_}, z{z_}
47 {}
48
49 // constructs a `Qua` by `static_cast<T>`ing each element in `q`
50 template<typename U>
51 explicit constexpr Qua(const Qua<U>& q) :
52 w{static_cast<T>(q.w)},
53 x{static_cast<T>(q.x)},
54 y{static_cast<T>(q.y)},
55 z{static_cast<T>(q.z)}
56 {}
57
65 {
66 T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v));
69
70 if(real_part < static_cast<T>(1.e-6f) * norm_u_norm_v) {
71 // If u and v are exactly opposite, rotate 180 degrees
72 // around an arbitrary orthogonal axis. Axis normalisation
73 // can happen later, when we normalise the quaternion.
74 real_part = static_cast<T>(0);
75 t = abs(u.x()) > abs(u.z()) ? Vector<T, 3>(-u.y(), u.x(), static_cast<T>(0)) : Vector<T, 3>(static_cast<T>(0), -u.z(), u.y());
76 }
77 else {
78 // Otherwise, build quaternion the standard way.
79 t = cross(u, v);
80 }
81
82 *this = normalize(Qua<T>::wxyz(real_part, t.x(), t.y(), t.z()));
83 }
84
85 // constructs a `Qua` from Euler angles that are assumed to represent an
86 // intrinsic, step-by-step, rotation about X, Y, and then Z
87 explicit Qua(const EulerAngles& euler_angles)
88 {
90 Vector<T, 3> s = sin(euler_angles * T(0.5));
91
92 this->w = c.x() * c.y() * c.z() + s.x() * s.y() * s.z();
93 this->x = s.x() * c.y() * c.z() - c.x() * s.y() * s.z();
94 this->y = c.x() * s.y() * c.z() + s.x() * c.y() * s.z();
95 this->z = c.x() * c.y() * s.z() - s.x() * s.y() * c.z();
96 }
97
98 // constructs a `Qua` by decomposing an orthogonal matrix
99 explicit Qua(const Matrix<T, 3, 3>& m)
100 {
101 *this = quaternion_cast(m);
102 }
103
104 // constructs a `Qua` by decomposing an orthogonal matrix
105 explicit Qua(const Matrix<T, 4, 4>& m)
106 {
107 *this = quaternion_cast(m);
108 }
109
110 constexpr size_type size() const { return 4; }
111 constexpr pointer data() { return &w; }
112 constexpr const_pointer data() const { return &w; }
113 constexpr iterator begin() { return data(); }
114 constexpr const_iterator begin() const { return data(); }
115 constexpr iterator end() { return data() + size(); }
116 constexpr const_iterator end() const { return data() + size(); }
117 constexpr reference operator[](size_type pos) { return begin()[pos]; }
118 constexpr const_reference operator[](size_type pos) const { return begin()[pos]; }
119
120 friend constexpr bool operator==(const Qua&, const Qua&) = default;
121
122 template<typename U>
123 constexpr Qua<T>& operator=(const Qua<U>& q)
124 {
125 this->w = static_cast<T>(q.w);
126 this->x = static_cast<T>(q.x);
127 this->y = static_cast<T>(q.y);
128 this->z = static_cast<T>(q.z);
129 return *this;
130 }
131
132 template<typename U>
133 constexpr Qua<T>& operator+=(const Qua<U>& q)
134 {
135 this->w += static_cast<T>(q.w);
136 this->x += static_cast<T>(q.x);
137 this->y += static_cast<T>(q.y);
138 this->z += static_cast<T>(q.z);
139 return *this;
140 }
141
142 template<typename U>
143 constexpr Qua<T>& operator-=(const Qua<U>& q)
144 {
145 this->w -= static_cast<T>(q.w);
146 this->x -= static_cast<T>(q.x);
147 this->y -= static_cast<T>(q.y);
148 this->z -= static_cast<T>(q.z);
149 return *this;
150 }
151
152 template<typename U>
153 constexpr Qua<T>& operator*=(const Qua<U>& r)
154 {
155 const Qua<T> p(*this);
156 const Qua<T> q(r);
157 this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z;
158 this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y;
159 this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z;
160 this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x;
161 return *this;
162 }
163
164 template<typename U>
165 constexpr Qua<T>& operator*=(U s)
166 {
167 this->w *= static_cast<T>(s);
168 this->x *= static_cast<T>(s);
169 this->y *= static_cast<T>(s);
170 this->z *= static_cast<T>(s);
171 return *this;
172 }
173
174 template<typename U>
175 constexpr Qua<T>& operator/=(U s)
176 {
177 this->w /= static_cast<T>(s);
178 this->x /= static_cast<T>(s);
179 this->y /= static_cast<T>(s);
180 this->z /= static_cast<T>(s);
181 return *this;
182 }
183
184 T w = T(1);
185 T x = T{};
186 T y = T{};
187 T z = T{};
188 };
189
190 template<typename T>
191 constexpr Qua<T> operator+(const Qua<T>& q)
192 {
193 return q;
194 }
195
196 template<typename T>
197 constexpr Qua<T> operator-(const Qua<T>& q)
198 {
199 return Qua<T>::wxyz(-q.w, -q.x, -q.y, -q.z);
200 }
201
202 template<typename T>
203 constexpr Qua<T> operator+(const Qua<T>& q, const Qua<T>& p)
204 {
205 return Qua<T>(q) += p;
206 }
207
208 template<typename T>
209 constexpr Qua<T> operator-(const Qua<T>& q, const Qua<T>& p)
210 {
211 return Qua<T>(q) -= p;
212 }
213
214 template<typename T>
215 constexpr Qua<T> operator*(const Qua<T>& q, const Qua<T>& p)
216 {
217 return Qua<T>(q) *= p;
218 }
219
220 template<typename T>
221 constexpr Vector<T, 3> operator*(const Qua<T>& q, const Vector<T, 3>& v)
222 {
223 const Vector<T, 3> qvector(q.x, q.y, q.z);
224 const Vector<T, 3> uv(cross(qvector, v));
226
227 return v + ((uv * q.w) + uuv) * static_cast<T>(2);
228 }
229
230 template<typename T>
231 constexpr Vector<T, 3> operator*(const Vector<T, 3>& v, const Qua<T>& q)
232 {
233 return inverse(q) * v;
234 }
235
236 template<typename T>
237 constexpr Vector<T, 4> operator*(const Qua<T>& q, const Vector<T, 4>& v)
238 {
239 return Vector<T, 4>(q * Vector<T, 3>(v), v.w);
240 }
241
242 template<typename T>
243 constexpr Vector<T, 4> operator*(const Vector<T, 4>& v, const Qua<T>& q)
244 {
245 return inverse(q) * v;
246 }
247
248 template<typename T>
249 constexpr Qua<T> operator*(const Qua<T>& q, const T& s)
250 {
251 return Qua<T>::wxyz(q.w * s, q.x * s, q.y * s, q.z * s);
252 }
253
254 template<typename T>
255 constexpr Qua<T> operator*(const T& s, const Qua<T>& q)
256 {
257 return q * s;
258 }
259
260 template<typename T>
261 constexpr Qua<T> operator/(const Qua<T>& q, const T& s)
262 {
263 return Qua<T>::wxyz(q.w / s, q.x / s, q.y / s, q.z / s);
264 }
265
266 template<typename T>
267 std::ostream& operator<<(std::ostream& o, const Qua<T>& v)
268 {
269 return o << "Quaternion(" << v.w << ", " << v.x << ", " << v.y << ", " << v.z << ')';
270 }
271
272 template<typename T>
273 std::string to_string(const Qua<T>& v)
274 {
275 std::stringstream ss;
276 ss << v;
277 return std::move(ss).str();
278 }
279
280 // when handled as a tuple-like object, a `Quaternion` decomposes into its elements
281
282 template<size_t I, typename T>
283 constexpr const T& get(const Qua<T>& v) { return v[I]; }
284
285 template<size_t I, typename T>
286 constexpr T& get(Qua<T>& v) { return v[I]; }
287
288 template<size_t I, typename T>
289 constexpr T&& get(Qua<T>&& v) { return std::move(v[I]); }
290
291 template<size_t I, typename T>
292 constexpr const T&& get(const Qua<T>&& v) { return std::move(v[I]); }
293}
294
295template<typename T>
296struct std::tuple_size<osc::Qua<T>> {
297 static inline constexpr size_t value = 4;
298};
299
300template<size_t I, typename T>
301struct std::tuple_element<I, osc::Qua<T>> {
302 using type = T;
303};
Definition vector.h:63
constexpr reference x()
Returns (*this)[0]
Definition vector.h:157
constexpr reference z()
Returns (*this)[2]
Definition vector.h:167
constexpr reference w()
Returns (*this)[3]
Definition vector.h:172
constexpr reference y()
Returns (*this)[1]
Definition vector.h:162
Definition custom_decoration_generator.h:5
std::ostream & operator<<(std::ostream &, const Object &)
GenType cos(GenType v)
Definition trigonometric_functions.h:34
Qua< T > quaternion_cast(const Matrix< T, 3, 3 > &m)
Definition quaternion_functions.h:73
constexpr std::common_type_t< Angle< Rep1, Units1 >, Angle< Rep2, Units2 > > operator+(const Angle< Rep1, Units1 > &lhs, const Angle< Rep2, Units2 > &rhs)
Definition angle.h:99
Matrix< T, 3, 3 > operator/(const Matrix< T, 3, 3 > &m, T scalar)
Definition matrix3x3.h:341
constexpr T dot(T x, T y)
Definition geometric_functions.h:29
constexpr const T & get(const Rgb< T > &v)
Definition rgb.h:88
T abs(T num)
Definition common_functions.h:24
std::string to_string(const Matrix< T, C, R > &m)
Definition matrix.h:32
constexpr U to(T &&value)
Definition conversion.h:56
GenType sin(GenType v)
Definition trigonometric_functions.h:13
T inverse(const Matrix< T, 3, 3 > &m)
Definition matrix_functions.h:158
Vector< T, N > normalize(const Vector< T, N > &v)
Definition geometric_functions.h:74
Matrix< T, 3, 3 > operator*(const Matrix< T, 3, 3 > &m, T scalar)
Definition matrix3x3.h:273
T sqrt(T num)
Definition geometric_functions.h:14
constexpr CoordinateDirection cross(CoordinateDirection x, CoordinateDirection y)
Definition coordinate_direction.h:117
constexpr std::common_type_t< Angle< Rep1, Units1 >, Angle< Rep2, Units2 > > operator-(const Angle< Rep1, Units1 > &lhs, const Angle< Rep2, Units2 > &rhs)
Definition angle.h:114
Definition matrix.h:15
Definition qua.h:22
T w
Definition qua.h:184
constexpr reference operator[](size_type pos)
Definition qua.h:117
T * iterator
Definition qua.h:30
constexpr Qua(T w_, T x_, T y_, T z_)
Definition qua.h:45
T value_type
Definition qua.h:23
size_t size_type
Definition qua.h:24
Qua(const Matrix< T, 3, 3 > &m)
Definition qua.h:99
static constexpr Qua< T > wxyz(T w, T x, T y, T z)
Definition qua.h:34
T y
Definition qua.h:186
constexpr iterator end()
Definition qua.h:115
constexpr const_iterator begin() const
Definition qua.h:114
constexpr const_pointer data() const
Definition qua.h:112
constexpr Qua()=default
constexpr const_iterator end() const
Definition qua.h:116
ptrdiff_t difference_type
Definition qua.h:25
constexpr pointer data()
Definition qua.h:111
friend constexpr bool operator==(const Qua &, const Qua &)=default
const T * const_iterator
Definition qua.h:31
constexpr Qua< T > & operator=(const Qua< U > &q)
Definition qua.h:123
const T * const_pointer
Definition qua.h:29
constexpr Qua(const Qua< U > &q)
Definition qua.h:51
constexpr Qua< T > & operator-=(const Qua< U > &q)
Definition qua.h:143
T * pointer
Definition qua.h:28
T x
Definition qua.h:185
constexpr Qua< T > & operator*=(const Qua< U > &r)
Definition qua.h:153
constexpr Qua< T > & operator+=(const Qua< U > &q)
Definition qua.h:133
constexpr Qua< T > & operator/=(U s)
Definition qua.h:175
constexpr iterator begin()
Definition qua.h:113
constexpr const_reference operator[](size_type pos) const
Definition qua.h:118
Qua(const Vector< T, 3 > &u, const Vector< T, 3 > &v)
Definition qua.h:64
constexpr Qua(T s, const Vector< T, 3 > &v)
Definition qua.h:40
Qua(const Matrix< T, 4, 4 > &m)
Definition qua.h:105
T & reference
Definition qua.h:26
T z
Definition qua.h:187
const T & const_reference
Definition qua.h:27
constexpr Qua< T > & operator*=(U s)
Definition qua.h:165
constexpr size_type size() const
Definition qua.h:110
Qua(const EulerAngles &euler_angles)
Definition qua.h:87