Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.