]> Creatis software - FrontAlgorithms.git/blobdiff - lib/fpa/Base/MinimumSpanningTree.hxx
Windows compilation (1/2)
[FrontAlgorithms.git] / lib / fpa / Base / MinimumSpanningTree.hxx
index c53a071dd2dba934907f5826c88a0afef23ce94e..8746005f8a776b11f8021a65a55d86341b65eea1 100644 (file)
@@ -1,27 +1,36 @@
-#ifndef __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
-#define __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
+#ifndef __fpa__Base__MinimumSpanningTree__hxx__
+#define __fpa__Base__MinimumSpanningTree__hxx__
 
 #include <limits>
 
 // -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-const unsigned long fpa::Base::
-MinimumSpanningTree< _TSuperclass, _TVertex >::INF_VALUE =
-  std::numeric_limits< unsigned long >::max( );
-  
+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 _TSuperclass, class _TVertex >
-void fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
+template< class _TVertex, class _TSuperclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
 SetCollisions( const TCollisions& collisions )
 {
-  // Prepare a front graph
+  static const unsigned long _inf =
+    std::numeric_limits< unsigned long >::max( );
+  if( this->m_Collisions == collisions )
+    return;
+
   this->m_Collisions = collisions;
-  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,16 +47,24 @@ SetCollisions( const TCollisions& collisions )
 
   } // rof
 
-  // Use Floyd-Warshall to compute all possible paths
-  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
@@ -61,176 +78,155 @@ SetCollisions( const TCollisions& collisions )
 }
 
 // -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TVertices fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetPath( const TVertex& a ) const
+template< class _TVertex, class _TSuperclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+ClearSeeds( )
 {
-  TVertices path;
-  if( this->_HasVertex( a ) )
-    this->_Path( path, a );
-  return( path );
+  this->m_Seeds.clear( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TSuperclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+AddSeed( const _TVertex& seed )
+{
+  this->m_Seeds.push_back( seed );
+  this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TVertices fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetPath( const TVertex& a, const TVertex& b ) const
+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 )
+  {
+    path.push_front( it );
+    it = p;
+    p = this->GetParent( it );
 
-  // Check existence
-  if( !this->_HasVertex( a ) || !this->_HasVertex( b ) )
-    return( path );
-  
-  // Get front ids
-  short fa = this->_FrontId( a );
-  short fb = this->_FrontId( b );
+  } // elihw
+  path.push_front( it );
+  return( path );
+}
 
-  if( fa == fb )
-  {
-    // Get paths
-    TVertices ap, bp;
-    this->_Path( ap, a );
-    this->_Path( bp, b );
-
-    // Ignore common part: find common ancestor
-    auto raIt = ap.rbegin( );
-    auto 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
-    for( auto iaIt = ap.begin( ); iaIt != ap.end( ) && *iaIt != *raIt; ++iaIt )
-      path.push_back( *iaIt );
-
-    // Add part from b
-    for( ; rbIt != bp.rend( ); ++rbIt )
-      path.push_back( *rbIt );
-  }
-  else
+// -------------------------------------------------------------------------
+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( N > 0 )
+    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
-        path = this->GetPath(
-          a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first
-          );
-
-        // Intermediary paths
-        for( unsigned int i = 1; i < N - 1; ++i )
+        // Compute front path
+        std::vector< long > fpath;
+        fpath.push_back( ia );
+        while( ia != ib )
         {
-          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( ) );
+          ia = this->m_FrontPaths[ ia ][ ib ];
+          fpath.push_back( ia );
 
-        } // rof
+        } // elihw
 
-        // Final path: from last collision to end point
-        TVertices lpath =
-          this->GetPath(
-            this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b
+        // Continue only if both fronts are connected
+        unsigned int N = fpath.size( );
+        if( N > 0 )
+        {
+          // First path: from start vertex to first collision
+          path = this->GetPath(
+            a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first
             );
-        path.insert( path.end( ), lpath.begin( ), lpath.end( ) );
 
-      } // fi
+          // 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( ) );
 
-    } // fi
+          } // rof
 
-  } // fi
-  return( path );
-}
+          // 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( ) );
 
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TPoints fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetEuclideanPath( const TVertex& a ) const
-{
-  TPoints points;
-  return( points );
-}
+        } // fi
 
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TPoints fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetEuclideanPath( const TVertex& a, const TVertex& b ) const
-{
-  TPoints points;
-  return( points );
-}
+      } // 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;
 
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-bool fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-IsDefinedInEuclideanSpace( ) const
-{
-  return( false );
-}
+      } // elihw
 
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-void fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-SetNode(
-  const TVertex& v, const TVertex& p,
-  const short& fid, const double& cost
-  )
-{
-  typedef typename TNodeQueue::value_type _TNodeQueueValue;
-  if( this->m_FillNodeQueue )
-    this->m_NodeQueue.insert( _TNodeQueueValue( cost, v ) );
-}
+      // Glue both parts
+      for( --aIt; aIt != pa.end( ); ++aIt )
+        path.push_front( *aIt );
+      for( ; bIt != pb.end( ); ++bIt )
+        path.push_back( *bIt );
 
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-void fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-Clear( )
-{
-  this->m_NodeQueue.clear( );
+    } // fi
+
+  } // fi
+  return( path );
 }
 
 // -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
+template< class _TVertex, class _TSuperclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
 MinimumSpanningTree( )
-  : Superclass( ),
-    m_FillNodeQueue( false )
+  : Superclass( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
+template< class _TVertex, class _TSuperclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
 ~MinimumSpanningTree( )
 {
 }
 
-#endif // __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
+#endif // __fpa__Base__MinimumSpanningTree__hxx__
 
 // eof - $RCSfile$