fw4spl
SrcLib/core/fwDataTools/src/fwDataTools/TransformationMatrix3D.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwDataTools/TransformationMatrix3D.hpp"
8 
9 #include <glm/gtc/type_ptr.hpp>
10 #include <glm/matrix.hpp>
11 
12 namespace fwDataTools
13 {
14 
15 //------------------------------------------------------------------------------
16 
17 bool TransformationMatrix3D::invert(const ::fwData::TransformationMatrix3D::csptr& _input,
18  ::fwData::TransformationMatrix3D::sptr& _output)
19 {
20  // Normally we should transpose matrices since GLM uses a column-major layout and FW4SPL uses row-major layout
21  // However the transposition has a cost and inversion does not care about the layout, so we skip it
22  const ::glm::dmat4x4 mat = ::glm::make_mat4<double>(_input->getCoefficients().data());
23  const ::glm::dmat4x4 matInverse = ::glm::inverse(mat);
24 
25  auto& coefs = _output->getCoefficients();
26  for (size_t i = 0; i < 4; ++i)
27  {
28  const size_t rowDst = i * 4;
29  const ::glm::length_t rowSrc = static_cast< ::glm::length_t>(i);
30  for (size_t j = 0; j < 4; ++j)
31  {
32  const ::glm::length_t colSrc = static_cast< ::glm::length_t>(j);
33  coefs[rowDst+j] = matInverse[rowSrc][colSrc];
34  }
35  }
36 
37  return true;
38 }
39 
40 // ----------------------------------------------------------------------------
41 
42 void TransformationMatrix3D::multiply(const ::fwData::TransformationMatrix3D::csptr& _trfA,
43  const ::fwData::TransformationMatrix3D::csptr& _trfB,
44  ::fwData::TransformationMatrix3D::sptr& _output)
45 {
46  // Normally we should transpose matrices since GLM uses a column-major layout and FW4SPL uses row-major layout
47  // However the transposition has a cost, so it is faster to not transpose them
48  // and perform the inverse multiplication
49  const ::glm::dmat4x4 matA = ::glm::make_mat4<double>(_trfA->getCoefficients().data());
50  const ::glm::dmat4x4 matB = ::glm::make_mat4<double>(_trfB->getCoefficients().data());
51 
52  const ::glm::dmat4x4 matC = matB * matA;
53 
54  auto& coefs = _output->getCoefficients();
55  for (size_t i = 0; i < 4; ++i)
56  {
57  const size_t rowDst = i * 4;
58  const ::glm::length_t rowSrc = static_cast< ::glm::length_t>(i);
59  for (size_t j = 0; j < 4; ++j)
60  {
61  const ::glm::length_t colSrc = static_cast< ::glm::length_t>(j);
62  coefs[rowDst + j] = matC[rowSrc][colSrc];
63  }
64  }
65 }
66 
67 // ----------------------------------------------------------------------------
68 
69 void TransformationMatrix3D::identity(::fwData::TransformationMatrix3D::sptr& _trf)
70 {
71  for (size_t i = 0; i < 4; ++i)
72  {
73  for (size_t j = 0; j < 4; ++j)
74  {
75  _trf->setCoefficient(i, j, i == j ? 1 : 0);
76  }
77  }
78 }
79 
80 // ----------------------------------------------------------------------------
81 
82 void TransformationMatrix3D::multiply(const ::fwData::TransformationMatrix3D::csptr& _trf,
83  const ::fwData::Point::csptr& _input, ::fwData::Point::sptr& _output)
84 {
85  // Normally we should transpose matrices since GLM uses a column-major layout and FW4SPL uses row-major layout
86  // However the transposition has a cost, so it is faster to not transpose them
87  // and perform the inverse multiplication
88  const ::glm::dmat4x4 mat = ::glm::make_mat4<double>(_trf->getCoefficients().data());
89 
90  const auto& inCoord = _input->getCoord();
91  ::glm::dvec4 in;
92  in[0] = inCoord[0];
93  in[1] = inCoord[1];
94  in[2] = inCoord[2];
95  in[3] = 1;
96 
97  ::glm::dvec4 out = in * mat;
98  std::array<double, 3> res = {{ out[0], out[1], out[2] }};
99  _output->setCoord(res);
100 }
101 
102 // ----------------------------------------------------------------------------
103 
104 bool TransformationMatrix3D::isIdentity(const ::fwData::TransformationMatrix3D::csptr& _trf, const double _epsilon)
105 {
106  static const ::fwData::TransformationMatrix3D::sptr s_IDENTITY = ::fwData::TransformationMatrix3D::New();
107 
108  const ::fwData::TransformationMatrix3D::TMCoefArray& arrayID = s_IDENTITY->getCoefficients();
109  const ::fwData::TransformationMatrix3D::TMCoefArray& arrayTrf = _trf->getCoefficients();
110 
111  for(size_t i = 0; i < arrayID.size(); ++i)
112  {
113  if(std::abs(arrayID[i] - arrayTrf[i]) > _epsilon)
114  {
115  return false;
116  }
117  }
118 
119  return true;
120 }
121 
122 // ----------------------------------------------------------------------------
123 
124 } // namespace fwDataTools
The namespace fwDataTools contains classes which provide helpers to manipulate fwData::Object. *.
static FWDATATOOLS_API void multiply(const ::fwData::TransformationMatrix3D::csptr &_trfA, const ::fwData::TransformationMatrix3D::csptr &_trfB,::fwData::TransformationMatrix3D::sptr &_output)
Multiply two matrices.
static FWDATATOOLS_API bool isIdentity(const ::fwData::TransformationMatrix3D::csptr &_trf, const double _epsilon=1e-12)
Return whether a fwData::TransformationMatrix3D is an identity matrix.
static FWDATATOOLS_API void identity(::fwData::TransformationMatrix3D::sptr &_trf)
Set the matrix to identity.
static FWDATATOOLS_API bool invert(const ::fwData::TransformationMatrix3D::csptr &_input,::fwData::TransformationMatrix3D::sptr &_output)
Invert a matrix.