OpenWalnut  1.4.0
WThreadedTrackingFunction_test.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WTHREADEDTRACKINGFUNCTION_TEST_H
00026 #define WTHREADEDTRACKINGFUNCTION_TEST_H
00027 
00028 #include <vector>
00029 
00030 #include <cxxtest/TestSuite.h>
00031 
00032 #include "../../common/WLogger.h"
00033 #include "../WThreadedTrackingFunction.h"
00034 
00035 /**
00036  * \class WTrackingUtilityTest
00037  *
00038  * Test the utility functions for tracking.
00039  */
00040 class WTrackingUtilityTest : public CxxTest::TestSuite
00041 {
00042     //! an abbreviation
00043     typedef WTrackingUtilityTest This;
00044 
00045 public:
00046     /**
00047      * Setup logger and other stuff for each test.
00048      */
00049     void setUp()
00050     {
00051         WLogger::startup();
00052     }
00053 
00054     /**
00055      * Test if positions with a distance less then TRACKING_EPS from a boundary
00056      * are determined correctly by onBoundary().
00057      */
00058     void testBoundary()
00059     {
00060         WVector3d x( 0.707, 0.707, 0.0 );
00061         WVector3d y( -0.707, 0.707, 0.0 );
00062         WVector3d z( 0.0, 0.0, 1.0 );
00063         x = normalize( x );
00064         y = normalize( y );
00065 
00066         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 0.0, 1.0, 0.0 ) );
00067         // test the test
00068         TS_ASSERT( ds );
00069         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00070 
00071         WVector3d v( 1.0, 0.0, 0.0 );
00072         v += x * -0.5;
00073         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00074         v[ 0 ] += 0.5 * TRACKING_EPS;
00075         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00076         v[ 2 ] -= 2.0 * TRACKING_EPS;
00077         v[ 1 ] += 1.6 * TRACKING_EPS;
00078         TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
00079 
00080         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 0.5;
00081         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00082         v[ 0 ] -= 0.6 * TRACKING_EPS;
00083         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00084         v[ 2 ] += 1.5 * TRACKING_EPS;
00085         v[ 1 ] += 2.6 * TRACKING_EPS;
00086         TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
00087 
00088         v = WVector3d( 1.0, 0.0, 0.0 ) + y * 1.77 + z * 0.65;
00089         TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
00090 
00091         v = WVector3d( 1.0, 0.0, 0.0 ) + y * 1.0 + z * 0.65;
00092         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00093 
00094         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.5 + y * 1.77 + z * 0.65;
00095         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00096 
00097         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 1.5 + y * 1.77 + z * 0.65;
00098         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00099 
00100         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.9 + y * 5.0 + z * 0.65;
00101         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00102 
00103         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 2.3 + y * 7.73 + z * 3.75;
00104         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00105 
00106         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.4 + y * 1.77 + z * 6.75;
00107         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00108 
00109         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.5 + y * 5.0 + z * 0.65;
00110         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00111         v[ 1 ] -= 0.7 * TRACKING_EPS;
00112         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, v ) );
00113         v[ 0 ] += 3.5 * TRACKING_EPS;
00114         v[ 1 ] += 0.7 * TRACKING_EPS;
00115         TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
00116 
00117         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 1.2 + y * 7.9 + z * 5.3;
00118         TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, v ) );
00119     }
00120 
00121     /**
00122      * Check if getDistanceToBoundary() returns the correct distance.
00123      */
00124     void testGetDistanceToBoundary()
00125     {
00126         WVector3d x( 0.707, 0.707, 0.0 );
00127         WVector3d y( -0.707, 0.707, 0.0 );
00128         WVector3d z( 0.0, 0.0, 1.0 );
00129         x = normalize( x );
00130         y = normalize( y );
00131 
00132         WVector3d v( 1.0, 0.0, 0.0 );
00133 
00134         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 0.0, 1.0, 0.0 ) );
00135         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00136 
00137         TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, x ), 0.5, TRACKING_EPS );
00138         TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, y ), 1.0, TRACKING_EPS );
00139         TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, z ), 0.75, TRACKING_EPS );
00140 
00141         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 0.5;
00142         TS_ASSERT_THROWS( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, x ), WException );
00143 
00144         v -= x * 2.0 * TRACKING_EPS;
00145         TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, x ), 2.0 * TRACKING_EPS, TRACKING_EPS );
00146 
00147         v = WVector3d( 2.9741, 3.527, 1.992 );
00148         WVector3d dir( 3, 4, -2.003 );
00149         dir = normalize( dir );
00150         double t = wtracking::WTrackingUtility::getDistanceToBoundary( g, v, dir );
00151         WVector3d res = v + dir * t;
00152         TS_ASSERT( wtracking::WTrackingUtility::onBoundary( g, res ) );
00153 
00154         v = WVector3d( 1.0, 0.0, 0.0 ) + x * 3.75 + y * 6.65 + z * 5.59;
00155         TS_ASSERT_DELTA( wtracking::WTrackingUtility::getDistanceToBoundary( g, v, y ), 0.35, TRACKING_EPS );
00156     }
00157 
00158     /**
00159      * Test if followToNextVoxel() returns a valid (inside the grid) position
00160      * in the next voxel (and not on any boundary).
00161      */
00162     void testFollowToNextVoxel()
00163     {
00164         {
00165             WVector3d x( 0.707, 0.707, 0.0 );
00166             WVector3d y( -0.707, 0.707, 0.0 );
00167             WVector3d z( 0.0, 0.0, 1.0 );
00168             x = normalize( x );
00169             y = normalize( y );
00170 
00171             boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 0.0, 1.0, 0.0 ) );
00172             boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00173 
00174             wtracking::WTrackingUtility::JobType j;
00175             // TODO(wiebel): somehow changing the order of the last multiplication does not find the desired operator*
00176             j.first = WVector3d( 1.0, 0.0, 0.0 ) + ( x + y + z ) * ( wlimits::FLT_EPS + 0.7 ); // the starting point
00177             j.second = x; // initial direction
00178             TS_ASSERT( g->encloses( j.first ) );
00179 
00180             WVector3d v = j.first;
00181 
00182             TS_ASSERT( wtracking::WTrackingUtility::followToNextVoxel( ds, j, boost::bind( &This::simpleDirFunc, this, _1, _2 ) ) );
00183             TS_ASSERT( !wtracking::WTrackingUtility::onBoundary( g, j.first ) );
00184             TS_ASSERT( g->encloses( j.first ) );
00185             v += x * 0.8;
00186             TS_ASSERT_DELTA( length( j.first - v ), 0.0, 2.0 * TRACKING_EPS );
00187         }
00188     }
00189 
00190 private:
00191     /**
00192      * A simple direction calculation function.
00193      *
00194      * \return A direction.
00195      */
00196     WVector3d simpleDirFunc( wtracking::WTrackingUtility::DataSetPtr, wtracking::WTrackingUtility::JobType const& )
00197     {
00198         WVector3d v( 1.0, 1.0, 0.0 );
00199         v = normalize( v );
00200         return v;
00201     }
00202 
00203     /**
00204      * Build a test dataset.
00205      *
00206      * \param data The vector for every voxel.
00207      *
00208      * \return the test dataset
00209      */
00210     boost::shared_ptr< WDataSetSingle > buildTestData( WVector3d data )
00211     {
00212         WVector3d x( 0.707, 0.707, 0.0 );
00213         WVector3d y( -0.707, 0.707, 0.0 );
00214         WVector3d z( 0.0, 0.0, 1.0 );
00215 
00216         x = normalize( x );
00217         y = normalize( y );
00218 
00219         y *= 2.0;
00220         z *= 1.5;
00221 
00222         WMatrix< double > mat( 4, 4 );
00223         mat.makeIdentity();
00224         mat( 0, 0 ) = x[ 0 ];
00225         mat( 1, 0 ) = x[ 1 ];
00226         mat( 2, 0 ) = x[ 2 ];
00227         mat( 0, 1 ) = y[ 0 ];
00228         mat( 1, 1 ) = y[ 1 ];
00229         mat( 2, 1 ) = y[ 2 ];
00230         mat( 0, 2 ) = z[ 0 ];
00231         mat( 1, 2 ) = z[ 1 ];
00232         mat( 2, 2 ) = z[ 2 ];
00233         mat( 0, 3 ) = 1.0;
00234 
00235         WGridTransformOrtho t( mat );
00236         boost::shared_ptr< WGrid > g( new WGridRegular3D( 5, 5, 5, t ) );
00237 
00238         data = normalize( data );
00239 
00240         boost::shared_ptr< std::vector< double > > v( new  std::vector< double > ( 5 * 5 * 5 * 3 ) );
00241         for( std::size_t k = 0; k < 5 * 5 * 5; ++k )
00242         {
00243             v->at( 3 * k + 0 ) = data[ 0 ];
00244             v->at( 3 * k + 1 ) = data[ 1 ];
00245             v->at( 3 * k + 2 ) = data[ 2 ];
00246         }
00247 
00248         boost::shared_ptr< WValueSetBase > vs( new WValueSet< double >( 1, 3, v, W_DT_DOUBLE ) );
00249         return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( vs, g ) );
00250     }
00251 };
00252 
00253 /**
00254  * \class WThreadedTrackingFunctionTest
00255  *
00256  * Test the WThreadedTrackingFunction class.
00257  */
00258 class WThreadedTrackingFunctionTest : public CxxTest::TestSuite
00259 {
00260     //! a handy abbreviation
00261     typedef WThreadedTrackingFunctionTest This;
00262 
00263 public:
00264     /**
00265      * Test if everything gets initialized correctly.
00266      */
00267     void testIndexInitialization()
00268     {
00269         std::vector< int > v0;
00270         std::vector< int > v1;
00271         std::size_t numSeeds = 1;
00272         std::size_t seedsPerPosition = 1;
00273 
00274         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
00275         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00276         TS_ASSERT( g );
00277 
00278         {
00279             wtracking::WThreadedTrackingFunction::IndexType i;
00280             i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition );
00281 
00282             // new test if everything was initialized correctly
00283             TS_ASSERT_EQUALS( i.m_done, false );
00284             TS_ASSERT_EQUALS( i.m_offset, 1.0 );
00285             TS_ASSERT_EQUALS( i.m_pos[ 0 ], 1 );
00286             TS_ASSERT_EQUALS( i.m_pos[ 1 ], 1 );
00287             TS_ASSERT_EQUALS( i.m_pos[ 2 ], 1 );
00288             TS_ASSERT_EQUALS( i.m_pos[ 3 ], 0 );
00289             TS_ASSERT_EQUALS( i.m_min[ 0 ], 1 );
00290             TS_ASSERT_EQUALS( i.m_min[ 1 ], 1 );
00291             TS_ASSERT_EQUALS( i.m_min[ 2 ], 1 );
00292             TS_ASSERT_EQUALS( i.m_min[ 3 ], 0 );
00293             TS_ASSERT_EQUALS( i.m_max[ 0 ], 4 );
00294             TS_ASSERT_EQUALS( i.m_max[ 1 ], 4 );
00295             TS_ASSERT_EQUALS( i.m_max[ 2 ], 4 );
00296             TS_ASSERT_EQUALS( i.m_max[ 3 ], 1 );
00297         }
00298         {
00299             v0.resize( 3 );
00300             v1.resize( 3 );
00301             v0[ 0 ] = 1;
00302             v0[ 1 ] = 2;
00303             v0[ 2 ] = 1;
00304             v1[ 0 ] = 3;
00305             v1[ 1 ] = 3;
00306             v1[ 2 ] = 4;
00307             numSeeds = 4;
00308             seedsPerPosition = 3;
00309 
00310             wtracking::WThreadedTrackingFunction::IndexType i;
00311             TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
00312 
00313             // new test if everything was initialized correctly
00314             TS_ASSERT_EQUALS( i.m_done, false );
00315             TS_ASSERT_EQUALS( i.m_offset, 0.25 );
00316             TS_ASSERT_EQUALS( i.m_pos[ 0 ], 4 );
00317             TS_ASSERT_EQUALS( i.m_pos[ 1 ], 8 );
00318             TS_ASSERT_EQUALS( i.m_pos[ 2 ], 4 );
00319             TS_ASSERT_EQUALS( i.m_pos[ 3 ], 0 );
00320             TS_ASSERT_EQUALS( i.m_min[ 0 ], 4 );
00321             TS_ASSERT_EQUALS( i.m_min[ 1 ], 8 );
00322             TS_ASSERT_EQUALS( i.m_min[ 2 ], 4 );
00323             TS_ASSERT_EQUALS( i.m_min[ 3 ], 0 );
00324             TS_ASSERT_EQUALS( i.m_max[ 0 ], 12 );
00325             TS_ASSERT_EQUALS( i.m_max[ 1 ], 12 );
00326             TS_ASSERT_EQUALS( i.m_max[ 2 ], 16 );
00327             TS_ASSERT_EQUALS( i.m_max[ 3 ], 3 );
00328         }
00329         {
00330             // now lets do something wrong
00331             wtracking::WThreadedTrackingFunction::IndexType i;
00332             v0[ 0 ] = -1;
00333             TS_ASSERT_THROWS( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ), WException );
00334             v0[ 0 ] = 0;
00335             v1[ 1 ] = 5;
00336             TS_ASSERT_THROWS( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ), WException );
00337         }
00338     }
00339 
00340     /**
00341      * Test if indices (seed positions) iteration works.
00342      */
00343     void testIndexIncrement()
00344     {
00345         std::vector< int > v0;
00346         std::vector< int > v1;
00347         std::size_t numSeeds = 1;
00348         std::size_t seedsPerPosition = 1;
00349 
00350         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
00351         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00352         TS_ASSERT( g );
00353 
00354         {
00355             wtracking::WThreadedTrackingFunction::IndexType i;
00356             TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
00357 
00358             for( int j = 0; j < 27; ++j )
00359             {
00360                 TS_ASSERT( !i.done() );
00361                 ++i;
00362             }
00363             TS_ASSERT( i.done() );
00364         }
00365         {
00366             numSeeds = 4;
00367             wtracking::WThreadedTrackingFunction::IndexType i;
00368             TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
00369 
00370             for( int j = 0; j < 27 * 64; ++j )
00371             {
00372                 TS_ASSERT( !i.done() );
00373                 ++i;
00374             }
00375             TS_ASSERT( i.done() );
00376         }
00377         {
00378             seedsPerPosition = 3;
00379             wtracking::WThreadedTrackingFunction::IndexType i;
00380             TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
00381 
00382             for( int j = 0; j < 27 * 64 * 3; ++j )
00383             {
00384                 TS_ASSERT( !i.done() );
00385                 ++i;
00386             }
00387             TS_ASSERT( i.done() );
00388         }
00389         {
00390             v0.resize( 3, 1 );
00391             v1.resize( 3 );
00392             v1[ 0 ] = 4;
00393             v1[ 1 ] = 3;
00394             v1[ 2 ] = 4;
00395             wtracking::WThreadedTrackingFunction::IndexType i;
00396             TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
00397 
00398             for( int j = 0; j < 18 * 64 * 3; ++j )
00399             {
00400                 TS_ASSERT( !i.done() );
00401                 ++i;
00402             }
00403             TS_ASSERT( i.done() );
00404         }
00405     }
00406 
00407     /**
00408      * Test if the right jobs get created from seeds.
00409      */
00410     void testIndexToJob()
00411     {
00412         WVector3d x( 0.707, 0.707, 0.0 );
00413         WVector3d y( -0.707, 0.707, 0.0 );
00414         WVector3d z( 0.0, 0.0, 1.0 );
00415         x = normalize( x );
00416         y = normalize( y );
00417         y *= 2.0;
00418         z *= 1.5;
00419 
00420         std::vector< int > v0;
00421         std::vector< int > v1;
00422         std::size_t numSeeds = 2;
00423         std::size_t seedsPerPosition = 1;
00424 
00425         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
00426         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00427         TS_ASSERT( g );
00428 
00429         {
00430             wtracking::WThreadedTrackingFunction::IndexType i;
00431             TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
00432 
00433             wtracking::WThreadedTrackingFunction::JobType job = i.job();
00434             WVector3d v = g->getOrigin() + 0.75 * x + 0.75 * y + 0.75 * z;
00435 
00436             std::cout << g->getOrigin() << std::endl;
00437 
00438             TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
00439             TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
00440             TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
00441 
00442             v += 0.5 * z;
00443             ++i;
00444             job = i.job();
00445             TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
00446             TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
00447             TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
00448 
00449             for( int k = 0; k < 6; ++k )
00450             {
00451                 ++i;
00452             }
00453             v += 0.5 * y;
00454             job = i.job();
00455             TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
00456             TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
00457             TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
00458 
00459             for( int k = 0; k < 36; ++k )
00460             {
00461                 ++i;
00462             }
00463             v += 0.5 * x;
00464             job = i.job();
00465             TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
00466             TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
00467             TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
00468 
00469             TS_ASSERT_EQUALS( job.second[ 0 ], 0.0 );
00470             TS_ASSERT_EQUALS( job.second[ 1 ], 0.0 );
00471             TS_ASSERT_EQUALS( job.second[ 2 ], 0.0 );
00472         }
00473         {
00474             numSeeds = 4;
00475             seedsPerPosition = 11;
00476             wtracking::WThreadedTrackingFunction::IndexType i;
00477             TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) );
00478 
00479             wtracking::WThreadedTrackingFunction::JobType job;
00480             WVector3d v = g->getOrigin() + 0.625 * x + 0.625 * y + 0.625 * z;
00481             for( int k = 0; k < 11; ++k )
00482             {
00483                 job = i.job();
00484                 TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS );
00485                 TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS );
00486                 TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS );
00487                 ++i;
00488             }
00489         }
00490     }
00491 
00492     /**
00493      * Test if everything gets initialized correctly.
00494      */
00495     void testInstantiation()
00496     {
00497         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 );
00498         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00499         TS_ASSERT( g );
00500 
00501         TS_ASSERT_THROWS_NOTHING(
00502                 wtracking::WThreadedTrackingFunction w( ds,
00503                                                         boost::bind( &This::dirFunc, this, _1, _2, WVector3d( 1.0, 0.0, 0.0 ) ),
00504                                                         boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
00505                                                         boost::bind( &This::fibVis, this, _1 ),
00506                                                         boost::bind( &This::pntVis, this, _1 ) ) );
00507     }
00508 
00509     /**
00510      * Test if the correct amount of jobs gets created.
00511      */
00512     void testGetJob()
00513     {
00514         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 7 );
00515         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00516         TS_ASSERT( g );
00517 
00518         wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, WVector3d( 1.0, 0.0, 0.0 ) ),
00519                                                     boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
00520                                                     boost::bind( &This::fibVis, this, _1 ),
00521                                                     boost::bind( &This::pntVis, this, _1 ) );
00522         wtracking::WThreadedTrackingFunction::JobType job;
00523         for( int i = 0; i < 125; ++i )
00524         {
00525             TS_ASSERT( w.getJob( job ) );
00526         }
00527         TS_ASSERT( !w.getJob( job ) );
00528     }
00529 
00530     /**
00531      * Test if fibers with the right number of points get created.
00532      */
00533     void testCompute()
00534     {
00535         WVector3d x( 0.707, 0.707, 0.0 );
00536         WVector3d y( -0.707, 0.707, 0.0 );
00537         WVector3d z( 0.0, 0.0, 1.0 );
00538         x = normalize( x );
00539         y = normalize( y );
00540 
00541         boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 7 );
00542         boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( ds->getGrid() );
00543         TS_ASSERT( g );
00544         {
00545             wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, x ),
00546                                                         boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
00547                                                         boost::bind( &This::fibVis, this, _1 ),
00548                                                         boost::bind( &This::pntVis, this, _1 ) );
00549             wtracking::WThreadedTrackingFunction::JobType job;
00550             m_points.getWriteTicket()->get() = 0;
00551             w.getJob( job );
00552             w.compute( ds, job );
00553             TS_ASSERT_EQUALS( m_points.getReadTicket()->get(), 7 );
00554         }
00555         {
00556             wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, y ),
00557                                                         boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ),
00558                                                         boost::bind( &This::fibVis, this, _1 ),
00559                                                         boost::bind( &This::pntVis, this, _1 ) );
00560             wtracking::WThreadedTrackingFunction::JobType job;
00561             m_points.getWriteTicket()->get() = 0;
00562             w.getJob( job );
00563             w.compute( ds, job );
00564             TS_ASSERT_EQUALS( m_points.getReadTicket()->get(), 7 );
00565         }
00566     }
00567 
00568 private:
00569     /**
00570      * Build a test dataset.
00571      *
00572      * \param data The vector for every voxel.
00573      * \param n The number of grid position in every direction.
00574      *
00575      * \return The dataset.
00576      */
00577     boost::shared_ptr< WDataSetSingle > buildTestData( WVector3d data, int n )
00578     {
00579         WVector3d x( 0.707, 0.707, 0.0 );
00580         WVector3d y( -0.707, 0.707, 0.0 );
00581         WVector3d z( 0.0, 0.0, 1.0 );
00582         x = normalize( x );
00583         y = normalize( y );
00584         y *= 2.0;
00585         z *= 1.5;
00586 
00587         WMatrix< double > mat( 4, 4 );
00588         mat.makeIdentity();
00589         mat( 0, 0 ) = x[ 0 ];
00590         mat( 1, 0 ) = x[ 1 ];
00591         mat( 2, 0 ) = x[ 2 ];
00592         mat( 0, 1 ) = y[ 0 ];
00593         mat( 1, 1 ) = y[ 1 ];
00594         mat( 2, 1 ) = y[ 2 ];
00595         mat( 0, 2 ) = z[ 0 ];
00596         mat( 1, 2 ) = z[ 1 ];
00597         mat( 2, 2 ) = z[ 2 ];
00598         mat( 0, 3 ) = 1.0;
00599 
00600         WGridTransformOrtho t( mat );
00601         boost::shared_ptr< WGrid > g( new WGridRegular3D( n, n, n, t ) );
00602 
00603         data = normalize( data );
00604 
00605         boost::shared_ptr< std::vector< double > > v( new  std::vector< double >( n * n * n * 3 ) );
00606         for( std::size_t k = 0; k < static_cast< std::size_t >( n * n * n ); ++k )
00607         {
00608             v->at( 3 * k + 0 ) = data[ 0 ];
00609             v->at( 3 * k + 1 ) = data[ 1 ];
00610             v->at( 3 * k + 2 ) = data[ 2 ];
00611         }
00612 
00613         boost::shared_ptr< WValueSetBase > vs( new WValueSet< double >( 1, 3, v, W_DT_DOUBLE ) );
00614         return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( vs, g ) );
00615     }
00616 
00617     /**
00618      * The direction computation function. Simply returns the parameter vector.
00619      *
00620      * \param j The current job.
00621      * \param d The direction to return.
00622      *
00623      * \return d
00624      */
00625     WVector3d dirFunc( wtracking::WThreadedTrackingFunction::DataSetPtr,
00626                               wtracking::WThreadedTrackingFunction::JobType const& j,
00627                               WVector3d d )
00628     {
00629         if( dot( j.second, d ) > 0.0 )
00630         {
00631             return d;
00632         }
00633         else
00634         {
00635             return d * -1.0;
00636         }
00637     }
00638 
00639     /**
00640      * The fiber visitor. Does nothing.
00641      */
00642     void fibVis( std::vector< WVector3d > const& )
00643     {
00644     }
00645 
00646     /**
00647      * The point visitor. Counts the number of points found.
00648      */
00649     void pntVis( WVector3d const& )
00650     {
00651         ++m_points.getWriteTicket()->get();
00652     }
00653 
00654     //! the number of points found
00655     WSharedObject< std::size_t > m_points;
00656 };
00657 
00658 #endif  // WTHREADEDTRACKINGFUNCTION_TEST_H