Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
affine_transform.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2022-2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#ifndef JAU_AFFINETRANSFORM_HPP_
25#define JAU_AFFINETRANSFORM_HPP_
26
27#include <jau/float_math.hpp>
29#include <jau/math/vec2f.hpp>
30#include <jau/math/vec3f.hpp>
31#include <jau/math/vec4f.hpp>
33
35
36 /** \addtogroup Math
37 *
38 * @{
39 */
40
41 enum class AffineTransformType : int {
42 /** The <code>AffineTransformType::TYPE_UNKNOWN</code> is an initial type_t value */
43 UNKNOWN = -1,
44 IDENTITY = 0,
45 TRANSLATION = 1,
46 UNIFORM_SCALE = 2,
47 GENERAL_SCALE = 4,
51 FLIP = 64,
54 };
55 constexpr static int number(const AffineTransformType rhs) noexcept {
56 return static_cast<int>(rhs);
57 }
58 constexpr static AffineTransformType operator ^(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
59 return static_cast<AffineTransformType> ( number(lhs) ^ number(rhs) );
60 }
61 constexpr static AffineTransformType operator |(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
62 return static_cast<AffineTransformType> ( number(lhs) | number(rhs) );
63 }
64 constexpr static AffineTransformType& operator |=(AffineTransformType& lhs, const AffineTransformType rhs) noexcept {
65 lhs = static_cast<AffineTransformType> ( number(lhs) | number(rhs) );
66 return lhs;
67 }
68 constexpr static AffineTransformType operator &(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
69 return static_cast<AffineTransformType> ( number(lhs) & number(rhs) );
70 }
71 constexpr static bool operator ==(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
72 return number(lhs) == number(rhs);
73 }
74 constexpr static bool operator !=(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
75 return !( lhs == rhs );
76 }
77 constexpr static bool is_set(const AffineTransformType mask, const AffineTransformType bit) noexcept {
78 return bit == ( mask & bit );
79 }
80
81 /**
82 * Represents a affine 2x3 transformation matrix in column major order (memory layout).
83 *
84 * Field notation row-column: m10 (row 1, column 0).
85 */
87 private:
88 // 2x3 matrix in column major order, notation row-column: m10 (row 1, column 0)
89
90 /** scale-x */
91 float m00;
92 /** shear-y */
93 float m10;
94 /** shear-x */
95 float m01;
96 /** scale-x */
97 float m11;
98 /** translate-x */
99 float m02;
100 /** translate-y */
101 float m12;
102
103 AffineTransformType m_type;
104
105 constexpr static const char* determinantIsZero = "Zero Determinante";
106
107 public:
108
109 /** The min absolute value equivalent to zero, aka EPSILON. */
110 constexpr static const float ZERO = (float)1E-10;
111
112 /** Initialized to identity. */
113 constexpr AffineTransform() noexcept
114 : m00(1.0f), m10(0.0f),
115 m01(0.0f), m11(1.0f),
116 m02(0.0f), m12(0.0f),
117 m_type(AffineTransformType::IDENTITY)
118 { }
119
120 constexpr AffineTransform(const float m00_, const float m10_, const float m01_, const float m11_, const float m02_, const float m12_) noexcept
121 : m00(m00_), m10(m10_),
122 m01(m01_), m11(m11_),
123 m02(m02_), m12(m12_),
125 { }
126
127 /**
128 * @param mat2xN either a 2x2 or 2x3 matrix depending on mat_len
129 * @param mat_len either 6 for 2x3 matrix or 4 for 2x2 matrix
130 */
131 AffineTransform(const float mat2xN[], const jau::nsize_t mat_len) noexcept
132 : m00(mat2xN[0]), m10(mat2xN[1]),
133 m01(mat2xN[2]), m11(mat2xN[3]),
134 m02(0.0f), m12(0.0f),
136 {
137 if (mat_len > 4) {
138 m02 = mat2xN[4];
139 m12 = mat2xN[5];
140 }
141 }
142
143 constexpr AffineTransform(const AffineTransform& o) noexcept = default;
144 constexpr AffineTransform(AffineTransform&& o) noexcept = default;
145 constexpr AffineTransform& operator=(const AffineTransform&) noexcept = default;
146 constexpr AffineTransform& operator=(AffineTransform&&) noexcept = default;
147
148 /*
149 * Method returns type of affine transformation.
150 *
151 * Transform matrix is
152 * m00 m01 m02
153 * m10 m11 m12
154 *
155 * According analytic geometry new basis vectors are (m00, m01) and (m10, m11),
156 * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1).
157 * Type transformations classification:
158 * AffineTransformType::TYPE_IDENTITY - new basis equals original one and zero translation
159 * AffineTransformType::TYPE_TRANSLATION - translation vector isn't zero
160 * AffineTransformType::TYPE_UNIFORM_SCALE - vectors length of new basis equals
161 * AffineTransformType::TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal
162 * AffineTransformType::TYPE_FLIP - new basis vector orientation differ from original one
163 * AffineTransformType::TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees
164 * AffineTransformType::TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle
165 * AffineTransformType::TYPE_GENERAL_TRANSFORM - transformation can't be inversed
166 */
167 AffineTransformType getType() const noexcept {
168 if (m_type != AffineTransformType::UNKNOWN) {
169 return m_type;
170 }
171
173
174 if (m00 * m01 + m10 * m11 != 0.0f) {
176 return type;
177 }
178
179 if ( !jau::is_zero(m02) || !jau::is_zero(m12) ) {
181 } else if ( jau::equals(m00, 1.0f) && jau::equals(m11, 1.0f) &&
182 jau::is_zero(m01) && jau::is_zero(m10) ) {
184 return type;
185 }
186
187 if (m00 * m11 - m01 * m10 < 0.0f) {
189 }
190
191 const float dx = m00 * m00 + m10 * m10;
192 const float dy = m01 * m01 + m11 * m11;
193 if ( !jau::equals(dx, dy) ) {
195 } else if ( !jau::equals(dx, 1.0f) ) {
197 }
198
199 if ( ( jau::is_zero( m00 ) && jau::is_zero( m11 ) ) ||
200 ( jau::is_zero( m10 ) && jau::is_zero( m01 ) && (m00 < 0.0f || m11 < 0.0f) ) )
201 {
203 } else if ( !jau::is_zero( m01 ) || !jau::is_zero( m10 ) ) {
205 }
206 return type;
207 }
208
209 float scaleX() const noexcept { return m00; }
210
211 float scaleY() const noexcept { return m11; }
212
213 float shearX() const noexcept { return m01; }
214
215 float shearY() const noexcept { return m10; }
216
217 float translateX() const noexcept { return m02; }
218
219 float translateY() const noexcept { return m12; }
220
221 bool isIdentity() const noexcept { return getType() == AffineTransformType::IDENTITY; }
222
223 /**
224 * @param mat2xN either a 2x2 or 2x3 matrix depending on mat_len
225 * @param mat_len either 6 for 2x3 matrix or 4 for 2x2 matrix
226 */
227 void getMatrix(float mat2xN[], const jau::nsize_t mat_len) const noexcept {
228 mat2xN[0] = m00;
229 mat2xN[1] = m10;
230 mat2xN[2] = m01;
231 mat2xN[3] = m11;
232 if (mat_len > 4) {
233 mat2xN[4] = m02;
234 mat2xN[5] = m12;
235 }
236 }
237
238 float determinant() const noexcept { return m00 * m11 - m01 * m10; }
239
240 AffineTransform& set(const float m00_, const float m10_, const float m01_, const float m11_, const float m02_, const float m12_) noexcept {
242 m00 = m00_;
243 m10 = m10_;
244 m01 = m01_;
245 m11 = m11_;
246 m02 = m02_;
247 m12 = m12_;
248 return *this;
249 }
250
253 m00 = m11 = 1.0f;
254 m10 = m01 = m02 = m12 = 0.0f;
255 return *this;
256 }
257
258 AffineTransform& setToTranslation(const float mx, const float my) noexcept {
259 m00 = m11 = 1.0f;
260 m01 = m10 = 0.0f;
261 m02 = mx;
262 m12 = my;
263 if ( jau::is_zero(mx) && jau::is_zero(my) ) {
265 } else {
267 }
268 return *this;
269 }
270
271 AffineTransform& setToScale(const float scx, const float scy) noexcept {
272 m00 = scx;
273 m11 = scy;
274 m10 = m01 = m02 = m12 = 0.0f;
275 if ( !jau::equals(scx, 1.0f) || !jau::equals(scy, 1.0f) ) {
277 } else {
279 }
280 return *this;
281 }
282
283 AffineTransform& setToShear(const float shx, const float shy) noexcept {
284 m00 = m11 = 1.0f;
285 m02 = m12 = 0.0f;
286 m01 = shx;
287 m10 = shy;
288 if ( !jau::is_zero(shx) || !jau::is_zero(shy) ) {
290 } else {
292 }
293 return *this;
294 }
295
296 AffineTransform& setToRotation(const float angle) noexcept {
297 float sin = std::sin(angle);
298 float cos = std::cos(angle);
299 if (std::abs(cos) < ZERO) {
300 cos = 0.0f;
301 sin = sin > 0.0f ? 1.0f : -1.0f;
302 } else if (std::abs(sin) < ZERO) {
303 sin = 0.0f;
304 cos = cos > 0.0f ? 1.0f : -1.0f;
305 }
306 m00 = m11 = cos;
307 m01 = -sin;
308 m10 = sin;
309 m02 = m12 = 0.0f;
311 return *this;
312 }
313
314 AffineTransform& setToRotation(const float angle, const float px, const float py) noexcept {
315 setToRotation(angle);
316 m02 = px * (1.0f - m00) + py * m10;
317 m12 = py * (1.0f - m00) - px * m10;
319 return *this;
320 }
321
322 AffineTransform& translate(const float mx, const float my, AffineTransform& tmp) noexcept {
323 return concat(tmp.setToTranslation(mx, my));
324 }
325
326 AffineTransform& scale(const float scx, const float scy, AffineTransform& tmp) noexcept {
327 return concat(tmp.setToScale(scx, scy));
328 }
329
330 AffineTransform& shear(const float shx, const float shy, AffineTransform& tmp) noexcept {
331 return concat(tmp.setToShear(shx, shy));
332 }
333
334 AffineTransform& rotate(const float angle, AffineTransform& tmp) noexcept {
335 return concat(tmp.setToRotation(angle));
336 }
337
338 AffineTransform& rotate(const float angle, const float px, const float py, AffineTransform& tmp) noexcept {
339 return concat(tmp.setToRotation(angle, px, py));
340 }
341
342 /**
343 * Multiply matrix of two AffineTransform objects.
344 * @param tL - the AffineTransform object is a multiplicand (left argument)
345 * @param tR - the AffineTransform object is a multiplier (right argument)
346 *
347 * @return A new AffineTransform object containing the result of [tL] X [tR].
348 */
349 static AffineTransform mul(const AffineTransform& tL, const AffineTransform& tR) noexcept {
350 return AffineTransform(
351 tR.m00 * tL.m00 + tR.m10 * tL.m01, // m00
352 tR.m00 * tL.m10 + tR.m10 * tL.m11, // m10
353 tR.m01 * tL.m00 + tR.m11 * tL.m01, // m01
354 tR.m01 * tL.m10 + tR.m11 * tL.m11, // m11
355 tR.m02 * tL.m00 + tR.m12 * tL.m01 + tL.m02, // m02
356 tR.m02 * tL.m10 + tR.m12 * tL.m11 + tL.m12);// m12
357 }
358
359 /**
360 * Concatenates the given matrix to this.
361 * <p>
362 * Implementations performs the matrix multiplication:
363 * <pre>
364 * [this] = [this] X [tR]
365 * </pre>
366 * </p>
367 * @param tR the right-argument of the matrix multiplication
368 * @return this transform for chaining
369 */
371 // set(mul(this, tR));
373 set( tR.m00 * m00 + tR.m10 * m01, // m00
374 tR.m00 * m10 + tR.m10 * m11, // m10
375 tR.m01 * m00 + tR.m11 * m01, // m01
376 tR.m01 * m10 + tR.m11 * m11, // m11
377 tR.m02 * m00 + tR.m12 * m01 + m02, // m02
378 tR.m02 * m10 + tR.m12 * m11 + m12);// m12
379 return *this;
380 }
381
382 /**
383 * Pre-concatenates the given matrix to this.
384 * <p>
385 * Implementations performs the matrix multiplication:
386 * <pre>
387 * [this] = [tL] X [this]
388 * </pre>
389 * </p>
390 * @param tL the left-argument of the matrix multiplication
391 * @return this transform for chaining
392 */
394 // setTransform(multiply(tL, this));
396 set( m00 * tL.m00 + m10 * tL.m01, // m00
397 m00 * tL.m10 + m10 * tL.m11, // m10
398 m01 * tL.m00 + m11 * tL.m01, // m01
399 m01 * tL.m10 + m11 * tL.m11, // m11
400 m02 * tL.m00 + m12 * tL.m01 + tL.m02, // m02
401 m02 * tL.m10 + m12 * tL.m11 + tL.m12);// m12
402 return *this;
403 }
404
406 const float det = determinant();
407 if (std::abs(det) < ZERO) {
408 throw MathDomainError(determinantIsZero, E_FILE_LINE);
409 }
410 return AffineTransform(
411 m11 / det, // m00
412 -m10 / det, // m10
413 -m01 / det, // m01
414 m00 / det, // m11
415 (m01 * m12 - m11 * m02) / det, // m02
416 (m10 * m02 - m00 * m12) / det // m12
417 );
418 }
419
420 /**
421 *
422 * @param src
423 * @param dst
424 * @return dst for chaining
425 */
426 AABBox3f& transform(const AABBox3f& src, AABBox3f& dst) const noexcept {
427 const Vec3f& lo = src.low();
428 const Vec3f& hi = src.high();
429 dst.setSize(lo.x * m00 + lo.y * m01 + m02, lo.x * m10 + lo.y * m11 + m12, lo.z,
430 hi.x * m00 + hi.y * m01 + m02, hi.x * m10 + hi.y * m11 + m12, hi.z);
431 return dst;
432 }
433
434 /**
435 * @param src
436 * @param dst
437 * @return dst for chaining
438 Vertex& transform(const Vertex& src, const Vertex& dst) const noexcept {
439 const float x = src.x();
440 const float y = src.y();
441 dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, src.z());
442 return dst;
443 }
444 void transform(const Vertex src[], const Vertex dst[], size_t length) const noexcept {
445 size_t srcOff=0;
446 size_t dstOff=0;
447 while (--length >= 0) {
448 const Vertex& srcPoint = src[srcOff++];
449 Vertex& dstPoint = dst[dstOff++];
450 const float x = srcPoint.x();
451 const float y = srcPoint.y();
452 dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, srcPoint.z());
453 }
454 } */
455
456 /**
457 * @param src float[2] source of transformation
458 * @param dst float[2] destination of transformation, maybe be equal to <code>src</code>
459 * @return dst for chaining
460 */
461 float* transform(const float src[], float dst[]) const noexcept {
462 const float x = src[0];
463 const float y = src[1];
464 dst[0] = x * m00 + y * m01 + m02;
465 dst[1] = x * m10 + y * m11 + m12;
466 return dst;
467 }
468
469 void transform(const float src[], float dst[], size_t length) const noexcept {
470 const float* src_end = src + length * 2;
471 if (src <= dst && dst < src_end ) {
472 // overlap -> reverse
473 size_t srcOff = length * 2 - 2;
474 size_t dstOff = length * 2 - 2;
475 while (length-- > 0) {
476 const float x = src[srcOff + 0];
477 const float y = src[srcOff + 1];
478 dst[dstOff + 0] = x * m00 + y * m01 + m02;
479 dst[dstOff + 1] = x * m10 + y * m11 + m12;
480 srcOff -= 2;
481 dstOff -= 2;
482 }
483 } else {
484 size_t srcOff = 0;
485 size_t dstOff = 0;
486 while (length-- > 0) {
487 const float x = src[srcOff++];
488 const float y = src[srcOff++];
489 dst[dstOff++] = x * m00 + y * m01 + m02;
490 dst[dstOff++] = x * m10 + y * m11 + m12;
491 }
492 }
493 }
494
495 /**
496 * @param src source of transformation
497 * @param dst destination of transformation, maybe be equal to <code>src</code>
498 * @return dst for chaining
499 */
500 Vec2f& transform(const Vec2f& src, Vec2f& dst) const noexcept {
501 const float x = src.x;
502 const float y = src.y;
503 dst.x = x * m00 + y * m01 + m02;
504 dst.y = x * m10 + y * m11 + m12;
505 return dst;
506 }
507
508 /**
509 * @param src source of transformation
510 * @return resulting Vec2f
511 */
512 Vec2f transform(const Vec2f& src) const noexcept {
513 const float x = src.x;
514 const float y = src.y;
515 return Vec2f( x * m00 + y * m01 + m02,
516 x * m10 + y * m11 + m12 );
517 }
518
519 /**
520 * @param src source of transformation
521 * @param dst destination of transformation, maybe be equal to <code>src</code>
522 * @return dst for chaining
523 */
524 Vec3f& transform(const Vec3f& src, Vec3f& dst) const noexcept {
525 const float x = src.x;
526 const float y = src.y;
527 dst.x = x * m00 + y * m01 + m02;
528 dst.y = x * m10 + y * m11 + m12;
529 dst.z = src.z; // just copy z
530 return dst;
531 }
532
533 private:
534 Vec3f transformVec3f(const Vec3f& src) const noexcept {
535 const float x = src.x;
536 const float y = src.y;
537 return Vec3f( x * m00 + y * m01 + m02,
538 x * m10 + y * m11 + m12,
539 src.z
540 ); // just copy z
541 }
542
543 public:
544 /**
545 * @param src source of transformation
546 * @param dst destination of transformation, maybe be equal to <code>src</code>
547 * @return resulting Vec3f
548 */
549 Vec3f transform(const Vec3f& src) const noexcept {
550 return transformVec3f(src);
551 }
552
553 /**
554 * Resize the aabbox3f to encapsulate another AABox, which will be <i>transformed</i> on the fly first.
555 * @param newBox aabbox3f to be encapsulated in
556 * @param t the {@link AffineTransform} applied on <i>newBox</i> on the fly
557 * @param tmpV3 temporary storage
558 * @return this aabbox3f for chaining
559 */
560 AABBox3f& resizeBox(AABBox3f& box, const AABBox3f& newBox) noexcept {
561 AABBox3f::transform_vec3f_func transform(this, &AffineTransform::transformVec3f);
562 return box.resize(newBox, transform);
563
564 }
565
566 /**
567 *
568 * @param src
569 * @param dst
570 * @return return dst for chaining
571 Vertex& deltaTransform(const Vertex& src, Vertex& dst) const noexcept {
572 const float x = src.x();
573 const float y = src.y();
574 dst.setCoord(x * m00 + y * m01, x * m10 + y * m11, src.z());
575 return dst;
576 }
577 */
578
579 void deltaTransform(const float src[], float dst[], size_t length) const noexcept {
580 size_t srcOff = 0;
581 size_t dstOff = 0;
582 while (length-- > 0) {
583 const float x = src[srcOff++];
584 const float y = src[srcOff++];
585 dst[dstOff++] = x * m00 + y * m01;
586 dst[dstOff++] = x * m10 + y * m11;
587 }
588 }
589
590 /**
591 *
592 * @param src
593 * @param dst
594 * @return return dst for chaining
595 * @throws NoninvertibleTransformException
596 Vertex& inverseTransform(const Vertex& src, Vertex& dst) const {
597 const float det = getDeterminant();
598 if (std::abs(det) < ZERO) {
599 throw new NoninvertibleTransformException(determinantIsZero);
600 }
601 const float x = src.x() - m02;
602 const float y = src.y() - m12;
603 dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det, src.z());
604 return dst;
605 } */
606
607 void inverseTransform(const float src[], float dst[], size_t length) const {
608 size_t srcOff = 0;
609 size_t dstOff = 0;
610 const float det = determinant();
611 if (std::abs(det) < ZERO) {
612 throw MathDomainError(determinantIsZero, E_FILE_LINE);
613 }
614 while (length-- > 0) {
615 const float x = src[srcOff++] - m02;
616 const float y = src[srcOff++] - m12;
617 dst[dstOff++] = (x * m11 - y * m01) / det;
618 dst[dstOff++] = (y * m00 - x * m10) / det;
619 }
620 }
621
622 std::string toString() const noexcept {
623 return "AffineTransform[[" + std::to_string(m00) + ", " + std::to_string(m01) + ", " + std::to_string(m02) + "], ["
624 + std::to_string(m10) + ", " + std::to_string(m11) + ", " + std::to_string(m12) + "]]";
625 }
626
627 constexpr bool equals(const AffineTransform& o, const float epsilon=std::numeric_limits<float>::epsilon()) const noexcept {
628 if( this == &o ) {
629 return true;
630 } else {
631 return jau::equals(m00, o.m00, epsilon) &&
632 jau::equals(m01, o.m01, epsilon) &&
633 jau::equals(m02, o.m02, epsilon) &&
634 jau::equals(m10, o.m10, epsilon) &&
635 jau::equals(m11, o.m11, epsilon) &&
636 jau::equals(m12, o.m12, epsilon);
637 }
638 }
639 constexpr bool operator==(const AffineTransform& rhs) const noexcept {
640 return equals(rhs);
641 }
642 };
643
644/**@}*/
645
646} // namespace jau::math::geom::plane
647
648#endif /* JAU_AFFINETRANSFORM_HPP_ */
649
#define E_FILE_LINE
Class template jau::function is a general-purpose static-polymorphic function wrapper.
math_error_t::invalid
Definition: math_error.hpp:72
value_type x
Definition: vec2f.hpp:68
value_type x
Definition: vec3f.hpp:72
value_type y
Definition: vec3f.hpp:73
value_type z
Definition: vec3f.hpp:74
Axis Aligned Bounding Box.
Definition: aabbox3f.hpp:49
Represents a affine 2x3 transformation matrix in column major order (memory layout).
constexpr AffineTransform(const float m00_, const float m10_, const float m01_, const float m11_, const float m02_, const float m12_) noexcept
Vec2f transform(const Vec2f &src) const noexcept
AffineTransform & shear(const float shx, const float shy, AffineTransform &tmp) noexcept
static constexpr const float ZERO
The min absolute value equivalent to zero, aka EPSILON.
void deltaTransform(const float src[], float dst[], size_t length) const noexcept
void transform(const float src[], float dst[], size_t length) const noexcept
AffineTransform(const float mat2xN[], const jau::nsize_t mat_len) noexcept
AffineTransform & translate(const float mx, const float my, AffineTransform &tmp) noexcept
Vec3f & transform(const Vec3f &src, Vec3f &dst) const noexcept
AffineTransformType getType() const noexcept
static AffineTransform mul(const AffineTransform &tL, const AffineTransform &tR) noexcept
Multiply matrix of two AffineTransform objects.
AffineTransform & setToShear(const float shx, const float shy) noexcept
float * transform(const float src[], float dst[]) const noexcept
constexpr AffineTransform & operator=(AffineTransform &&) noexcept=default
constexpr bool operator==(const AffineTransform &rhs) const noexcept
AffineTransform & concat(const AffineTransform &tR) noexcept
Concatenates the given matrix to this.
AffineTransform & setToRotation(const float angle) noexcept
AffineTransform & setToRotation(const float angle, const float px, const float py) noexcept
AffineTransform & preConcat(const AffineTransform &tL) noexcept
Pre-concatenates the given matrix to this.
constexpr AffineTransform() noexcept
Initialized to identity.
AABBox3f & resizeBox(AABBox3f &box, const AABBox3f &newBox) noexcept
Resize the aabbox3f to encapsulate another AABox, which will be transformed on the fly first.
AffineTransform & scale(const float scx, const float scy, AffineTransform &tmp) noexcept
AffineTransform & setToScale(const float scx, const float scy) noexcept
std::string toString() const noexcept
constexpr AffineTransform & operator=(const AffineTransform &) noexcept=default
constexpr AffineTransform(const AffineTransform &o) noexcept=default
void getMatrix(float mat2xN[], const jau::nsize_t mat_len) const noexcept
AffineTransform & rotate(const float angle, const float px, const float py, AffineTransform &tmp) noexcept
AffineTransform & setToIdentity() noexcept
AffineTransform & setToTranslation(const float mx, const float my) noexcept
AffineTransform & set(const float m00_, const float m10_, const float m01_, const float m11_, const float m02_, const float m12_) noexcept
void inverseTransform(const float src[], float dst[], size_t length) const
AffineTransform & rotate(const float angle, AffineTransform &tmp) noexcept
constexpr AffineTransform(AffineTransform &&o) noexcept=default
constexpr bool equals(const AffineTransform &o, const float epsilon=std::numeric_limits< float >::epsilon()) const noexcept
AABBox3f & transform(const AABBox3f &src, AABBox3f &dst) const noexcept
Vec2f & transform(const Vec2f &src, Vec2f &dst) const noexcept
Vec3f transform(const Vec3f &src) const noexcept
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
std::enable_if< std::is_floating_point_v< T >, bool >::type constexpr is_zero(const T &a, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if the given value is less than epsilon, w/ epsilon > 0.
Definition: float_math.hpp:255
std::enable_if< std::is_floating_point_v< T >, bool >::type constexpr equals(const T &a, const T &b, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if both values are equal, i.e.
Definition: float_math.hpp:394
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
Definition: base_math.hpp:155
static constexpr bool is_set(const AffineTransformType mask, const AffineTransformType bit) noexcept
static constexpr AffineTransformType operator&(const AffineTransformType lhs, const AffineTransformType rhs) noexcept
static constexpr AffineTransformType operator|(const AffineTransformType lhs, const AffineTransformType rhs) noexcept
static constexpr bool operator==(const AffineTransformType lhs, const AffineTransformType rhs) noexcept
static constexpr int number(const AffineTransformType rhs) noexcept
Vector2F< float > Vec2f
Definition: vec2f.hpp:356
static constexpr bool operator!=(const AffineTransformType lhs, const AffineTransformType rhs) noexcept
Vector3F< float > Vec3f
Definition: vec3f.hpp:371
static constexpr AffineTransformType & operator|=(AffineTransformType &lhs, const AffineTransformType rhs) noexcept
static constexpr AffineTransformType operator^(const AffineTransformType lhs, const AffineTransformType rhs) noexcept
@ UNKNOWN
The AffineTransformType::TYPE_UNKNOWN is an initial type_t value.