OpenWalnut
1.2.5
|
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::shared_dynamic_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::shared_dynamic_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::shared_dynamic_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 /** 00193 * A simple direction calculation function. 00194 * 00195 * \return A direction. 00196 */ 00197 WVector3d simpleDirFunc( wtracking::WTrackingUtility::DataSetPtr, wtracking::WTrackingUtility::JobType const& ) 00198 { 00199 WVector3d v( 1.0, 1.0, 0.0 ); 00200 v = normalize( v ); 00201 return v; 00202 } 00203 00204 /** 00205 * Build a test dataset. 00206 * 00207 * \param data The vector for every voxel. 00208 * 00209 * \return the test dataset 00210 */ 00211 boost::shared_ptr< WDataSetSingle > buildTestData( WVector3d data ) 00212 { 00213 WVector3d x( 0.707, 0.707, 0.0 ); 00214 WVector3d y( -0.707, 0.707, 0.0 ); 00215 WVector3d z( 0.0, 0.0, 1.0 ); 00216 00217 x = normalize( x ); 00218 y = normalize( y ); 00219 00220 y *= 2.0; 00221 z *= 1.5; 00222 00223 WMatrix< double > mat( 4, 4 ); 00224 mat.makeIdentity(); 00225 mat( 0, 0 ) = x[ 0 ]; 00226 mat( 1, 0 ) = x[ 1 ]; 00227 mat( 2, 0 ) = x[ 2 ]; 00228 mat( 0, 1 ) = y[ 0 ]; 00229 mat( 1, 1 ) = y[ 1 ]; 00230 mat( 2, 1 ) = y[ 2 ]; 00231 mat( 0, 2 ) = z[ 0 ]; 00232 mat( 1, 2 ) = z[ 1 ]; 00233 mat( 2, 2 ) = z[ 2 ]; 00234 mat( 0, 3 ) = 1.0; 00235 00236 WGridTransformOrtho t( mat ); 00237 boost::shared_ptr< WGrid > g( new WGridRegular3D( 5, 5, 5, t ) ); 00238 00239 data = normalize( data ); 00240 00241 boost::shared_ptr< std::vector< double > > v = boost::shared_ptr< std::vector< double > >( new std::vector< double > ( 5 * 5 * 5 * 3 ) ); 00242 for( std::size_t k = 0; k < 5 * 5 * 5; ++k ) 00243 { 00244 v->at( 3 * k + 0 ) = data[ 0 ]; 00245 v->at( 3 * k + 1 ) = data[ 1 ]; 00246 v->at( 3 * k + 2 ) = data[ 2 ]; 00247 } 00248 00249 boost::shared_ptr< WValueSetBase > vs( new WValueSet< double >( 1, 3, v, W_DT_DOUBLE ) ); 00250 return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( vs, g ) ); 00251 } 00252 }; 00253 00254 /** 00255 * \class WThreadedTrackingFunctionTest 00256 * 00257 * Test the WThreadedTrackingFunction class. 00258 */ 00259 class WThreadedTrackingFunctionTest : public CxxTest::TestSuite 00260 { 00261 //! a handy abbreviation 00262 typedef WThreadedTrackingFunctionTest This; 00263 00264 public: 00265 /** 00266 * Test if everything gets initialized correctly. 00267 */ 00268 void testIndexInitialization() 00269 { 00270 std::vector< int > v0; 00271 std::vector< int > v1; 00272 std::size_t numSeeds = 1; 00273 std::size_t seedsPerPosition = 1; 00274 00275 boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 ); 00276 boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( ds->getGrid() ); 00277 TS_ASSERT( g ); 00278 00279 { 00280 wtracking::WThreadedTrackingFunction::IndexType i; 00281 i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ); 00282 00283 // new test if everything was initialized correctly 00284 TS_ASSERT_EQUALS( i.m_done, false ); 00285 TS_ASSERT_EQUALS( i.m_offset, 1.0 ); 00286 TS_ASSERT_EQUALS( i.m_pos[ 0 ], 1 ); 00287 TS_ASSERT_EQUALS( i.m_pos[ 1 ], 1 ); 00288 TS_ASSERT_EQUALS( i.m_pos[ 2 ], 1 ); 00289 TS_ASSERT_EQUALS( i.m_pos[ 3 ], 0 ); 00290 TS_ASSERT_EQUALS( i.m_min[ 0 ], 1 ); 00291 TS_ASSERT_EQUALS( i.m_min[ 1 ], 1 ); 00292 TS_ASSERT_EQUALS( i.m_min[ 2 ], 1 ); 00293 TS_ASSERT_EQUALS( i.m_min[ 3 ], 0 ); 00294 TS_ASSERT_EQUALS( i.m_max[ 0 ], 4 ); 00295 TS_ASSERT_EQUALS( i.m_max[ 1 ], 4 ); 00296 TS_ASSERT_EQUALS( i.m_max[ 2 ], 4 ); 00297 TS_ASSERT_EQUALS( i.m_max[ 3 ], 1 ); 00298 } 00299 { 00300 v0.resize( 3 ); 00301 v1.resize( 3 ); 00302 v0[ 0 ] = 1; 00303 v0[ 1 ] = 2; 00304 v0[ 2 ] = 1; 00305 v1[ 0 ] = 3; 00306 v1[ 1 ] = 3; 00307 v1[ 2 ] = 4; 00308 numSeeds = 4; 00309 seedsPerPosition = 3; 00310 00311 wtracking::WThreadedTrackingFunction::IndexType i; 00312 TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) ); 00313 00314 // new test if everything was initialized correctly 00315 TS_ASSERT_EQUALS( i.m_done, false ); 00316 TS_ASSERT_EQUALS( i.m_offset, 0.25 ); 00317 TS_ASSERT_EQUALS( i.m_pos[ 0 ], 4 ); 00318 TS_ASSERT_EQUALS( i.m_pos[ 1 ], 8 ); 00319 TS_ASSERT_EQUALS( i.m_pos[ 2 ], 4 ); 00320 TS_ASSERT_EQUALS( i.m_pos[ 3 ], 0 ); 00321 TS_ASSERT_EQUALS( i.m_min[ 0 ], 4 ); 00322 TS_ASSERT_EQUALS( i.m_min[ 1 ], 8 ); 00323 TS_ASSERT_EQUALS( i.m_min[ 2 ], 4 ); 00324 TS_ASSERT_EQUALS( i.m_min[ 3 ], 0 ); 00325 TS_ASSERT_EQUALS( i.m_max[ 0 ], 12 ); 00326 TS_ASSERT_EQUALS( i.m_max[ 1 ], 12 ); 00327 TS_ASSERT_EQUALS( i.m_max[ 2 ], 16 ); 00328 TS_ASSERT_EQUALS( i.m_max[ 3 ], 3 ); 00329 } 00330 { 00331 // now lets do something wrong 00332 wtracking::WThreadedTrackingFunction::IndexType i; 00333 v0[ 0 ] = -1; 00334 TS_ASSERT_THROWS( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ), WException ); 00335 v0[ 0 ] = 0; 00336 v1[ 1 ] = 5; 00337 TS_ASSERT_THROWS( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ), WException ); 00338 } 00339 } 00340 00341 /** 00342 * Test if indices (seed positions) iteration works. 00343 */ 00344 void testIndexIncrement() 00345 { 00346 std::vector< int > v0; 00347 std::vector< int > v1; 00348 std::size_t numSeeds = 1; 00349 std::size_t seedsPerPosition = 1; 00350 00351 boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 ); 00352 boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( ds->getGrid() ); 00353 TS_ASSERT( g ); 00354 00355 { 00356 wtracking::WThreadedTrackingFunction::IndexType i; 00357 TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) ); 00358 00359 for( int j = 0; j < 27; ++j ) 00360 { 00361 TS_ASSERT( !i.done() ); 00362 ++i; 00363 } 00364 TS_ASSERT( i.done() ); 00365 } 00366 { 00367 numSeeds = 4; 00368 wtracking::WThreadedTrackingFunction::IndexType i; 00369 TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) ); 00370 00371 for( int j = 0; j < 27 * 64; ++j ) 00372 { 00373 TS_ASSERT( !i.done() ); 00374 ++i; 00375 } 00376 TS_ASSERT( i.done() ); 00377 } 00378 { 00379 seedsPerPosition = 3; 00380 wtracking::WThreadedTrackingFunction::IndexType i; 00381 TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) ); 00382 00383 for( int j = 0; j < 27 * 64 * 3; ++j ) 00384 { 00385 TS_ASSERT( !i.done() ); 00386 ++i; 00387 } 00388 TS_ASSERT( i.done() ); 00389 } 00390 { 00391 v0.resize( 3, 1 ); 00392 v1.resize( 3 ); 00393 v1[ 0 ] = 4; 00394 v1[ 1 ] = 3; 00395 v1[ 2 ] = 4; 00396 wtracking::WThreadedTrackingFunction::IndexType i; 00397 TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) ); 00398 00399 for( int j = 0; j < 18 * 64 * 3; ++j ) 00400 { 00401 TS_ASSERT( !i.done() ); 00402 ++i; 00403 } 00404 TS_ASSERT( i.done() ); 00405 } 00406 } 00407 00408 /** 00409 * Test if the right jobs get created from seeds. 00410 */ 00411 void testIndexToJob() 00412 { 00413 WVector3d x( 0.707, 0.707, 0.0 ); 00414 WVector3d y( -0.707, 0.707, 0.0 ); 00415 WVector3d z( 0.0, 0.0, 1.0 ); 00416 x = normalize( x ); 00417 y = normalize( y ); 00418 y *= 2.0; 00419 z *= 1.5; 00420 00421 std::vector< int > v0; 00422 std::vector< int > v1; 00423 std::size_t numSeeds = 2; 00424 std::size_t seedsPerPosition = 1; 00425 00426 boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 ); 00427 boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( ds->getGrid() ); 00428 TS_ASSERT( g ); 00429 00430 { 00431 wtracking::WThreadedTrackingFunction::IndexType i; 00432 TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) ); 00433 00434 wtracking::WThreadedTrackingFunction::JobType job = i.job(); 00435 WVector3d v = g->getOrigin() + 0.75 * x + 0.75 * y + 0.75 * z; 00436 00437 std::cout << g->getOrigin() << std::endl; 00438 00439 TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS ); 00440 TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS ); 00441 TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS ); 00442 00443 v += 0.5 * z; 00444 ++i; 00445 job = i.job(); 00446 TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS ); 00447 TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS ); 00448 TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS ); 00449 00450 for( int k = 0; k < 6; ++k ) 00451 { 00452 ++i; 00453 } 00454 v += 0.5 * y; 00455 job = i.job(); 00456 TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS ); 00457 TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS ); 00458 TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS ); 00459 00460 for( int k = 0; k < 36; ++k ) 00461 { 00462 ++i; 00463 } 00464 v += 0.5 * x; 00465 job = i.job(); 00466 TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS ); 00467 TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS ); 00468 TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS ); 00469 00470 TS_ASSERT_EQUALS( job.second[ 0 ], 0.0 ); 00471 TS_ASSERT_EQUALS( job.second[ 1 ], 0.0 ); 00472 TS_ASSERT_EQUALS( job.second[ 2 ], 0.0 ); 00473 } 00474 { 00475 numSeeds = 4; 00476 seedsPerPosition = 11; 00477 wtracking::WThreadedTrackingFunction::IndexType i; 00478 TS_ASSERT_THROWS_NOTHING( i = wtracking::WThreadedTrackingFunction::IndexType( g, v0, v1, numSeeds, seedsPerPosition ) ); 00479 00480 wtracking::WThreadedTrackingFunction::JobType job; 00481 WVector3d v = g->getOrigin() + 0.625 * x + 0.625 * y + 0.625 * z; 00482 for( int k = 0; k < 11; ++k ) 00483 { 00484 job = i.job(); 00485 TS_ASSERT_DELTA( v[ 0 ], job.first[ 0 ], TRACKING_EPS ); 00486 TS_ASSERT_DELTA( v[ 1 ], job.first[ 1 ], TRACKING_EPS ); 00487 TS_ASSERT_DELTA( v[ 2 ], job.first[ 2 ], TRACKING_EPS ); 00488 ++i; 00489 } 00490 } 00491 } 00492 00493 /** 00494 * Test if everything gets initialized correctly. 00495 */ 00496 void testInstantiation() 00497 { 00498 boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 5 ); 00499 boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( ds->getGrid() ); 00500 TS_ASSERT( g ); 00501 00502 TS_ASSERT_THROWS_NOTHING( 00503 wtracking::WThreadedTrackingFunction w( ds, 00504 boost::bind( &This::dirFunc, this, _1, _2, WVector3d( 1.0, 0.0, 0.0 ) ), 00505 boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ), 00506 boost::bind( &This::fibVis, this, _1 ), 00507 boost::bind( &This::pntVis, this, _1 ) ) ); 00508 } 00509 00510 /** 00511 * Test if the correct amount of jobs gets created. 00512 */ 00513 void testGetJob() 00514 { 00515 boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 7 ); 00516 boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( ds->getGrid() ); 00517 TS_ASSERT( g ); 00518 00519 wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, WVector3d( 1.0, 0.0, 0.0 ) ), 00520 boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ), 00521 boost::bind( &This::fibVis, this, _1 ), 00522 boost::bind( &This::pntVis, this, _1 ) ); 00523 wtracking::WThreadedTrackingFunction::JobType job; 00524 for( int i = 0; i < 125; ++i ) 00525 { 00526 TS_ASSERT( w.getJob( job ) ); 00527 } 00528 TS_ASSERT( !w.getJob( job ) ); 00529 } 00530 00531 /** 00532 * Test if fibers with the right number of points get created. 00533 */ 00534 void testCompute() 00535 { 00536 WVector3d x( 0.707, 0.707, 0.0 ); 00537 WVector3d y( -0.707, 0.707, 0.0 ); 00538 WVector3d z( 0.0, 0.0, 1.0 ); 00539 x = normalize( x ); 00540 y = normalize( y ); 00541 00542 boost::shared_ptr< WDataSetSingle > ds = buildTestData( WVector3d( 1.0, 0.0, 0.0 ), 7 ); 00543 boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( ds->getGrid() ); 00544 TS_ASSERT( g ); 00545 { 00546 wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, x ), 00547 boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ), 00548 boost::bind( &This::fibVis, this, _1 ), 00549 boost::bind( &This::pntVis, this, _1 ) ); 00550 wtracking::WThreadedTrackingFunction::JobType job; 00551 m_points.getWriteTicket()->get() = 0; 00552 w.getJob( job ); 00553 w.compute( ds, job ); 00554 TS_ASSERT_EQUALS( m_points.getReadTicket()->get(), 7 ); 00555 } 00556 { 00557 wtracking::WThreadedTrackingFunction w( ds, boost::bind( &This::dirFunc, this, _1, _2, y ), 00558 boost::bind( &wtracking::WTrackingUtility::followToNextVoxel, _1, _2, _3 ), 00559 boost::bind( &This::fibVis, this, _1 ), 00560 boost::bind( &This::pntVis, this, _1 ) ); 00561 wtracking::WThreadedTrackingFunction::JobType job; 00562 m_points.getWriteTicket()->get() = 0; 00563 w.getJob( job ); 00564 w.compute( ds, job ); 00565 TS_ASSERT_EQUALS( m_points.getReadTicket()->get(), 7 ); 00566 } 00567 } 00568 00569 private: 00570 /** 00571 * Build a test dataset. 00572 * 00573 * \param data The vector for every voxel. 00574 * \param n The number of grid position in every direction. 00575 * 00576 * \return The dataset. 00577 */ 00578 boost::shared_ptr< WDataSetSingle > buildTestData( WVector3d data, int n ) 00579 { 00580 WVector3d x( 0.707, 0.707, 0.0 ); 00581 WVector3d y( -0.707, 0.707, 0.0 ); 00582 WVector3d z( 0.0, 0.0, 1.0 ); 00583 x = normalize( x ); 00584 y = normalize( y ); 00585 y *= 2.0; 00586 z *= 1.5; 00587 00588 WMatrix< double > mat( 4, 4 ); 00589 mat.makeIdentity(); 00590 mat( 0, 0 ) = x[ 0 ]; 00591 mat( 1, 0 ) = x[ 1 ]; 00592 mat( 2, 0 ) = x[ 2 ]; 00593 mat( 0, 1 ) = y[ 0 ]; 00594 mat( 1, 1 ) = y[ 1 ]; 00595 mat( 2, 1 ) = y[ 2 ]; 00596 mat( 0, 2 ) = z[ 0 ]; 00597 mat( 1, 2 ) = z[ 1 ]; 00598 mat( 2, 2 ) = z[ 2 ]; 00599 mat( 0, 3 ) = 1.0; 00600 00601 WGridTransformOrtho t( mat ); 00602 boost::shared_ptr< WGrid > g( new WGridRegular3D( n, n, n, t ) ); 00603 00604 data = normalize( data ); 00605 00606 boost::shared_ptr< std::vector< double > > v = boost::shared_ptr< std::vector< double > >( new std::vector< double >( n * n * n * 3 ) ); 00607 for( std::size_t k = 0; k < static_cast< std::size_t >( n * n * n ); ++k ) 00608 { 00609 v->at( 3 * k + 0 ) = data[ 0 ]; 00610 v->at( 3 * k + 1 ) = data[ 1 ]; 00611 v->at( 3 * k + 2 ) = data[ 2 ]; 00612 } 00613 00614 boost::shared_ptr< WValueSetBase > vs( new WValueSet< double >( 1, 3, v, W_DT_DOUBLE ) ); 00615 return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( vs, g ) ); 00616 } 00617 00618 /** 00619 * The direction computation function. Simply returns the parameter vector. 00620 * 00621 * \param j The current job. 00622 * \param d The direction to return. 00623 * 00624 * \return d 00625 */ 00626 WVector3d dirFunc( wtracking::WThreadedTrackingFunction::DataSetPtr, 00627 wtracking::WThreadedTrackingFunction::JobType const& j, 00628 WVector3d d ) 00629 { 00630 if( dot( j.second, d ) > 0.0 ) 00631 { 00632 return d; 00633 } 00634 else 00635 { 00636 return d * -1.0; 00637 } 00638 } 00639 00640 /** 00641 * The fiber visitor. Does nothing. 00642 */ 00643 void fibVis( std::vector< WVector3d > const& ) 00644 { 00645 } 00646 00647 /** 00648 * The point visitor. Counts the number of points found. 00649 */ 00650 void pntVis( WVector3d const& ) 00651 { 00652 ++m_points.getWriteTicket()->get(); 00653 } 00654 00655 //! the number of points found 00656 WSharedObject< std::size_t > m_points; 00657 }; 00658 00659 #endif // WTHREADEDTRACKINGFUNCTION_TEST_H