1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
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.
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.
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/>.
23
//---------------------------------------------------------------------------
29
#include "../common/WLimits.h"
30
#include "WThreadedTrackingFunction.h"
34
bool WTrackingUtility::followToNextVoxel( DataSetPtr dataset, JobType& job, DirFunc const& dirFunc )
36
// TODO(reichenbach): Give those WAsserts correct strings incase they occur
37
WAssert( dataset->getGrid(), "" );
38
Grid3DPtr g = boost::shared_dynamic_cast< WGridRegular3D >( dataset->getGrid() );
40
WAssert( g->encloses( job.first ), "" );
42
// find matching direction
43
WVector3d dir = dirFunc( dataset, job );
45
if( fabs( length( dir ) - 1.0 ) > TRACKING_EPS )
50
// find t such that job.first() + t * dir is a point on the boundary of the current voxel
51
double t = getDistanceToBoundary( g, job.first, dir );
52
WAssert( !wlimits::isInf( t ) && !wlimits::isNaN( t ), "Warning in WTrackingUtility::followToNextVoxel NaN's or INF's occured" );
53
WAssert( t > 0.0, "" );
54
WAssert( onBoundary( g, job.first + dir * t ), "" );
56
if( !g->encloses( job.first + dir * t ) )
61
// increase t, so that job.first() + t * dir does not lie on any boundary anymore
62
// ( so we can find the corresponding voxel without ambiguities )
63
// ( this also means the resulting new position will never be in the same
64
// voxel as the starting position )
66
while( onBoundary( g, job.first + dir * t ) && i < 50 )
69
if( !g->encloses( job.first + dir * t ) )
80
// set the new position
86
bool WTrackingUtility::onBoundary( Grid3DPtr grid, WVector3d const& pos )
88
WVector3d v = pos - grid->getOrigin();
91
WVector3d d = grid->getDirectionX();
93
double c = dot( d, v ) / grid->getOffsetX() + 0.5;
94
p = c >= 0.0 ? modf( c, &z ) : 1.0 + modf( c, &z );
95
if( fabs( p ) < TRACKING_EPS || fabs( p - 1 ) < TRACKING_EPS )
99
d = grid->getDirectionY();
101
c = dot( d, v ) / grid->getOffsetY() + 0.5;
102
p = c >= 0.0 ? modf( c, &z ) : 1.0 + modf( c, &z );
103
if( fabs( p ) < TRACKING_EPS || fabs( p - 1 ) < TRACKING_EPS )
107
d = grid->getDirectionZ();
109
c = dot( d, v ) / grid->getOffsetZ() + 0.5;
110
p = c >= 0.0 ? modf( c, &z ) : 1.0 + modf( c, &z );
111
if( fabs( p ) < TRACKING_EPS || fabs( p - 1 ) < TRACKING_EPS )
118
double WTrackingUtility::getDistanceToBoundary( Grid3DPtr grid, WVector3d const& pos, WVector3d const& dir )
120
// the input pos is at least TRACKING_EPS away from the boundary
121
// so distance calculations don't get screwed
122
WAssert( !onBoundary( grid, pos ), "" );
124
double dist = std::numeric_limits< double >::infinity();
126
WVector3d v = pos - grid->getOrigin();
129
WVector3d o( grid->getOffsetX(), grid->getOffsetY(), grid->getOffsetZ() );
130
WVector3d s[ 3 ] = { grid->getDirectionX() / o[ 0 ], grid->getDirectionY() / o[ 1 ], grid->getDirectionZ() / o[ 2 ] };
131
double c = dot( s[ 0 ], v ) / o[ 0 ] + 0.5;
132
p[ 0 ] = c >= 0.0 ? modf( c, &z ) : 1.0 + modf( c, &z );
133
c = dot( s[ 1 ], v ) / o[ 1 ] + 0.5;
134
p[ 1 ] = c >= 0.0 ? modf( c, &z ) : 1.0 + modf( c, &z );
135
c = dot( s[ 2 ], v ) / o[ 2 ] + 0.5;
136
p[ 2 ] = c >= 0.0 ? modf( c, &z ) : 1.0 + modf( c, &z );
137
WVector3d d( dot( dir, s[ 0 ] ), dot( dir, s[ 1 ] ), dot( dir, s[ 2 ] ) );
140
for( int i = 0; i < 3; ++i )
142
WAssert( -TRACKING_EPS < p[ i ] && p[ i ] < o[ i ] + TRACKING_EPS, "" );
143
for( double j = 0.0; j <= 1.0; j += 1.0 )
145
if( fabs( d[ i ] ) > TRACKING_EPS )
147
t = ( j - p[ i ] ) * o[ i ] / d[ i ];
148
if( t > 0.0 && t < dist )
155
// distance absolute must be at least TRACKING_EPS!
156
WAssert( dist >= TRACKING_EPS, "" );
160
//////////////////////////////////////////////////////////////////////////////////////////
162
WThreadedTrackingFunction::WThreadedTrackingFunction( DataSetPtr dataset, DirFunc dirFunc,
163
NextPositionFunc nextFunc,
164
FiberVisitorFunc fiberVst, PointVisitorFunc pointVst,
165
std::size_t seedPositions, std::size_t seedsPerPos,
166
std::vector< int > v0, std::vector< int > v1 )
168
m_grid( boost::shared_dynamic_cast< GridType >( dataset->getGrid() ) ),
169
m_directionFunc( dirFunc ),
170
m_nextPosFunc( nextFunc ),
171
m_fiberVisitor( fiberVst ),
172
m_pointVisitor( pointVst ),
176
// dataset != 0 is tested by the base constructor
179
throw WException( std::string( "Cannot find WGridRegular3D. Are you sure the dataset has the correct grid type?" ) );
182
m_maxPoints = static_cast< std::size_t >( 5 * pow( static_cast< double >( m_grid->size() ), 1.0 / 3.0 ) );
184
m_currentIndex.getWriteTicket()->get() = IndexType( m_grid, v0, v1, seedPositions, seedsPerPos );
187
WThreadedTrackingFunction::~WThreadedTrackingFunction()
191
bool WThreadedTrackingFunction::getJob( JobType& job ) // NOLINT
193
WSharedObject< IndexType >::WriteTicket t = m_currentIndex.getWriteTicket();
194
if( t->get().done() )
200
job = t->get().job();
206
void WThreadedTrackingFunction::compute( DataSetPtr input, JobType const& job )
208
WVector3d e = m_directionFunc( input, job );
212
std::vector< WVector3d > fiber;
213
if( fabs( length( e ) - 1.0 ) > TRACKING_EPS )
217
m_fiberVisitor( fiber );
222
fiber.push_back( j.first );
225
m_pointVisitor( j.first );
228
// forward integration
229
for( std::size_t k = 0; k < m_maxPoints; ++k )
231
if( fabs( length( j.second ) - 1.0 ) > TRACKING_EPS )
235
if( !m_nextPosFunc( input, j, m_directionFunc ) )
239
fiber.push_back( j.first );
242
m_pointVisitor( j.first );
246
// backward integration
247
std::reverse( fiber.begin(), fiber.end() );
250
for( std::size_t k = 0; k < m_maxPoints; ++k )
252
if( fabs( length( j.second ) - 1.0 ) > TRACKING_EPS )
256
if( !m_nextPosFunc( input, j, m_directionFunc ) )
260
fiber.push_back( j.first );
263
m_pointVisitor( j.first );
270
m_fiberVisitor( fiber );
274
WThreadedTrackingFunction::IndexType::IndexType()
280
WThreadedTrackingFunction::IndexType::IndexType( GridPtr grid, std::vector< int > const& v0,
281
std::vector< int > const& v1, std::size_t seedPositions,
282
std::size_t seedsPerPosition )
288
m_min[ 0 ] = m_min[ 1 ] = m_min[ 2 ] = seedPositions;
292
WAssert( v0[ 0 ] >= 1 && static_cast< std::size_t >( v0[ 0 ] ) < m_grid->getNbCoordsX() - 1, "" );
293
WAssert( v0[ 1 ] >= 1 && static_cast< std::size_t >( v0[ 1 ] ) < m_grid->getNbCoordsY() - 1, "" );
294
WAssert( v0[ 2 ] >= 1 && static_cast< std::size_t >( v0[ 2 ] ) < m_grid->getNbCoordsZ() - 1, "" );
295
for( int i = 0; i < 3; ++i )
297
m_min[ i ] = v0[ i ] * seedPositions;
302
m_max[ 0 ] = ( m_grid->getNbCoordsX() - 1 ) * seedPositions;
303
m_max[ 1 ] = ( m_grid->getNbCoordsY() - 1 ) * seedPositions;
304
m_max[ 2 ] = ( m_grid->getNbCoordsZ() - 1 ) * seedPositions;
308
WAssert( v1[ 0 ] > v0[ 0 ] && static_cast< std::size_t >( v1[ 0 ] ) < grid->getNbCoordsX(), "" );
309
WAssert( v1[ 1 ] > v0[ 1 ] && static_cast< std::size_t >( v1[ 1 ] ) < grid->getNbCoordsY(), "" );
310
WAssert( v1[ 2 ] > v0[ 2 ] && static_cast< std::size_t >( v1[ 2 ] ) < grid->getNbCoordsZ(), "" );
311
for( int i = 0; i < 3; ++i )
313
m_max[ i ] = v1[ i ] * seedPositions;
316
m_offset = 1.0 / seedPositions;
318
m_max[ 3 ] = seedsPerPosition;
319
m_pos[ 0 ] = m_min[ 0 ];
320
m_pos[ 1 ] = m_min[ 1 ];
321
m_pos[ 2 ] = m_min[ 2 ];
325
WThreadedTrackingFunction::IndexType& WThreadedTrackingFunction::IndexType::operator++ ()
329
for( int i = 3; i > -1; --i )
332
if( m_pos[ i ] == m_max[ i ] )
334
m_pos[ i ] = m_min[ i ];
346
bool WThreadedTrackingFunction::IndexType::done()
351
WThreadedTrackingFunction::JobType WThreadedTrackingFunction::IndexType::job()
354
job.second = WVector3d( 0.0, 0.0, 0.0 );
355
job.first = m_grid->getOrigin() + m_grid->getDirectionX() * ( m_offset * ( 0.5 + m_pos[ 0 ] ) - 0.5 )
356
+ m_grid->getDirectionY() * ( m_offset * ( 0.5 + m_pos[ 1 ] ) - 0.5 )
357
+ m_grid->getDirectionZ() * ( m_offset * ( 0.5 + m_pos[ 2 ] ) - 0.5 );
361
} // namespace wtracking