Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
mitkGeometryTransformHolder.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 /*
14 * mitkGeometryTransformHolder.cpp
15 *
16 * Created on: Sep 3, 2014
17 * Author: wirkert
18 */
19 
20 #include <cassert>
21 #include <itkMatrix.h>
22 #include <itkScalableAffineTransform.h>
23 #include <itkSmartPointer.h>
24 #include <mitkBaseGeometry.h>
26 #include <mitkMatrix.h>
27 #include <mitkMatrixConvert.h>
28 #include <mitkPoint.h>
29 #include <mitkVector.h>
30 #include <vnl/vnl_matrix_fixed.h>
31 #include <vnl/vnl_vector.h>
32 #include <vnl/vnl_vector_fixed.h>
33 #include <vtkMatrix4x4.h>
34 #include <vtkMatrixToLinearTransform.h>
35 #include <vtkTransform.h>
36 
37 namespace mitk
38 {
39  void GeometryTransformHolder::CopySpacingFromTransform(const mitk::AffineTransform3D *transform,
40  mitk::Vector3D &spacing)
41  {
42  mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
43  vnlmatrix = transform->GetMatrix().GetVnlMatrix();
44 
45  spacing[0] = vnlmatrix.get_column(0).magnitude();
46  spacing[1] = vnlmatrix.get_column(1).magnitude();
47  spacing[2] = vnlmatrix.get_column(2).magnitude();
48  }
49 
51  {
52  m_VtkMatrix = vtkMatrix4x4::New();
53  m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New();
54  m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix);
55  this->Initialize();
56  }
57 
59  {
60  m_VtkMatrix = vtkMatrix4x4::New();
61  m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New();
62  m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix);
63  this->Initialize(&other);
64  }
65 
67  {
68  m_VtkMatrix->Delete();
69  m_VtkIndexToWorldTransform->Delete();
70  }
71 
73  {
74  if (m_IndexToWorldTransform.IsNull())
75  m_IndexToWorldTransform = TransformType::New();
76  else
77  m_IndexToWorldTransform->SetIdentity();
78 
79  m_VtkMatrix->Identity();
80  }
81 
83  {
84  Initialize();
85 
86  if (other->GetIndexToWorldTransform())
87  {
88  TransformType::Pointer indexToWorldTransform = other->GetIndexToWorldTransform()->Clone();
89  this->SetIndexToWorldTransform(indexToWorldTransform);
90  }
91  }
92 
93  //##Documentation
94  //## @brief Copy the ITK transform
95  //## (m_IndexToWorldTransform) to the VTK transform
96  //## \sa SetIndexToWorldTransform
97  void GeometryTransformHolder::TransferItkToVtkTransform()
98  {
99  TransferItkTransformToVtkMatrix(m_IndexToWorldTransform.GetPointer(), m_VtkMatrix);
100  }
101 
102  //##Documentation
103  //## @brief Copy the VTK transform
104  //## to the ITK transform (m_IndexToWorldTransform)
105  //## \sa SetIndexToWorldTransform
106  void GeometryTransformHolder::TransferVtkToItkTransform()
107  {
108  TransferVtkMatrixToItkTransform(m_VtkMatrix, m_IndexToWorldTransform.GetPointer());
109  }
110 
111  //##Documentation
112  //## @brief Get the origin, e.g. the upper-left corner of the plane
114  {
115  mitk::Point3D origin = this->GetIndexToWorldTransform()->GetOffset();
116  return origin;
117  }
118 
119  //##Documentation
120  //## @brief Set the origin, i.e. the upper-left corner of the plane
121  //##
123  {
124  m_IndexToWorldTransform->SetOffset(origin.GetVectorFromOrigin());
125  TransferItkToVtkTransform();
126  }
127 
128  //##Documentation
129  //## @brief Get the spacing (size of a pixel).
130  //##
132  {
133  mitk::Vector3D spacing;
134  CopySpacingFromTransform(this->GetIndexToWorldTransform(), spacing);
135  return spacing;
136  }
137 
138  //##Documentation
139  //## @brief Set the spacing.
140  //##
141  //##The spacing is also changed in the IndexToWorldTransform.
142  void GeometryTransformHolder::SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing)
143  {
144  if (mitk::Equal(this->GetSpacing(), aSpacing) == false || enforceSetSpacing)
145  {
146  assert(aSpacing[0] > 0 && aSpacing[1] > 0 && aSpacing[2] > 0);
147 
148  AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
149 
150  vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix();
151 
152  mitk::VnlVector col;
153  col = vnlmatrix.get_column(0);
154  col.normalize();
155  col *= aSpacing[0];
156  vnlmatrix.set_column(0, col);
157  col = vnlmatrix.get_column(1);
158  col.normalize();
159  col *= aSpacing[1];
160  vnlmatrix.set_column(1, col);
161  col = vnlmatrix.get_column(2);
162  col.normalize();
163  col *= aSpacing[2];
164  vnlmatrix.set_column(2, col);
165 
166  Matrix3D matrix;
167  matrix = vnlmatrix;
168 
169  AffineTransform3D::Pointer transform = AffineTransform3D::New();
170  transform->SetMatrix(matrix);
171  transform->SetOffset(m_IndexToWorldTransform->GetOffset());
172 
173  SetIndexToWorldTransform(transform.GetPointer());
174  }
175  }
176 
177  //##Documentation
178  //## @brief Get the transformation used to convert from index
179  //## to world coordinates
181  //##Documentation
182  //## @brief Get the transformation used to convert from index
183  //## to world coordinates
185  {
186  return m_IndexToWorldTransform;
187  }
188 
189  //## @brief Set the transformation used to convert from index
190  //## to world coordinates. The spacing of the new transform is
191  //## copied to m_spacing.
193  {
194  m_IndexToWorldTransform = transform;
195  TransferItkToVtkTransform();
196  }
197 
198  //##Documentation
199  //## @brief Convenience method for setting the ITK transform
200  //## (m_IndexToWorldTransform) via an vtkMatrix4x4.The spacing of
201  //## the new transform is copied to m_spacing.
202  //## \sa SetIndexToWorldTransform
204  {
205  m_VtkMatrix->DeepCopy(vtkmatrix);
206  TransferVtkToItkTransform();
207  }
208 
209  //## @brief Set the transformation used to convert from index
210  //## to world coordinates.This function keeps the original spacing.
212  {
213  mitk::Vector3D originalSpacing = this->GetSpacing();
214  this->SetIndexToWorldTransform(transform);
215  this->SetSpacing(originalSpacing);
216  }
217 
218  //##Documentation
219  //## @brief Convenience method for setting the ITK transform
220  //## (m_IndexToWorldTransform) via an vtkMatrix4x4. This function keeps the original spacing.
221  //## \sa SetIndexToWorldTransform
223  {
224  mitk::Vector3D originalSpacing = this->GetSpacing();
225  this->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
226  this->SetSpacing(originalSpacing);
227  }
228 
229  //## Get the Vtk Matrix which describes the transform.
230  vtkMatrix4x4 *GeometryTransformHolder::GetVtkMatrix() { return m_VtkMatrix; }
231  //## Get the Vtk Matrix which describes the transform.
232  const vtkMatrix4x4 *GeometryTransformHolder::GetVtkMatrix() const { return m_VtkMatrix; }
233  //##Documentation
234  //## @brief Get the m_IndexToWorldTransform as a vtkLinearTransform
235  vtkLinearTransform *GeometryTransformHolder::GetVtkTransform() const
236  {
237  return (vtkLinearTransform *)m_VtkIndexToWorldTransform;
238  }
239 
241  {
242  m_IndexToWorldTransform->SetMatrix(matrix);
243  TransferItkToVtkTransform();
244  }
245 
247  {
248  m_IndexToWorldTransform->SetIdentity();
249  TransferItkToVtkTransform();
250  }
251 
252  void GeometryTransformHolder::Compose(const TransformType *other, bool pre)
253  {
254  m_IndexToWorldTransform->Compose(other, pre);
255  TransferItkToVtkTransform();
256  }
257 
258  void GeometryTransformHolder::SetVtkMatrixDeepCopy(vtkTransform *vtktransform)
259  {
260  m_VtkMatrix->DeepCopy(vtktransform->GetMatrix());
261  TransferVtkToItkTransform();
262  }
263 
264  bool GeometryTransformHolder::IsIndexToWorldTransformNull() { return m_IndexToWorldTransform.IsNull(); }
265  AffineTransform3D::MatrixType::InternalMatrixType GeometryTransformHolder::GetVnlMatrix()
266  {
267  return m_IndexToWorldTransform->GetMatrix().GetVnlMatrix();
268  }
269 }
270 
272  const mitk::GeometryTransformHolder *rightHandSide,
273  ScalarType eps,
274  bool verbose)
275 {
276  if ((leftHandSide == nullptr) || (rightHandSide == nullptr))
277  {
278  MITK_ERROR << "mitk::Equal(const mitk::Geometry3D *leftHandSide, const mitk::Geometry3D *rightHandSide, ScalarType "
279  "eps, bool verbose) does not with nullptr pointer input.";
280  return false;
281  }
282  return Equal(*leftHandSide, *rightHandSide, eps, verbose);
283 }
284 
286  const mitk::GeometryTransformHolder &rightHandSide,
287  ScalarType eps,
288  bool verbose)
289 {
290  bool result = true;
291 
292  // Compare spacings
293  if (!mitk::Equal(leftHandSide.GetSpacing(), rightHandSide.GetSpacing(), eps))
294  {
295  if (verbose)
296  {
297  MITK_INFO << "[( Geometry3D )] Spacing differs.";
298  MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetSpacing() << " : leftHandSide is "
299  << leftHandSide.GetSpacing() << " and tolerance is " << eps;
300  }
301  result = false;
302  }
303 
304  // Compare Origins
305  if (!mitk::Equal(leftHandSide.GetOrigin(), rightHandSide.GetOrigin(), eps))
306  {
307  if (verbose)
308  {
309  MITK_INFO << "[( Geometry3D )] Origin differs.";
310  MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetOrigin() << " : leftHandSide is "
311  << leftHandSide.GetOrigin() << " and tolerance is " << eps;
312  }
313  result = false;
314  }
315 
316  // Compare IndexToWorldTransform Matrix
317  if (!mitk::Equal(*leftHandSide.GetIndexToWorldTransform(), *rightHandSide.GetIndexToWorldTransform(), eps, verbose))
318  {
319  result = false;
320  }
321 
322  // Compare vtk Matrix
323  for (int i = 0; i < 4; i++)
324  {
325  for (int j = 0; j < 4; j++)
326  {
327  if (leftHandSide.GetVtkMatrix()->GetElement(i, j) != rightHandSide.GetVtkMatrix()->GetElement(i, j))
328  {
329  result = false;
330  }
331  }
332  }
333 
334  return result;
335 }
void TransferVtkMatrixToItkTransform(const vtkMatrix4x4 *vtkmatrix, TTransformType *itkTransform)
void SetVtkMatrixDeepCopy(vtkTransform *vtktransform)
void SetIndexToWorldTransformByVtkMatrixWithoutChangingSpacing(vtkMatrix4x4 *vtkmatrix)
Convenience method for setting the ITK transform (m_IndexToWorldTransform) via an vtkMatrix4x4...
#define MITK_INFO
Definition: mitkLogMacros.h:18
vnl_vector< ScalarType > VnlVector
Definition: mitkVector.h:134
#define MITK_ERROR
Definition: mitkLogMacros.h:20
double ScalarType
DataCollection - Class to facilitate loading/accessing structured data.
void TransferItkTransformToVtkMatrix(const TTransformType *itkTransform, vtkMatrix4x4 *vtkmatrix)
AffineTransform3D::MatrixType::InternalMatrixType GetVnlMatrix()
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
void SetIndexToWorldTransformWithoutChangingSpacing(mitk::AffineTransform3D *transform)
void Compose(const TransformType *other, bool pre=false)
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
bool verbose(false)
vtkLinearTransform * GetVtkTransform() const
Get the m_IndexToWorldTransform as a vtkLinearTransform.
itk::ScalableAffineTransform< ScalarType, 3 > TransformType
itk::AffineGeometryFrame< ScalarType, 3 >::TransformType AffineTransform3D
void SetIndexToWorldTransform(mitk::AffineTransform3D *transform)
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
MITKCORE_EXPORT const ScalarType eps
virtual void SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4 *vtkmatrix)
Convenience method for setting the ITK transform (m_IndexToWorldTransform) via an vtkMatrix4x4...
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.