Blender V4.3
BLI_math_euler_types.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
29#include <ostream>
30
32#include "BLI_math_base.hh"
35
36namespace blender::math {
37
38/* WARNING: must match the #eRotationModes in `DNA_action_types.h`
39 * order matters - types are saved to file. */
41 XYZ = 1,
47};
48
49std::ostream &operator<<(std::ostream &stream, EulerOrder order);
50
51/* -------------------------------------------------------------------- */
55template<typename T> struct EulerBase {
57
58 protected:
64
65 EulerBase() = default;
66
67 EulerBase(const AngleT &x, const AngleT &y, const AngleT &z) : xyz_(x, y, z){};
68
69 EulerBase(const VecBase<AngleT, 3> &vec) : xyz_(vec){};
70
71 EulerBase(const VecBase<T, 3> &vec) : xyz_(vec.x, vec.y, vec.z){};
72
73 public:
78 explicit operator VecBase<AngleT, 3>() const
79 {
80 return this->xyz_;
81 }
82
83 explicit operator VecBase<T, 3>() const
84 {
85 return {T(x()), T(y()), T(z())};
86 }
87
91 {
92 return this->xyz_;
93 }
94 const VecBase<AngleT, 3> &xyz() const
95 {
96 return this->xyz_;
97 }
98
99 const AngleT &x() const
100 {
101 return this->xyz_.x;
102 }
103
104 const AngleT &y() const
105 {
106 return this->xyz_.y;
107 }
108
109 const AngleT &z() const
110 {
111 return this->xyz_.z;
112 }
113
115 {
116 return this->xyz_.x;
117 }
118
120 {
121 return this->xyz_.y;
122 }
123
125 {
126 return this->xyz_.z;
127 }
128};
129
132/* -------------------------------------------------------------------- */
136template<typename T> struct EulerXYZBase : public EulerBase<T> {
138
139 public:
140 EulerXYZBase() = default;
141
145 template<typename AngleU> EulerXYZBase(const VecBase<AngleU, 3> &vec) : EulerBase<T>(vec){};
146
147 EulerXYZBase(const AngleT &x, const AngleT &y, const AngleT &z) : EulerBase<T>(x, y, z){};
148
153 EulerXYZBase(const Axis axis, const AngleT &angle)
154 {
155 *this = identity();
156 this->xyz_[axis] = angle;
157 }
158
167
173 EulerXYZBase wrapped() const;
174
181 EulerXYZBase wrapped_around(const EulerXYZBase &reference) const;
182
186 {
187 return {-a.xyz_.x, -a.xyz_.y, -a.xyz_.z};
188 }
189
191
192 friend std::ostream &operator<<(std::ostream &stream, const EulerXYZBase &rot)
193 {
194 return stream << "EulerXYZ" << static_cast<VecBase<T, 3>>(rot);
195 }
196};
197
200/* -------------------------------------------------------------------- */
204template<typename T> struct Euler3Base : public EulerBase<T> {
206
207 private:
209 EulerOrder order_;
210
214 class Swizzle {
215 private:
216 Euler3Base &eul_;
217
218 public:
219 explicit Swizzle(Euler3Base &eul) : eul_(eul){};
220
221 Euler3Base &operator=(const VecBase<AngleT, 3> &angles)
222 {
223 eul_.xyz_.x = angles[eul_.i_index()];
224 eul_.xyz_.y = angles[eul_.j_index()];
225 eul_.xyz_.z = angles[eul_.k_index()];
226 return eul_;
227 }
228
229 operator VecBase<AngleT, 3>() const
230 {
231 return {eul_.i(), eul_.j(), eul_.k()};
232 }
233
234 explicit operator VecBase<T, 3>() const
235 {
236 return {T(eul_.i()), T(eul_.j()), T(eul_.k())};
237 }
238 };
239
240 public:
241 Euler3Base() = delete;
242
248 template<typename AngleU>
249 Euler3Base(const VecBase<AngleU, 3> &angles_xyz, EulerOrder order)
250 : EulerBase<T>(angles_xyz), order_(order){};
251
252 Euler3Base(const AngleT &x, const AngleT &y, const AngleT &z, EulerOrder order)
253 : EulerBase<T>(x, y, z), order_(order){};
254
258 Euler3Base(const Axis axis, AngleT angle, EulerOrder order) : EulerBase<T>(), order_(order)
259 {
260 this->xyz_[axis] = angle;
261 }
262
267 Euler3Base(EulerOrder order) : order_(order){};
268
271 const EulerOrder &order() const
272 {
273 return order_;
274 }
275
280 Swizzle ijk()
281 {
282 return Swizzle{*this};
283 }
285 {
286 return {i(), j(), k()};
287 }
288
293 const AngleT &i() const
294 {
295 return this->xyz_[i_index()];
296 }
297 const AngleT &j() const
298 {
299 return this->xyz_[j_index()];
300 }
301 const AngleT &k() const
302 {
303 return this->xyz_[k_index()];
304 }
306 {
307 return this->xyz_[i_index()];
308 }
310 {
311 return this->xyz_[j_index()];
312 }
314 {
315 return this->xyz_[k_index()];
316 }
317
324 Euler3Base wrapped_around(const Euler3Base &reference) const
325 {
326 return {VecBase<AngleT, 3>(EulerXYZBase<T>(this->xyz_).wrapped_around(reference.xyz_)),
327 order_};
328 }
329
333 {
334 return {-a.xyz_, a.order_};
335 }
336
338
339 friend std::ostream &operator<<(std::ostream &stream, const Euler3Base &rot)
340 {
341 return stream << "Euler3_" << rot.order_ << rot.xyz_;
342 }
343
344 /* Utilities for conversions and functions operating on Euler3.
345 * This should be private in theory. */
346
352 bool parity() const
353 {
354 switch (order_) {
355 default:
357 return false;
358 case XYZ:
359 case ZXY:
360 case YZX:
361 return false;
362 case XZY:
363 case YXZ:
364 case ZYX:
365 return true;
366 }
367 }
368
372 int i_index() const
373 {
374 switch (order_) {
375 default:
377 return 0;
378 case XYZ:
379 case XZY:
380 return 0;
381 case YXZ:
382 case YZX:
383 return 1;
384 case ZXY:
385 case ZYX:
386 return 2;
387 }
388 }
389
393 int j_index() const
394 {
395 switch (order_) {
396 default:
398 return 0;
399 case YXZ:
400 case ZXY:
401 return 0;
402 case XYZ:
403 case ZYX:
404 return 1;
405 case XZY:
406 case YZX:
407 return 2;
408 }
409 }
410
414 int k_index() const
415 {
416 switch (order_) {
417 default:
419 return 0;
420 case YZX:
421 case ZYX:
422 return 0;
423 case XZY:
424 case ZXY:
425 return 1;
426 case XYZ:
427 case YXZ:
428 return 2;
429 }
430 }
431};
432
437
438} // namespace blender::math
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_STRUCT_EQUALITY_OPERATORS_1(Type, m)
#define BLI_STRUCT_EQUALITY_OPERATORS_2(Type, m1, m2)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
#define rot(x, k)
#define T
std::ostream & operator<<(std::ostream &stream, EulerOrder order)
static AngleRadianBase identity()
Euler3Base(const AngleT &x, const AngleT &y, const AngleT &z, EulerOrder order)
Euler3Base wrapped_around(const Euler3Base &reference) const
Euler3Base(const Axis axis, AngleT angle, EulerOrder order)
const EulerOrder & order() const
const VecBase< AngleT, 3 > ijk() const
friend Euler3Base operator-(const Euler3Base &a)
Euler3Base(const VecBase< AngleU, 3 > &angles_xyz, EulerOrder order)
VecBase< AngleT, 3 > & xyz()
const VecBase< AngleT, 3 > & xyz() const
EulerBase(const VecBase< T, 3 > &vec)
EulerBase(const VecBase< AngleT, 3 > &vec)
EulerBase(const AngleT &x, const AngleT &y, const AngleT &z)
EulerXYZBase wrapped() const
EulerXYZBase(const AngleT &x, const AngleT &y, const AngleT &z)
EulerXYZBase wrapped_around(const EulerXYZBase &reference) const
EulerXYZBase(const Axis axis, const AngleT &angle)
friend EulerXYZBase operator-(const EulerXYZBase &a)
EulerXYZBase(const VecBase< AngleU, 3 > &vec)