#ifndef __FPA__BASE__TREEEXTRACTOR__HXX__ #define __FPA__BASE__TREEEXTRACTOR__HXX__ #include // ------------------------------------------------------------------------- template< class A > const unsigned long fpa::Base::TreeExtractor< A >::INF_VALUE = std::numeric_limits< unsigned long >::max( ) >> 1; // ------------------------------------------------------------------------- template< class A > unsigned int fpa::Base::TreeExtractor< A >:: AddLeaf( const TVertex& leaf ) { this->m_Leafs.push_back( leaf ); this->Modified( ); return( this->m_Leafs.size( ) - 1 ); } // ------------------------------------------------------------------------- template< class A > unsigned int fpa::Base::TreeExtractor< A >:: GetNumberOfLeafs( ) const { return( this->m_Leafs.size( ) ); } // ------------------------------------------------------------------------- template< class A > const typename fpa::Base::TreeExtractor< A >:: TVertex& fpa::Base::TreeExtractor< A >:: GetLeaf( const unsigned int& id ) const { static const TVertex zero; if( id < this->m_Leafs.size( ) ) return( this->m_Leafs[ id ] ); else return( zero ); } // ------------------------------------------------------------------------- template< class A > fpa::Base::TreeExtractor< A >:: TreeExtractor( ) : Superclass( ) { } // ------------------------------------------------------------------------- template< class A > fpa::Base::TreeExtractor< A >:: ~TreeExtractor( ) { } // ------------------------------------------------------------------------- template< class A > void fpa::Base::TreeExtractor< A >:: _BeforeMainLoop( ) { this->Superclass::_BeforeMainLoop( ); this->m_Tree.clear( ); } // ------------------------------------------------------------------------- template< class A > void fpa::Base::TreeExtractor< A >:: _AfterMainLoop( ) { this->Superclass::_AfterMainLoop( ); // Prepare fronts graph using Floyd-Warshall unsigned long nSeeds = this->GetNumberOfSeeds( ); _TMatrix dist( nSeeds, _TRow( nSeeds, Self::INF_VALUE ) ); this->m_FrontPaths = dist; for( unsigned long i = 0; i < nSeeds; ++i ) { for( unsigned long j = 0; j < nSeeds; ++j ) { if( this->m_CollisionSites[ i ][ j ].second ) { dist[ i ][ j ] = 1; dist[ j ][ i ] = 1; this->m_FrontPaths[ i ][ j ] = j; this->m_FrontPaths[ j ][ i ] = i; } // fi } // rof dist[ i ][ i ] = 0; this->m_FrontPaths[ i ][ i ] = i; } // rof for( unsigned long k = 0; k < nSeeds; ++k ) { for( unsigned long i = 0; i < nSeeds; ++i ) { for( unsigned long j = 0; j < nSeeds; ++j ) { if( ( dist[ i ][ k ] + dist[ k ][ j ] ) < dist[ i ][ j ] ) { dist[ i ][ j ] = dist[ i ][ k ] + dist[ k ][ j ]; this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ]; } // fi } // rof } // rof } // rof // Build tree this->m_Tree.clear( ); typename TVertices::const_iterator vIt = this->m_Leafs.begin( ); for( ; vIt != this->m_Leafs.end( ); ++vIt ) { TVertices path = this->_Path( this->m_Root, *vIt ); typename TVertices::const_iterator pIt = path.begin( ); TVertex parent = *pIt; for( ; pIt != path.end( ); ++pIt ) { this->m_Tree[ *pIt ] = parent; parent = *pIt; } // rof } // rof } // ------------------------------------------------------------------------- template< class A > typename fpa::Base::TreeExtractor< A >:: TVertices fpa::Base::TreeExtractor< A >:: _Path( const TVertex& s, const TVertex& e ) { TVertices pS, pE; // Check if both vertices belong to the same front or if collisions // should be analyzed. _TFrontId fs = this->_FrontId( s ); _TFrontId fe = this->_FrontId( e ); if( fs == fe ) { // Path from start vertex until seed TVertex vIt = s; TVertex parent = this->_Parent( vIt ); while( parent != vIt ) { pS.push_back( vIt ); vIt = parent; parent = this->_Parent( vIt ); } // elihw pS.push_back( vIt ); // Path from end vertex until seed vIt = e; parent = this->_Parent( vIt ); while( parent != vIt ) { pE.push_back( vIt ); vIt = parent; parent = this->_Parent( vIt ); } // elihw pE.push_back( vIt ); // Erase duplicate vertices if( pS.size( ) > 0 && pE.size( ) > 0 ) { bool cont = ( pS.back( ) == pE.back( ) ); bool enter = false; TVertex lastVertex = pS.back( ); while( cont ) { enter = true; lastVertex = pS.back( ); pS.pop_back( ); pE.pop_back( ); cont = ( pS.size( ) > 0 && pE.size( ) > 0 ); if( cont ) cont = ( pS.back( ) == pE.back( ) ); } // elihw if( enter ) pS.push_back( lastVertex ); } // fi // Contatenate both paths pS.insert( pS.end( ), pE.rbegin( ), pE.rend( ) ); } else { // Use this->m_FrontPaths from Floyd-Warshall if( this->m_FrontPaths[ fs ][ fe ] != Self::INF_VALUE ) { // Compute front path std::vector< unsigned long > fpath; fpath.push_back( fs ); while( fs != fe ) { fs = this->m_FrontPaths[ fs ][ fe ]; fpath.push_back( fs ); } // elihw // Continue only if both fronts are connected unsigned int N = fpath.size( ); if( 0 < N ) { // First path: from start vertex to first collision pS = this->_Path( s, this->m_CollisionSites[ fpath[ 0 ] ][ fpath[ 1 ] ].first ); // Intermediary paths for( unsigned int i = 1; i < N - 1; ++i ) { pE = this->_Path( this->m_CollisionSites[ fpath[ i ] ][ fpath[ i - 1 ] ].first, this->m_CollisionSites[ fpath[ i ] ][ fpath[ i + 1 ] ].first ); pS.insert( pS.end( ), pE.begin( ), pE.end( ) ); } // rof // Final path: from last collision to end point pE = this->_Path( this->m_CollisionSites[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, e ); pS.insert( pS.end( ), pE.begin( ), pE.end( ) ); } // fi } // fi } // fi return( pS ); } #endif // __FPA__BASE__TREEEXTRACTOR__HXX__ // eof - $RCSfile$