1 /*
2 * Medical Image Registration ToolKit (MIRTK)
3 *
4 * Copyright 2013-2015 Imperial College London
5 * Copyright 2013-2015 Andreas Schuh
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 // TODO: Rewrite test using GTest library. -as12312
21
22 #include "mirtk/GenericImage.h"
23 #include "mirtk/InterpolateImageFunction.h"
24 #include "mirtk/ExtrapolateImageFunction.h"
25
26 using namespace mirtk;
27
28 // ===========================================================================
29 // Macros
30 // ===========================================================================
31
32 // ---------------------------------------------------------------------------
33 #define TEST(id) \
34 const char *_id = id; \
35 int _nfail = 0; \
36 cout << "Test case: " << _id << endl
37
38 // ---------------------------------------------------------------------------
39 #define RESULT _nfail
40
41 // ---------------------------------------------------------------------------
42 #define NULLPTR(actual, message, exit_if_not) \
43 do { \
44 void *_actual = (actual); \
45 if (_actual != NULL) { \
46 _nfail++; \
47 cerr << message << endl; \
48 cerr << " Actual: " << _actual << endl; \
49 cerr << " Expected: NULL" << endl; \
50 if (exit_if_not) exit(_nfail); \
51 } \
52 }while(false)
53
54 // ---------------------------------------------------------------------------
55 #define NOT_NULLPTR(actual, message, exit_if_not) \
56 do { \
57 void *_actual = (actual); \
58 if (_actual == NULL) { \
59 _nfail++; \
60 cerr << message << endl; \
61 cerr << " Actual: " << _actual << endl; \
62 cerr << " Expected: !NULL" << endl; \
63 if (exit_if_not) exit(_nfail); \
64 } \
65 }while(false)
66
67 // ---------------------------------------------------------------------------
68 #define EQUAL(actual, expected, message, exit_if_not) \
69 do { \
70 double _actual = (actual); \
71 double _expected = (expected); \
72 if (fabs(_actual - _expected) >= 1e-10) { \
73 _nfail++; \
74 cerr << message << endl; \
75 cerr << " Actual: " << setprecision(15) << _actual << endl; \
76 cerr << " Expected: " << setprecision(15) << _expected << endl; \
77 if (exit_if_not) exit(_nfail); \
78 } \
79 }while(false)
80
81 // ---------------------------------------------------------------------------
82 #define NOT_EQUAL(actual, expected, message, exit_if_not) \
83 do { \
84 double _actual = (actual); \
85 double _expected = (expected); \
86 if (fabs(_actual - _expected) < 1e-10) { \
87 _nfail++; \
88 cerr << message << endl; \
89 cerr << " Actual: " << setprecision(15) << _actual << endl; \
90 cerr << " Expected: " << setprecision(15) << _expected << endl; \
91 if (exit_if_not) exit(_nfail); \
92 } \
93 }while(false)
94
95 // ---------------------------------------------------------------------------
96 #define STREQUAL(actual, expected, message, exit_if_not) \
97 do { \
98 string _actual = (actual); \
99 string _expected = (expected); \
100 if (_actual != _expected) { \
101 _nfail++; \
102 cerr << message << endl; \
103 cerr << " Actual: " << _actual << endl; \
104 cerr << " Expected: " << _expected << endl; \
105 if (exit_if_not) exit(_nfail); \
106 } \
107 }while(false)
108
109 // ---------------------------------------------------------------------------
110 #define EXPECT_NULL(actual, message) NULLPTR(actual, message, false)
111 #define EXPECT_NOT_NULL(actual, message) NOT_NULLPTR(actual, message, false)
112 #define EXPECT_EQUAL(actual, expected, message) EQUAL(actual, expected, message, false)
113 #define EXPECT_NOT_EQUAL(actual, expected, message) NOT_EQUAL(actual, expected, message, false)
114 #define EXPECT_STREQUAL (actual, expected, message) STREQUAL(actual, expected, message, false)
115
116 // ---------------------------------------------------------------------------
117 #define ASSERT_NULL(actual, message) NULLPTR(actual, message, true)
118 #define ASSERT_NOT_NULL(actual, message) NOT_NULLPTR(actual, message, true)
119 #define ASSERT_EQUAL(actual, expected, message) EQUAL(actual, expected, message, true)
120 #define ASSERT_NOT_EQUAL(actual, expected, message) NOT_EQUAL(actual, expected, message, true)
121 #define ASSERT_STREQUAL(actual, expected, message) STREQUAL(actual, expected, message, true)
122
123 // ===========================================================================
124 // Test images
125 // ===========================================================================
126
127 // ---------------------------------------------------------------------------
128 template <class VoxelType>
create_test_image(int x=16,int y=16,int z=1,int t=1,int n=1)129 GenericImage<VoxelType> *create_test_image(int x = 16, int y = 16, int z = 1, int t = 1, int n = 1)
130 {
131 // Instantiate image
132 GenericImage<VoxelType> *image = new GenericImage<double>(x, y, z, t, n);
133 // Fill test image
134 for (int l = 0; l < image->T(); l++) {
135 for (int k = 0; k < image->Z(); k++) {
136 for (int j = 0; j < image->Y(); j++) {
137 for (int i = 0; i < image->X(); i++) {
138 image->Put(i, j, k, l, static_cast<VoxelType>(image->VoxelToIndex(i, j, k, l)));
139 }
140 }
141 }
142 }
143 return image;
144 }
145
146 // ===========================================================================
147 // Tests
148 // ===========================================================================
149
150 // ---------------------------------------------------------------------------
test_Initialize()151 int test_Initialize()
152 {
153 TEST("test_Initialize");
154
155 GenericImage<double> *image = create_test_image<double>(16, 16);
156 InterpolateImageFunction *inter = InterpolateImageFunction::New(Interpolation_NN, Extrapolation_Const, image);
157 ExtrapolateImageFunction *extra = inter->Extrapolator();
158
159 inter->Initialize();
160 extra->Initialize(); // not required, but shall also not hurt (ie., recurse infinitely)
161 inter->Initialize();
162
163 return RESULT;
164 }
165
166 // ---------------------------------------------------------------------------
test_IsInsideOutside()167 int test_IsInsideOutside()
168 {
169 TEST("test_IsInsideOutside");
170
171 GenericImage<double> *image = NULL;
172 InterpolateImageFunction *inter = NULL;
173 //ExtrapolateImageFunction *extra = NULL;
174
175 // --------------------------------------------------------------------------
176 // 2D
177 image = create_test_image<double>(16, 16);
178 inter = InterpolateImageFunction::New(Interpolation_NN, Extrapolation_Const, image);
179 //extra = inter->Extrapolator();
180
181 inter->Initialize();
182
183 EXPECT_EQUAL(inter->IsInside (3.0, 2.0), true, "Check if voxel is inside image domain");
184 EXPECT_EQUAL(inter->IsInside (3.4, 2.1), true, "Check if sub-voxel is inside image domain");
185
186 EXPECT_EQUAL(inter->IsInside (-3.0, 0.0), false, "Check if voxel is outside image domain");
187 EXPECT_EQUAL(inter->IsInside (-3.4, 2.1), false, "Check if sub-voxel is outside image domain");
188
189 delete image;
190 delete inter;
191
192 // --------------------------------------------------------------------------
193 // 3D
194 image = create_test_image<double>(16, 16, 16);
195 inter = InterpolateImageFunction::New(Interpolation_NN, Extrapolation_Const, image);
196 //extra = inter->Extrapolator();
197
198 inter->Initialize();
199
200 EXPECT_EQUAL(inter->IsInside (3.0, 2.0, 5.0), true, "Check if voxel is inside image domain");
201 EXPECT_EQUAL(inter->IsInside (3.4, 2.1, 5.5), true, "Check if sub-voxel is inside image domain");
202
203 EXPECT_EQUAL(inter->IsInside (-3.0, 0.0, 1.0), false, "Check if voxel is outside image domain");
204 EXPECT_EQUAL(inter->IsInside (-3.4, 2.1, 1.0), false, "Check if sub-voxel is outside image domain");
205
206 delete image;
207 delete inter;
208
209 return RESULT;
210 }
211
212 // ---------------------------------------------------------------------------
test_Interpolation_NN_Extrapolation_Default()213 int test_Interpolation_NN_Extrapolation_Default()
214 {
215 TEST("test_Interpolation_NN_Extrapolation_Default");
216
217 GenericImage<double> *image = create_test_image<double>(16, 16, 16);
218 InterpolateImageFunction *func = InterpolateImageFunction::New(Interpolation_NN, image);
219
220 // Initialize image function
221 EXPECT_NULL(func->Extrapolator(), "Extrapolator not instantiated yet");
222
223 func->Initialize();
224
225 ASSERT_NOT_NULL(func->Extrapolator(), "Extrapolator initialized");
226
227 // Check instantiated image function
228 ASSERT_STREQUAL(func->NameOfClass(), "GenericNearestNeighborInterpolateImageFunction", "Type of interpolator");
229 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericConstExtrapolateImageFunction", "Type of extrapolator");
230 EXPECT_EQUAL(func->Extrapolator()->DefaultValue(), 0, "Constant outside value");
231
232 // Interpolate inside of image domain
233 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.0), image->VoxelToIndex(3, 2, 5), "Interpolate image value at voxel position");
234 EXPECT_EQUAL(func->Evaluate(3.4, 2.1, 5.5), image->VoxelToIndex(3, 2, 6), "Interpolate image value at sub-voxel position");
235
236 // Extrapolate outside of image domain
237 EXPECT_EQUAL(func->Evaluate(-3.0, 0.0, 1.0), 0, "Extrapolate image value at voxel position");
238 EXPECT_EQUAL(func->Evaluate(-3.4, 2.1, 1.0), 0, "Extrapolate image value at sub-voxel position");
239
240 // Clean up
241 delete image;
242 delete func;
243
244 return RESULT;
245 }
246
247 // ---------------------------------------------------------------------------
test_Interpolation_NN_Extrapolation_Const()248 int test_Interpolation_NN_Extrapolation_Const()
249 {
250 TEST("test_Interpolation_NN_Extrapolation_Const");
251
252 GenericImage<double> *image = NULL;
253 InterpolateImageFunction *func = NULL;
254
255 // -------------------------------------------------------------------------
256 // 2D
257 image = create_test_image<double>(16, 16);
258 func = InterpolateImageFunction::New(Interpolation_NN, Extrapolation_Const, image);
259
260 // Initialize image function
261 func->Initialize();
262
263 // Check instantiated image function
264 ASSERT_STREQUAL(func->NameOfClass(), "GenericNearestNeighborInterpolateImageFunction", "Type of interpolator");
265 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericConstExtrapolateImageFunction", "Type of extrapolator");
266 EXPECT_EQUAL(func->Extrapolator()->DefaultValue(), 0, "Constant outside value");
267
268 // Interpolate inside of image domain
269 EXPECT_EQUAL(func->Evaluate(3.0, 2.0), image->VoxelToIndex(3, 2), "Interpolate image value at voxel position");
270 EXPECT_EQUAL(func->Evaluate(3.4, 2.1), image->VoxelToIndex(3, 2), "Interpolate image value at sub-voxel position");
271
272 // Extrapolate outside of image domain
273 EXPECT_EQUAL(func->Evaluate(-3.0, 0.0), 0, "Extrapolate image value at voxel position");
274 EXPECT_EQUAL(func->Evaluate(-3.4, 2.1), 0, "Extrapolate image value at sub-voxel position");
275
276 // Clean up
277 delete image;
278 delete func;
279
280 // -------------------------------------------------------------------------
281 // 3D
282 image = create_test_image<double>(16, 16, 16);
283 func = InterpolateImageFunction::New(Interpolation_NN, Extrapolation_Const, image);
284
285 // Initialize image function
286 func->Initialize();
287
288 // Check instantiated image function
289 ASSERT_STREQUAL(func->NameOfClass(), "GenericNearestNeighborInterpolateImageFunction", "Type of interpolator");
290 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericConstExtrapolateImageFunction", "Type of extrapolator");
291 EXPECT_EQUAL(func->Extrapolator()->DefaultValue(), 0, "Constant outside value");
292
293 // Interpolate inside of image domain
294 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.0), image->VoxelToIndex(3, 2, 5), "Interpolate image value at voxel position");
295 EXPECT_EQUAL(func->Evaluate(3.4, 2.1, 5.5), image->VoxelToIndex(3, 2, 6), "Interpolate image value at sub-voxel position");
296
297 // Extrapolate outside of image domain
298 EXPECT_EQUAL(func->Evaluate(-3.0, 0.0, 1.0), 0, "Extrapolate image value at voxel position");
299 EXPECT_EQUAL(func->Evaluate(-3.4, 2.1, 1.0), 0, "Extrapolate image value at sub-voxel position");
300
301 // Clean up
302 delete image;
303 delete func;
304
305 return RESULT;
306 }
307
308 // ---------------------------------------------------------------------------
test_Interpolation_Linear_Extrapolation_Const()309 int test_Interpolation_Linear_Extrapolation_Const()
310 {
311 TEST("test_Interpolation_Linear_Extrapolation_Const");
312
313 GenericImage<double> *image = NULL;
314 InterpolateImageFunction *func = NULL;
315
316 // -------------------------------------------------------------------------
317 // 2D
318 image = create_test_image<double>(16, 16);
319 func = InterpolateImageFunction::New(Interpolation_Linear, Extrapolation_Const, image);
320
321 // Initialize image function
322 func->Initialize();
323 func->Extrapolator()->DefaultValue(-1);
324
325 // Check instantiated image function
326 ASSERT_STREQUAL(func->NameOfClass(), "GenericLinearInterpolateImageFunction2D", "Type of interpolator");
327 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericConstExtrapolateImageFunction", "Type of extrapolator");
328
329 // Interpolate inside image domain
330 EXPECT_EQUAL(func->Evaluate(3.0, 2.0), image->VoxelToIndex(3, 2), "Interpolate image value at voxel position");
331 EXPECT_EQUAL(func->Evaluate(3.4, 2.0), 0.6 * image->VoxelToIndex(3, 2) + 0.4 * image->VoxelToIndex(4, 2), "Interpolate image value at sub-voxel position along x");
332 EXPECT_EQUAL(func->Evaluate(3.0, 2.7), 0.3 * image->VoxelToIndex(3, 2) + 0.7 * image->VoxelToIndex(3, 3), "Interpolate image value at sub-voxel position along y");
333
334 // Extrapolate outside image domain
335 ASSERT_EQUAL(func->Extrapolator()->DefaultValue(), -1, "Default value of extrapolator");
336 EXPECT_EQUAL(func->Evaluate(-0.1, -0.1), -0.19, "Extrapolate image value outside of image domain");
337 EXPECT_EQUAL(func->Evaluate(-1.1, 0.0), -1, "Extrapolate image value outside of image domain in x");
338 EXPECT_EQUAL(func->Evaluate(16.1, 0.0), -1, "Extrapolate image value outside of image domain in x");
339 EXPECT_EQUAL(func->Evaluate( 0.0, -1.1), -1, "Extrapolate image value outside of image domain in y");
340 EXPECT_EQUAL(func->Evaluate( 0.0, 16.1), -1, "Extrapolate image value outside of image domain in y");
341 EXPECT_EQUAL(func->Evaluate(-1.1, -1.1), -1, "Extrapolate image value outside of image domain in x and y");
342 EXPECT_EQUAL(func->Evaluate(16.1, 16.1), -1, "Extrapolate image value outside of image domain in x and y");
343
344 // Clean up
345 delete image;
346 delete func;
347
348 // -------------------------------------------------------------------------
349 // 3D
350 image = create_test_image<double>(16, 16, 16);
351 func = InterpolateImageFunction::New(Interpolation_Linear, Extrapolation_Const, image);
352
353 // Initialize image function
354 func->Initialize();
355 func->Extrapolator()->DefaultValue(-1);
356
357 // Check instantiated image function
358 ASSERT_STREQUAL(func->NameOfClass(), "GenericLinearInterpolateImageFunction3D", "Type of interpolator");
359 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericConstExtrapolateImageFunction", "Type of extrapolator");
360
361 // Interpolate inside image domain
362 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.0), image->VoxelToIndex(3, 2, 5), "Interpolate image value at voxel position");
363 EXPECT_EQUAL(func->Evaluate(3.4, 2.0, 5.0), 0.6 * image->VoxelToIndex(3, 2, 5) + 0.4 * image->VoxelToIndex(4, 2, 5), "Interpolate image value at sub-voxel position along x");
364 EXPECT_EQUAL(func->Evaluate(3.0, 2.7, 5.0), 0.3 * image->VoxelToIndex(3, 2, 5) + 0.7 * image->VoxelToIndex(3, 3, 5), "Interpolate image value at sub-voxel position along y");
365 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.1), 0.9 * image->VoxelToIndex(3, 2, 5) + 0.1 * image->VoxelToIndex(3, 2, 6), "Interpolate image value at sub-voxel position along z");
366
367 // Extrapolate outside image domain
368 ASSERT_EQUAL(func->Extrapolator()->DefaultValue(), -1, "Default value of extrapolator");
369 EXPECT_EQUAL(func->Evaluate(-1.1, 0.0, 0.0), -1, "Extrapolate image value slightly outside of image domain in x");
370 EXPECT_EQUAL(func->Evaluate(16.1, 0.0, 0.0), -1, "Extrapolate image value slightly outside of image domain in x");
371 EXPECT_EQUAL(func->Evaluate( 0.0, -1.1, 0.0), -1, "Extrapolate image value slightly outside of image domain in y");
372 EXPECT_EQUAL(func->Evaluate( 0.0, 16.1, 0.0), -1, "Extrapolate image value slightly outside of image domain in y");
373 EXPECT_EQUAL(func->Evaluate( 0.0, 0.0, -1.1), -1, "Extrapolate image value slightly outside of image domain in z");
374 EXPECT_EQUAL(func->Evaluate( 0.0, 0.0, 16.1), -1, "Extrapolate image value slightly outside of image domain in z");
375 EXPECT_EQUAL(func->Evaluate(-1.1, -1.1, 0.0), -1, "Extrapolate image value slightly outside of image domain in x and y");
376 EXPECT_EQUAL(func->Evaluate(16.1, 16.1, 0.0), -1, "Extrapolate image value slightly outside of image domain in x and y");
377 EXPECT_EQUAL(func->Evaluate(-1.1, 0.0, -1.1), -1, "Extrapolate image value slightly outside of image domain in x and z");
378 EXPECT_EQUAL(func->Evaluate(16.1, 0.0, 16.1), -1, "Extrapolate image value slightly outside of image domain in x and z");
379 EXPECT_EQUAL(func->Evaluate( 0.0, -1.1, -1.1), -1, "Extrapolate image value slightly outside of image domain in y and z");
380 EXPECT_EQUAL(func->Evaluate( 0.0, 16.1, 16.1), -1, "Extrapolate image value slightly outside of image domain in y and z");
381
382 // Clean up
383 delete image;
384 delete func;
385
386 // -------------------------------------------------------------------------
387 // 3D vector field
388 image = create_test_image<double>(16, 16, 16, 1, 3);
389 func = InterpolateImageFunction::New(Interpolation_Linear, Extrapolation_Const, image);
390
391 // Initialize image function
392 func->Initialize();
393 func->Extrapolator()->DefaultValue(-1);
394
395 // Check instantiated image function
396 ASSERT_STREQUAL(func->NameOfClass(), "GenericLinearInterpolateImageFunction3D", "Type of interpolator");
397 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericConstExtrapolateImageFunction", "Type of extrapolator");
398
399 // Interpolate inside image domain
400 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.0, 0.0), image->VoxelToIndex(3, 2, 5, 0), "Interpolate image value at voxel position");
401 EXPECT_EQUAL(func->Evaluate(3.4, 2.0, 5.0, 0.0), 0.6 * image->VoxelToIndex(3, 2, 5, 0) + 0.4 * image->VoxelToIndex(4, 2, 5, 0), "Interpolate image value at sub-voxel position along x");
402 EXPECT_EQUAL(func->Evaluate(3.0, 2.7, 5.0, 0.0), 0.3 * image->VoxelToIndex(3, 2, 5, 0) + 0.7 * image->VoxelToIndex(3, 3, 5, 0), "Interpolate image value at sub-voxel position along y");
403 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.1, 0.0), 0.9 * image->VoxelToIndex(3, 2, 5, 0) + 0.1 * image->VoxelToIndex(3, 2, 6, 0), "Interpolate image value at sub-voxel position along z");
404
405 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.0, 1.0), image->VoxelToIndex(3, 2, 5, 1), "Interpolate image value at voxel position");
406 EXPECT_EQUAL(func->Evaluate(3.4, 2.0, 5.0, 1.0), 0.6 * image->VoxelToIndex(3, 2, 5, 1) + 0.4 * image->VoxelToIndex(4, 2, 5, 1), "Interpolate image value at sub-voxel position along x");
407 EXPECT_EQUAL(func->Evaluate(3.0, 2.7, 5.0, 1.0), 0.3 * image->VoxelToIndex(3, 2, 5, 1) + 0.7 * image->VoxelToIndex(3, 3, 5, 1), "Interpolate image value at sub-voxel position along y");
408 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.1, 1.0), 0.9 * image->VoxelToIndex(3, 2, 5, 1) + 0.1 * image->VoxelToIndex(3, 2, 6, 1), "Interpolate image value at sub-voxel position along z");
409
410 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.0, 2.0), image->VoxelToIndex(3, 2, 5, 2), "Interpolate image value at voxel position");
411 EXPECT_EQUAL(func->Evaluate(3.4, 2.0, 5.0, 2.0), 0.6 * image->VoxelToIndex(3, 2, 5, 2) + 0.4 * image->VoxelToIndex(4, 2, 5, 2), "Interpolate image value at sub-voxel position along x");
412 EXPECT_EQUAL(func->Evaluate(3.0, 2.7, 5.0, 2.0), 0.3 * image->VoxelToIndex(3, 2, 5, 2) + 0.7 * image->VoxelToIndex(3, 3, 5, 2), "Interpolate image value at sub-voxel position along y");
413 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.1, 2.0), 0.9 * image->VoxelToIndex(3, 2, 5, 2) + 0.1 * image->VoxelToIndex(3, 2, 6, 2), "Interpolate image value at sub-voxel position along z");
414
415 // Clean up
416 delete image;
417 delete func;
418
419 return RESULT;
420 }
421
422 // ---------------------------------------------------------------------------
test_Interpolation_Linear_Extrapolation_NN()423 int test_Interpolation_Linear_Extrapolation_NN()
424 {
425 TEST("test_Interpolation_Linear_Extrapolation_NN");
426
427 GenericImage<double> *image = NULL;
428 InterpolateImageFunction *func = NULL;
429
430 // -------------------------------------------------------------------------
431 // 2D
432 image = create_test_image<double>(16, 16);
433 func = InterpolateImageFunction::New(Interpolation_Linear, Extrapolation_NN, image);
434
435 // Initialize image function
436 func->Initialize();
437
438 // Check instantiated image function
439 ASSERT_STREQUAL(func->NameOfClass(), "GenericLinearInterpolateImageFunction2D", "Type of interpolator");
440 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericNearestNeighborExtrapolateImageFunction", "Type of extrapolator");
441
442 // Interpolate inside image domain
443 EXPECT_EQUAL(func->Evaluate(3.0, 2.0), image->VoxelToIndex(3, 2), "Interpolate image value at voxel position");
444 EXPECT_EQUAL(func->Evaluate(3.4, 2.0), 0.6 * image->VoxelToIndex(3, 2) + 0.4 * image->VoxelToIndex(4, 2), "Interpolate image value at sub-voxel position along x");
445 EXPECT_EQUAL(func->Evaluate(3.0, 2.7), 0.3 * image->VoxelToIndex(3, 2) + 0.7 * image->VoxelToIndex(3, 3), "Interpolate image value at sub-voxel position along y");
446
447 // Extrapolate outside image domain
448 EXPECT_EQUAL(func->Evaluate(-0.1, 0.0), image->VoxelToIndex( 0, 0), "Extrapolate image value slightly outside of image domain in x");
449 EXPECT_EQUAL(func->Evaluate(15.1, 0.0), image->VoxelToIndex(15, 0), "Extrapolate image value slightly outside of image domain in x");
450 EXPECT_EQUAL(func->Evaluate( 0.0, -0.1), image->VoxelToIndex( 0, 0), "Extrapolate image value slightly outside of image domain in y");
451 EXPECT_EQUAL(func->Evaluate( 0.0, 15.1), image->VoxelToIndex( 0, 15), "Extrapolate image value slightly outside of image domain in y");
452 EXPECT_EQUAL(func->Evaluate(-0.1, -0.1), image->VoxelToIndex( 0, 0), "Extrapolate image value slightly outside of image domain in x and y");
453 EXPECT_EQUAL(func->Evaluate(15.1, 15.1), image->VoxelToIndex(15, 15), "Extrapolate image value slightly outside of image domain in x and y");
454
455 // Clean up
456 delete image;
457 delete func;
458
459 // -------------------------------------------------------------------------
460 // 3D
461 image = create_test_image<double>(16, 16, 16);
462 func = InterpolateImageFunction::New(Interpolation_Linear, Extrapolation_NN, image);
463
464 // Initialize image function
465 func->Initialize();
466
467 // Check instantiated image function
468 ASSERT_STREQUAL(func->NameOfClass(), "GenericLinearInterpolateImageFunction3D", "Type of interpolator");
469 ASSERT_STREQUAL(func->Extrapolator()->NameOfClass(), "GenericNearestNeighborExtrapolateImageFunction", "Type of extrapolator");
470
471 // Interpolate inside image domain
472 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.0), image->VoxelToIndex(3, 2, 5), "Interpolate image value at voxel position");
473 EXPECT_EQUAL(func->Evaluate(3.4, 2.0, 5.0), 0.6 * image->VoxelToIndex(3, 2, 5) + 0.4 * image->VoxelToIndex(4, 2, 5), "Interpolate image value at sub-voxel position along x");
474 EXPECT_EQUAL(func->Evaluate(3.0, 2.7, 5.0), 0.3 * image->VoxelToIndex(3, 2, 5) + 0.7 * image->VoxelToIndex(3, 3, 5), "Interpolate image value at sub-voxel position along y");
475 EXPECT_EQUAL(func->Evaluate(3.0, 2.0, 5.1), 0.9 * image->VoxelToIndex(3, 2, 5) + 0.1 * image->VoxelToIndex(3, 2, 6), "Interpolate image value at sub-voxel position along z");
476
477 // Extrapolate outside image domain
478 EXPECT_EQUAL(func->Evaluate(-0.1, 0.0, 0.0), image->VoxelToIndex( 0, 0, 0), "Extrapolate image value slightly outside of image domain in x");
479 EXPECT_EQUAL(func->Evaluate(15.1, 0.0, 0.0), image->VoxelToIndex(15, 0, 0), "Extrapolate image value slightly outside of image domain in x");
480 EXPECT_EQUAL(func->Evaluate( 0.0, -0.1, 0.0), image->VoxelToIndex( 0, 0, 0), "Extrapolate image value slightly outside of image domain in y");
481 EXPECT_EQUAL(func->Evaluate( 0.0, 15.1, 0.0), image->VoxelToIndex( 0, 15, 0), "Extrapolate image value slightly outside of image domain in y");
482 EXPECT_EQUAL(func->Evaluate( 0.0, 0.0, -0.1), image->VoxelToIndex( 0, 0, 0), "Extrapolate image value slightly outside of image domain in z");
483 EXPECT_EQUAL(func->Evaluate( 0.0, 0.0, 15.1), image->VoxelToIndex( 0, 0, 15), "Extrapolate image value slightly outside of image domain in z");
484 EXPECT_EQUAL(func->Evaluate(-0.1, -0.1, 0.0), image->VoxelToIndex( 0, 0, 0), "Extrapolate image value slightly outside of image domain in x and y");
485 EXPECT_EQUAL(func->Evaluate(15.1, 15.1, 0.0), image->VoxelToIndex(15, 15, 0), "Extrapolate image value slightly outside of image domain in x and y");
486 EXPECT_EQUAL(func->Evaluate(-0.1, 0.0, -0.1), image->VoxelToIndex( 0, 0, 0), "Extrapolate image value slightly outside of image domain in x and z");
487 EXPECT_EQUAL(func->Evaluate(15.1, 0.0, 15.1), image->VoxelToIndex(15, 0, 15), "Extrapolate image value slightly outside of image domain in x and z");
488 EXPECT_EQUAL(func->Evaluate( 0.0, -0.1, -0.1), image->VoxelToIndex( 0, 0, 0), "Extrapolate image value slightly outside of image domain in y and z");
489 EXPECT_EQUAL(func->Evaluate( 0.0, 15.1, 15.1), image->VoxelToIndex( 0, 15, 15), "Extrapolate image value slightly outside of image domain in y and z");
490
491 // Clean up
492 delete image;
493 delete func;
494
495 return RESULT;
496 }
497
498 // ===========================================================================
499 // Main
500 // ===========================================================================
501
502 // ---------------------------------------------------------------------------
InterpolateExtrapolateImageFunctionTest(int,char * [])503 int InterpolateExtrapolateImageFunctionTest(int, char *[])
504 {
505 int retval = 0;
506
507 retval += test_Initialize();
508 retval += test_IsInsideOutside();
509 retval += test_Interpolation_NN_Extrapolation_Default();
510 retval += test_Interpolation_NN_Extrapolation_Const();
511 retval += test_Interpolation_Linear_Extrapolation_Const();
512 retval += test_Interpolation_Linear_Extrapolation_NN();
513
514 return retval;
515 }
516