]> Creatis software - FrontAlgorithms.git/blobdiff - lib/fpa/Base/Algorithm.hxx
...
[FrontAlgorithms.git] / lib / fpa / Base / Algorithm.hxx
index 35307874ab8a43c732169bb008612b13994ff10e..c29ff03e174791bea40b5155fab7e55f2526db72 100644 (file)
-#ifndef __FPA__BASE__ALGORITHM__HXX__
-#define __FPA__BASE__ALGORITHM__HXX__
+#ifndef __fpa__Base__Algorithm__hxx__
+#define __fpa__Base__Algorithm__hxx__
 
 #include <queue>
-#include <itkProcessObject.h>
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-fpa::Base::Algorithm< V, C, R, S, VC, B >::_TNode::
-_TNode( )
-  : Result( TResult( 0 ) ),
-    FrontId( -1 ),
-    Label( Self::FarLabel )
+template < class _TFilter, class _TVertex, class _TOutput >
+fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode::
+_TQueueNode( )
 {
+  this->Vertex.Fill( 0 );
+  this->Parent.Fill( 0 );
+  this->Result = _TOutput( 0 );
+  this->FrontId = 0;
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-fpa::Base::Algorithm< V, C, R, S, VC, B >::_TNode::
-~_TNode( )
+template < class _TFilter, class _TVertex, class _TOutput >
+fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode::
+_TQueueNode( const _TVertex& v )
 {
+  this->Vertex = v;
+  this->Parent = v;
+  this->Result = _TOutput( 0 );
+  this->FrontId = 0;
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
-InvokeEvent( const itk::EventObject& e )
+template < class _TFilter, class _TVertex, class _TOutput >
+fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode::
+_TQueueNode( const _TVertex& v, const _TQueueNode& n )
 {
-  if( this->m_ThrowEvents )
-    this->Superclass::InvokeEvent( e );
+  this->Vertex = v;
+  this->Parent = n.Vertex;
+  this->Result = n.Result;
+  this->FrontId = n.FrontId;
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
-InvokeEvent( const itk::EventObject& e ) const
-{
-  if( this->m_ThrowEvents )
-    this->Superclass::InvokeEvent( e );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
-AddSeed( const TVertex& s, const TResult& r )
-{
-  _TNode ns;
-  ns.Parent = s;
-  ns.Result = r;
-  ns.FrontId = this->m_SeedVertices.size( );
-  ns.Label = Self::FrontLabel;
-  this->m_Seeds[ s ] = ns;
-  this->m_SeedVertices.push_back( s );
-  this->Modified( );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-const typename fpa::Base::Algorithm< V, C, R, S, VC, B >::
-TVertex& fpa::Base::Algorithm< V, C, R, S, VC, B >::
-GetSeed( const unsigned int& id ) const
-{
-  return( this->m_SeedVertices[ id ] );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 ClearSeeds( )
 {
   this->m_Seeds.clear( );
-  this->m_SeedVertices.clear( );
   this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-unsigned long fpa::Base::Algorithm< V, C, R, S, VC, B >::
-GetNumberOfSeeds( ) const
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
+AddSeed( const _TVertex& seed, const TOutput& value )
 {
-  return( this->m_Seeds.size( ) );
+  _TQueueNode node( seed );
+  node.FrontId = this->m_Seeds.size( ) + 1;
+  node.Result = value;
+  this->m_Seeds.push_back( node );
+  this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 Algorithm( )
   : Superclass( ),
-    m_ThrowEvents( false ),
+    m_InitResult( _TOutput( 0 ) ),
     m_StopAtOneFront( false )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 ~Algorithm( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 GenerateData( )
 {
-  unsigned long N = this->m_Seeds.size( );
-  if( N == 0 )
-    return;
-
   this->InvokeEvent( TStartEvent( ) );
   this->_BeforeGenerateData( );
+  this->m_NumberOfFronts = this->m_Seeds.size( );
+  if( this->m_NumberOfFronts > 0 )
+  {
+    // Prepare collisions
+    TCollision coll( TVertex( ), false );
+    TCollisionsRow row( this->m_NumberOfFronts, coll );
+    this->m_Collisions.clear( );
+    this->m_Collisions.resize( this->m_NumberOfFronts, row );
+
+    // Put seeds on queue
+    this->_QueueClear( );
+    for(
+      auto nIt = this->m_Seeds.begin( );
+      nIt != this->m_Seeds.end( );
+      ++nIt
+      )
+      this->_QueuePush( *nIt );
+
+    // Init marks and results
+    this->_InitMarks( );
+    this->_InitResults( this->m_InitResult );
+
+    // Main loop
+    do
+      this->_Loop( );
+    while( this->_ContinueGenerateData( ) );
 
-  this->m_Collisions.clear( );
-  this->m_Collisions.
-    resize( N, _TCollisionsRow( N, _TCollision( TVertex( ), false ) ) );
-  this->_InitResults( );
-  this->_InitMarks( );
-  this->_InitQueue( );
-  this->_Loop( );
+  } // fi
   this->_AfterGenerateData( );
   this->InvokeEvent( TEndEvent( ) );
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+bool fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
+_ContinueGenerateData( )
+{
+  return( false );
+}
+
+// -------------------------------------------------------------------------
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 _Loop( )
 {
   this->InvokeEvent( TStartLoopEvent( ) );
   this->_BeforeLoop( );
-  while( !( this->_IsQueueEmpty( ) ) )
+  while( this->_ValidLoop( ) )
   {
-    // Get next candidate
-    TVertex vertex;
-    _TNode node;
-    this->_QueuePop( vertex, node );
-    if( this->_Node( vertex ).Label == Self::AliveLabel )
-      continue;
+    _TQueueNode node = this->_QueuePop( );
+    this->InvokeEvent( TPopEvent( node.Vertex, node.FrontId ) );
 
-    // Mark it as "Alive" and update final result
-    node.Label = Self::AliveLabel;
-    this->_Mark( vertex, node );
-    this->_SetResult( vertex, node );
-    this->InvokeEvent( TAliveEvent( vertex, node.FrontId ) );
+    // Process actual vertex
+    if( this->_IsMarked( node.Vertex ) )
+      continue;
+    this->_Mark( node );
+    this->_UpdateResult( node );
+    this->InvokeEvent( TMarkEvent( node.Vertex, node.FrontId ) );
 
-    // Check if a forced stop condition arises
-    if( !( this->_NeedToStop( ) ) )
+    // Add neighbors to queue
+    TNeighborhood neighs = this->m_NeighborhoodFunction->Evaluate( node.Vertex );
+    for( auto it = neighs.begin( ); it != neighs.end( ); ++it )
     {
-      // Compute neighborhood
-      _TVertices neighborhood;
-      this->_Neighborhood( neighborhood, vertex );
-
-      // Iterate over neighbors
-      typename _TVertices::iterator nIt = neighborhood.begin( );
-      while( nIt != neighborhood.end( ) )
+      if( !( this->_IsMarked( *it ) ) )
       {
-        _TNode neighbor = this->_Node( *nIt );
-        if( neighbor.Label == Self::AliveLabel )
+        _TQueueNode neigh( *it, node );
+        if( this->_UpdateValue( neigh, node ) )
         {
-          // Update collisions
-          if( this->_UpdateCollisions( vertex, *nIt ) )
-          {
-            this->_QueueClear( );
-            nIt = neighborhood.end( );
-            continue;
-
-          } // fi
-        }
-        else
-        {
-          // Add new candidate to queue
-          if( this->_ComputeNeighborResult( neighbor.Result, *nIt, vertex ) )
-          {
-            neighbor.FrontId = node.FrontId;
-            neighbor.Parent = vertex;
-            neighbor.Label = Self::FrontLabel;
-            this->_QueuePush( *nIt, neighbor );
-            this->_Mark( *nIt, neighbor );
-            this->InvokeEvent( TFrontEvent( *nIt, node.FrontId ) );
-          }
-          else
-            this->InvokeEvent( TFreezeEvent( *nIt, node.FrontId ) );
+          this->_QueuePush( neigh );
+          this->InvokeEvent( TPushEvent( node.Vertex, node.FrontId ) );
 
         } // fi
-        ++nIt;
+      }
+      else
+        this->_UpdateCollisions( node.Vertex, *it );
 
-      } // elihw
-    }
-    else
-      this->_QueueClear( );
+    } // rof
 
   } // elihw
   this->_AfterLoop( );
@@ -195,172 +165,105 @@ _Loop( )
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 _BeforeGenerateData( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 _AfterGenerateData( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 _BeforeLoop( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
 _AfterLoop( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-bool fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_UpdateCollisions( const TVertex& a, const TVertex& b )
+template < class _TFilter, class _TVertex, class _TOutput >
+bool fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
+_ValidLoop( ) const
 {
-  bool ret = false;
-  _TNode na = this->_Node( a );
-  _TNode nb = this->_Node( b );
-  long fa = na.FrontId;
-  long fb = nb.FrontId;
-
-  if( fa != fb )
-  {
-    // Mark collision, if it is new
-    bool exists = this->m_Collisions[ fa ][ fb ].second;
-    exists     &= this->m_Collisions[ fb ][ fa ].second;
-        
-    if( !exists )
-    {
-      this->m_Collisions[ fa ][ fb ].first = a;
-      this->m_Collisions[ fa ][ fb ].second = true;
-      this->m_Collisions[ fb ][ fa ].first = b;
-      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 count = 0;
-        std::vector< bool > m( N, false );
-        std::queue< unsigned long > q;
-        q.push( 0 );
-        while( !q.empty( ) )
-        {
-          unsigned long f = q.front( );
-          q.pop( );
-
-          if( m[ f ] )
-            continue;
-          m[ f ] = true;
-          count++;
-
-          for( unsigned int n = 0; n < N; ++n )
-            if( this->m_Collisions[ f ][ n ].second && !m[ n ] )
-              q.push( n );
-
-        } // elihw
-        ret = ( count == N );
-
-      } // fi
-
-    } // fi
-
-  } // fi
-  return( ret );
+  bool r = ( this->_QueueSize( ) > 0 );
+  if( this->m_StopAtOneFront )
+    r &= ( this->m_NumberOfFronts > 0 );
+  return( r );
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-bool fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_NeedToStop( ) const
+template < class _TFilter, class _TVertex, class _TOutput >
+void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
+_UpdateCollisions( const TVertex& a, const TVertex& b )
 {
-  return( false );
-}
+  auto ma = this->_GetMark( a );
+  auto mb = this->_GetMark( b );
+  if( ma == mb || ma == 0 || mb == 0 )
+    return;
 
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-typename fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_TNode& fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_Node( const TVertex& v )
-{
-  typename _TNodes::iterator vIt = this->m_Marks.find( v );
-  if( vIt == this->m_Marks.end( ) )
+  // Mark collision, if it is new
+  ma--; mb--;
+  bool ret = false;
+  bool exists = this->m_Collisions[ ma ][ mb ].second;
+  exists     &= this->m_Collisions[ mb ][ ma ].second;
+  if( !exists )
   {
-    _TNode new_node;
-    new_node.Parent = v;
-    new_node.Result = TResult( 0 );
-    new_node.FrontId = -1;
-    new_node.Label = Self::FarLabel;
-    this->m_Marks[ v ] = new_node;
-    vIt = this->m_Marks.find( v );
-
-  } // fi
-  return( vIt->second );
-}
+    this->m_Collisions[ ma ][ mb ].first = a;
+    this->m_Collisions[ ma ][ mb ].second = true;
+    this->m_Collisions[ mb ][ ma ].first = b;
+    this->m_Collisions[ mb ][ ma ].second = true;
+
+    // Update number of fronts
+    unsigned long N = this->m_Seeds.size( );
+    unsigned long count = 0;
+    std::vector< bool > m( N, false );
+    std::queue< unsigned long > q;
+    q.push( 0 );
+    while( !q.empty( ) )
+    {
+      unsigned long f = q.front( );
+      q.pop( );
 
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_SetResult( const TVertex& v, const _TNode& n )
-{
-  // Do nothing at this hierarchy level
-}
+      if( m[ f ] )
+        continue;
+      m[ f ] = true;
+      count++;
 
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-const typename fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_TNode& fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_Node( const TVertex& v ) const
-{
-  typename _TNodes::const_iterator vIt = this->m_Marks.find( v );
-  return( vIt->second );
-}
+      for( unsigned int n = 0; n < N; ++n )
+        if( this->m_Collisions[ f ][ n ].second && !m[ n ] )
+          q.push( n );
 
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_InitMarks( )
-{
-  this->m_Marks.clear( );
-}
+    } // elihw
+    this->m_NumberOfFronts = N - count;
 
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_Mark( const TVertex& v, const _TNode& node )
-{
-  this->m_Marks[ v ] = node;
+  } // fi
 }
 
 // -------------------------------------------------------------------------
-template< class V, class C, class R, class S, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, S, VC, B >::
-_InitQueue( )
+template < class _TFilter, class _TVertex, class _TOutput >
+_TOutput fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
+_GetInputValue( const _TQueueNode& v, const _TQueueNode& p )
 {
-  this->_QueueClear( );
-  for(
-    typename _TNodes::const_iterator sIt = this->m_Seeds.begin( );
-    sIt != this->m_Seeds.end( );
-    sIt++
-    )
-  {
-    this->_QueuePush( sIt->first, sIt->second );
-    this->_Mark( sIt->first, sIt->second );
-
-  } // rof
+  _TOutput res = this->m_InitResult;
+  if( this->m_VertexFunction.IsNotNull( ) )
+    res = this->m_VertexFunction->Evaluate( v.Vertex, p.Vertex );
+  if( this->m_ConversionFunction.IsNotNull( ) )
+    res = this->m_ConversionFunction->Evaluate( res );
+  return( res );
 }
 
-#endif // __FPA__BASE__ALGORITHM__HXX__
+#endif // __fpa__Base__Algorithm__hxx__
 
 // eof - $RCSfile$