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