11#ifndef JAU_AFFINETRANSFORM_HPP_
12#define JAU_AFFINETRANSFORM_HPP_
43 return static_cast<int>(rhs);
62 return !( lhs == rhs );
65 return bit == ( mask & bit );
92 constexpr static const char* determinantIsZero =
"Zero Determinante";
97 constexpr static const float ZERO = (float)1E-10;
101 : m00(1.0f), m10(0.0f),
102 m01(0.0f), m11(1.0f),
103 m02(0.0f), m12(0.0f),
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_),
119 : m00(mat2xN[0]), m10(mat2xN[1]),
120 m01(mat2xN[2]), m11(mat2xN[3]),
121 m02(0.0f), m12(0.0f),
161 if (m00 * m01 + m10 * m11 != 0.0f) {
174 if (m00 * m11 - m01 * m10 < 0.0f) {
178 const float dx = m00 * m00 + m10 * m10;
179 const float dy = m01 * m01 + m11 * m11;
196 float scaleX() const noexcept {
return m00; }
198 float scaleY() const noexcept {
return m11; }
200 float shearX() const noexcept {
return m01; }
202 float shearY() const noexcept {
return m10; }
225 float determinant() const noexcept {
return m00 * m11 - m01 * m10; }
227 AffineTransform&
set(
const float m00_,
const float m10_,
const float m01_,
const float m11_,
const float m02_,
const float m12_)
noexcept {
241 m10 = m01 = m02 = m12 = 0.0f;
261 m10 = m01 = m02 = m12 = 0.0f;
284 float sin = std::sin(angle);
285 float cos = std::cos(angle);
286 if (std::abs(cos) <
ZERO) {
288 sin = sin > 0.0f ? 1.0f : -1.0f;
289 }
else if (std::abs(sin) <
ZERO) {
291 cos = cos > 0.0f ? 1.0f : -1.0f;
303 m02 = px * (1.0f - m00) + py * m10;
304 m12 = py * (1.0f - m00) - px * m10;
310 return concat(tmp.setToTranslation(mx, my));
314 return concat(tmp.setToScale(scx, scy));
318 return concat(tmp.setToShear(shx, shy));
322 return concat(tmp.setToRotation(angle));
326 return concat(tmp.setToRotation(angle, px, py));
338 tR.m00 * tL.m00 + tR.m10 * tL.m01,
339 tR.m00 * tL.m10 + tR.m10 * tL.m11,
340 tR.m01 * tL.m00 + tR.m11 * tL.m01,
341 tR.m01 * tL.m10 + tR.m11 * tL.m11,
342 tR.m02 * tL.m00 + tR.m12 * tL.m01 + tL.m02,
343 tR.m02 * tL.m10 + tR.m12 * tL.m11 + tL.m12);
360 set( tR.m00 * m00 + tR.m10 * m01,
361 tR.m00 * m10 + tR.m10 * m11,
362 tR.m01 * m00 + tR.m11 * m01,
363 tR.m01 * m10 + tR.m11 * m11,
364 tR.m02 * m00 + tR.m12 * m01 + m02,
365 tR.m02 * m10 + tR.m12 * m11 + m12);
383 set( m00 * tL.m00 + m10 * tL.m01,
384 m00 * tL.m10 + m10 * tL.m11,
385 m01 * tL.m00 + m11 * tL.m01,
386 m01 * tL.m10 + m11 * tL.m11,
387 m02 * tL.m00 + m12 * tL.m01 + tL.m02,
388 m02 * tL.m10 + m12 * tL.m11 + tL.m12);
394 if (std::abs(det) <
ZERO) {
402 (m01 * m12 - m11 * m02) / det,
403 (m10 * m02 - m00 * m12) / det
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);
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;
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 ) {
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;
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;
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;
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 );
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;
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,
537 return transformVec3f(src);
566 void deltaTransform(
const float src[],
float dst[],
size_t length)
const noexcept {
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;
598 if (std::abs(det) <
ZERO) {
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;
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) +
"]]";
614 constexpr bool equals(
const AffineTransform& o,
const float epsilon=std::numeric_limits<float>::epsilon()) const noexcept {
Axis Aligned Bounding Box.
jau::function< jau::math::Vec3f(const jau::math::Vec3f &)> transform_vec3f_func
General purpose Vec3f transform function.
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.
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
static constexpr bool operator!=(const AffineTransformType lhs, const AffineTransformType rhs) noexcept
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.