OpenWalnut  1.4.0
WThreadedTrackingFunction_test.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WTHREADEDTRACKINGFUNCTION_TEST_H
26 #define WTHREADEDTRACKINGFUNCTION_TEST_H
27 
28 #include <vector>
29 
30 #include <cxxtest/TestSuite.h>
31 
32 #include "../../common/WLogger.h"
33 #include "../WThreadedTrackingFunction.h"
34 
35 /**
36  * \class WTrackingUtilityTest
37  *
38  * Test the utility functions for tracking.
39  */
40 class WTrackingUtilityTest : public CxxTest::TestSuite
41 {
42  //! an abbreviation
44 
45 public:
46  /**
47  * Setup logger and other stuff for each test.
48  */
49  void setUp()
50  {
52  }
53 
54  /**
55  * Test if positions with a distance less then TRACKING_EPS from a boundary
56  * are determined correctly by onBoundary().
57  */
58  void testBoundary()
59  {
60  WVector3d x( 0.707, 0.707, 0.0 );
61  WVector3d y( -0.707, 0.707, 0.0 );
62  WVector3d z( 0.0, 0.0, 1.0 );
63  x = normalize( x );
64  y = normalize( y );
65 
66  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 0.0, 1.0, 0.0 ) );
67  // test the test
68  TS_ASSERT( ds );
69  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
70 
71  WVector3d v( 1.0, 0.0, 0.0 );
72  v += x * -0.5;
73  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
74  v[ 0 ] += 0.5 * TRACKING_EPS;
75  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
76  v[ 2 ] -= 2.0 * TRACKING_EPS;
77  v[ 1 ] += 1.6 * TRACKING_EPS;
78  TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
79 
80  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 0.5;
81  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
82  v[ 0 ] -= 0.6 * TRACKING_EPS;
83  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
84  v[ 2 ] += 1.5 * TRACKING_EPS;
85  v[ 1 ] += 2.6 * TRACKING_EPS;
86  TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
87 
88  v = WVector3d( 1.0, 0.0, 0.0 ) + y * 1.77 + z * 0.65;
89  TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
90 
91  v = WVector3d( 1.0, 0.0, 0.0 ) + y * 1.0 + z * 0.65;
92  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
93 
94  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.5 + y * 1.77 + z * 0.65;
95  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
96 
97  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 1.5 + y * 1.77 + z * 0.65;
98  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
99 
100  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.9 + y * 5.0 + z * 0.65;
101  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
102 
103  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 2.3 + y * 7.73 + z * 3.75;
104  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
105 
106  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.4 + y * 1.77 + z * 6.75;
107  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
108 
109  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.5 + y * 5.0 + z * 0.65;
110  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
111  v[ 1 ] -= 0.7 * TRACKING_EPS;
112  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
113  v[ 0 ] += 3.5 * TRACKING_EPS;
114  v[ 1 ] += 0.7 * TRACKING_EPS;
115  TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
116 
117  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 1.2 + y * 7.9 + z * 5.3;
118  TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
119  }
120 
121  /**
122  * Check if getDistanceToBoundary() returns the correct distance.
123  */
125  {
126  WVector3d x( 0.707, 0.707, 0.0 );
127  WVector3d y( -0.707, 0.707, 0.0 );
128  WVector3d z( 0.0, 0.0, 1.0 );
129  x = normalize( x );
130  y = normalize( y );
131 
132  WVector3d v( 1.0, 0.0, 0.0 );
133 
134  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 0.0, 1.0, 0.0 ) );
135  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
136 
137  TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, x ), 0.5, TRACKING_EPS );
138  TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, y ), 1.0, TRACKING_EPS );
139  TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, z ), 0.75, TRACKING_EPS );
140 
141  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 0.5;
142  TS_ASSERT_THROWS( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, x ), WException );
143 
144  v -= x * 2.0 * TRACKING_EPS;
145  TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, x ), 2.0 * TRACKING_EPS, TRACKING_EPS );
146 
147  v = WVector3d( 2.9741, 3.527, 1.992 );
148  WVector3d dir( 3, 4, -2.003 );
149  dir = normalize( dir );
151  WVector3d res = v + dir * t;
152  TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, res ) );
153 
154  v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.75 + y * 6.65 + z * 5.59;
155  TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, y ), 0.35, TRACKING_EPS );
156  }
157 
158  /**
159  * Test if followToNextVoxel() returns a valid (inside the grid) position
160  * in the next voxel (and not on any boundary).
161  */
163  {
164  {
165  WVector3d x( 0.707, 0.707, 0.0 );
166  WVector3d y( -0.707, 0.707, 0.0 );
167  WVector3d z( 0.0, 0.0, 1.0 );
168  x = normalize( x );
169  y = normalize( y );
170 
171  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 0.0, 1.0, 0.0 ) );
172  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
173 
175  // TODO(wiebel): somehow changing the order of the last multiplication does not find the desired operator*
176  j.first = WVector3d( 1.0, 0.0, 0.0 ) + ( x + y + z ) * ( wlimits::FLT_EPS + 0.7 ); // the starting point
177  j.second = x; // initial direction
178  TS_ASSERT( g->encloses( j.first ) );
179 
180  WVector3d v = j.first;
181 
182  TS_ASSERT( wtracking::WTrackingUtility::followToNextVoxel( ds, j, boost::bind( &This::simpleDirFunc, this, _1, _2 ) ) );
183  TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, j.first ) );
184  TS_ASSERT( g->encloses( j.first ) );
185  v += x * 0.8;
186  TS_ASSERT_DELTA( length( j.first - v ), 0.0, 2.0 * TRACKING_EPS );
187  }
188  }
189 
190 private:
191  /**
192  * A simple direction calculation function.
193  *
194  * \return A direction.
195  */
197  {
198  WVector3d v( 1.0, 1.0, 0.0 );
199  v = normalize( v );
200  return v;
201  }
202 
203  /**
204  * Build a test dataset.
205  *
206  * \param data The vector for every voxel.
207  *
208  * \return the test dataset
209  */
210  boost::shared_ptr< WDataSetSingle > buildTestData( WVector3d data )
211  {
212  WVector3d x( 0.707, 0.707, 0.0 );
213  WVector3d y( -0.707, 0.707, 0.0 );
214  WVector3d z( 0.0, 0.0, 1.0 );
215 
216  x = normalize( x );
217  y = normalize( y );
218 
219  y *= 2.0;
220  z *= 1.5;
221 
222  WMatrix< double > mat( 4, 4 );
223  mat.makeIdentity();
224  mat( 0, 0 ) = x[ 0 ];
225  mat( 1, 0 ) = x[ 1 ];
226  mat( 2, 0 ) = x[ 2 ];
227  mat( 0, 1 ) = y[ 0 ];
228  mat( 1, 1 ) = y[ 1 ];
229  mat( 2, 1 ) = y[ 2 ];
230  mat( 0, 2 ) = z[ 0 ];
231  mat( 1, 2 ) = z[ 1 ];
232  mat( 2, 2 ) = z[ 2 ];
233  mat( 0, 3 ) = 1.0;
234 
235  WGridTransformOrtho t( mat );
236  boost::shared_ptr< WGrid > g( new WGridRegular3D( 5, 5, 5, t ) );
237 
238  data = normalize( data );
239 
240  boost::shared_ptr< std::vector< double > > v( new std::vector< double > ( 5 * 5 * 5 * 3 ) );
241  for( std::size_t k = 0; k < 5 * 5 * 5; ++k )
242  {
243  v->at( 3 * k + 0 ) = data[ 0 ];
244  v->at( 3 * k + 1 ) = data[ 1 ];
245  v->at( 3 * k + 2 ) = data[ 2 ];
246  }
247 
248  boost::shared_ptr< WValueSetBase > vs( new WValueSet< double >( 1, 3, v, W_DT_DOUBLE ) );
249  return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( vs, g ) );
250  }
251 };
252 
253 /**
254  * \class WThreadedTrackingFunctionTest
255  *
256  * Test the WThreadedTrackingFunction class.
257  */
258 class WThreadedTrackingFunctionTest : public CxxTest::TestSuite
259 {
260  //! a handy abbreviation
262 
263 public:
264  /**
265  * Test if everything gets initialized correctly.
266  */
268  {
269  std::vector< int > v0;
270  std::vector< int > v1;
271  std::size_t numSeeds = 1;
272  std::size_t seedsPerPosition = 1;
273 
274  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
275  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
276  TS_ASSERT( g );
277 
278  {
280  i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition );
281 
282  // new test if everything was initialized correctly
283  TS_ASSERT_EQUALS( i.m_done, false );
284  TS_ASSERT_EQUALS( i.m_offset, 1.0 );
285  TS_ASSERT_EQUALS( i.m_pos[ 0 ], 1 );
286  TS_ASSERT_EQUALS( i.m_pos[ 1 ], 1 );
287  TS_ASSERT_EQUALS( i.m_pos[ 2 ], 1 );
288  TS_ASSERT_EQUALS( i.m_pos[ 3 ], 0 );
289  TS_ASSERT_EQUALS( i.m_min[ 0 ], 1 );
290  TS_ASSERT_EQUALS( i.m_min[ 1 ], 1 );
291  TS_ASSERT_EQUALS( i.m_min[ 2 ], 1 );
292  TS_ASSERT_EQUALS( i.m_min[ 3 ], 0 );
293  TS_ASSERT_EQUALS( i.m_max[ 0 ], 4 );
294  TS_ASSERT_EQUALS( i.m_max[ 1 ], 4 );
295  TS_ASSERT_EQUALS( i.m_max[ 2 ], 4 );
296  TS_ASSERT_EQUALS( i.m_max[ 3 ], 1 );
297  }
298  {
299  v0.resize( 3 );
300  v1.resize( 3 );
301  v0[ 0 ] = 1;
302  v0[ 1 ] = 2;
303  v0[ 2 ] = 1;
304  v1[ 0 ] = 3;
305  v1[ 1 ] = 3;
306  v1[ 2 ] = 4;
307  numSeeds = 4;
308  seedsPerPosition = 3;
309 
311  TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
312 
313  // new test if everything was initialized correctly
314  TS_ASSERT_EQUALS( i.m_done, false );
315  TS_ASSERT_EQUALS( i.m_offset, 0.25 );
316  TS_ASSERT_EQUALS( i.m_pos[ 0 ], 4 );
317  TS_ASSERT_EQUALS( i.m_pos[ 1 ], 8 );
318  TS_ASSERT_EQUALS( i.m_pos[ 2 ], 4 );
319  TS_ASSERT_EQUALS( i.m_pos[ 3 ], 0 );
320  TS_ASSERT_EQUALS( i.m_min[ 0 ], 4 );
321  TS_ASSERT_EQUALS( i.m_min[ 1 ], 8 );
322  TS_ASSERT_EQUALS( i.m_min[ 2 ], 4 );
323  TS_ASSERT_EQUALS( i.m_min[ 3 ], 0 );
324  TS_ASSERT_EQUALS( i.m_max[ 0 ], 12 );
325  TS_ASSERT_EQUALS( i.m_max[ 1 ], 12 );
326  TS_ASSERT_EQUALS( i.m_max[ 2 ], 16 );
327  TS_ASSERT_EQUALS( i.m_max[ 3 ], 3 );
328  }
329  {
330  // now lets do something wrong
332  v0[ 0 ] = -1;
333  TS_ASSERT_THROWS( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ), WException );
334  v0[ 0 ] = 0;
335  v1[ 1 ] = 5;
336  TS_ASSERT_THROWS( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ), WException );
337  }
338  }
339 
340  /**
341  * Test if indices (seed positions) iteration works.
342  */
344  {
345  std::vector< int > v0;
346  std::vector< int > v1;
347  std::size_t numSeeds = 1;
348  std::size_t seedsPerPosition = 1;
349 
350  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
351  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
352  TS_ASSERT( g );
353 
354  {
356  TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
357 
358  for( int j = 0; j < 27; ++j )
359  {
360  TS_ASSERT( !i.done() );
361  ++i;
362  }
363  TS_ASSERT( i.done() );
364  }
365  {
366  numSeeds = 4;
368  TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
369 
370  for( int j = 0; j < 27 * 64; ++j )
371  {
372  TS_ASSERT( !i.done() );
373  ++i;
374  }
375  TS_ASSERT( i.done() );
376  }
377  {
378  seedsPerPosition = 3;
380  TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
381 
382  for( int j = 0; j < 27 * 64 * 3; ++j )
383  {
384  TS_ASSERT( !i.done() );
385  ++i;
386  }
387  TS_ASSERT( i.done() );
388  }
389  {
390  v0.resize( 3, 1 );
391  v1.resize( 3 );
392  v1[ 0 ] = 4;
393  v1[ 1 ] = 3;
394  v1[ 2 ] = 4;
396  TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
397 
398  for( int j = 0; j < 18 * 64 * 3; ++j )
399  {
400  TS_ASSERT( !i.done() );
401  ++i;
402  }
403  TS_ASSERT( i.done() );
404  }
405  }
406 
407  /**
408  * Test if the right jobs get created from seeds.
409  */
411  {
412  WVector3d x( 0.707, 0.707, 0.0 );
413  WVector3d y( -0.707, 0.707, 0.0 );
414  WVector3d z( 0.0, 0.0, 1.0 );
415  x = normalize( x );
416  y = normalize( y );
417  y *= 2.0;
418  z *= 1.5;
419 
420  std::vector< int > v0;
421  std::vector< int > v1;
422  std::size_t numSeeds = 2;
423  std::size_t seedsPerPosition = 1;
424 
425  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
426  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
427  TS_ASSERT( g );
428 
429  {
431  TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
432 
434  WVector3d v = g->getOrigin() + 0.75 * x + 0.75 * y + 0.75 * z;
435 
436  std::cout << g->getOrigin() << std::endl;
437 
438  TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
439  TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
440  TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
441 
442  v += 0.5 * z;
443  ++i;
444  job = i.job();
445  TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
446  TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
447  TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
448 
449  for( int k = 0; k < 6; ++k )
450  {
451  ++i;
452  }
453  v += 0.5 * y;
454  job = i.job();
455  TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
456  TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
457  TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
458 
459  for( int k = 0; k < 36; ++k )
460  {
461  ++i;
462  }
463  v += 0.5 * x;
464  job = i.job();
465  TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
466  TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
467  TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
468 
469  TS_ASSERT_EQUALS( job.second[ 0 ], 0.0 );
470  TS_ASSERT_EQUALS( job.second[ 1 ], 0.0 );
471  TS_ASSERT_EQUALS( job.second[ 2 ], 0.0 );
472  }
473  {
474  numSeeds = 4;
475  seedsPerPosition = 11;
477  TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
478 
480  WVector3d v = g->getOrigin() + 0.625 * x + 0.625 * y + 0.625 * z;
481  for( int k = 0; k < 11; ++k )
482  {
483  job = i.job();
484  TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
485  TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
486  TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
487  ++i;
488  }
489  }
490  }
491 
492  /**
493  * Test if everything gets initialized correctly.
494  */
496  {
497  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
498  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
499  TS_ASSERT( g );
500 
501  TS_ASSERT_THROWS_NOTHING(
503  boost::bind( &This::dirFunc, this, _1, _2, WVector3d( 1.0, 0.0, 0.0 ) ),
504  boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
505  boost::bind( &This::fibVis, this, _1 ),
506  boost::bind( &This::pntVis, this, _1 ) ) );
507  }
508 
509  /**
510  * Test if the correct amount of jobs gets created.
511  */
512  void testGetJob()
513  {
514  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 7 );
515  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
516  TS_ASSERT( g );
517 
518  wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, WVector3d( 1.0, 0.0, 0.0 ) ),
519  boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
520  boost::bind( &This::fibVis, this, _1 ),
521  boost::bind( &This::pntVis, this, _1 ) );
523  for( int i = 0; i < 125; ++i )
524  {
525  TS_ASSERT( w.getJob( job ) );
526  }
527  TS_ASSERT( !w.getJob( job ) );
528  }
529 
530  /**
531  * Test if fibers with the right number of points get created.
532  */
533  void testCompute()
534  {
535  WVector3d x( 0.707, 0.707, 0.0 );
536  WVector3d y( -0.707, 0.707, 0.0 );
537  WVector3d z( 0.0, 0.0, 1.0 );
538  x = normalize( x );
539  y = normalize( y );
540 
541  boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 7 );
542  boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
543  TS_ASSERT( g );
544  {
545  wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, x ),
546  boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
547  boost::bind( &This::fibVis, this, _1 ),
548  boost::bind( &This::pntVis, this, _1 ) );
550  m_points.getWriteTicket()->get() = 0;
551  w.getJob( job );
552  w.compute( ds, job );
553  TS_ASSERT_EQUALS( m_points.getReadTicket()->get(), 7 );
554  }
555  {
556  wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, y ),
557  boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
558  boost::bind( &This::fibVis, this, _1 ),
559  boost::bind( &This::pntVis, this, _1 ) );
561  m_points.getWriteTicket()->get() = 0;
562  w.getJob( job );
563  w.compute( ds, job );
564  TS_ASSERT_EQUALS( m_points.getReadTicket()->get(), 7 );
565  }
566  }
567 
568 private:
569  /**
570  * Build a test dataset.
571  *
572  * \param data The vector for every voxel.
573  * \param n The number of grid position in every direction.
574  *
575  * \return The dataset.
576  */
577  boost::shared_ptr< WDataSetSingle > buildTestData( WVector3d data, int n )
578  {
579  WVector3d x( 0.707, 0.707, 0.0 );
580  WVector3d y( -0.707, 0.707, 0.0 );
581  WVector3d z( 0.0, 0.0, 1.0 );
582  x = normalize( x );
583  y = normalize( y );
584  y *= 2.0;
585  z *= 1.5;
586 
587  WMatrix< double > mat( 4, 4 );
588  mat.makeIdentity();
589  mat( 0, 0 ) = x[ 0 ];
590  mat( 1, 0 ) = x[ 1 ];
591  mat( 2, 0 ) = x[ 2 ];
592  mat( 0, 1 ) = y[ 0 ];
593  mat( 1, 1 ) = y[ 1 ];
594  mat( 2, 1 ) = y[ 2 ];
595  mat( 0, 2 ) = z[ 0 ];
596  mat( 1, 2 ) = z[ 1 ];
597  mat( 2, 2 ) = z[ 2 ];
598  mat( 0, 3 ) = 1.0;
599 
600  WGridTransformOrtho t( mat );
601  boost::shared_ptr< WGrid > g( new WGridRegular3D( n, n, n, t ) );
602 
603  data = normalize( data );
604 
605  boost::shared_ptr< std::vector< double > > v( new std::vector< double >( n * n * n * 3 ) );
606  for( std::size_t k = 0; k < static_cast< std::size_t >( n * n * n ); ++k )
607  {
608  v->at( 3 * k + 0 ) = data[ 0 ];
609  v->at( 3 * k + 1 ) = data[ 1 ];
610  v->at( 3 * k + 2 ) = data[ 2 ];
611  }
612 
613  boost::shared_ptr< WValueSetBase > vs( new WValueSet< double >( 1, 3, v, W_DT_DOUBLE ) );
614  return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( vs, g ) );
615  }
616 
617  /**
618  * The direction computation function. Simply returns the parameter vector.
619  *
620  * \param j The current job.
621  * \param d The direction to return.
622  *
623  * \return d
624  */
627  WVector3d d )
628  {
629  if( dot( j.second, d ) > 0.0 )
630  {
631  return d;
632  }
633  else
634  {
635  return d * -1.0;
636  }
637  }
638 
639  /**
640  * The fiber visitor. Does nothing.
641  */
642  void fibVis( std::vector< WVector3d > const& )
643  {
644  }
645 
646  /**
647  * The point visitor. Counts the number of points found.
648  */
649  void pntVis( WVector3d const& )
650  {
651  ++m_points.getWriteTicket()->get();
652  }
653 
654  //! the number of points found
656 };
657 
658 #endif // WTHREADEDTRACKINGFUNCTION_TEST_H
Test the utility functions for tracking.
WThreadedTrackingFunctionTest This
a handy abbreviation
WTrackingUtility::DataSetPtr DataSetPtr
a pointer to a dataset
A grid that has parallelepiped cells which all have the same proportion.
WTrackingUtilityTest This
an abbreviation
void testFollowToNextVoxel()
Test if followToNextVoxel() returns a valid (inside the grid) position in the next voxel (and not on ...
WMatrix & makeIdentity()
Makes the matrix contain the identity matrix, i.e.
Definition: WMatrix.h:352
void testIndexToJob()
Test if the right jobs get created from seeds.
boost::shared_ptr< WDataSetSingle > buildTestData(WVector3d data)
Build a test dataset.
void testIndexInitialization()
Test if everything gets initialized correctly.
void testGetDistanceToBoundary()
Check if getDistanceToBoundary() returns the correct distance.
std::pair< WVector3d, WVector3d > JobType
define a job type for tracking algorithms
bool done()
Check if there aren't any more seed positions.
boost::shared_ptr< DataSetType const > DataSetPtr
a pointer to a dataset
void pntVis(WVector3d const &)
The point visitor.
boost::array< std::size_t, 4 > m_pos
the position in the seed space
virtual bool getJob(JobType &job)
The job generator.
double m_offset
the relative (to the size of a voxel) distance between seeds
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
virtual void compute(DataSetPtr input, JobType const &job)
The calculation per job.
static void startup(std::ostream &output=std::cout, LogLevel level=LL_DEBUG)
Create the first and only instance of the logger as it is a singleton.
Definition: WLogger.cpp:41
WriteTicket getWriteTicket(bool suppressNotify=false) const
Returns a ticket to get write access to the contained data.
const float FLT_EPS
Smallest float such: 1.0 + FLT_EPS == 1.0 is still true.
Definition: WLimits.cpp:37
void testInstantiation()
Test if everything gets initialized correctly.
void testIndexIncrement()
Test if indices (seed positions) iteration works.
boost::array< std::size_t, 4 > m_max
the maximum position in the seed space
WVector3d simpleDirFunc(wtracking::WTrackingUtility::DataSetPtr, wtracking::WTrackingUtility::JobType const &)
A simple direction calculation function.
boost::array< std::size_t, 4 > m_min
the minimum position in the seed space
static bool followToNextVoxel(DataSetPtr dataset, JobType &job, DirFunc const &dirFunc)
A function that follows a direction until leaving the current voxel.
A data set consisting of a set of values based on a grid.
WSharedObject< std::size_t > m_points
the number of points found
static double getDistanceToBoundary(Grid3DPtr grid, WVector3d const &pos, WVector3d const &dir)
Calculate the distance from a given position to the nearest voxel boundary on the ray from the positi...
void setUp()
Setup logger and other stuff for each test.
Implements a generalized multithreaded tracking algorithm.
void fibVis(std::vector< WVector3d > const &)
The fiber visitor.
ValueT & at(size_t row, size_t col)
Returns a reference to the component of an row and column in order to provide access to the component...
Base Class for all value set types.
Definition: WValueSet.h:46
void testBoundary()
Test if positions with a distance less then TRACKING_EPS from a boundary are determined correctly by ...
void testGetJob()
Test if the correct amount of jobs gets created.
WVector3d dirFunc(wtracking::WThreadedTrackingFunction::DataSetPtr, wtracking::WThreadedTrackingFunction::JobType const &j, WVector3d d)
The direction computation function.
void testCompute()
Test if fibers with the right number of points get created.
boost::shared_ptr< WDataSetSingle > buildTestData(WVector3d data, int n)
Build a test dataset.
Test the WThreadedTrackingFunction class.
static bool onBoundary(Grid3DPtr grid, WVector3d const &pos)
Check if a point is on the boundary of the given grid, where boundary means a distance less then TRAC...
Basic exception handler.
Definition: WException.h:38
WTrackingUtility::JobType JobType
the job type
Implements an orthogonal grid transformation.