jaulib v1.3.8
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
affine_transform.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11#ifndef JAU_AFFINETRANSFORM_HPP_
12#define JAU_AFFINETRANSFORM_HPP_
13
14#include <jau/float_math.hpp>
16#include <jau/math/vec2f.hpp>
17#include <jau/math/vec3f.hpp>
18#include <jau/math/vec4f.hpp>
20
22
23 /** \addtogroup Math
24 *
25 * @{
26 */
27
28 enum class AffineTransformType : int {
29 /** The <code>AffineTransformType::TYPE_UNKNOWN</code> is an initial type_t value */
30 UNKNOWN = -1,
38 FLIP = 64,
41 };
42 constexpr static int number(const AffineTransformType rhs) noexcept {
43 return static_cast<int>(rhs);
44 }
45 constexpr static AffineTransformType operator ^(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
46 return static_cast<AffineTransformType> ( number(lhs) ^ number(rhs) );
47 }
48 constexpr static AffineTransformType operator |(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
49 return static_cast<AffineTransformType> ( number(lhs) | number(rhs) );
50 }
51 constexpr static AffineTransformType& operator |=(AffineTransformType& lhs, const AffineTransformType rhs) noexcept {
52 lhs = static_cast<AffineTransformType> ( number(lhs) | number(rhs) );
53 return lhs;
54 }
55 constexpr static AffineTransformType operator &(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
56 return static_cast<AffineTransformType> ( number(lhs) & number(rhs) );
57 }
58 constexpr static bool operator ==(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
59 return number(lhs) == number(rhs);
60 }
61 constexpr static bool operator !=(const AffineTransformType lhs, const AffineTransformType rhs) noexcept {
62 return !( lhs == rhs );
63 }
64 constexpr static bool is_set(const AffineTransformType mask, const AffineTransformType bit) noexcept {
65 return bit == ( mask & bit );
66 }
67
68 /**
69 * Represents a affine 2x3 transformation matrix in column major order (memory layout).
70 *
71 * Field notation row-column: m10 (row 1, column 0).
72 */
74 private:
75 // 2x3 matrix in column major order, notation row-column: m10 (row 1, column 0)
76
77 /** scale-x */
78 float m00;
79 /** shear-y */
80 float m10;
81 /** shear-x */
82 float m01;
83 /** scale-x */
84 float m11;
85 /** translate-x */
86 float m02;
87 /** translate-y */
88 float m12;
89
91
92 constexpr static const char* determinantIsZero = "Zero Determinante";
93
94 public:
95
96 /** The min absolute value equivalent to zero, aka EPSILON. */
97 constexpr static const float ZERO = (float)1E-10;
98
99 /** Initialized to identity. */
100 constexpr AffineTransform() noexcept
101 : m00(1.0f), m10(0.0f),
102 m01(0.0f), m11(1.0f),
103 m02(0.0f), m12(0.0f),
105 { }
106
107 constexpr AffineTransform(const float m00_, const float m10_, const float m01_, const float m11_, const float m02_, const float m12_) noexcept
108 : m00(m00_), m10(m10_),
109 m01(m01_), m11(m11_),
110 m02(m02_), m12(m12_),
112 { }
113
114 /**
115 * @param mat2xN either a 2x2 or 2x3 matrix depending on mat_len
116 * @param mat_len either 6 for 2x3 matrix or 4 for 2x2 matrix
117 */
118 AffineTransform(const float mat2xN[], const jau::nsize_t mat_len) noexcept
119 : m00(mat2xN[0]), m10(mat2xN[1]),
120 m01(mat2xN[2]), m11(mat2xN[3]),
121 m02(0.0f), m12(0.0f),
123 {
124 if (mat_len > 4) {
125 m02 = mat2xN[4];
126 m12 = mat2xN[5];
127 }
128 }
129
130 constexpr AffineTransform(const AffineTransform& o) noexcept = default;
131 constexpr AffineTransform(AffineTransform&& o) noexcept = default;
132 constexpr AffineTransform& operator=(const AffineTransform&) noexcept = default;
133 constexpr AffineTransform& operator=(AffineTransform&&) noexcept = default;
134
135 /*
136 * Method returns type of affine transformation.
137 *
138 * Transform matrix is
139 * m00 m01 m02
140 * m10 m11 m12
141 *
142 * According analytic geometry new basis vectors are (m00, m01) and (m10, m11),
143 * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1).
144 * Type transformations classification:
145 * AffineTransformType::TYPE_IDENTITY - new basis equals original one and zero translation
146 * AffineTransformType::TYPE_TRANSLATION - translation vector isn't zero
147 * AffineTransformType::TYPE_UNIFORM_SCALE - vectors length of new basis equals
148 * AffineTransformType::TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal
149 * AffineTransformType::TYPE_FLIP - new basis vector orientation differ from original one
150 * AffineTransformType::TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees
151 * AffineTransformType::TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle
152 * AffineTransformType::TYPE_GENERAL_TRANSFORM - transformation can't be inversed
153 */
154 AffineTransformType getType() const noexcept {
155 if (m_type != AffineTransformType::UNKNOWN) {
156 return m_type;
157 }
158
160
161 if (m00 * m01 + m10 * m11 != 0.0f) {
163 return type;
164 }
165
166 if ( !jau::is_zero(m02) || !jau::is_zero(m12) ) {
168 } else if ( jau::equals(m00, 1.0f) && jau::equals(m11, 1.0f) &&
169 jau::is_zero(m01) && jau::is_zero(m10) ) {
171 return type;
172 }
173
174 if (m00 * m11 - m01 * m10 < 0.0f) {
176 }
177
178 const float dx = m00 * m00 + m10 * m10;
179 const float dy = m01 * m01 + m11 * m11;
180 if ( !jau::equals(dx, dy) ) {
182 } else if ( !jau::equals(dx, 1.0f) ) {
184 }
185
186 if ( ( jau::is_zero( m00 ) && jau::is_zero( m11 ) ) ||
187 ( jau::is_zero( m10 ) && jau::is_zero( m01 ) && (m00 < 0.0f || m11 < 0.0f) ) )
188 {
190 } else if ( !jau::is_zero( m01 ) || !jau::is_zero( m10 ) ) {
192 }
193 return type;
194 }
195
196 float scaleX() const noexcept { return m00; }
197
198 float scaleY() const noexcept { return m11; }
199
200 float shearX() const noexcept { return m01; }
201
202 float shearY() const noexcept { return m10; }
203
204 float translateX() const noexcept { return m02; }
205
206 float translateY() const noexcept { return m12; }
207
208 bool isIdentity() const noexcept { return getType() == AffineTransformType::IDENTITY; }
209
210 /**
211 * @param mat2xN either a 2x2 or 2x3 matrix depending on mat_len
212 * @param mat_len either 6 for 2x3 matrix or 4 for 2x2 matrix
213 */
214 void getMatrix(float mat2xN[], const jau::nsize_t mat_len) const noexcept {
215 mat2xN[0] = m00;
216 mat2xN[1] = m10;
217 mat2xN[2] = m01;
218 mat2xN[3] = m11;
219 if (mat_len > 4) {
220 mat2xN[4] = m02;
221 mat2xN[5] = m12;
222 }
223 }
224
225 float determinant() const noexcept { return m00 * m11 - m01 * m10; }
226
227 AffineTransform& set(const float m00_, const float m10_, const float m01_, const float m11_, const float m02_, const float m12_) noexcept {
229 m00 = m00_;
230 m10 = m10_;
231 m01 = m01_;
232 m11 = m11_;
233 m02 = m02_;
234 m12 = m12_;
235 return *this;
236 }
237
240 m00 = m11 = 1.0f;
241 m10 = m01 = m02 = m12 = 0.0f;
242 return *this;
243 }
244
245 AffineTransform& setToTranslation(const float mx, const float my) noexcept {
246 m00 = m11 = 1.0f;
247 m01 = m10 = 0.0f;
248 m02 = mx;
249 m12 = my;
250 if ( jau::is_zero(mx) && jau::is_zero(my) ) {
252 } else {
254 }
255 return *this;
256 }
257
258 AffineTransform& setToScale(const float scx, const float scy) noexcept {
259 m00 = scx;
260 m11 = scy;
261 m10 = m01 = m02 = m12 = 0.0f;
262 if ( !jau::equals(scx, 1.0f) || !jau::equals(scy, 1.0f) ) {
264 } else {
266 }
267 return *this;
268 }
269
270 AffineTransform& setToShear(const float shx, const float shy) noexcept {
271 m00 = m11 = 1.0f;
272 m02 = m12 = 0.0f;
273 m01 = shx;
274 m10 = shy;
275 if ( !jau::is_zero(shx) || !jau::is_zero(shy) ) {
277 } else {
279 }
280 return *this;
281 }
282
283 AffineTransform& setToRotation(const float angle) noexcept {
284 float sin = std::sin(angle);
285 float cos = std::cos(angle);
286 if (std::abs(cos) < ZERO) {
287 cos = 0.0f;
288 sin = sin > 0.0f ? 1.0f : -1.0f;
289 } else if (std::abs(sin) < ZERO) {
290 sin = 0.0f;
291 cos = cos > 0.0f ? 1.0f : -1.0f;
292 }
293 m00 = m11 = cos;
294 m01 = -sin;
295 m10 = sin;
296 m02 = m12 = 0.0f;
298 return *this;
299 }
300
301 AffineTransform& setToRotation(const float angle, const float px, const float py) noexcept {
302 setToRotation(angle);
303 m02 = px * (1.0f - m00) + py * m10;
304 m12 = py * (1.0f - m00) - px * m10;
306 return *this;
307 }
308
309 AffineTransform& translate(const float mx, const float my, AffineTransform& tmp) noexcept {
310 return concat(tmp.setToTranslation(mx, my));
311 }
312
313 AffineTransform& scale(const float scx, const float scy, AffineTransform& tmp) noexcept {
314 return concat(tmp.setToScale(scx, scy));
315 }
316
317 AffineTransform& shear(const float shx, const float shy, AffineTransform& tmp) noexcept {
318 return concat(tmp.setToShear(shx, shy));
319 }
320
321 AffineTransform& rotate(const float angle, AffineTransform& tmp) noexcept {
322 return concat(tmp.setToRotation(angle));
323 }
324
325 AffineTransform& rotate(const float angle, const float px, const float py, AffineTransform& tmp) noexcept {
326 return concat(tmp.setToRotation(angle, px, py));
327 }
328
329 /**
330 * Multiply matrix of two AffineTransform objects.
331 * @param tL - the AffineTransform object is a multiplicand (left argument)
332 * @param tR - the AffineTransform object is a multiplier (right argument)
333 *
334 * @return A new AffineTransform object containing the result of [tL] X [tR].
335 */
336 static AffineTransform mul(const AffineTransform& tL, const AffineTransform& tR) noexcept {
337 return AffineTransform(
338 tR.m00 * tL.m00 + tR.m10 * tL.m01, // m00
339 tR.m00 * tL.m10 + tR.m10 * tL.m11, // m10
340 tR.m01 * tL.m00 + tR.m11 * tL.m01, // m01
341 tR.m01 * tL.m10 + tR.m11 * tL.m11, // m11
342 tR.m02 * tL.m00 + tR.m12 * tL.m01 + tL.m02, // m02
343 tR.m02 * tL.m10 + tR.m12 * tL.m11 + tL.m12);// m12
344 }
345
346 /**
347 * Concatenates the given matrix to this.
348 * <p>
349 * Implementations performs the matrix multiplication:
350 * <pre>
351 * [this] = [this] X [tR]
352 * </pre>
353 * </p>
354 * @param tR the right-argument of the matrix multiplication
355 * @return this transform for chaining
356 */
358 // set(mul(this, tR));
360 set( tR.m00 * m00 + tR.m10 * m01, // m00
361 tR.m00 * m10 + tR.m10 * m11, // m10
362 tR.m01 * m00 + tR.m11 * m01, // m01
363 tR.m01 * m10 + tR.m11 * m11, // m11
364 tR.m02 * m00 + tR.m12 * m01 + m02, // m02
365 tR.m02 * m10 + tR.m12 * m11 + m12);// m12
366 return *this;
367 }
368
369 /**
370 * Pre-concatenates the given matrix to this.
371 * <p>
372 * Implementations performs the matrix multiplication:
373 * <pre>
374 * [this] = [tL] X [this]
375 * </pre>
376 * </p>
377 * @param tL the left-argument of the matrix multiplication
378 * @return this transform for chaining
379 */
381 // setTransform(multiply(tL, this));
383 set( m00 * tL.m00 + m10 * tL.m01, // m00
384 m00 * tL.m10 + m10 * tL.m11, // m10
385 m01 * tL.m00 + m11 * tL.m01, // m01
386 m01 * tL.m10 + m11 * tL.m11, // m11
387 m02 * tL.m00 + m12 * tL.m01 + tL.m02, // m02
388 m02 * tL.m10 + m12 * tL.m11 + tL.m12);// m12
389 return *this;
390 }
391
393 const float det = determinant();
394 if (std::abs(det) < ZERO) {
395 throw MathDomainError(determinantIsZero, E_FILE_LINE);
396 }
397 return AffineTransform(
398 m11 / det, // m00
399 -m10 / det, // m10
400 -m01 / det, // m01
401 m00 / det, // m11
402 (m01 * m12 - m11 * m02) / det, // m02
403 (m10 * m02 - m00 * m12) / det // m12
404 );
405 }
406
407 /**
408 *
409 * @param src
410 * @param dst
411 * @return dst for chaining
412 */
413 AABBox3f& transform(const AABBox3f& src, AABBox3f& dst) const noexcept {
414 const Vec3f& lo = src.low();
415 const Vec3f& hi = src.high();
416 dst.setSize(lo.x * m00 + lo.y * m01 + m02, lo.x * m10 + lo.y * m11 + m12, lo.z,
417 hi.x * m00 + hi.y * m01 + m02, hi.x * m10 + hi.y * m11 + m12, hi.z);
418 return dst;
419 }
420
421 /**
422 * @param src
423 * @param dst
424 * @return dst for chaining
425 Vertex& transform(const Vertex& src, const Vertex& dst) const noexcept {
426 const float x = src.x();
427 const float y = src.y();
428 dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, src.z());
429 return dst;
430 }
431 void transform(const Vertex src[], const Vertex dst[], size_t length) const noexcept {
432 size_t srcOff=0;
433 size_t dstOff=0;
434 while (--length >= 0) {
435 const Vertex& srcPoint = src[srcOff++];
436 Vertex& dstPoint = dst[dstOff++];
437 const float x = srcPoint.x();
438 const float y = srcPoint.y();
439 dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, srcPoint.z());
440 }
441 } */
442
443 /**
444 * @param src float[2] source of transformation
445 * @param dst float[2] destination of transformation, maybe be equal to <code>src</code>
446 * @return dst for chaining
447 */
448 float* transform(const float src[], float dst[]) const noexcept {
449 const float x = src[0];
450 const float y = src[1];
451 dst[0] = x * m00 + y * m01 + m02;
452 dst[1] = x * m10 + y * m11 + m12;
453 return dst;
454 }
455
456 void transform(const float src[], float dst[], size_t length) const noexcept {
457 const float* src_end = src + length * 2;
458 if (src <= dst && dst < src_end ) {
459 // overlap -> reverse
460 size_t srcOff = length * 2 - 2;
461 size_t dstOff = length * 2 - 2;
462 while (length-- > 0) {
463 const float x = src[srcOff + 0];
464 const float y = src[srcOff + 1];
465 dst[dstOff + 0] = x * m00 + y * m01 + m02;
466 dst[dstOff + 1] = x * m10 + y * m11 + m12;
467 srcOff -= 2;
468 dstOff -= 2;
469 }
470 } else {
471 size_t srcOff = 0;
472 size_t dstOff = 0;
473 while (length-- > 0) {
474 const float x = src[srcOff++];
475 const float y = src[srcOff++];
476 dst[dstOff++] = x * m00 + y * m01 + m02;
477 dst[dstOff++] = x * m10 + y * m11 + m12;
478 }
479 }
480 }
481
482 /**
483 * @param src source of transformation
484 * @param dst destination of transformation, maybe be equal to <code>src</code>
485 * @return dst for chaining
486 */
487 Vec2f& transform(const Vec2f& src, Vec2f& dst) const noexcept {
488 const float x = src.x;
489 const float y = src.y;
490 dst.x = x * m00 + y * m01 + m02;
491 dst.y = x * m10 + y * m11 + m12;
492 return dst;
493 }
494
495 /**
496 * @param src source of transformation
497 * @return resulting Vec2f
498 */
499 Vec2f transform(const Vec2f& src) const noexcept {
500 const float x = src.x;
501 const float y = src.y;
502 return Vec2f( x * m00 + y * m01 + m02,
503 x * m10 + y * m11 + m12 );
504 }
505
506 /**
507 * @param src source of transformation
508 * @param dst destination of transformation, maybe be equal to <code>src</code>
509 * @return dst for chaining
510 */
511 Vec3f& transform(const Vec3f& src, Vec3f& dst) const noexcept {
512 const float x = src.x;
513 const float y = src.y;
514 dst.x = x * m00 + y * m01 + m02;
515 dst.y = x * m10 + y * m11 + m12;
516 dst.z = src.z; // just copy z
517 return dst;
518 }
519
520 private:
521 Vec3f transformVec3f(const Vec3f& src) const noexcept {
522 const float x = src.x;
523 const float y = src.y;
524 return Vec3f( x * m00 + y * m01 + m02,
525 x * m10 + y * m11 + m12,
526 src.z
527 ); // just copy z
528 }
529
530 public:
531 /**
532 * @param src source of transformation
533 * @param dst destination of transformation, maybe be equal to <code>src</code>
534 * @return resulting Vec3f
535 */
536 Vec3f transform(const Vec3f& src) const noexcept {
537 return transformVec3f(src);
538 }
539
540 /**
541 * Resize the aabbox3f to encapsulate another AABox, which will be <i>transformed</i> on the fly first.
542 * @param newBox aabbox3f to be encapsulated in
543 * @param t the {@link AffineTransform} applied on <i>newBox</i> on the fly
544 * @param tmpV3 temporary storage
545 * @return this aabbox3f for chaining
546 */
547 AABBox3f& resizeBox(AABBox3f& box, const AABBox3f& newBox) noexcept {
548 AABBox3f::transform_vec3f_func transform(this, &AffineTransform::transformVec3f);
549 return box.resize(newBox, transform);
550
551 }
552
553 /**
554 *
555 * @param src
556 * @param dst
557 * @return return dst for chaining
558 Vertex& deltaTransform(const Vertex& src, Vertex& dst) const noexcept {
559 const float x = src.x();
560 const float y = src.y();
561 dst.setCoord(x * m00 + y * m01, x * m10 + y * m11, src.z());
562 return dst;
563 }
564 */
565
566 void deltaTransform(const float src[], float dst[], size_t length) const noexcept {
567 size_t srcOff = 0;
568 size_t dstOff = 0;
569 while (length-- > 0) {
570 const float x = src[srcOff++];
571 const float y = src[srcOff++];
572 dst[dstOff++] = x * m00 + y * m01;
573 dst[dstOff++] = x * m10 + y * m11;
574 }
575 }
576
577 /**
578 *
579 * @param src
580 * @param dst
581 * @return return dst for chaining
582 * @throws NoninvertibleTransformException
583 Vertex& inverseTransform(const Vertex& src, Vertex& dst) const {
584 const float det = getDeterminant();
585 if (std::abs(det) < ZERO) {
586 throw new NoninvertibleTransformException(determinantIsZero);
587 }
588 const float x = src.x() - m02;
589 const float y = src.y() - m12;
590 dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det, src.z());
591 return dst;
592 } */
593
594 void inverseTransform(const float src[], float dst[], size_t length) const {
595 size_t srcOff = 0;
596 size_t dstOff = 0;
597 const float det = determinant();
598 if (std::abs(det) < ZERO) {
599 throw MathDomainError(determinantIsZero, E_FILE_LINE);
600 }
601 while (length-- > 0) {
602 const float x = src[srcOff++] - m02;
603 const float y = src[srcOff++] - m12;
604 dst[dstOff++] = (x * m11 - y * m01) / det;
605 dst[dstOff++] = (y * m00 - x * m10) / det;
606 }
607 }
608
609 std::string toString() const noexcept {
610 return "AffineTransform[[" + std::to_string(m00) + ", " + std::to_string(m01) + ", " + std::to_string(m02) + "], ["
611 + std::to_string(m10) + ", " + std::to_string(m11) + ", " + std::to_string(m12) + "]]";
612 }
613
614 constexpr bool equals(const AffineTransform& o, const float epsilon=std::numeric_limits<float>::epsilon()) const noexcept {
615 if( this == &o ) {
616 return true;
617 } else {
618 return jau::equals(m00, o.m00, epsilon) &&
619 jau::equals(m01, o.m01, epsilon) &&
620 jau::equals(m02, o.m02, epsilon) &&
621 jau::equals(m10, o.m10, epsilon) &&
622 jau::equals(m11, o.m11, epsilon) &&
623 jau::equals(m12, o.m12, epsilon);
624 }
625 }
626 constexpr bool operator==(const AffineTransform& rhs) const noexcept {
627 return equals(rhs);
628 }
629 };
630
631/**@}*/
632
633} // namespace jau::math::geom::plane
634
635#endif /* JAU_AFFINETRANSFORM_HPP_ */
636
#define E_FILE_LINE
math_error_t::invalid
value_type x
Definition vec3f.hpp:69
value_type y
Definition vec3f.hpp:70
value_type z
Definition vec3f.hpp:71
Axis Aligned Bounding Box.
Definition aabbox3f.hpp:43
jau::function< jau::math::Vec3f(const jau::math::Vec3f &)> transform_vec3f_func
General purpose Vec3f transform function.
Definition aabbox3f.hpp:257
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
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::enable_if_t< std::is_floating_point_v< T >, bool > 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.
std::enable_if_t< std::is_floating_point_v< T >, bool > 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.
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition int_types.hpp:55
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:416
static constexpr bool operator!=(const AffineTransformType lhs, const AffineTransformType rhs) noexcept
Vector3F< float > Vec3f
Definition vec3f.hpp:433
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.