OpenWalnut
1.4.0
|
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