Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkNavigationData.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 ===================================================================*/
16 
17 #include "mitkNavigationData.h"
18 #include "vnl/vnl_det.h"
19 #include "mitkException.h"
20 
22 m_Position(), m_Orientation(0.0, 0.0, 0.0, 1.0), m_CovErrorMatrix(),
23 m_HasPosition(true), m_HasOrientation(true), m_DataValid(false), m_IGTTimeStamp(0.0),
24 m_Name()
25 {
26  m_Position.Fill(0.0);
27  m_CovErrorMatrix.SetIdentity();
28 }
29 
30 
32  m_Position(toCopy.GetPosition()), m_Orientation(toCopy.GetOrientation()), m_CovErrorMatrix(toCopy.GetCovErrorMatrix()),
33  m_HasPosition(toCopy.GetHasPosition()), m_HasOrientation(toCopy.GetHasOrientation()), m_DataValid(toCopy.IsDataValid()), m_IGTTimeStamp(toCopy.GetIGTTimeStamp()),
34  m_Name(toCopy.GetName())
35 {/* TODO SW: Graft does the same, remove code duplications, set Graft to deprecated, remove duplication in tescode */}
36 
38 {
39 }
40 
41 
42 void mitk::NavigationData::Graft( const DataObject *data )
43 {
44  // Attempt to cast data to an NavigationData
45  const Self* nd;
46  try
47  {
48  nd = dynamic_cast<const Self *>( data );
49  }
50  catch( ... )
51  {
52  itkExceptionMacro( << "mitk::NavigationData::Graft cannot cast "
53  << typeid(data).name() << " to "
54  << typeid(const Self *).name() );
55  return;
56  }
57  if (!nd)
58  {
59  // pointer could not be cast back down
60  itkExceptionMacro( << "mitk::NavigationData::Graft cannot cast "
61  << typeid(data).name() << " to "
62  << typeid(const Self *).name() );
63  return;
64  }
65  // Now copy anything that is needed
66  this->SetPosition(nd->GetPosition());
67  this->SetOrientation(nd->GetOrientation());
68  this->SetDataValid(nd->IsDataValid());
69  this->SetIGTTimeStamp(nd->GetIGTTimeStamp());
70  this->SetHasPosition(nd->GetHasPosition());
71  this->SetHasOrientation(nd->GetHasOrientation());
72  this->SetCovErrorMatrix(nd->GetCovErrorMatrix());
73  this->SetName(nd->GetName());
74 }
75 
76 
78 {
79  return m_DataValid;
80 }
81 
82 
83 void mitk::NavigationData::PrintSelf(std::ostream& os, itk::Indent indent) const
84 {
85  this->Superclass::PrintSelf(os, indent);
86  os << indent << "data valid: " << this->IsDataValid() << std::endl;
87  os << indent << "Position: " << this->GetPosition() << std::endl;
88  os << indent << "Orientation: " << this->GetOrientation() << std::endl;
89  os << indent << "TimeStamp: " << this->GetIGTTimeStamp() << std::endl;
90  os << indent << "HasPosition: " << this->GetHasPosition() << std::endl;
91  os << indent << "HasOrientation: " << this->GetHasOrientation() << std::endl;
92  os << indent << "CovErrorMatrix: " << this->GetCovErrorMatrix() << std::endl;
93 }
94 
95 
96 void mitk::NavigationData::CopyInformation( const DataObject* data )
97 {
98  this->Superclass::CopyInformation( data );
99 
100  const Self * nd = nullptr;
101  try
102  {
103  nd = dynamic_cast<const Self*>(data);
104  }
105  catch( ... )
106  {
107  // data could not be cast back down
108  itkExceptionMacro(<< "mitk::NavigationData::CopyInformation() cannot cast "
109  << typeid(data).name() << " to "
110  << typeid(Self*).name() );
111  }
112  if ( !nd )
113  {
114  // pointer could not be cast back down
115  itkExceptionMacro(<< "mitk::NavigationData::CopyInformation() cannot cast "
116  << typeid(data).name() << " to "
117  << typeid(Self*).name() );
118  }
119  /* copy all meta data */
120 }
121 
122 
124 {
125  for ( int i = 0; i < 3; i++ )
126  for ( int j = 0; j < 3; j++ )
127  {
128  m_CovErrorMatrix[ i ][ j ] = 0;
129  // assume independence of position and orientation
130  m_CovErrorMatrix[ i + 3 ][ j ] = 0;
131  m_CovErrorMatrix[ i ][ j + 3 ] = 0;
132  }
133  m_CovErrorMatrix[0][0] = m_CovErrorMatrix[1][1] = m_CovErrorMatrix[2][2] = error * error;
134 }
135 
136 
138 {
139  for ( int i = 0; i < 3; i++ )
140  for ( int j = 0; j < 3; j++ ) {
141  m_CovErrorMatrix[ i + 3 ][ j + 3 ] = 0;
142  // assume independence of position and orientation
143  m_CovErrorMatrix[ i + 3 ][ j ] = 0;
144  m_CovErrorMatrix[ i ][ j + 3 ] = 0;
145  }
146  m_CovErrorMatrix[3][3] = m_CovErrorMatrix[4][4] = m_CovErrorMatrix[5][5] = error * error;
147 }
148 
149 void
151 {
153  if (!pre)
154  nd3 = getComposition(this, n);
155  else
156  nd3 = getComposition(n, this);
157 
158  this->Graft(nd3);
159 }
160 
162  mitk::AffineTransform3D::Pointer affineTransform3D,
163  const bool checkForRotationMatrix) : itk::DataObject(),
164  m_Position(),
165  m_CovErrorMatrix(), m_HasPosition(true), m_HasOrientation(true), m_DataValid(true), m_IGTTimeStamp(0.0),
166  m_Name()
167 {
168  mitk::Vector3D offset = affineTransform3D->GetOffset();
169 
170  m_Position[0] = offset[0];
171  m_Position[1] = offset[1];
172  m_Position[2] = offset[2];
173 
174  vnl_matrix_fixed<ScalarType, 3, 3> rotationMatrix = affineTransform3D->GetMatrix().GetVnlMatrix();
175  vnl_matrix_fixed<ScalarType, 3, 3> rotationMatrixTransposed = rotationMatrix.transpose();
176 
177  if (checkForRotationMatrix)
178  {
179  // a quadratic matrix is a rotation matrix exactly when determinant is 1 and transposed is inverse
180  if (!Equal(1.0, vnl_det(rotationMatrix), 0.1)
181  || !((rotationMatrix*rotationMatrixTransposed).is_identity(0.1)))
182  {
183  mitkThrow() << "tried to initialize NavigationData with non-rotation matrix :" << rotationMatrix << " (Does your AffineTransform3D object include spacing? This is not supported by NavigationData objects!)";
184  }
185 
186  }
187 
188  // the transpose is because vnl_quaterion expects a transposed rotation matrix
189  m_Orientation = Quaternion(rotationMatrixTransposed);
190 }
191 
194 {
196 
197  // first set rotation
198  affineTransform3D->SetMatrix(this->GetRotationMatrix());
199 
200  // now set offset
201  Vector3D vector3D;
202 
203  for (int i = 0; i < 3; ++i) {
204  vector3D[i] = m_Position[i];
205  }
206  affineTransform3D->SetOffset(vector3D);
207 
208  return affineTransform3D;
209 }
210 
213 {
214  vnl_matrix_fixed<ScalarType,3,3> vnl_rotation = m_Orientation.rotation_matrix_transpose().transpose(); // :-)
215  Matrix3D mitkRotation;
216 
217  for (int i = 0; i < 3; ++i) {
218  for (int j = 0; j < 3; ++j) {
219  mitkRotation[i][j] = vnl_rotation[i][j];
220  }
221  }
222 
223  return mitkRotation;
224 }
225 
228 {
229  vnl_vector_fixed<ScalarType, 3> vnlPoint;
230 
231  for (int i = 0; i < 3; ++i) {
232  vnlPoint[i] = point[i];
233  }
234 
235  Quaternion normalizedQuaternion = this->GetOrientation().normalize();
236  // first get rotated point
237  vnlPoint = normalizedQuaternion.rotate(vnlPoint);
238 
239  Point3D resultingPoint;
240 
241  for (int i = 0; i < 3; ++i) {
242  // now copy it to our format + offset
243  resultingPoint[i] = vnlPoint[i] + this->GetPosition()[i];
244  }
245 
246  return resultingPoint;
247 }
248 
251 {
252  // non-zero quaternion does not have inverse: throw exception in this case.
253  Quaternion zeroQuaternion;
254  zeroQuaternion.fill(0);
255  if (Equal(zeroQuaternion, this->GetOrientation()))
256  mitkThrow() << "tried to invert zero quaternion in NavigationData";
257 
258  mitk::NavigationData::Pointer navigationDataInverse = this->Clone();
259  navigationDataInverse->SetOrientation(this->GetOrientation().inverse());
260 
261  // To vnl_vector
262  vnl_vector_fixed<ScalarType, 3> vnlPoint;
263  for (int i = 0; i < 3; ++i) {
264  vnlPoint[i] = this->GetPosition()[i];
265  }
266 
267  // invert position
268  vnlPoint = -(navigationDataInverse->GetOrientation().rotate(vnlPoint));
269 
270  // back to Point3D
271  Point3D invertedPosition = this->GetPosition();
272  for (int i = 0; i < 3; ++i) {
273  invertedPosition[i] = vnlPoint[i];
274  }
275 
276  navigationDataInverse->SetPosition(invertedPosition);
277 
278  // Inversion does not care for covariances for now
279  navigationDataInverse->ResetCovarianceValidity();
280 
281  return navigationDataInverse;
282 }
283 
284 void
285 mitk::NavigationData::ResetCovarianceValidity()
286 {
287  this->SetHasPosition(false);
288  this->SetHasOrientation(false);
289 }
290 
292 mitk::NavigationData::getComposition(const mitk::NavigationData::Pointer nd1,
294 {
295  NavigationData::Pointer nd3 = nd1->Clone();
296 
297  // A2 * A1
298  nd3->SetOrientation(nd2->GetOrientation() * nd1->GetOrientation());
299 
300  // first: b1, b2 vnl vector
301  vnl_vector_fixed<ScalarType,3> b1, b2, b3;
302  for (int i = 0; i < 3; ++i) {
303  b1[i] = nd1->GetPosition()[i];
304  b2[i] = nd2->GetPosition()[i];
305  }
306 
307  // b3 = A2b1 + b2
308  b3 = nd2->GetOrientation().rotate(b1) + b2;
309 
310  // back to mitk::Point3D
311  Point3D point;
312  for (int i = 0; i < 3; ++i) {
313  point[i] = b3[i];
314  }
315 
316  nd3->SetPosition(point);
317 
318  nd3->ResetCovarianceValidity();
319 
320  return nd3;
321 }
322 
323 bool mitk::Equal(const mitk::NavigationData& leftHandSide, const mitk::NavigationData& rightHandSide, ScalarType eps, bool verbose)
324 {
325  bool returnValue = true;
326 
327  // Dimensionality
328  if( !mitk::Equal(rightHandSide.GetPosition(), leftHandSide.GetPosition(), eps) )
329  {
330  if(verbose)
331  {
332  MITK_INFO << "[( NavigationData )] Position differs.";
333  MITK_INFO << "leftHandSide is " << leftHandSide.GetPosition()
334  << "rightHandSide is " << rightHandSide.GetPosition();
335  }
336  returnValue = false;
337  }
338 
339  // Dimensionality
340  if( !mitk::Equal(rightHandSide.GetOrientation(), leftHandSide.GetOrientation(), eps) )
341  {
342  if(verbose)
343  {
344  MITK_INFO << "[( NavigationData )] Orientation differs.";
345  MITK_INFO << "leftHandSide is " << leftHandSide.GetOrientation()
346  << "rightHandSide is " << rightHandSide.GetOrientation();
347  }
348  returnValue = false;
349  }
350 
351  if( rightHandSide.GetCovErrorMatrix() != leftHandSide.GetCovErrorMatrix() )
352  {
353  if(verbose)
354  {
355  MITK_INFO << "[( NavigationData )] CovErrorMatrix differs.";
356  MITK_INFO << "leftHandSide is " << leftHandSide.GetCovErrorMatrix()
357  << "rightHandSide is " << rightHandSide.GetCovErrorMatrix();
358  }
359  returnValue = false;
360  }
361 
362  if( std::string(rightHandSide.GetName()) != std::string(leftHandSide.GetName()) )
363  {
364  if(verbose)
365  {
366  MITK_INFO << "[( NavigationData )] Name differs.";
367  MITK_INFO << "leftHandSide is " << leftHandSide.GetName()
368  << "rightHandSide is " << rightHandSide.GetName();
369  }
370  returnValue = false;
371  }
372 
373  if( rightHandSide.GetIGTTimeStamp() != leftHandSide.GetIGTTimeStamp() )
374  {
375  if(verbose)
376  {
377  MITK_INFO << "[( NavigationData )] IGTTimeStamp differs.";
378  MITK_INFO << "leftHandSide is " << leftHandSide.GetIGTTimeStamp()
379  << "rightHandSide is " << rightHandSide.GetIGTTimeStamp();
380  }
381  returnValue = false;
382  }
383 
384  return returnValue;
385 }
itk::SmartPointer< Self > Pointer
void SetOrientationAccuracy(mitk::ScalarType error)
Pointer Clone() const
virtual void CopyInformation(const DataObject *data) override
copy meta data of a NavigationData object
#define MITK_INFO
Definition: mitkLogMacros.h:22
virtual const char * GetName() const
returns the name of the NavigationData object
mitk::Point3D TransformPoint(const mitk::Point3D point) const
Transform by an affine transformation.
mitk::NavigationData::Pointer GetInverse() const
double ScalarType
Navigation Data.
OrientationType m_Orientation
holds the orientation part of the tracking data
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Prints the object information to the given stream os.
mitk::Matrix3D GetRotationMatrix() const
Calculate the RotationMatrix of this transformation.
mitk::AffineTransform3D::Pointer GetAffineTransform3D() const
Calculate AffineTransform3D from the transformation held by this NavigationData. TODO: should throw a...
virtual OrientationType GetOrientation() const
returns the orientation of the NavigationData object
CovarianceMatrixType m_CovErrorMatrix
A 6x6 covariance matrix parameterizing the Gaussian error distribution of the measured position and o...
static Vector3D offset
virtual CovarianceMatrixType GetCovErrorMatrix() const
gets the 6x6 Error Covariance Matrix of the NavigationData object
#define mitkThrow()
virtual TimeStampType GetIGTTimeStamp() const
gets the IGT timestamp of the NavigationData object
vnl_quaternion< ScalarType > Quaternion
Point< ScalarType, 3 > Point3D
Definition: mitkPoint.h:99
virtual bool IsDataValid() const
returns true if the object contains valid data
virtual PositionType GetPosition() const
returns position of the NavigationData object
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.
void Compose(const mitk::NavigationData::Pointer n, const bool pre=false)
PositionType m_Position
holds the position part of the tracking data
MITKCORE_EXPORT const ScalarType eps
static std::string GetName(std::string fileName, std::string suffix)
void SetPositionAccuracy(mitk::ScalarType error)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.