#ifndef __JMATRIX4D__ #define __JMATRIX4D__ #include #include #include #include #include "JIO/JSerialisable.hh" #include "JLang/JEquals.hh" #include "JLang/JManip.hh" #include "JMath/JMath.hh" #include "JMath/JMatrix3D.hh" /** * \author mdejong */ namespace JMATH {} namespace JPP { using namespace JMATH; } namespace JMATH { using JIO::JReader; using JIO::JWriter; using JLANG::JEquals; /** * 4 x 4 matrix */ class JMatrix4D : public JMath , public JEquals { public: using JMath::mul; /** * Default constructor. */ JMatrix4D() : a00(0.0), a01(0.0), a02(0.0), a03(0.0), a10(0.0), a11(0.0), a12(0.0), a13(0.0), a20(0.0), a21(0.0), a22(0.0), a23(0.0), a30(0.0), a31(0.0), a32(0.0), a33(0.0) {} /** * Contructor. * * \param __a00 (0,0) * \param __a01 (0,1) * \param __a02 (0,2) * \param __a03 (0,3) * \param __a10 (1,0) * \param __a11 (1,1) * \param __a12 (1,2) * \param __a13 (1,3) * \param __a20 (2,0) * \param __a21 (2,1) * \param __a22 (2,2) * \param __a23 (2,3) * \param __a30 (3,0) * \param __a31 (3,1) * \param __a32 (3,2) * \param __a33 (3,3) */ JMatrix4D(const double __a00, const double __a01, const double __a02, const double __a03, const double __a10, const double __a11, const double __a12, const double __a13, const double __a20, const double __a21, const double __a22, const double __a23, const double __a30, const double __a31, const double __a32, const double __a33) : a00(__a00), a01(__a01), a02(__a02), a03(__a03), a10(__a10), a11(__a11), a12(__a12), a13(__a13), a20(__a20), a21(__a21), a22(__a22), a23(__a23), a30(__a30), a31(__a31), a32(__a32), a33(__a33) {} /** * Get reference to unique instance of this class object. * * \return zero matrix */ static const JMatrix4D& getInstance() { static JMatrix4D matrix; return matrix; } /** * Set to identity matrix * * \return this matrix */ JMatrix4D& setIdentity() { a00 = 1.0; a01 = 0.0; a02 = 0.0; a03 = 0.0; a10 = 0.0; a11 = 1.0; a12 = 0.0; a13 = 0.0; a20 = 0.0; a21 = 0.0; a22 = 1.0; a23 = 0.0; a30 = 0.0; a31 = 0.0; a32 = 0.0; a33 = 1.0; return *this; } /** * Get reference to unique instance of this class object. * * \return identity matrix */ static const JMatrix4D& getIdentity() { static JMatrix4D matrix(JMatrix4D().setIdentity()); return matrix; } /** * Set matrix. * * \param A matrix */ void set(const JMatrix4D& A) { static_cast(*this) = A; } /** * Set matrix to the null matrix. * * \return this matrix */ JMatrix4D& reset() { *this = JMatrix4D(); return *this; } /** * Transpose. * * \return this matrix */ JMatrix4D& transpose() { using std::swap; swap(a10, a01); swap(a20, a02); swap(a21, a12); swap(a30, a03); swap(a31, a13); swap(a32, a23); return *this; } /** * Negate matrix. * * \return -this matrix */ JMatrix4D& negate() { a00 = -a00; a01 = -a01; a02 = -a02; a03 = -a03; a10 = -a10; a11 = -a11; a12 = -a12; a13 = -a13; a20 = -a20; a21 = -a21; a22 = -a22; a13 = -a23; a30 = -a30; a31 = -a31; a32 = -a32; a33 = -a33; return *this; } /** * Matrix addition. * * \param A matrix * \return this matrix + A */ JMatrix4D& add(const JMatrix4D& A) { a00 += A.a00; a01 += A.a01; a02 += A.a02; a03 += A.a03; a10 += A.a10; a11 += A.a11; a12 += A.a12; a13 += A.a13; a20 += A.a20; a21 += A.a21; a22 += A.a22; a23 += A.a23; a30 += A.a30; a31 += A.a31; a32 += A.a32; a33 += A.a33; return *this; } /** * Matrix subtraction. * * \param A matrix * \return this matrix - A */ JMatrix4D& sub(const JMatrix4D& A) { a00 -= A.a00; a01 -= A.a01; a02 -= A.a02; a03 -= A.a03; a10 -= A.a10; a11 -= A.a11; a12 -= A.a12; a13 -= A.a13; a20 -= A.a20; a21 -= A.a21; a22 -= A.a22; a23 -= A.a23; a30 -= A.a30; a31 -= A.a31; a32 -= A.a32; a33 -= A.a33; return *this; } /** * Scale matrix. * * \param factor factor * \return this matrix * factor */ JMatrix4D& mul(const double factor) { a00 *= factor; a01 *= factor; a02 *= factor; a03 *= factor; a10 *= factor; a11 *= factor; a12 *= factor; a13 *= factor; a20 *= factor; a21 *= factor; a22 *= factor; a23 *= factor; a30 *= factor; a31 *= factor; a32 *= factor; a33 *= factor; return *this; } /** * Scale matrix. * * \param factor factor * \return this matrix / factor */ JMatrix4D& div(const double factor) { a00 /= factor; a01 /= factor; a02 /= factor; a03 /= factor; a10 /= factor; a11 /= factor; a12 /= factor; a13 /= factor; a20 /= factor; a21 /= factor; a22 /= factor; a23 /= factor; a30 /= factor; a31 /= factor; a32 /= factor; a33 /= factor; return *this; } /** * Matrix multiplication. * * \param A matrix * \param B matrix * \return this matrix */ const JMatrix4D& mul(const JMatrix4D& A, const JMatrix4D& B) { a00 = A.a00 * B.a00 + A.a01 * B.a10 + A.a02 * B.a20 + A.a03 * B.a30; a01 = A.a00 * B.a01 + A.a01 * B.a11 + A.a02 * B.a21 + A.a03 * B.a31; a02 = A.a00 * B.a02 + A.a01 * B.a12 + A.a02 * B.a22 + A.a03 * B.a32; a03 = A.a00 * B.a03 + A.a01 * B.a13 + A.a02 * B.a23 + A.a03 * B.a33; a10 = A.a10 * B.a00 + A.a11 * B.a10 + A.a12 * B.a20 + A.a13 * B.a30; a11 = A.a10 * B.a01 + A.a11 * B.a11 + A.a12 * B.a21 + A.a13 * B.a31; a12 = A.a10 * B.a02 + A.a11 * B.a12 + A.a12 * B.a22 + A.a13 * B.a32; a13 = A.a10 * B.a03 + A.a11 * B.a13 + A.a12 * B.a23 + A.a13 * B.a33; a20 = A.a20 * B.a00 + A.a21 * B.a10 + A.a22 * B.a20 + A.a23 * B.a30; a21 = A.a20 * B.a01 + A.a21 * B.a11 + A.a22 * B.a21 + A.a23 * B.a31; a22 = A.a20 * B.a02 + A.a21 * B.a12 + A.a22 * B.a22 + A.a23 * B.a32; a23 = A.a20 * B.a03 + A.a21 * B.a13 + A.a22 * B.a23 + A.a23 * B.a33; a30 = A.a30 * B.a00 + A.a31 * B.a10 + A.a32 * B.a20 + A.a33 * B.a30; a31 = A.a30 * B.a01 + A.a31 * B.a11 + A.a32 * B.a21 + A.a33 * B.a31; a32 = A.a30 * B.a02 + A.a31 * B.a12 + A.a32 * B.a22 + A.a33 * B.a32; a33 = A.a30 * B.a03 + A.a31 * B.a13 + A.a32 * B.a23 + A.a33 * B.a33; return *this; } /** * Equality. * * \param A matrix * \param eps numerical precision * \return true if matrices identical; else false */ bool equals(const JMatrix4D& A, const double eps = std::numeric_limits::min()) const { return (fabs(a00 - A.a00) <= eps && fabs(a01 - A.a01) <= eps && fabs(a02 - A.a02) <= eps && fabs(a03 - A.a03) <= eps && fabs(a10 - A.a10) <= eps && fabs(a11 - A.a11) <= eps && fabs(a12 - A.a12) <= eps && fabs(a13 - A.a13) <= eps && fabs(a20 - A.a20) <= eps && fabs(a21 - A.a21) <= eps && fabs(a22 - A.a22) <= eps && fabs(a23 - A.a23) <= eps && fabs(a30 - A.a30) <= eps && fabs(a31 - A.a31) <= eps && fabs(a32 - A.a32) <= eps && fabs(a33 - A.a33) <= eps); } /** * Test identity. * * \param eps numerical precision * \return true if identity matrix; else false */ bool isIdentity(const double eps = std::numeric_limits::min()) const { return equals(getIdentity(), eps); } /** * Get determinant of matrix. * * \return determinant of matrix */ double getDeterminant() const { double det = 0.0; det += a00 * JMatrix3D(a11, a12, a13, a21, a22, a23, a31, a32, a33).getDeterminant(); det -= a01 * JMatrix3D(a10, a12, a13, a20, a22, a23, a30, a32, a33).getDeterminant(); det += a02 * JMatrix3D(a10, a11, a13, a20, a21, a23, a30, a31, a33).getDeterminant(); det -= a03 * JMatrix3D(a10, a11, a12, a20, a21, a22, a30, a31, a32).getDeterminant(); return det; } /** * Transform. * * \param __x0 x0 value * \param __x1 x1 value * \param __x2 x2 value * \param __x3 x3 value */ void transform(double& __x0, double& __x1, double& __x2, double& __x3) const { const double x0 = a00 * __x0 + a01 * __x1 + a02 * __x2 + a03 * __x3; const double x1 = a10 * __x0 + a11 * __x1 + a12 * __x2 + a13 * __x3; const double x2 = a20 * __x0 + a21 * __x1 + a22 * __x2 + a23 * __x3; const double x3 = a30 * __x0 + a31 * __x1 + a32 * __x2 + a33 * __x3; __x0 = x0; __x1 = x1; __x2 = x2; __x3 = x3; } /** * Read matrix from input. * * \param in reader * \param matrix matrix * \return reader */ friend inline JReader& operator>>(JReader& in, JMatrix4D& matrix) { in >> matrix.a00; in >> matrix.a01; in >> matrix.a02; in >> matrix.a03; in >> matrix.a10; in >> matrix.a11; in >> matrix.a12; in >> matrix.a13; in >> matrix.a20; in >> matrix.a21; in >> matrix.a22; in >> matrix.a23; in >> matrix.a30; in >> matrix.a31; in >> matrix.a32; in >> matrix.a33; return in; } /** * Write matrix to output. * * \param out writer * \param matrix matrix * \return writer */ friend inline JWriter& operator<<(JWriter& out, const JMatrix4D& matrix) { out << matrix.a00; out << matrix.a01; out << matrix.a02; out << matrix.a03; out << matrix.a10; out << matrix.a11; out << matrix.a12; out << matrix.a13; out << matrix.a20; out << matrix.a21; out << matrix.a22; out << matrix.a23; out << matrix.a30; out << matrix.a31; out << matrix.a32; out << matrix.a33; return out; } /** * Print ASCII formatted output. * * \param out output stream * \param A matrix * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JMatrix4D& A) { using namespace std; const JFormat format(out, getFormat(JFormat_t(10, 3, std::ios::fixed | std::ios::showpos))); out << format << A.a00 << ' ' << format << A.a01 << ' ' << format << A.a02 << ' ' << format << A.a03 << endl; out << format << A.a10 << ' ' << format << A.a11 << ' ' << format << A.a12 << ' ' << format << A.a13 << endl; out << format << A.a20 << ' ' << format << A.a21 << ' ' << format << A.a22 << ' ' << format << A.a23 << endl; out << format << A.a30 << ' ' << format << A.a31 << ' ' << format << A.a32 << ' ' << format << A.a33 << endl; return out; } double a00, a01, a02, a03; double a10, a11, a12, a13; double a20, a21, a22, a23; double a30, a31, a32, a33; }; } #endif