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