13 #ifndef INCLUDED_ATOMSMATHMATRIXALGO_H
14 #define INCLUDED_ATOMSMATHMATRIXALGO_H
16 #include <AtomsMath/ImathEuler.h>
17 #include <AtomsMath/ImathExport.h>
18 #include <AtomsMath/ImathMatrix.h>
19 #include <AtomsMath/ImathNamespace.h>
20 #include <AtomsMath/ImathQuat.h>
21 #include <AtomsMath/ImathVec.h>
24 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_ENTER
31 ATOMSMATH_EXPORT_CONST
M22f identity22f;
33 ATOMSMATH_EXPORT_CONST
M33f identity33f;
35 ATOMSMATH_EXPORT_CONST
M44f identity44f;
37 ATOMSMATH_EXPORT_CONST
M22d identity22d;
39 ATOMSMATH_EXPORT_CONST
M33d identity33d;
41 ATOMSMATH_EXPORT_CONST
M44d identity44d;
96 template <
class T>
bool extractScaling (
const Matrix44<T>& mat,
Vec3<T>& scl,
bool exc =
true);
111 template <
class T>
bool removeScaling (
Matrix44<T>& mat,
bool exc =
true);
143 template <
class T>
bool removeScalingAndShear (
Matrix44<T>& mat,
bool exc =
true);
238 template <
class T>
bool checkForZeroScaleInRow (
const T& scl,
const Vec3<T>& row,
bool exc =
true);
324 template <
class T>
bool extractScaling (
const Matrix33<T>& mat,
Vec2<T>& scl,
bool exc =
true);
339 template <
class T>
bool removeScaling (
Matrix33<T>& mat,
bool exc =
true);
351 bool extractScalingAndShear (
const Matrix33<T>& mat,
Vec2<T>& scl, T& shr,
bool exc =
true);
365 template <
class T>
bool removeScalingAndShear (
Matrix33<T>& mat,
bool exc =
true);
376 bool extractAndRemoveScalingAndShear (
Matrix33<T>& mat,
Vec2<T>& scl, T& shr,
bool exc =
true);
382 template <
class T>
void extractEuler (
const Matrix22<T>& mat, T& rot);
388 template <
class T>
void extractEuler (
const Matrix33<T>& mat, T& rot);
408 template <
class T>
bool checkForZeroScaleInRow (
const T& scl,
const Vec2<T>& row,
bool exc =
true);
424 if (!extractAndRemoveScalingAndShear (M, scl, shr, exc))
439 if (!extractSHRT (mat, scl, shr, rot, tran, exc))
460 if (!extractSHRT (mat, scl, shr, rot, tran, exc))
477 if (!extractAndRemoveScalingAndShear (M, scl, shr, exc))
485 sansScalingAndShear (
const Matrix44<T>& mat,
bool exc)
491 if (!extractAndRemoveScalingAndShear (M, scl, shr, exc))
504 if (!extractAndRemoveScalingAndShear (result, scl, shr, exc))
515 if (!extractAndRemoveScalingAndShear (mat, scl, shr, exc))
533 row[0] =
Vec3<T> (mat[0][0], mat[0][1], mat[0][2]);
534 row[1] =
Vec3<T> (mat[1][0], mat[1][1], mat[1][2]);
535 row[2] =
Vec3<T> (mat[2][0], mat[2][1], mat[2][2]);
538 for (
int i = 0; i < 3; i++)
539 for (
int j = 0; j < 3; j++)
540 if (ATOMSMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal)
541 maxVal = ATOMSMATH_INTERNAL_NAMESPACE::abs (row[i][j]);
553 for (
int i = 0; i < 3; i++)
554 if (!checkForZeroScaleInRow (maxVal, row[i], exc))
562 if (!checkForZeroScaleInRow (scl.x, row[0], exc))
579 shr[0] = row[0].
dot (row[1]);
580 row[1] -= shr[0] * row[0];
583 scl.y = row[1].length();
584 if (!checkForZeroScaleInRow (scl.y, row[1], exc))
592 shr[1] = row[0].
dot (row[2]);
593 row[2] -= shr[1] * row[0];
594 shr[2] = row[1].
dot (row[2]);
595 row[2] -= shr[2] * row[1];
598 scl.z = row[2].length();
599 if (!checkForZeroScaleInRow (scl.z, row[2], exc))
610 if (row[0].dot (row[1].cross (row[2])) < 0)
611 for (
int i = 0; i < 3; i++)
619 for (
int i = 0; i < 3; i++)
621 mat[i][0] = row[i][0];
622 mat[i][1] = row[i][1];
623 mat[i][2] = row[i][2];
642 Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]);
643 Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]);
644 Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]);
650 Matrix44<T> M (i[0], i[1], i[2], 0, j[0], j[1], j[2], 0, k[0], k[1], k[2], 0, 0, 0, 0, 1);
656 rot.x = std::atan2 (M[1][2], M[2][2]);
672 T cy = std::sqrt (N[0][0] * N[0][0] + N[0][1] * N[0][1]);
673 rot.y = std::atan2 (-N[0][2], cy);
674 rot.z = std::atan2 (-N[1][0], N[1][1]);
685 Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]);
686 Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]);
687 Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]);
693 Matrix44<T> M (i[0], i[1], i[2], 0, j[0], j[1], j[2], 0, k[0], k[1], k[2], 0, 0, 0, 0, 1);
699 rot.x = -std::atan2 (M[1][0], M[0][0]);
715 T cy = std::sqrt (N[2][2] * N[2][2] + N[2][1] * N[2][1]);
716 rot.y = -std::atan2 (-N[2][0], cy);
717 rot.z = -std::atan2 (-N[1][2], N[1][1]);
729 int nxt[3] = { 1, 2, 0 };
730 tr = mat[0][0] + mat[1][1] + mat[2][2];
735 s = std::sqrt (tr + T (1.0));
736 quat.
r = s / T (2.0);
739 quat.
v.x = (mat[1][2] - mat[2][1]) * s;
740 quat.
v.y = (mat[2][0] - mat[0][2]) * s;
741 quat.
v.z = (mat[0][1] - mat[1][0]) * s;
747 if (mat[1][1] > mat[0][0])
749 if (mat[2][2] > mat[i][i])
754 s = std::sqrt ((mat[i][i] - (mat[j][j] + mat[k][k])) + T (1.0));
760 q[3] = (mat[j][k] - mat[k][j]) * s;
761 q[j] = (mat[i][j] + mat[j][i]) * s;
762 q[k] = (mat[i][k] + mat[k][i]) * s;
786 if (!extractAndRemoveScalingAndShear (rot, s, h, exc))
789 extractEulerXYZ (rot, r);
821 return extractSHRT (mat, s, h, r, t, exc, r.
order());
826 checkForZeroScaleInRow (
const T& scl,
const Vec3<T>& row,
bool exc )
828 for (
int i = 0; i < 3; i++)
830 if ((abs (scl) < 1 && abs (row[i]) >= std::numeric_limits<T>::max() * abs (scl)))
832 #ifdef ATOMS_USE_EXCEPTIONS
834 throw std::domain_error (
"Cannot remove zero scaling "
889 if (fromDir.
length() == 0)
895 alignZAxisWithTargetDir (zAxis2FromDir, fromDir,
Vec3<T> (0, 1, 0));
900 alignZAxisWithTargetDir (zAxis2ToDir, toDir, upDir);
902 return fromDir2zAxis * zAxis2ToDir;
914 if (targetDir.
length() == 0)
955 result.
x[0][0] = row[0][0];
956 result.
x[0][1] = row[0][1];
957 result.
x[0][2] = row[0][2];
958 result.
x[0][3] = (T) 0;
960 result.
x[1][0] = row[1][0];
961 result.
x[1][1] = row[1][1];
962 result.
x[1][2] = row[1][2];
963 result.
x[1][3] = (T) 0;
965 result.
x[2][0] = row[2][0];
966 result.
x[2][1] = row[2][1];
967 result.
x[2][2] = row[2][2];
968 result.
x[2][3] = (T) 0;
970 result.
x[3][0] = (T) 0;
971 result.
x[3][1] = (T) 0;
972 result.
x[3][2] = (T) 0;
973 result.
x[3][3] = (T) 1;
989 Vec3<T> y = (normal % x).normalize();
990 Vec3<T> z = (x % y).normalize();
1036 _rOffset *= M_PI / 180.0;
1039 O[3][0] = tOffset[0];
1040 O[3][1] = tOffset[1];
1041 O[3][2] = tOffset[2];
1063 extractSHRT (A, as, ah, ar, at);
1066 extractSHRT (B, bs, bh, br, bt);
1094 if (!extractAndRemoveScalingAndShear (M, scl, shr, exc))
1109 if (!extractSHRT (mat, scl, shr, rot, tran, exc))
1130 if (!extractSHRT (mat, scl, shr, rot, tran, exc))
1147 if (!extractAndRemoveScalingAndShear (M, scl, shr, exc))
1155 sansScalingAndShear (
const Matrix33<T>& mat,
bool exc)
1161 if (!extractAndRemoveScalingAndShear (M, scl, shr, exc))
1169 removeScalingAndShear (
Matrix33<T>& mat,
bool exc)
1174 if (!extractAndRemoveScalingAndShear (mat, scl, shr, exc))
1186 row[0] =
Vec2<T> (mat[0][0], mat[0][1]);
1187 row[1] =
Vec2<T> (mat[1][0], mat[1][1]);
1190 for (
int i = 0; i < 2; i++)
1191 for (
int j = 0; j < 2; j++)
1192 if (ATOMSMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal)
1193 maxVal = ATOMSMATH_INTERNAL_NAMESPACE::abs (row[i][j]);
1205 for (
int i = 0; i < 2; i++)
1206 if (!checkForZeroScaleInRow (maxVal, row[i], exc))
1214 if (!checkForZeroScaleInRow (scl.x, row[0], exc))
1230 shr = row[0].
dot (row[1]);
1231 row[1] -= shr * row[0];
1234 scl.y = row[1].length();
1235 if (!checkForZeroScaleInRow (scl.y, row[1], exc))
1246 if (row[0][0] * row[1][1] - row[0][1] * row[1][0] < 0)
1256 for (
int i = 0; i < 2; i++)
1258 mat[i][0] = row[i][0];
1259 mat[i][1] = row[i][1];
1275 Vec2<T> i (mat[0][0], mat[0][1]);
1276 Vec2<T> j (mat[1][0], mat[1][1]);
1285 rot = -std::atan2 (j[0], i[0]);
1296 Vec2<T> i (mat[0][0], mat[0][1]);
1297 Vec2<T> j (mat[1][0], mat[1][1]);
1306 rot = -std::atan2 (j[0], i[0]);
1316 if (!extractAndRemoveScalingAndShear (rot, s, h, exc))
1319 extractEuler (rot, r);
1330 checkForZeroScaleInRow (
const T& scl,
const Vec2<T>& row,
bool exc )
1332 for (
int i = 0; i < 2; i++)
1334 if ((abs (scl) < 1 && abs (row[i]) >= std::numeric_limits<T>::max() * abs (scl)))
1336 #ifdef ATOMS_USE_EXCEPTIONS
1338 throw std::domain_error (
"Cannot remove zero scaling from matrix.");
1379 template <
typename T>
1381 procrustesRotationAndTranslation (
const Vec3<T>* A,
1384 const size_t numPoints,
1385 const bool doScaling =
false);
1401 template <
typename T>
1403 procrustesRotationAndTranslation (
const Vec3<T>* A,
1405 const size_t numPoints,
1406 const bool doScaling =
false);
1423 template <
typename T>
1428 const T tol = std::numeric_limits<T>::epsilon(),
1429 const bool forcePositiveDeterminant =
false);
1446 template <
typename T>
1451 const T tol = std::numeric_limits<T>::epsilon(),
1452 const bool forcePositiveDeterminant =
false);
1463 template <
typename T>
1474 template <
typename T>
1478 jacobiEigenSolver (A, S, V, std::numeric_limits<T>::epsilon());
1490 template <
typename T>
1501 template <
typename T>
1505 jacobiEigenSolver (A, S, V, std::numeric_limits<T>::epsilon());
1510 template <
typename TM,
typename TV>
void maxEigenVector (TM& A, TV& S);
1514 template <
typename TM,
typename TV>
void minEigenVector (TM& A, TV& S);
1516 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_EXIT
Definition: ImathEuler.h:118
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Order order() const noexcept
Return the order.
Order
Definition: ImathEuler.h:129
Definition: ImathMatrix.h:44
Definition: ImathMatrix.h:305
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Matrix33 & translate(const Vec2< S > &t) noexcept
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Matrix33 & shear(const S &xy) noexcept
ATOMSMATH_HOSTDEVICE void makeIdentity() noexcept
Set to the identity matrix.
Definition: ImathMatrix.h:1875
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Matrix33 & rotate(S r) noexcept
Definition: ImathMatrix.h:631
constexpr ATOMSMATH_HOSTDEVICE Matrix44 transposed() const noexcept
Return the transpose.
Definition: ImathMatrix.h:3708
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Matrix44 & scale(const Vec3< S > &s) noexcept
ATOMSMATH_HOSTDEVICE void makeIdentity() noexcept
Set to the identity matrix.
Definition: ImathMatrix.h:3223
T x[4][4]
Matrix elements.
Definition: ImathMatrix.h:638
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Matrix44 & translate(const Vec3< S > &t) noexcept
ATOMSMATH_HOSTDEVICE const Matrix44 & rotate(const Vec3< S > &r) noexcept
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Matrix44 & shear(const Vec3< S > &h) noexcept
Definition: ImathQuat.h:41
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat< T > & setRotation(const Vec3< T > &fromDirection, const Vec3< T > &toDirection) noexcept
Definition: ImathQuat.h:673
Vec3< T > v
The imaginary vector.
Definition: ImathQuat.h:51
T r
The real part.
Definition: ImathQuat.h:48
constexpr ATOMSMATH_HOSTDEVICE Matrix44< T > toMatrix44() const noexcept
Return a 4x4 rotation matrix.
Definition: ImathQuat.h:795
Definition: ImathVec.h:43
constexpr ATOMSMATH_HOSTDEVICE T dot(const Vec2 &v) const noexcept
Dot product.
Definition: ImathVec.h:931
ATOMSMATH_HOSTDEVICE T length() const noexcept
Return the Euclidean norm.
Definition: ImathVec.h:1098
Definition: ImathVec.h:260
constexpr ATOMSMATH_HOSTDEVICE Vec3 cross(const Vec3 &v) const noexcept
Right-handed cross product.
Definition: ImathVec.h:1384
constexpr ATOMSMATH_HOSTDEVICE T dot(const Vec3 &v) const noexcept
Dot product.
Definition: ImathVec.h:1370
ATOMSMATH_HOSTDEVICE Vec3< T > normalized() const noexcept
Return a normalized vector. Does not modify *this.
Definition: ImathVec.h:1629
ATOMSMATH_HOSTDEVICE T length() const noexcept
Return the Euclidean norm.
Definition: ImathVec.h:1562
ATOMSMATH_HOSTDEVICE const Vec3 & normalize() noexcept
Normalize in place. If length()==0, return a null vector.
Definition: ImathVec.h:1581
Definition: ImathVec.h:486