MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkNavigationDataTransformFilterTest.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============================================================================*/
12
14#include "mitkNavigationData.h"
15
16#include "mitkTestingMacros.h"
17
18#include <itkQuaternionRigidTransform.h>
19
20#include <itkTransform.h>
21#include <itkVector.h>
22#include <iostream>
23
24
28typedef itk::VersorRigid3DTransform<mitk::ScalarType > TransformType;
29
30typedef itk::Vector<double,3> VectorType;
31
32int mitkNavigationDataTransformFilterTest(int /* argc */, char* /*argv*/[])
33{
34 MITK_TEST_BEGIN("NavigationDataTransformFilter")
35
36 // let's create an object of our class
37 mitk::NavigationDataTransformFilter::Pointer myFilter = mitk::NavigationDataTransformFilter::New();
38
39 // first test: did this work?
40 // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since
41 // it makes no sense to continue without an object.
42 MITK_TEST_CONDITION_REQUIRED(myFilter.IsNotNull(),"Testing instantiation");
43
44 /* create helper objects: navigation data with position as origin, zero quaternion, zero error and data valid */
45 mitk::NavigationData::PositionType initialPos, resultPos;
46 mitk::FillVector3D(initialPos, 1.1, 2.2, 3.3);
47 mitk::FillVector3D(resultPos, 5.0, 5.0,5.0);
48
49
50 mitk::NavigationData::OrientationType initialOri(0.0, 0.0, -0.7071, 0.7071);
51 mitk::ScalarType initialError(0.0);
52 bool initialValid(true);
53
54 mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New();
55 nd1->SetPosition(initialPos);
56 nd1->SetOrientation(initialOri);
57 nd1->SetPositionAccuracy(initialError);
58 nd1->SetOrientationAccuracy(initialError);
59 nd1->SetDataValid(initialValid);
60
61 MITK_TEST_CONDITION(myFilter->GetPrecompose() == false, "Testing default Precompose mode");
62
63 myFilter->SetPrecompose(true);
64 MITK_TEST_CONDITION(myFilter->GetPrecompose() == true, "Testing Set-/GetPrecompose, part 1");
65
66 myFilter->PrecomposeOff();
67 MITK_TEST_CONDITION(myFilter->GetPrecompose() == false, "Testing PrecomposeOff");
68
69 myFilter->PrecomposeOn();
70 MITK_TEST_CONDITION(myFilter->GetPrecompose() == true, "Testing PrecomposeOn");
71
72 myFilter->SetInput(nd1);
73 MITK_TEST_CONDITION(myFilter->GetInput() == nd1, "Testing Set-/GetInput()");
74
75 mitk::NavigationData* output = myFilter->GetOutput();
76
77 /*test case no transform set*/
78 MITK_TEST_FOR_EXCEPTION(std::exception, output->Update(););
79
80 /* test transformation */
81 mitk::NavigationDataTransformFilter::TransformType::Pointer transform = mitk::NavigationDataTransformFilter::TransformType::New();
82 VectorType translationVector;
83 translationVector[0] = 3.9;
84 translationVector[1] = 2.8;
85 translationVector[2] = 1.7;
86
87
88 //
89 // Test translation-only transform with PrecomposeOff
90 //
91 transform->Translate(translationVector);
92
93 myFilter->SetRigid3DTransform(transform);
94 myFilter->SetPrecompose(false);
95
96 output = myFilter->GetOutput();
97 MITK_TEST_CONDITION_REQUIRED(output != nullptr, "Testing GetOutput()");
98
99 output->Update(); // execute filter
100
101 MITK_TEST_CONDITION(output->GetPosition() == resultPos, "Testing if translation was calculated correct");
102 MITK_TEST_CONDITION( mitk::Equal( output->GetOrientation(),initialOri, 0.00001 ),"Testing if Orientation remains unchanged ");
103 MITK_TEST_CONDITION(output->IsDataValid() == initialValid, "Testing if DataValid remains unchanged");
104
105 // Repeat the same translation test with precompose on - results should
106 // be the same for a translation-only transform
107 myFilter->PrecomposeOn();
108 MITK_TEST_CONDITION(output->GetPosition() == resultPos,
109 "Testing if precomposed translation was calculated correct");
110 MITK_TEST_CONDITION(mitk::Equal(output->GetOrientation(),initialOri,0.00001),
111 "Testing if precomposed Orientation remains unchanged ");
112 MITK_TEST_CONDITION(output->IsDataValid() == initialValid,
113 "Testing if precomposed DataValid remains unchanged");
114
115
116 mitk::NavigationDataTransformFilter::Pointer myFilter2 = mitk::NavigationDataTransformFilter::New();
117 // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since
118 // it makes no sense to continue without an object.
119 MITK_TEST_CONDITION_REQUIRED(myFilter2.IsNotNull(),"Testing instantiation");
120
121 // Setup for subsequent PrecomposeOff/PrecomposeOn tests
122 mitk::FillVector3D(initialPos, 1.1, 2.2, 3.3);
123 initialOri[0] = 0;
124 initialOri[1] = 0;
125 initialOri[2] = 0;
126 initialOri[3] = 1;
127
128 nd1->SetPosition(initialPos);
129 nd1->SetOrientation(initialOri);
130
131 myFilter2->SetInput(nd1);
132
133 //
134 // Test rotation-only transform with PrecomposeOff
135 //
136 myFilter2->PrecomposeOff();
137
138 // Rotate 90 degrees about Z axis
139 mitk::NavigationDataTransformFilter::TransformType::MatrixType rotMatrix;
140 rotMatrix[0][0] = 0;
141 rotMatrix[0][1] = 1;
142 rotMatrix[0][2] = 0;
143 rotMatrix[1][0] = -1;
144 rotMatrix[1][1] = 0;
145 rotMatrix[1][2] = 0;
146 rotMatrix[2][0] = 0;
147 rotMatrix[2][1] = 0;
148 rotMatrix[2][2] = 1;
149
150 mitk::NavigationDataTransformFilter::TransformType::Pointer transform2 = mitk::NavigationDataTransformFilter::TransformType::New();
151 transform2->SetMatrix(rotMatrix);
152
153 myFilter2->SetRigid3DTransform(transform2);
154
155 mitk::NavigationData* output2 = myFilter2->GetOutput();
156 MITK_TEST_CONDITION_REQUIRED(output2 != nullptr, "Testing GetOutput()");
157
158 output2->Update(); // execute filter
159
160 mitk::FillVector3D(resultPos, 2.2, -1.1, 3.3);
161 mitk::NavigationData::OrientationType resultOri(0.0, 0.0, -0.7071067690849304, 0.7071067690849304);
162 MITK_TEST_CONDITION(mitk::Equal(output2->GetPosition(), resultPos, 0.00001), "Testing if position after rotation is correctly calculated");
163 MITK_TEST_CONDITION(mitk::Equal(output2->GetOrientation(), resultOri, 0.00001),"Testing if orientation after rotation is correctly caclculated ");
164 MITK_TEST_CONDITION(output2->IsDataValid() == initialValid, "Testing if DataValid remains unchanged");
165
166 //
167 // Test rotation-only transform with PrecomposeOn
168 //
169 myFilter2->PrecomposeOn();
170 output2->Update();
171
172 // Output position should be the same as input position for rotation-only with PrecomposeOn
173 MITK_TEST_CONDITION(output2->GetPosition() == initialPos,
174 "Testing if precomposed position after rotation is correctly calculated");
175 MITK_TEST_CONDITION(mitk::Equal(output2->GetOrientation(), resultOri, 0.00001),
176 "Testing if precomposed orientation after rotation is correctly calculated");
177 MITK_TEST_CONDITION(output2->IsDataValid() == initialValid,
178 "Testing if precomposed DataValid remains unchanged");
179
180 //
181 // test obscure rotation angle vs. ITK precision requirements
182 //
183 itk::QuaternionRigidTransform<mitk::NavigationDataTransformFilter::TransformType::ScalarType>::VnlQuaternionType obscureRotationQuat(37,29,71);
184 obscureRotationQuat.normalize(); // Just to demonstrate that even normalizing doesn't help
185
186 itk::QuaternionRigidTransform<mitk::NavigationDataTransformFilter::TransformType::ScalarType>::Pointer rotation =
187 itk::QuaternionRigidTransform<mitk::NavigationDataTransformFilter::TransformType::ScalarType>::New();
188 rotation->SetRotation(obscureRotationQuat);
189
190 mitk::NavigationDataTransformFilter::TransformType::Pointer transform3 = mitk::NavigationDataTransformFilter::TransformType::New();
191 // For lack of an MITK Test macro that tests for *no* exception
192 try
193 {
194 MITK_TEST_OUTPUT_NO_ENDL(<< "Testing whether NavigationDataTransformFilter's internal transform has sufficient precision for ITK ")
195 transform3->SetMatrix(rotation->GetMatrix());
196 MITK_TEST_OUTPUT(<< " [PASSED]")
197 mitk::TestManager::GetInstance()->TestPassed();
198 }
199 catch(std::exception&)
200 {
201 MITK_TEST_OUTPUT(<< " [FAILED]")
202 mitk::TestManager::GetInstance()->TestFailed();
203 }
204
205 //-----------------------------------------------------------------------------------------------------------
206 /* now test the filter with multiple inputs */
207 mitk::NavigationData::PositionType initialPos2, resultPos2;
208 mitk::FillVector3D(initialPos, 1.1, 2.2, 3.3);
209 mitk::FillVector3D(initialPos2, -1000.0, 567.89, 0.0);
210 mitk::FillVector3D(resultPos, 2.2,-1.1, 3.3);
211 mitk::FillVector3D(resultPos2, 567.89, 1000, 0.0);
212 mitk::NavigationData::OrientationType initialOri2(0.5,0.5,0.5,0.5);
213 mitk::NavigationData::OrientationType resultOri2(0.7071,0.0,0.0,0.7071);
214 mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New();
215
216 nd1->SetPosition(initialPos);
217 nd1->SetOrientation(initialOri);
218 nd1->SetPositionAccuracy(initialError);
219 nd1->SetDataValid(initialValid);
220
221 nd2->SetPosition(initialPos2);
222 nd2->SetOrientation(initialOri2);
223 nd2->SetPositionAccuracy(initialError);
224 nd2->SetDataValid(initialValid);
225
226 myFilter = nullptr;
227 myFilter = mitk::NavigationDataTransformFilter::New();
228 myFilter->SetRigid3DTransform(transform2);
229 myFilter->SetInput(0, nd1);
230 myFilter->SetInput(1, nd2);
231
232 MITK_TEST_CONDITION(((myFilter->GetInput(0) == nd1)
233 && (myFilter->GetInput(1) == nd2)), "Testing Set-/GetInput(index, data)");
234 output = nullptr;
235 output2 = nullptr;
236 output = myFilter->GetOutput();
237 output2 = myFilter->GetOutput(1);
238 output2->Update(); // execute filter pipeline. this should update both outputs!
239 MITK_TEST_CONDITION_REQUIRED(((output != nullptr) && (output2 != nullptr)), "Testing GetOutput(index)");
240
241 MITK_TEST_CONDITION(mitk::Equal(output->GetPosition(), resultPos, 0.00001), "Testing if position rotation was calculated correct [output 0]");
242 MITK_TEST_CONDITION(mitk::Equal(output->GetOrientation(), resultOri, 0.00001),"Testing if orientation rotation was calculated correct [output 0]");
243 MITK_TEST_CONDITION(output->IsDataValid() == initialValid, "Testing if DataValid remains unchanged for output 0");
244
245 MITK_TEST_CONDITION(mitk::Equal(output2->GetPosition(), resultPos2, 0.0001), "Testing if rotation was calculated correct [output 1]");
246 MITK_TEST_CONDITION(mitk::Equal(output2->GetOrientation(), resultOri2, 0.00001),"Testing if orientation rotation was calculated correct [output 1]");
247 MITK_TEST_CONDITION(output2->IsDataValid() == initialValid, "Testing if DataValid remains unchanged for output 1");
248 //
249 // /* test if anything changes on second ->Update() */
250 output->Update(); // nothing should change, since inputs remain unchanged
251 MITK_TEST_CONDITION(mitk::Equal(output->GetPosition(), resultPos, 0.0001) &&
252 mitk::Equal(output2->GetPosition(), resultPos2, 0.0001), "Testing translation calculation after second update()");
253
254 /* change an input, see if output changes too */
256 mitk::FillVector3D(pos3, 123.456, -234.567, 789.987);
257 mitk::FillVector3D(resultPos3, -234.567, -123.456, 789.987);
258 nd1->SetPosition(pos3); // nd1 is modified, but nothing should change until pipe gets updated
259 MITK_TEST_CONDITION(mitk::Equal(output->GetPosition(),resultPos, 0.00001)
260 && mitk::Equal(output2->GetPosition(), resultPos2, 0.0001), "Testing transform calculation after input change, before update()");
261
262 output->Update(); // update pipeline. should recalculate positions, because input has changed
263 MITK_TEST_CONDITION(mitk::Equal(output->GetPosition(), resultPos3, 0.00001) &&
264 mitk::Equal(output2->GetPosition(), resultPos2, 0.0001), "Testing transform calculation after input change, after update()");
265
266 // always end with this!
267 MITK_TEST_END();
268}
269
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
mitk::Point3D PositionType
Type that holds the position part of the tracking data.
int mitkNavigationDataTransformFilterTest(int, char *[])
itk::VersorRigid3DTransform< mitk::ScalarType > TransformType
itk::Vector< double, 3 > VectorType
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.