11#ifndef JAU_AFFINETRANSFORM_HPP_
12#define JAU_AFFINETRANSFORM_HPP_
71 constexpr static const char* determinantIsZero =
"Zero Determinante";
76 constexpr static const float ZERO = (float)1E-10;
80 : m00(1.0f), m10(0.0f),
86 constexpr AffineTransform(
const float m00_,
const float m10_,
const float m01_,
const float m11_,
const float m02_,
const float m12_) noexcept
87 : m00(m00_), m10(m10_),
98 : m00(mat2xN[0]), m10(mat2xN[1]),
99 m01(mat2xN[2]), m11(mat2xN[3]),
100 m02(0.0f), m12(0.0f),
140 if (m00 * m01 + m10 * m11 != 0.0f) {
153 if (m00 * m11 - m01 * m10 < 0.0f) {
157 const float dx = m00 * m00 + m10 * m10;
158 const float dy = m01 * m01 + m11 * m11;
175 float scaleX() const noexcept {
return m00; }
177 float scaleY() const noexcept {
return m11; }
179 float shearX() const noexcept {
return m01; }
181 float shearY() const noexcept {
return m10; }
204 float determinant() const noexcept {
return m00 * m11 - m01 * m10; }
206 AffineTransform&
set(
const float m00_,
const float m10_,
const float m01_,
const float m11_,
const float m02_,
const float m12_)
noexcept {
220 m10 = m01 = m02 = m12 = 0.0f;
240 m10 = m01 = m02 = m12 = 0.0f;
263 float sin = std::sin(angle);
264 float cos = std::cos(angle);
265 if (std::abs(cos) <
ZERO) {
267 sin = sin > 0.0f ? 1.0f : -1.0f;
268 }
else if (std::abs(sin) <
ZERO) {
270 cos = cos > 0.0f ? 1.0f : -1.0f;
282 m02 = px * (1.0f - m00) + py * m10;
283 m12 = py * (1.0f - m00) - px * m10;
289 return concat(tmp.setToTranslation(mx, my));
293 return concat(tmp.setToScale(scx, scy));
297 return concat(tmp.setToShear(shx, shy));
301 return concat(tmp.setToRotation(angle));
305 return concat(tmp.setToRotation(angle, px, py));
317 tR.m00 * tL.m00 + tR.m10 * tL.m01,
318 tR.m00 * tL.m10 + tR.m10 * tL.m11,
319 tR.m01 * tL.m00 + tR.m11 * tL.m01,
320 tR.m01 * tL.m10 + tR.m11 * tL.m11,
321 tR.m02 * tL.m00 + tR.m12 * tL.m01 + tL.m02,
322 tR.m02 * tL.m10 + tR.m12 * tL.m11 + tL.m12);
339 set( tR.m00 * m00 + tR.m10 * m01,
340 tR.m00 * m10 + tR.m10 * m11,
341 tR.m01 * m00 + tR.m11 * m01,
342 tR.m01 * m10 + tR.m11 * m11,
343 tR.m02 * m00 + tR.m12 * m01 + m02,
344 tR.m02 * m10 + tR.m12 * m11 + m12);
362 set( m00 * tL.m00 + m10 * tL.m01,
363 m00 * tL.m10 + m10 * tL.m11,
364 m01 * tL.m00 + m11 * tL.m01,
365 m01 * tL.m10 + m11 * tL.m11,
366 m02 * tL.m00 + m12 * tL.m01 + tL.m02,
367 m02 * tL.m10 + m12 * tL.m11 + tL.m12);
373 if (std::abs(det) <
ZERO) {
381 (m01 * m12 - m11 * m02) / det,
382 (m10 * m02 - m00 * m12) / det
393 const Vec3f& lo = src.low();
394 const Vec3f& hi = src.high();
395 dst.setSize(lo.
x * m00 + lo.
y * m01 + m02, lo.
x * m10 + lo.
y * m11 + m12, lo.
z,
396 hi.
x * m00 + hi.
y * m01 + m02, hi.
x * m10 + hi.
y * m11 + m12, hi.
z);
427 float*
transform(
const float src[],
float dst[])
const noexcept {
428 const float x = src[0];
429 const float y = src[1];
430 dst[0] = x * m00 + y * m01 + m02;
431 dst[1] = x * m10 + y * m11 + m12;
435 void transform(
const float src[],
float dst[],
size_t length)
const noexcept {
436 const float* src_end = src + length * 2;
437 if (src <= dst && dst < src_end ) {
439 size_t srcOff = length * 2 - 2;
440 size_t dstOff = length * 2 - 2;
441 while (length-- > 0) {
442 const float x = src[srcOff + 0];
443 const float y = src[srcOff + 1];
444 dst[dstOff + 0] = x * m00 + y * m01 + m02;
445 dst[dstOff + 1] = x * m10 + y * m11 + m12;
452 while (length-- > 0) {
453 const float x = src[srcOff++];
454 const float y = src[srcOff++];
455 dst[dstOff++] = x * m00 + y * m01 + m02;
456 dst[dstOff++] = x * m10 + y * m11 + m12;
467 const float x = src.x;
468 const float y = src.y;
469 dst.x = x * m00 + y * m01 + m02;
470 dst.y = x * m10 + y * m11 + m12;
479 const float x = src.x;
480 const float y = src.y;
481 return Vec2f( x * m00 + y * m01 + m02,
482 x * m10 + y * m11 + m12 );
491 const float x = src.x;
492 const float y = src.y;
493 dst.x = x * m00 + y * m01 + m02;
494 dst.y = x * m10 + y * m11 + m12;
500 Vec3f transformVec3f(
const Vec3f& src)
noexcept {
501 const float x = src.x;
502 const float y = src.y;
503 return Vec3f( x * m00 + y * m01 + m02,
504 x * m10 + y * m11 + m12,
516 const float x = src.x;
517 const float y = src.y;
518 return Vec3f( x * m00 + y * m01 + m02,
519 x * m10 + y * m11 + m12,
549 void deltaTransform(
const float src[],
float dst[],
size_t length)
const noexcept {
552 while (length-- > 0) {
553 const float x = src[srcOff++];
554 const float y = src[srcOff++];
555 dst[dstOff++] = x * m00 + y * m01;
556 dst[dstOff++] = x * m10 + y * m11;
581 if (std::abs(det) <
ZERO) {
584 while (length-- > 0) {
585 const float x = src[srcOff++] - m02;
586 const float y = src[srcOff++] - m12;
587 dst[dstOff++] = (x * m11 - y * m01) / det;
588 dst[dstOff++] = (y * m00 - x * m10) / det;
593 return "AffineTransform[[" + std::to_string(m00) +
", " + std::to_string(m01) +
", " + std::to_string(m02) +
"], ["
594 + std::to_string(m10) +
", " + std::to_string(m11) +
", " + std::to_string(m12) +
"]]";
597 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.
#define JAU_MAKE_BITFIELD_ENUM_STRING(type,...)
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.
jau::function< R(A...)> bind_member(C1 *base, R(C0::*mfunc)(A...)) noexcept
Bind given class instance and non-void member function to an anonymous function using func_member_tar...
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
@ unknown
The AffineTransformType::unknown is the initial value.
Author: Sven Gothel sgothel@jausoft.com Copyright Gothel Software e.K.