UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
transform.hpp
1
41#ifndef UFO_NUMERIC_TRANSFORM_HPP
42#define UFO_NUMERIC_TRANSFORM_HPP
43
44// UFO
45#include <ufo/numeric/mat.hpp>
46#include <ufo/numeric/quat.hpp>
47#include <ufo/numeric/vec.hpp>
48
49// STL
50#include <cmath>
51#include <concepts>
52#include <cstddef>
53#include <format>
54#include <ostream>
55
61namespace ufo
62{
63
64/**************************************************************************************
65| |
66| Transform<Dim, T> |
67| |
68**************************************************************************************/
69
79template <std::size_t Dim, std::floating_point T = float>
80 requires(Dim == 2 || Dim == 3)
81struct Transform {
82 using value_type = T;
83 using size_type = std::size_t;
84
92 Vec<Dim, T> translation{};
93
94 /**************************************************************************************
95 | |
96 | Constructors |
97 | |
98 **************************************************************************************/
99
104 constexpr Transform() noexcept = default;
105
109 constexpr Transform(Transform const&) noexcept = default;
110
116 constexpr Transform(Mat<Dim, Dim, T> const& rotation, Vec<Dim, T> const& translation)
117 : rotation(rotation), translation(translation)
118 {
119 }
120
125 constexpr explicit Transform(Mat<Dim, Dim, T> const& rotation) : rotation(rotation) {}
126
135 template <std::floating_point T1, std::floating_point T2>
136 constexpr Transform(Mat<Dim, Dim, T1> const& rotation, Vec<Dim, T2> const& translation)
137 : rotation(rotation), translation(translation)
138 {
139 }
140
147 template <std::floating_point U>
148 constexpr explicit Transform(Mat<Dim, Dim, U> const& rotation) : rotation(rotation)
149 {
150 }
151
159 template <std::floating_point T1, std::floating_point T2>
160 requires(Dim == 2)
161 constexpr Transform(T1 const& angle, Vec<2, T2> const& translation)
162 : translation(translation)
163 {
164 auto const s = std::sin(angle);
165 auto const c = std::cos(angle);
166 this->rotation = Mat<2, 2, T>(c, -s, s, c);
167 }
168
174 template <std::floating_point U>
175 requires(Dim == 2)
176 constexpr explicit Transform(U const& angle)
177 {
178 auto const s = std::sin(angle);
179 auto const c = std::cos(angle);
180 this->rotation = Mat<2, 2, T>(c, -s, s, c);
181 }
182
190 template <std::floating_point T1, std::floating_point T2>
191 requires(Dim == 3)
192 constexpr Transform(Quat<T1> const& rotation, Vec<3, T2> const& translation)
193 : Transform(Mat<3, 3, T1>(rotation), translation)
194 {
195 }
196
202 template <std::floating_point U>
203 requires(Dim == 3)
204 constexpr explicit Transform(Quat<U> const& rotation)
205 : Transform(Mat<3, 3, U>(rotation))
206 {
207 }
208
216 template <std::floating_point U>
217 constexpr explicit Transform(Mat<Dim + 1, Dim + 1, U> const& m)
218 {
219 rotation = Mat<Dim, Dim, U>(m);
220 for (std::size_t i = 0; i < Dim; ++i) {
221 translation[i] = m[i][Dim];
222 }
223 }
224
231 template <std::floating_point U>
232 constexpr explicit Transform(Transform<Dim, U> const& other) noexcept
233 : rotation(other.rotation), translation(other.translation)
234 {
235 }
236
237 /**************************************************************************************
238 | |
239 | Assignment operator |
240 | |
241 **************************************************************************************/
242
247 constexpr Transform& operator=(Transform const&) noexcept = default;
248
255 template <std::floating_point U>
256 constexpr Transform& operator=(Transform<Dim, U> const& rhs) noexcept
257 {
258 rotation = rhs.rotation;
259 translation = rhs.translation;
260 return *this;
261 }
262
263 /**************************************************************************************
264 | |
265 | Conversion operators |
266 | |
267 **************************************************************************************/
268
274 template <std::floating_point U>
275 constexpr explicit operator Mat<Dim, Dim, U>() const
276 {
277 return Mat<Dim, Dim, U>(rotation);
278 }
279
287 template <std::floating_point U>
288 constexpr explicit operator Mat<Dim + 1, Dim + 1, U>() const
289 {
291 for (std::size_t i = 0; i < Dim; ++i) {
292 m[i][Dim] = static_cast<U>(translation[i]);
293 }
294 m[Dim][Dim] = U(1);
295 return m;
296 }
297
303 template <std::floating_point U>
304 requires(Dim == 3)
305 constexpr explicit operator Quat<U>() const
306 {
307 return Quat<U>(rotation);
308 }
309
310 /**************************************************************************************
311 | |
312 | Operations |
313 | |
314 **************************************************************************************/
315
322 template <std::floating_point U>
323 [[nodiscard]] constexpr Vec<Dim, U> operator()(Vec<Dim, U> const& v) const
324 {
325 return Mat<Dim, Dim, U>(rotation) * v + Vec<Dim, U>(translation);
326 }
327
335 template <std::floating_point U>
336 requires(Dim == 3)
337 [[nodiscard]] constexpr Quat<U> operator()(Quat<U> const& q) const
338 {
339 return Quat<U>(*this) * q;
340 }
341
346 [[nodiscard]] constexpr T theta() const
347 requires(Dim == 2)
348 {
349 return std::atan2(rotation[1][0], rotation[0][0]);
350 }
351
357 constexpr Transform& operator*=(Transform const& t)
358 {
359 auto tmp = (*this)(t.translation);
360 rotation *= t.rotation;
361 translation = tmp;
362 return *this;
363 }
364
371 [[nodiscard]] constexpr bool operator==(Transform const& other) const noexcept =
372 default;
373};
374
375/**************************************************************************************
376| |
377| Aliases |
378| |
379**************************************************************************************/
380
381template <std::floating_point T = float>
383template <std::floating_point T = float>
385
390
391/**************************************************************************************
392| |
393| Binary operators |
394| |
395**************************************************************************************/
396
405template <std::size_t Dim, std::floating_point T>
407 Transform<Dim, T> const& t2)
408{
409 t1 *= t2;
410 return t1;
411}
412
421template <std::size_t Dim, std::floating_point T>
422[[nodiscard]] constexpr Vec<Dim, T> operator*(Transform<Dim, T> const& t,
423 Vec<Dim, T> const& v)
424{
425 return t(v);
426}
427
435template <std::floating_point T>
436[[nodiscard]] constexpr Quat<T> operator*(Transform<3, T> const& t, Quat<T> const& q)
437{
438 return t(q);
439}
440
450template <std::size_t Dim, std::floating_point T>
451std::ostream& operator<<(std::ostream& out, Transform<Dim, T> const& t)
452{
453 out << "Translation: " << t.translation << " ";
454 if constexpr (Dim == 2) {
455 out << "Theta: " << t.theta();
456 } else {
457 out << "Rotation: " << Quat<T>(t);
458 }
459 return out;
460}
461
462/**************************************************************************************
463| |
464| Free functions |
465| |
466**************************************************************************************/
467
477template <std::size_t Dim, std::floating_point T>
478[[nodiscard]] constexpr Transform<Dim, T> inverse(Transform<Dim, T> const& t)
479{
480 Mat<Dim, Dim, T> const inv_r = transpose(t.rotation);
481 return {inv_r, inv_r * -t.translation};
482}
483} // namespace ufo
484
485/**************************************************************************************
486| |
487| std::formatter support |
488| |
489**************************************************************************************/
490
491template <std::size_t Dim, std::floating_point T>
492 requires(std::formattable<T, char>)
493struct std::formatter<ufo::Transform<Dim, T>> {
494 constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); }
495
496 auto format(ufo::Transform<Dim, T> const& t, std::format_context& ctx) const
497 {
498 if constexpr (Dim == 2) {
499 return std::format_to(ctx.out(), "translation: {} Theta: {}", t.translation,
500 t.theta());
501 } else {
502 return std::format_to(ctx.out(), "translation: {} Rotation: {}", t.translation,
503 ufo::Quat<T>(t));
504 }
505 }
506};
507
512#endif // UFO_NUMERIC_TRANSFORM_HPP
constexpr Transform & operator=(Transform const &) noexcept=default
Default copy assignment operator.
constexpr Transform() noexcept=default
Default constructor; initializes to the identity transform (zero translation and identity rotation).
T angle(Quat< T > const &q) noexcept
Extracts the rotation angle (in radians) from a unit quaternion.
Definition quat.hpp:852
constexpr Vec< Dim, U > operator()(Vec< Dim, U > const &v) const
Applies the transform to a vector: result = R * v + t.
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr Mat< Rows, Cols, T > operator*(Mat< Rows, Cols, T > lhs, T rhs) noexcept
Multiplies every element of lhs by scalar rhs.
Definition mat.hpp:863
constexpr Mat< Cols, Rows, T > transpose(Mat< Rows, Cols, T > const &m) noexcept
Returns the transpose of a matrix.
Definition mat.hpp:1184
constexpr M inverse(M const &m) noexcept
Computes the inverse of a square floating-point matrix.
Definition mat.hpp:1097
A fixed-size matrix with Rows rows and Cols columns.
Definition mat.hpp:113
static consteval Mat identity() noexcept
Returns the identity matrix (square matrices only).
Definition mat.hpp:151
Unit quaternion representing an orientation or rotation in 3-D space.
Definition quat.hpp:76
Rigid-body transform: a rotation matrix plus a translation vector.
Definition transform.hpp:81
Mat< Dim, Dim, T > rotation
Rotation component of the transform, represented as a Dim × Dim matrix.
Definition transform.hpp:88
constexpr Transform & operator*=(Transform const &t)
Composes this transform with t in place: *this = *this * t.
constexpr Transform(Mat< Dim, Dim, T1 > const &rotation, Vec< Dim, T2 > const &translation)
Constructs from rotation and translation with potentially different scalar types.
constexpr Transform(Mat< Dim, Dim, T > const &rotation)
Constructs a pure-rotation transform (zero translation).
constexpr Transform(T1 const &angle, Vec< 2, T2 > const &translation)
(2D only) Constructs from a rotation angle and a translation vector.
constexpr Transform & operator=(Transform< Dim, U > const &rhs) noexcept
Converting assignment from a Transform<Dim, U> with a different scalar type.
constexpr Transform(Quat< T1 > const &rotation, Vec< 3, T2 > const &translation)
(3D only) Constructs from a quaternion and a translation vector.
constexpr bool operator==(Transform const &other) const noexcept=default
Equality comparison; two transforms are equal if their rotation and translation components are equal.
Vec< Dim, T > translation
Translation component of the transform.
Definition transform.hpp:92
constexpr Transform(Mat< Dim+1, Dim+1, U > const &m)
Constructs from a (Dim+1) × (Dim+1) homogeneous matrix.
constexpr T theta() const
(2D only) Returns the rotation angle θ in [-π, π].
constexpr Transform(Mat< Dim, Dim, U > const &rotation)
Constructs a pure-rotation transform from a rotation matrix of a different type.
constexpr Transform(Quat< U > const &rotation)
(3D only) Constructs a pure-rotation transform from a quaternion.
constexpr Transform(U const &angle)
(2D only) Constructs a pure-rotation transform from an angle.
constexpr Transform(Transform< Dim, U > const &other) noexcept
Converting constructor from a Transform<Dim, U> with a different scalar type.
A fixed-size arithmetic vector of up to 4 dimensions.
Definition vec.hpp:76