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