X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=lib%2Ffpa%2FBase%2FMinimumSpanningTree.hxx;h=8746005f8a776b11f8021a65a55d86341b65eea1;hb=3f4722ccf68d830e26dac9b945925efa68e39e4c;hp=d932247c7bc2dcbc739e5902848da20879509bb5;hpb=6fcc9fc78c44fa789bf092e2897cb6b391259b42;p=FrontAlgorithms.git diff --git a/lib/fpa/Base/MinimumSpanningTree.hxx b/lib/fpa/Base/MinimumSpanningTree.hxx index d932247..8746005 100644 --- a/lib/fpa/Base/MinimumSpanningTree.hxx +++ b/lib/fpa/Base/MinimumSpanningTree.hxx @@ -1,28 +1,36 @@ -#ifndef __FPA__BASE__MINIMUMSPANNINGTREE__HXX__ -#define __FPA__BASE__MINIMUMSPANNINGTREE__HXX__ +#ifndef __fpa__Base__MinimumSpanningTree__hxx__ +#define __fpa__Base__MinimumSpanningTree__hxx__ #include // ------------------------------------------------------------------------- -template< class V, class C, class B > -const unsigned long fpa::Base::MinimumSpanningTree< V, C, B >::INF_VALUE = - std::numeric_limits< unsigned long >::max( ) >> 1; +template< class _TVertex, class _TSuperclass > +const typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +TCollisions& fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +GetCollisions( ) const +{ + return( this->m_Collisions ); +} // ------------------------------------------------------------------------- -template< class V, class C, class B > -void fpa::Base::MinimumSpanningTree< V, C, B >:: +template< class _TVertex, class _TSuperclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: SetCollisions( const TCollisions& collisions ) { + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + if( this->m_Collisions == collisions ) + return; + this->m_Collisions = collisions; - // Prepare fronts graph using Floyd-Warshall - unsigned long nSeeds = this->m_Collisions.size( ); - _TMatrix dist( nSeeds, _TRow( nSeeds, Self::INF_VALUE ) ); + // Prepare a front graph + unsigned long N = this->m_Collisions.size( ); + _TMatrix dist( N, _TRow( N, _inf ) ); this->m_FrontPaths = dist; - - for( unsigned long i = 0; i < nSeeds; ++i ) + for( unsigned long i = 0; i < N; ++i ) { - for( unsigned long j = 0; j < nSeeds; ++j ) + for( unsigned long j = 0; j < N; ++j ) { if( this->m_Collisions[ i ][ j ].second ) { @@ -38,15 +46,25 @@ SetCollisions( const TCollisions& collisions ) this->m_FrontPaths[ i ][ i ] = i; } // rof - for( unsigned long k = 0; k < nSeeds; ++k ) + + // Use Floyd-Warshall to compute all possible paths between fronts + for( unsigned long k = 0; k < N; ++k ) { - for( unsigned long i = 0; i < nSeeds; ++i ) + for( unsigned long i = 0; i < N; ++i ) { - for( unsigned long j = 0; j < nSeeds; ++j ) + for( unsigned long j = 0; j < N; ++j ) { - if( ( dist[ i ][ k ] + dist[ k ][ j ] ) < dist[ i ][ j ] ) + // WARNING: you don't want a numeric overflow!!! + unsigned long dik = dist[ i ][ k ]; + unsigned long dkj = dist[ k ][ j ]; + unsigned long sum = _inf; + if( dik < _inf && dkj < _inf ) + sum = dik + dkj; + + // Ok, continue Floyd-Warshall + if( sum < dist[ i ][ j ] ) { - dist[ i ][ j ] = dist[ i ][ k ] + dist[ k ][ j ]; + dist[ i ][ j ] = sum; this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ]; } // fi @@ -60,131 +78,155 @@ SetCollisions( const TCollisions& collisions ) } // ------------------------------------------------------------------------- -template< class V, class C, class B > -void fpa::Base::MinimumSpanningTree< V, C, B >:: -GetPath( std::vector< V >& path, const V& a, const V& b ) const +template< class _TVertex, class _TSuperclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +ClearSeeds( ) { - typename TDecorated::const_iterator aIt = this->Get( ).find( a ); - typename TDecorated::const_iterator bIt = this->Get( ).find( b ); + this->m_Seeds.clear( ); + this->Modified( ); +} - if( aIt == this->Get( ).end( ) || bIt == this->Get( ).end( ) ) - return; - - short fa = aIt->second.second; - short fb = bIt->second.second; +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +AddSeed( const _TVertex& seed ) +{ + this->m_Seeds.push_back( seed ); + this->Modified( ); +} - if( fa == fb ) +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +TVertices fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +GetPath( const _TVertex& a ) const +{ + TVertices path; + _TVertex it = a; + _TVertex p = this->GetParent( it ); + while( it != p ) { - std::vector< V > ap, bp; - this->_Path( ap, a ); - this->_Path( bp, b ); - - // Ignore common part - typename std::vector< V >::const_reverse_iterator raIt, rbIt; - raIt = ap.rbegin( ); - rbIt = bp.rbegin( ); - while( *raIt == *rbIt && raIt != ap.rend( ) && rbIt != bp.rend( ) ) - { - ++raIt; - ++rbIt; - - } // elihw - if( raIt != ap.rbegin( ) ) --raIt; - if( rbIt != bp.rbegin( ) ) --rbIt; - - // Add part from a - typename std::vector< V >::const_iterator iaIt = ap.begin( ); - for( ; iaIt != ap.end( ) && *iaIt != *raIt; ++iaIt ) - path.push_back( *iaIt ); - - // Add part from b - for( ; rbIt != bp.rend( ); ++rbIt ) - path.push_back( *rbIt ); - } - else + path.push_front( it ); + it = p; + p = this->GetParent( it ); + + } // elihw + path.push_front( it ); + return( path ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +TVertices fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +GetPath( const _TVertex& a, const _TVertex& b ) const +{ + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + + TVertices path; + TVertices pa = this->GetPath( a ); + TVertices pb = this->GetPath( b ); + if( pa.size( ) > 0 && pb.size( ) > 0 ) { - // Use this->m_FrontPaths from Floyd-Warshall - if( this->m_FrontPaths[ fa ][ fb ] != Self::INF_VALUE ) + // Find front identifiers + unsigned long ia = _inf, ib = _inf; + unsigned long N = this->m_Seeds.size( ); + for( unsigned long i = 0; i < N; ++i ) { - // Compute front path - std::vector< long > fpath; - fpath.push_back( fa ); - while( fa != fb ) - { - fa = this->m_FrontPaths[ fa ][ fb ]; - fpath.push_back( fa ); + if( this->m_Seeds[ i ] == pa.front( ) ) + ia = i; + if( this->m_Seeds[ i ] == pb.front( ) ) + ib = i; - } // elihw + } // rof - // Continue only if both fronts are connected - unsigned int N = fpath.size( ); - if( 0 < N ) + if( ia != ib ) + { + // Use this->m_FrontPaths from Floyd-Warshall + if( this->m_FrontPaths[ ia ][ ib ] < _inf ) { - // First path: from start vertex to first collision - this->GetPath( - path, a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first - ); + // Compute front path + std::vector< long > fpath; + fpath.push_back( ia ); + while( ia != ib ) + { + ia = this->m_FrontPaths[ ia ][ ib ]; + fpath.push_back( ia ); + + } // elihw - // Intermediary paths - for( unsigned int i = 1; i < N - 1; ++i ) + // Continue only if both fronts are connected + unsigned int N = fpath.size( ); + if( N > 0 ) { - this->GetPath( - path, - this->m_Collisions[ fpath[ i ] ][ fpath[ i - 1 ] ].first, - this->m_Collisions[ fpath[ i ] ][ fpath[ i + 1 ] ].first + // First path: from start vertex to first collision + path = this->GetPath( + a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first ); - } // rof + // Intermediary paths + for( unsigned int i = 1; i < N - 1; ++i ) + { + TVertices ipath = + this->GetPath( + this->m_Collisions[ fpath[ i ] ][ fpath[ i - 1 ] ].first, + this->m_Collisions[ fpath[ i ] ][ fpath[ i + 1 ] ].first + ); + path.insert( path.end( ), ipath.begin( ), ipath.end( ) ); + + } // rof + + // Final path: from last collision to end point + TVertices lpath = + this->GetPath( + this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b + ); + path.insert( path.end( ), lpath.begin( ), lpath.end( ) ); - // Final path: from last collision to end point - this->GetPath( - path, - this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b - ); + } // fi } // fi + } + else + { + // Ignore common part: find common ancestor + auto aIt = pa.begin( ); + auto bIt = pb.begin( ); + while( *aIt == *bIt && aIt != pa.end( ) && bIt != pb.end( ) ) + { + ++aIt; + ++bIt; + + } // elihw + + // Glue both parts + for( --aIt; aIt != pa.end( ); ++aIt ) + path.push_front( *aIt ); + for( ; bIt != pb.end( ); ++bIt ) + path.push_back( *bIt ); } // fi } // fi + return( path ); } // ------------------------------------------------------------------------- -template< class V, class C, class B > -fpa::Base::MinimumSpanningTree< V, C, B >:: +template< class _TVertex, class _TSuperclass > +fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: MinimumSpanningTree( ) : Superclass( ) { } // ------------------------------------------------------------------------- -template< class V, class C, class B > -fpa::Base::MinimumSpanningTree< V, C, B >:: +template< class _TVertex, class _TSuperclass > +fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: ~MinimumSpanningTree( ) { } -// ------------------------------------------------------------------------- -template< class V, class C, class B > -void fpa::Base::MinimumSpanningTree< V, C, B >:: -_Path( std::vector< V >& path, const V& a ) const -{ - typename TDecorated::const_iterator dIt = this->Get( ).find( a ); - if( dIt != this->Get( ).end( ) ) - { - do - { - path.push_back( dIt->first ); - dIt = this->Get( ).find( dIt->second.first ); - - } while( dIt->first != dIt->second.first && dIt != this->Get( ).end( ) ); - - if( dIt != this->Get( ).end( ) ) - path.push_back( dIt->first ); - - } // fi -} - -#endif // __FPA__BASE__MINIMUMSPANNINGTREE__HXX__ +#endif // __fpa__Base__MinimumSpanningTree__hxx__ // eof - $RCSfile$