MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkNavigationDataSliceVisualization.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found 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 {
84 NavigationData::OrientationType orientation = this->GetInput()->GetOrientation();
85
86 Vector3D transformedTipOffset;
87 transformedTipOffset.SetVnlVector(orientation.rotate(m_TipOffset.GetVnlVector()).as_ref());
88
89 slicePosition += transformedTipOffset;
90
91 mitk::SliceNavigationController::Pointer snc = m_Renderer->GetSliceNavigationController();
92
93 if (Axial == m_ViewDirection)
94 {
95 snc->SetViewDirection(mitk::AnatomicalPlane::Axial);
96 snc->SelectSliceByPoint(slicePosition);
97 }
98 else if (Sagittal == m_ViewDirection)
99 {
100 snc->SetViewDirection(mitk::AnatomicalPlane::Sagittal);
101 snc->SelectSliceByPoint(slicePosition);
102 }
103 else if (Coronal == m_ViewDirection)
104 {
105 snc->SetViewDirection(mitk::AnatomicalPlane::Coronal);
106 snc->SelectSliceByPoint(slicePosition);
107 }
108 else if (AxialOblique == m_ViewDirection || SagittalOblique == m_ViewDirection)
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()).as_ref());
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()).as_ref());
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
177 mitk::PlaneGeometry::Pointer slicingPlane = mitk::PlaneGeometry::New();
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
virtual void SetToolTrajectory(Vector3D direction)
Set/get the tool trajectory used to define the cutting plane normal direction.
NavigationDataToNavigationDataFilter is the base class of all filters that receive NavigationDatas as...
void Graft(const DataObject *data) override
Graft the data and information from one NavigationData to another.
mitk::Quaternion OrientationType
Type that holds the orientation part of the tracking data.
virtual bool IsDataValid() const
returns true if the object contains valid data
IGT Exceptions.
MITKIGTBASE_EXPORT bool Equal(const mitk::NavigationData &leftHandSide, const mitk::NavigationData &rightHandSide, ScalarType eps=mitk::eps, bool verbose=false)
Equal A function comparing two navigation data objects for beeing equal in meta- and imagedata.