Medical Imaging Interaction Toolkit  2018.4.99-ef453c4b
Medical Imaging Interaction Toolkit
mitkNavigationDataSliceVisualization.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 ============================================================================*/
13 
14 #include "mitkBaseRenderer.h"
15 
17  m_Renderer(nullptr),
18  m_ViewDirection(Axial)
19 {
20  m_TipOffset[0] = 0.0f;
21  m_TipOffset[1] = 0.0f;
22  m_TipOffset[2] = 0.0f;
23 
24  m_ToolTrajectory[0] = 0;
25  m_ToolTrajectory[1] = 0;
26  m_ToolTrajectory[2] = -1;
27 
28  m_WorldVerticalVector[0] = 0.0;
29  m_WorldVerticalVector[1] = 1.0;
30  m_WorldVerticalVector[2] = 0.0;
31 }
32 
34 {
35  if (Equal(direction.GetNorm(), 0.0))
36  {
37  MITK_WARN << "Ignoring invalid direction of projection: " << direction;
38  return;
39  }
40 
41  if (m_ToolTrajectory != direction)
42  {
43  m_ToolTrajectory = direction;
44  this->SetViewDirection(Oblique);
45  this->Modified();
46  }
47 }
48 
50 {
51  // check if renderer was set
52  if (m_Renderer.IsNull())
53  {
54  itkExceptionMacro(<< "Renderer was not properly set");
55  }
56 
57  /* update outputs with tracking data from tools */
58  unsigned int numberOfInputs = this->GetNumberOfInputs();
59  if (numberOfInputs == 0)
60  {
61  return;
62  }
63  for (unsigned int i = 0; i < numberOfInputs ; ++i)
64  {
65  NavigationData* output = this->GetOutput(i);
66  assert(output);
67  const NavigationData* input = this->GetInput(i);
68  assert(input);
69 
70  if (!input->IsDataValid())
71  continue;
72 
73  output->Graft(input); // First, copy all information from input to output
74  }
75 
76  // Nothing left to do if we don't have an input with valid data
77  if (numberOfInputs == 0 || !this->GetInput()->IsDataValid())
78  return;
79 
80  // get position from NavigationData to move the slice to this position
81  Point3D slicePosition = this->GetInput()->GetPosition();
82 
83  {
85 
86  Vector3D transformedTipOffset;
87  transformedTipOffset.SetVnlVector(orientation.rotate(m_TipOffset.GetVnlVector()));
88 
89  slicePosition += transformedTipOffset;
90 
91  mitk::SliceNavigationController::Pointer snc = m_Renderer->GetSliceNavigationController();
92 
93  if (Axial == m_ViewDirection)
94  {
95  snc->SetViewDirection(mitk::SliceNavigationController::Axial);
96  snc->SelectSliceByPoint(slicePosition);
97  }
98  else if (Sagittal == m_ViewDirection)
99  {
100  snc->SetViewDirection(mitk::SliceNavigationController::Sagittal);
101  snc->SelectSliceByPoint(slicePosition);
102  }
103  else if (Frontal == m_ViewDirection)
104  {
105  snc->SetViewDirection(mitk::SliceNavigationController::Frontal);
106  snc->SelectSliceByPoint(slicePosition);
107  }
109  {
110  const int slicingPlaneXAxis = AxialOblique == m_ViewDirection ? 0 : 2;
111 
112  // The column 0 is the slicing plane's x-axis, column 1 is the slicing plane's y-axis
113  const mitk::PlaneGeometry::TransformType::MatrixType &m =
114  m_Renderer->GetCurrentWorldPlaneGeometry()->GetIndexToWorldTransform()->GetMatrix();
115 
116  // Rotate the tool trajectory vector into world coordinate frame (assuming
117  // NavigationData has passed through a NavigationDataTransformFilter to
118  // convert it into world coordinate frame)
119  Vector3D slicingPlaneYAxisVector;
120  slicingPlaneYAxisVector.SetVnlVector(orientation.rotate(m_ToolTrajectory.GetVnlVector()));
121 
122  // Project the tool trajectory onto the plane normal to x-axis of this
123  // oblique slicing. This defines the y-axis ("up") of the oblique slicing
124  // plane
125  slicingPlaneYAxisVector[slicingPlaneXAxis] = 0.0;
126 
127  // Do nothing for ambigous/undefined cases:
128  // - the R-L component of the x-axis is zero (for AxialOblique)
129  // - the S-I component of the x-axis is zero (for SagittalOblique)
130  // - the A-P component of the y-axis is zero
131  if ( m(slicingPlaneXAxis,0) == 0.0 ||
132  m(1,1) == 0.0 ||
133  (slicingPlaneXAxis != 0 && slicingPlaneYAxisVector[0] == 0.0) ||
134  (slicingPlaneXAxis != 1 && slicingPlaneYAxisVector[1] == 0.0) ||
135  (slicingPlaneXAxis != 2 && slicingPlaneYAxisVector[2] == 0.0) )
136  {
137  return;
138  }
139 
140  // Maintain the A-P orientation of the slice's y-axis regardless of what
141  // direction the tool trajectory points
143  if ( (m(1,1) > 0) != (slicingPlaneYAxisVector[1] > 0) )
144  {
145  slicingPlaneYAxisVector *= -1;
146  }
147 
148  Vector3D slicingPlaneXAxisVector;
149  slicingPlaneXAxisVector.Fill(0.0);
150  // For AxialOblique: maintain the Left/Right direction of the slice's x-axis
151  // For SagittalOblique: maintain the Superior/Inferior direction of the slice's x-axis
153  slicingPlaneXAxisVector[slicingPlaneXAxis] = m(slicingPlaneXAxis,0) > 0 ? 1.0 : -1.0;
154 
155  Point3D origin;
156  FillVector3D(origin, 0.0, 0.0, 0.0);
157  snc->ReorientSlices(origin, slicingPlaneXAxisVector, slicingPlaneYAxisVector);
158  snc->SelectSliceByPoint(slicePosition);
159  }
160  else if (Oblique == m_ViewDirection)
161  {
162  Vector3D slicingPlaneNormalVector;
163  slicingPlaneNormalVector.SetVnlVector(orientation.rotate(m_ToolTrajectory.GetVnlVector()));
164 
165  // The second column of the Index-to-World matrix is the positive y-axis
166  // of the current slicing plane in world coordinates.
167  const mitk::PlaneGeometry::TransformType::MatrixType &m =
168  m_Renderer->GetCurrentWorldPlaneGeometry()->GetIndexToWorldTransform()->GetMatrix();
169  mitk::Vector3D currentSlicingPlaneUpVector;
170  mitk::FillVector3D(currentSlicingPlaneUpVector, m[0][1], m[1][1], m[2][1]);
171  mitk::Vector3D worldUpVector = m_WorldVerticalVector;
172  if (angle(worldUpVector.GetVnlVector(), currentSlicingPlaneUpVector.GetVnlVector()) > vnl_math::pi_over_2 )
173  {
174  worldUpVector *= -1;
175  }
176 
178  Point3D origin;
179  FillVector3D(origin, 0.0, 0.0, 0.0);
180  slicingPlane->InitializePlane(origin, slicingPlaneNormalVector);
181 
182  // Now that we have the direction of WorldVerticalVector chosen to be the
183  // most "up" direction, project it onto the slicing plane to define the
184  // up vector (y-axis) of the reoriented slices
185  mitk::Vector3D slicingPlaneUpVector;
186  if ( slicingPlane->Project(worldUpVector, slicingPlaneUpVector) )
187  {
188  // slicingPlaneUpVector CROSS slicingPlaneNormalVector -> slicingPlaneRightVector
189  // Math is done in double precision as much as possible to get more
190  // orthogonal right and up vectors which fixes a VNL SVD error when
191  // the WorldGeometry matrix is later inverted
192  itk::Vector<double,3> slicingPlaneUpVector_double;
193  FillVector3D(slicingPlaneUpVector_double,
194  slicingPlaneUpVector[0], slicingPlaneUpVector[1], slicingPlaneUpVector[2]);
195  itk::Vector<double,3> slicingPlaneNormalVector_double;
196  FillVector3D(slicingPlaneNormalVector_double,
197  slicingPlaneNormalVector[0], slicingPlaneNormalVector[1], slicingPlaneNormalVector[2]);
198  itk::Vector<double,3> slicingPlaneRightVector_double = itk::CrossProduct(slicingPlaneUpVector_double,
199  slicingPlaneNormalVector_double);
200 
201  mitk::Vector3D slicingPlaneRightVector;
202  mitk::FillVector3D(slicingPlaneRightVector,
203  slicingPlaneRightVector_double[0], slicingPlaneRightVector_double[1], slicingPlaneRightVector_double[2]);
204  mitk::FillVector3D(slicingPlaneUpVector,
205  slicingPlaneUpVector_double[0], slicingPlaneUpVector_double[1], slicingPlaneUpVector_double[2]);
206 
207  snc->ReorientSlices(origin, slicingPlaneRightVector, slicingPlaneUpVector);
208  snc->SelectSliceByPoint(slicePosition);
209  }
210  }
211  else
212  {
213  MITK_ERROR << "Unsupported ViewDirection: " << m_ViewDirection;
214  }
215 
216  m_Renderer->RequestUpdate();
217  }
218 }
219 
NavigationData * GetOutput(void)
return the output (output with id 0) of the filter
NavigationDataToNavigationDataFilter is the base class of all filters that receive NavigationDatas as...
#define MITK_ERROR
Definition: mitkLogMacros.h:20
Navigation Data.
DataCollection - Class to facilitate loading/accessing structured data.
virtual void SetToolTrajectory(Vector3D direction)
Set/get the tool trajectory used to define the cutting plane normal direction.
mitk::Quaternion OrientationType
Type that holds the orientation part of the tracking data.
virtual PositionType GetPosition() const
returns position of the NavigationData object
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
const NavigationData * GetInput(void) const
Get the input of this filter.
#define MITK_WARN
Definition: mitkLogMacros.h:19
void Graft(const DataObject *data) override
Graft the data and information from one NavigationData to another.
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.
static Pointer New()
virtual OrientationType GetOrientation() const
returns the orientation of the NavigationData object
virtual bool IsDataValid() const
returns true if the object contains valid data