-#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 VC, class B >
-fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-typename fpa::Base::Algorithm< V, C, R, VC, B >::
-TMinimumSpanningTree* fpa::Base::Algorithm< V, C, R, VC, B >::
-GetMinimumSpanningTree( )
+template < class _TFilter, class _TVertex, class _TOutput >
+fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode::
+_TQueueNode( const _TVertex& v, const _TQueueNode& n )
{
- return(
- dynamic_cast< TMinimumSpanningTree* >(
- this->itk::ProcessObject::GetOutput( 1 )
- )
- );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-const typename fpa::Base::Algorithm< V, C, R, VC, B >::
-TMinimumSpanningTree* fpa::Base::Algorithm< V, C, R, VC, B >::
-GetMinimumSpanningTree( ) const
-{
- return(
- dynamic_cast< const TMinimumSpanningTree* >(
- this->itk::ProcessObject::GetOutput( 1 )
- )
- );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, VC, B >::
-GraftMinimumSpanningTree( itk::DataObject* obj )
-{
- TMinimumSpanningTree* mst = dynamic_cast< TMinimumSpanningTree* >( obj );
- if( mst != NULL )
- this->GraftNthOutput( 1, mst );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, VC, B >::
-InvokeEvent( const itk::EventObject& e )
-{
- if( this->m_ThrowEvents )
- this->Superclass::InvokeEvent( e );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, VC, B >::
-InvokeEvent( const itk::EventObject& e ) const
-{
- if( this->m_ThrowEvents )
- this->Superclass::InvokeEvent( e );
-}
-
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-const typename fpa::Base::Algorithm< V, C, R, VC, B >::
-TVertex& fpa::Base::Algorithm< V, C, R, VC, B >::
-GetSeed( const unsigned int& id ) const
-{
- return( this->m_SeedVertices[ id ] );
+ this->Vertex = v;
+ this->Parent = n.Vertex;
+ this->Result = n.Result;
+ this->FrontId = n.FrontId;
}
// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-unsigned long fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-fpa::Base::Algorithm< V, C, R, 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 )
{
- this->m_MinimumSpanningTreeIndex = this->GetNumberOfRequiredOutputs( );
- this->SetNumberOfRequiredOutputs( this->m_MinimumSpanningTreeIndex + 1 );
- this->itk::ProcessObject::SetNthOutput(
- this->m_MinimumSpanningTreeIndex, TMinimumSpanningTree::New( )
- );
}
// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-fpa::Base::Algorithm< V, C, R, VC, B >::
+template < class _TFilter, class _TVertex, class _TOutput >
+fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
~Algorithm( )
{
}
// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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 );
- this->m_Collisions.clear( );
- this->m_Collisions.
- resize( N, _TCollisionsRow( N, _TCollision( TVertex( ), false ) ) );
- this->_InitResults( );
- this->_InitMarks( );
- this->_InitQueue( );
- this->_Loop( );
+ // Main loop
+ do
+ this->_Loop( );
+ while( this->_ContinueGenerateData( ) );
+
+ } // fi
this->_AfterGenerateData( );
this->InvokeEvent( TEndEvent( ) );
}
// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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( );
}
// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-bool fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-bool fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-typename fpa::Base::Algorithm< V, C, R, VC, B >::
-_TNode& fpa::Base::Algorithm< V, C, R, 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 );
+ 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( );
- } // fi
- return( vIt->second );
-}
+ if( m[ f ] )
+ continue;
+ m[ f ] = true;
+ count++;
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-const typename fpa::Base::Algorithm< V, C, R, VC, B >::
-_TNode& fpa::Base::Algorithm< V, C, R, 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 VC, class B >
-void fpa::Base::Algorithm< V, C, R, VC, B >::
-_InitMarks( )
-{
- this->m_Marks.clear( );
-}
+ } // elihw
+ this->m_NumberOfFronts = N - count;
-// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, VC, B >::
-_Mark( const TVertex& v, const _TNode& node )
-{
- this->m_Marks[ v ] = node;
+ } // fi
}
// -------------------------------------------------------------------------
-template< class V, class C, class R, class VC, class B >
-void fpa::Base::Algorithm< V, C, R, 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$