+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MinimumSpanningTree__hxx__
+#define __fpa__Base__MinimumSpanningTree__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+const typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+TCollisions& fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+GetCollisions( ) const
+{
+ return( this->m_Collisions );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+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 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 < N; ++i )
+ {
+ for( unsigned long j = 0; j < N; ++j )
+ {
+ if( this->m_Collisions[ 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
+
+ // Use Floyd-Warshall to compute all possible paths between fronts
+ for( unsigned long k = 0; k < N; ++k )
+ {
+ for( unsigned long i = 0; i < N; ++i )
+ {
+ for( unsigned long j = 0; j < N; ++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 ] = sum;
+ this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ];
+
+ } // fi
+
+ } // rof
+
+ } // rof
+
+ } // rof
+ this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+ClearSeeds( )
+{
+ this->m_Seeds.clear( );
+ if( this->m_DataObject != NULL )
+ this->m_DataObject->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+AddSeed( const _TVertex& seed )
+{
+ this->m_Seeds.push_back( seed );
+ if( this->m_DataObject != NULL )
+ this->m_DataObject->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+TVertices fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+GetPath( const _TVertex& a ) const
+{
+ TVertices vertices;
+ _TVertex it = a;
+ _TVertex p = this->GetParent( it );
+ while( it != p )
+ {
+ vertices.push_back( it );
+ it = p;
+ p = this->GetParent( it );
+
+ } // elihw
+ vertices.push_back( it );
+ return( vertices );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+TVertices fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+GetPath( const _TVertex& a, const _TVertex& b ) const
+{
+ static const unsigned long _inf =
+ std::numeric_limits< unsigned long >::max( );
+
+ TVertices vertices;
+ TVertices pa = this->GetPath( a );
+ TVertices pb = this->GetPath( b );
+ if( pa.size( ) > 0 && pb.size( ) > 0 )
+ {
+ // Find front identifiers
+ unsigned long ia = _inf, ib = _inf;
+ unsigned long N = this->m_Seeds.size( );
+ for( unsigned long i = 0; i < N; ++i )
+ {
+ if( this->m_Seeds[ i ] == pa[ pa.size( ) - 1 ] )
+ ia = i;
+ if( this->m_Seeds[ i ] == pb[ pb.size( ) - 1 ] )
+ ib = i;
+
+ } // rof
+
+ // Check if there is a front-jump between given seeds
+ if( ia != ib )
+ {
+ // 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
+
+ // Continue only if both fronts are connected
+ unsigned int N = fpath.size( );
+ if( N > 0 )
+ {
+ // First path: from start vertex to first collision
+ vertices = this->GetPath(
+ a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first
+ );
+
+ // 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
+ );
+ for( long id = 0; id < ipath.size( ); ++id )
+ vertices.push_back( ipath[ id ] );
+
+ } // rof
+
+ // Final path: from last collision to end point
+ TVertices lpath =
+ this->GetPath(
+ this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b
+ );
+ for( long id = 0; id < lpath.size( ); ++id )
+ vertices.push_back( lpath[ id ] );
+
+ } // fi
+ }
+ else
+ {
+ // Ignore common part: find common ancestor
+ long aIt = pa.size( ) - 1;
+ long bIt = pb.size( ) - 1;
+ bool cont = true;
+ while( aIt >= 0 && bIt >= 0 && cont )
+ {
+ cont = ( pa[ aIt ] == pb[ bIt ] );
+ aIt--;
+ bIt--;
+
+ } // elihw
+ aIt++;
+ bIt++;
+
+ // Glue both parts
+ for( long cIt = 0; cIt <= aIt; ++cIt )
+ vertices.push_back( pa[ cIt ] );
+ for( ; bIt >= 0; --bIt )
+ vertices.push_back( pb[ bIt ] );
+
+ } // fi
+
+ } // fi
+ return( vertices );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+MinimumSpanningTree( )
+ : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+~MinimumSpanningTree( )
+{
+}
+
+#endif // __fpa__Base__MinimumSpanningTree__hxx__
+
+// eof - $RCSfile$