]> Creatis software - FrontAlgorithms.git/blobdiff - lib/fpa/Base/Algorithm.hxx
Major refactoring
[FrontAlgorithms.git] / lib / fpa / Base / Algorithm.hxx
index a58f2a6a047366e2896a302109a6eb887095711d..21670ef7396522c40c2a918432182d7d96037b34 100644 (file)
@@ -1,13 +1,28 @@
 #ifndef __FPA__BASE__ALGORITHM__HXX__
 #define __FPA__BASE__ALGORITHM__HXX__
 
-#include <algorithm>
-#include <limits>
 #include <queue>
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+fpa::Base::Algorithm< V, C, R, B >::_TNode::
+_TNode( )
+  : Result( TResult( 0 ) ),
+    FrontId( -1 ),
+    Label( Self::FarLabel )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class R, class B >
+fpa::Base::Algorithm< V, C, R, B >::_TNode::
+~_TNode( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
 InvokeEvent( const itk::EventObject& e )
 {
   if( this->m_ThrowEvents )
@@ -15,8 +30,8 @@ InvokeEvent( const itk::EventObject& e )
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
 InvokeEvent( const itk::EventObject& e ) const
 {
   if( this->m_ThrowEvents )
@@ -24,26 +39,32 @@ InvokeEvent( const itk::EventObject& e ) const
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
-AddSeed( const TVertex& s, const TResult& v )
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
+AddSeed( const TVertex& s, const TResult& r )
 {
-  this->m_Seeds.push_back( _TNode( s, v, this->m_Seeds.size( ) ) );
+  _TNode ns;
+  ns.Vertex = s;
+  ns.Parent = s;
+  ns.Result = r;
+  ns.FrontId = this->m_Seeds.size( );
+  ns.Label = Self::FrontLabel;
+  this->m_Seeds.push_back( ns );
   this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-const typename fpa::Base::Algorithm< T, B >::
-TVertex& fpa::Base::Algorithm< T, B >::
-GetSeed( const unsigned long& i ) const
+template< class V, class C, class R, class B >
+const typename fpa::Base::Algorithm< V, C, R, B >::
+TVertex& fpa::Base::Algorithm< V, C, R, B >::
+GetSeed( const unsigned int& id ) const
 {
-  return( this->m_Seeds[ i ].Vertex );
+  return( this->m_Seeds[ id ].Vertex );
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
 ClearSeeds( )
 {
   this->m_Seeds.clear( );
@@ -51,170 +72,184 @@ ClearSeeds( )
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-unsigned long fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+unsigned long fpa::Base::Algorithm< V, C, R, B >::
 GetNumberOfSeeds( ) const
 {
   return( this->m_Seeds.size( ) );
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+fpa::Base::Algorithm< V, C, R, B >::
 Algorithm( )
   : Superclass( ),
-    m_StopAtOneFront( false ),
-    m_ThrowEvents( false )
+    m_ThrowEvents( false ),
+    m_StopAtOneFront( false )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+fpa::Base::Algorithm< V, C, R, B >::
 ~Algorithm( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
 GenerateData( )
 {
-  this->AllocateOutputs( );
-
   unsigned long N = this->m_Seeds.size( );
   if( N == 0 )
     return;
-  this->m_CollisionSites.clear( );
-  this->m_CollisionSites.
-    resize( N, _TCollisionSitesRow( N, _TCollision( TVertex( ), false ) ) );
-
-  this->_BeforeMainLoop( );
-  this->_InitializeMarks( );
-  this->_InitializeResults( );
-  this->_InitializeQueue( );
-  this->_Loop( );
-  this->_AfterMainLoop( );
-  this->InvokeEvent( TEndEvent( ) );
-}
-
-// -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
-_BeforeMainLoop( )
-{
-}
 
-// -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
-_AfterMainLoop( )
-{
-}
+  this->InvokeEvent( TStartEvent( ) );
+  this->_BeforeGenerateData( );
 
-// -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
-_BeforeLoop( )
-{
-}
-
-// -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
-_AfterLoop( )
-{
+  this->m_Collisions.clear( );
+  this->m_Collisions.
+    resize( N, _TCollisionsRow( N, _TCollision( TVertex( ), false ) ) );
+  this->_InitResults( );
+  this->_InitMarks( );
+  this->_InitQueue( );
+  this->_Loop( );
+  this->_AfterGenerateData( );
+  this->InvokeEvent( TEndEvent( ) );
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
 _Loop( )
 {
+  this->InvokeEvent( TStartLoopEvent( ) );
   this->_BeforeLoop( );
   while( !( this->_IsQueueEmpty( ) ) )
   {
-    _TNode n = this->_QueuePop( );
-    if( this->_IsMarked( n.Vertex ) )
+    // Get next candidate
+    _TNode candidate = this->_QueuePop( );
+    if( this->_Node( candidate.Vertex ).Label == Self::AliveLabel )
       continue;
 
-    this->_Mark( n );
-    this->InvokeEvent( TMarkEvent( n ) );
-    if( this->_UpdateResult( n ) )
+    // Mark it as "Alive" and update final result
+    candidate.Label = Self::AliveLabel;
+    this->_Mark( candidate );
+    this->_SetResult( candidate.Vertex, candidate.Result );
+    this->InvokeEvent( TAliveEvent( candidate.Vertex, candidate.FrontId ) );
+
+    // Check if a forced stop condition arises
+    if( !( this->_NeedToStop( ) ) )
     {
-      if( !( this->_CheckStopCondition( ) ) )
+      // Compute neighborhood
+      _TVertices neighborhood;
+      this->_Neighborhood( neighborhood, candidate.Vertex );
+
+      // Iterate over neighbors
+      typename _TVertices::iterator nIt = neighborhood.begin( );
+      for( ; nIt != neighborhood.end( ); ++nIt )
       {
-        _TNodes N;
-        this->_Neighs( n, N );
-        typename _TNodes::iterator nnIt = N.begin( );
-        while( nnIt != N.end( ) )
+        _TNode neighbor = this->_Node( *nIt );
+        neighbor.Vertex = *nIt;
+        if( neighbor.Label == Self::AliveLabel )
         {
-          if( this->_IsMarked( nnIt->Vertex ) )
+          // Update collisions
+          if( this->_UpdateCollisions( candidate.Vertex, *nIt ) )
           {
-            // Update real front identifier
-            nnIt->FrontId = this->_FrontId( nnIt->Vertex );
+            this->_QueueClear( );
+            nIt = neighborhood.end( );
 
-            // Update collisions
-            if( this->_CheckCollisions( n, *nnIt ) )
-            {
-              if( this->m_StopAtOneFront )
-              {
-                this->_QueueClear( );
-                nnIt = N.end( );
-
-              } // fi
-
-            } // fi
+          } // fi
+        }
+        else
+        {
+          // Add new candidate to queue
+          if(
+            this->_ComputeNeighborResult(
+              neighbor.Result, *nIt, candidate.Vertex
+              )
+            )
+          {
+            neighbor.FrontId = candidate.FrontId;
+            neighbor.Parent = candidate.Vertex;
+            neighbor.Label = Self::FrontLabel;
+            this->_QueuePush( neighbor );
+            this->_Mark( neighbor );
+            this->InvokeEvent( TFrontEvent( *nIt, candidate.FrontId ) );
           }
           else
-          {
-            if( this->_UpdateNeigh( *nnIt, n ) )
-            {
-              nnIt->Parent = n.Vertex;
-              this->_QueuePush( *nnIt );
-              this->InvokeEvent( TFrontEvent( *nnIt ) );
+            this->InvokeEvent( TFreezeEvent( *nIt, candidate.FrontId ) );
 
-            } // fi
+        } // fi
 
-          } // fi
-          if( nnIt != N.end( ) )
-            nnIt++;
-
-        } // elihw
-      }
-      else
-        this->_QueueClear( );
-
-    } // fi
+      } // rof
+    }
+    else
+      this->_QueueClear( );
 
   } // elihw
   this->_AfterLoop( );
+  this->InvokeEvent( TEndLoopEvent( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
+_BeforeGenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
+_AfterGenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
+_BeforeLoop( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
+_AfterLoop( )
+{
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-bool fpa::Base::Algorithm< T, B >::
-_CheckCollisions( const _TNode& a, const _TNode& b )
+template< class V, class C, class R, class B >
+bool fpa::Base::Algorithm< V, C, R, B >::
+_UpdateCollisions( const TVertex& a, const TVertex& b )
 {
   bool ret = false;
-  if( a.FrontId != b.FrontId )
+  _TNode na = this->_Node( a );
+  _TNode nb = this->_Node( b );
+  long fa = na.FrontId;
+  long fb = na.FrontId;
+
+  if( fa != fb )
   {
     // Mark collision, if it is new
-    bool exists = this->m_CollisionSites[ a.FrontId ][ b.FrontId ].second;
-    exists     &= this->m_CollisionSites[ b.FrontId ][ a.FrontId ].second;
+    bool exists = this->m_Collisions[ fa ][ fb ].second;
+    exists     &= this->m_Collisions[ fb ][ fa ].second;
     if( !exists )
     {
-      this->m_CollisionSites[ a.FrontId ][ b.FrontId ].first = a.Vertex;
-      this->m_CollisionSites[ a.FrontId ][ b.FrontId ].second = true;
-      this->m_CollisionSites[ b.FrontId ][ a.FrontId ].first = b.Vertex;
-      this->m_CollisionSites[ b.FrontId ][ a.FrontId ].second = true;
+      this->m_Collisions[ fa ][ fb ].first = na.Vertex;
+      this->m_Collisions[ fa ][ fb ].second = true;
+      this->m_Collisions[ fb ][ fa ].first = nb.Vertex;
+      this->m_Collisions[ fb ][ fa ].second = true;
 
       // Stop if one front is desired
       if( this->m_StopAtOneFront )
       {
         // Perform a depth-first iteration on front graph
         unsigned long N = this->GetNumberOfSeeds( );
-        unsigned long C = 0;
+        unsigned long count = 0;
         std::vector< bool > m( N, false );
         std::queue< unsigned long > q;
         q.push( 0 );
@@ -226,14 +261,14 @@ _CheckCollisions( const _TNode& a, const _TNode& b )
           if( m[ f ] )
             continue;
           m[ f ] = true;
-          C++;
+          count++;
 
           for( unsigned int n = 0; n < N; ++n )
-            if( this->m_CollisionSites[ f ][ n ].second && !m[ n ] )
+            if( this->m_Collisions[ f ][ n ].second && !m[ n ] )
               q.push( n );
 
         } // elihw
-        ret = ( C == N );
+        ret = ( count == N );
 
       } // fi
 
@@ -244,69 +279,29 @@ _CheckCollisions( const _TNode& a, const _TNode& b )
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-bool fpa::Base::Algorithm< T, B >::
-_CheckStopCondition( )
+template< class V, class C, class R, class B >
+bool fpa::Base::Algorithm< V, C, R, B >::
+_NeedToStop( ) const
 {
   return( false );
 }
 
 // -------------------------------------------------------------------------
-template< class T, class B >
-bool fpa::Base::Algorithm< T, B >::
-_UpdateResult( _TNode& n )
+template< class V, class C, class R, class B >
+void fpa::Base::Algorithm< V, C, R, B >::
+_InitQueue( )
 {
-  return( true );
-}
-
-// -------------------------------------------------------------------------
-template< class T, class B >
-void fpa::Base::Algorithm< T, B >::
-_InitializeMarks( )
-{
-  this->m_Marks.clear( );
-}
-
-// -------------------------------------------------------------------------
-template< class T, class B >
-bool  fpa::Base::Algorithm< T, B >::
-_IsMarked( const TVertex& v ) const
-{
-  return( this->m_Marks.find( v ) != this->m_Marks.end( ) );
-}
-
-// -------------------------------------------------------------------------
-template< class T, class B >
-typename fpa::Base::Algorithm< T, B >::
-_TFrontId fpa::Base::Algorithm< T, B >::
-_FrontId( const TVertex& v ) const
-{
-  typename _TMarks::const_iterator mIt = this->m_Marks.find( v );
-  if( mIt != this->m_Marks.end( ) )
-    return( mIt->second.FrontId );
-  else
-    return( std::numeric_limits< _TFrontId >::max( ) );
-}
-
-// -------------------------------------------------------------------------
-template< class T, class B >
-typename fpa::Base::Algorithm< T, B >::
-TVertex fpa::Base::Algorithm< T, B >::
-_Parent( const TVertex& v ) const
-{
-  typename _TMarks::const_iterator mIt = this->m_Marks.find( v );
-  if( mIt == this->m_Marks.end( ) )
-    return( TVertex( ) );
-  else
-    return( mIt->second.Parent );
-}
+  this->_QueueClear( );
+  for(
+    typename _TNodes::const_iterator sIt = this->m_Seeds.begin( );
+    sIt != this->m_Seeds.end( );
+    sIt++
+    )
+  {
+    this->_QueuePush( *sIt );
+    this->_Mark( *sIt );
 
-// -------------------------------------------------------------------------
-template< class T, class B >
-void  fpa::Base::Algorithm< T, B >::
-_Mark( const _TNode& n )
-{
-  this->m_Marks[ n.Vertex ] = n;
+  } // rof
 }
 
 #endif // __FPA__BASE__ALGORITHM__HXX__