//################################################################################################## // // Custom Visualization Core library // Copyright (C) 2011-2013 Ceetron AS // // This library may be used under the terms of either the GNU General Public License or // the GNU Lesser General Public License as follows: // // GNU General Public License Usage // This library is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at <> // for more details. // // GNU Lesser General Public License Usage // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; either version 2.1 of the License, or // (at your option) any later version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU Lesser General Public License at <> // for more details. // //################################################################################################## namespace cvf { //================================================================================================== /// /// \class cvf::Matrix3 /// \ingroup Core /// /// Matrices are stored internally as a one dimensional array for performance reasons. /// /// The internal indices into the 1D array are as follows: /// ///
///   | m00  m01  m02 |     | 0  3   6 | 
///   | m10  m11  m12 |     | 1  4   7 | 
///   | m20  m21  m22 |     | 2  5  18 | 
/// 
/// /// See description of Matrix4 for more details on storage /// //================================================================================================== template Matrix3 const Matrix3::IDENTITY; template Matrix3 const Matrix3::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0); //---------------------------------------------------------------------------------------------------- /// Default constructor. Initializes matrix to identity //---------------------------------------------------------------------------------------------------- template Matrix3::Matrix3() { setIdentity(); } //---------------------------------------------------------------------------------------------------- /// Copy constructor //---------------------------------------------------------------------------------------------------- template inline Matrix3::Matrix3(const Matrix3& other) { System::memcpy(m_v, sizeof(m_v), other.m_v, sizeof(other.m_v)); } //---------------------------------------------------------------------------------------------------- /// Constructor with explicit initialization of all matrix elements. /// /// The value of the parameter \a mrc will be placed in row r and column c of the matrix, eg m12 /// goes into row 1, column 2. //---------------------------------------------------------------------------------------------------- template Matrix3::Matrix3(S m00, S m01, S m02, S m10, S m11, S m12, S m20, S m21, S m22) { m_v[e00] = m00; m_v[e10] = m10; m_v[e20] = m20; m_v[e01] = m01; m_v[e11] = m11; m_v[e21] = m21; m_v[e02] = m02; m_v[e12] = m12; m_v[e22] = m22; } //---------------------------------------------------------------------------------------------------- /// //---------------------------------------------------------------------------------------------------- template template Matrix3::Matrix3(const Matrix3& other) { m_v[e00] = static_cast(other.rowCol(0, 0)); m_v[e01] = static_cast(other.rowCol(0, 1)); m_v[e02] = static_cast(other.rowCol(0, 2)); m_v[e10] = static_cast(other.rowCol(1, 0)); m_v[e11] = static_cast(other.rowCol(1, 1)); m_v[e12] = static_cast(other.rowCol(1, 2)); m_v[e20] = static_cast(other.rowCol(2, 0)); m_v[e21] = static_cast(other.rowCol(2, 1)); m_v[e22] = static_cast(other.rowCol(2, 2)); } //---------------------------------------------------------------------------------------------------- /// Assignment operator //---------------------------------------------------------------------------------------------------- template inline Matrix3& Matrix3::operator=(const Matrix3& obj) { System::memcpy(m_v, sizeof(m_v), obj.m_v, sizeof(obj.m_v)); return *this; } //---------------------------------------------------------------------------------------------------- /// Check if matrices are equal using exact comparisons. //---------------------------------------------------------------------------------------------------- template bool Matrix3::equals(const Matrix3& mat) const { for (int i = 0; i < 9; i++) { if (m_v[i] != mat.m_v[i]) return false; } return true; } //---------------------------------------------------------------------------------------------------- /// Comparison operator. Checks for equality using exact comparisons. //---------------------------------------------------------------------------------------------------- template bool Matrix3::operator==(const Matrix3& rhs) const { return this->equals(rhs); } //---------------------------------------------------------------------------------------------------- /// Comparison operator. Checks for not equal using exact comparisons. //---------------------------------------------------------------------------------------------------- template bool Matrix3::operator!=(const Matrix3& rhs) const { int i; for (i = 0; i < 9; i++) { if (m_v[i] != rhs.m_v[i]) return true; } return false; } //-------------------------------------------------------------------------------------------------- /// Multiplies this matrix M with the matrix \a mat, M = M*mat //-------------------------------------------------------------------------------------------------- template void Matrix3::multiply(const Matrix3& mat) { *this = (*this)*mat; } //---------------------------------------------------------------------------------------------------- /// //---------------------------------------------------------------------------------------------------- template const Matrix3 Matrix3::operator*(const Matrix3& rhs) const { Matrix3 m; int r; for (r = 0; r < 3; r++) { int c; for (c = 0; c < 3; c++) { S val = 0; int a; for (a = 0; a < 3; a++) { val += rowCol(r, a)*rhs.rowCol(a, c); } m.setRowCol(r, c, val); } } return m; } //---------------------------------------------------------------------------------------------------- /// Sets this matrix to identity //---------------------------------------------------------------------------------------------------- template void Matrix3::setIdentity() { m_v[0] = 1; m_v[1] = 0; m_v[2] = 0; m_v[3] = 0; m_v[4] = 1; m_v[5] = 0; m_v[6] = 0; m_v[7] = 0; m_v[8] = 1; } //---------------------------------------------------------------------------------------------------- /// Check if this matrix is identity using exact comparisons //---------------------------------------------------------------------------------------------------- template bool Matrix3::isIdentity() const { if (m_v[0] != 1) return false; if (m_v[1] != 0) return false; if (m_v[2] != 0) return false; if (m_v[3] != 0) return false; if (m_v[4] != 1) return false; if (m_v[5] != 0) return false; if (m_v[6] != 0) return false; if (m_v[7] != 0) return false; if (m_v[8] != 1) return false; return true; } //---------------------------------------------------------------------------------------------------- /// Set all matrix elements to 0 //---------------------------------------------------------------------------------------------------- template void Matrix3::setZero() { m_v[0] = 0; m_v[1] = 0; m_v[2] = 0; m_v[3] = 0; m_v[4] = 0; m_v[5] = 0; m_v[6] = 0; m_v[7] = 0; m_v[8] = 0; } //---------------------------------------------------------------------------------------------------- /// Returns true if all elements of the matrix are 0. Uses exact comparison. //---------------------------------------------------------------------------------------------------- template bool Matrix3::isZero() const { if (m_v[0] != 0) return false; if (m_v[1] != 0) return false; if (m_v[2] != 0) return false; if (m_v[3] != 0) return false; if (m_v[4] != 0) return false; if (m_v[5] != 0) return false; if (m_v[6] != 0) return false; if (m_v[7] != 0) return false; if (m_v[8] != 0) return false; return true; } //---------------------------------------------------------------------------------------------------- /// Set the matrix element at the specified row and column //---------------------------------------------------------------------------------------------------- template inline void Matrix3::setRowCol(int row, int col, S value) { CVF_TIGHT_ASSERT(row >= 0 && row < 3); CVF_TIGHT_ASSERT(col >= 0 && col < 3); m_v[3*col + row] = value; } //---------------------------------------------------------------------------------------------------- /// Get the matrix element at the specified row and column //---------------------------------------------------------------------------------------------------- template inline S Matrix3::rowCol(int row, int col) const { CVF_TIGHT_ASSERT(row >= 0 && row < 3); CVF_TIGHT_ASSERT(col >= 0 && col < 3); return m_v[3*col + row]; } //-------------------------------------------------------------------------------------------------- /// Get modifiable reference to the the matrix element at the specified row and column //-------------------------------------------------------------------------------------------------- template inline S& Matrix3::operator()(int row, int col) { CVF_TIGHT_ASSERT(row >= 0 && row < 3); CVF_TIGHT_ASSERT(col >= 0 && col < 3); return m_v[3*col + row]; } //-------------------------------------------------------------------------------------------------- /// Get the matrix element at the specified row and column //-------------------------------------------------------------------------------------------------- template inline S Matrix3::operator()(int row, int col) const { CVF_TIGHT_ASSERT(row >= 0 && row < 3); CVF_TIGHT_ASSERT(col >= 0 && col < 3); return m_v[3*col + row]; } //---------------------------------------------------------------------------------------------------- /// //---------------------------------------------------------------------------------------------------- template bool Matrix3::invert() { // Use double internally here double m00 = static_cast(m_v[e00]); double m10 = static_cast(m_v[e10]); double m20 = static_cast(m_v[e20]); double m01 = static_cast(m_v[e01]); double m11 = static_cast(m_v[e11]); double m21 = static_cast(m_v[e21]); double m02 = static_cast(m_v[e02]); double m12 = static_cast(m_v[e12]); double m22 = static_cast(m_v[e22]); double det = m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 - m02*m11*m20; if (Math::abs(det) > std::numeric_limits::epsilon()) { double invDet = 1/det; m_v[e00] = static_cast( (m11*m22 - m12*m21) * invDet ); m_v[e01] = static_cast( (m02*m21 - m01*m22) * invDet ); m_v[e02] = static_cast( (m01*m12 - m02*m11) * invDet ); m_v[e10] = static_cast( (m12*m20 - m10*m22) * invDet ); m_v[e11] = static_cast( (m00*m22 - m02*m20) * invDet ); m_v[e12] = static_cast( (m02*m10 - m00*m12) * invDet ); m_v[e20] = static_cast( (m10*m21 - m11*m20) * invDet ); m_v[e21] = static_cast( (m01*m20 - m00*m21) * invDet ); m_v[e22] = static_cast( (m00*m11 - m01*m10) * invDet ); return true; } else { return false; } } //---------------------------------------------------------------------------------------------------- /// //---------------------------------------------------------------------------------------------------- template const Matrix3 Matrix3::getInverted(bool* pInvertible) const { Matrix3 m(*this); if (m.invert()) { if (pInvertible) *pInvertible = true; } else { if (pInvertible) *pInvertible = false; m.setZero(); } return m; } //---------------------------------------------------------------------------------------------------- /// //---------------------------------------------------------------------------------------------------- template S Matrix3::determinant() const { S det = m_v[e00]*m_v[e11]*m_v[e22] + m_v[e01]*m_v[e12]*m_v[e20] + m_v[e02]*m_v[e10]*m_v[e21] - m_v[e00]*m_v[e12]*m_v[e21] - m_v[e01]*m_v[e10]*m_v[e22] - m_v[e02]*m_v[e11]*m_v[e20]; return det; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void Matrix3::transpose() { S tmp; int i, j; for (i = 0; i < 3; i++) { for (j = i + 1; j < 3; j++) { tmp = m_v[j + 3*i]; m_v[j + 3*i] = m_v[3*j + i]; m_v[3*j + i] = tmp; } } } //---------------------------------------------------------------------------------------------------- /// //---------------------------------------------------------------------------------------------------- template const S* Matrix3::ptr() const { return m_v; } //---------------------------------------------------------------------------------------------------- /// //---------------------------------------------------------------------------------------------------- template Matrix3 Matrix3::fromRotation(Vector3 axis, S angle) { axis.normalize(); S rcos = Math::cos(angle); S rsin = Math::sin(angle); Matrix3 m; m.m_v[e00] = rcos + axis.x()*axis.x()*(1 - rcos); m.m_v[e10] = axis.z() * rsin + axis.y()*axis.x()*(1 - rcos); m.m_v[e20] = -axis.y() * rsin + axis.z()*axis.x()*(1 - rcos); m.m_v[e01] = -axis.z() * rsin + axis.x()*axis.y()*(1 - rcos); m.m_v[e11] = rcos + axis.y()*axis.y()*(1 - rcos); m.m_v[e21] = axis.x() * rsin + axis.z()*axis.y()*(1 - rcos); m.m_v[e02] = axis.y() * rsin + axis.x()*axis.z()*(1 - rcos); m.m_v[e12] = -axis.x() * rsin + axis.y()*axis.z()*(1 - rcos); m.m_v[e22] = rcos + axis.z()*axis.z()*(1 - rcos); return m; } }