]> Creatis software - FrontAlgorithms.git/blob - lib/fpa/Base/Algorithm.hxx
c29ff03e174791bea40b5155fab7e55f2526db72
[FrontAlgorithms.git] / lib / fpa / Base / Algorithm.hxx
1 #ifndef __fpa__Base__Algorithm__hxx__
2 #define __fpa__Base__Algorithm__hxx__
3
4 #include <queue>
5
6 // -------------------------------------------------------------------------
7 template < class _TFilter, class _TVertex, class _TOutput >
8 fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode::
9 _TQueueNode( )
10 {
11   this->Vertex.Fill( 0 );
12   this->Parent.Fill( 0 );
13   this->Result = _TOutput( 0 );
14   this->FrontId = 0;
15 }
16
17 // -------------------------------------------------------------------------
18 template < class _TFilter, class _TVertex, class _TOutput >
19 fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode::
20 _TQueueNode( const _TVertex& v )
21 {
22   this->Vertex = v;
23   this->Parent = v;
24   this->Result = _TOutput( 0 );
25   this->FrontId = 0;
26 }
27
28 // -------------------------------------------------------------------------
29 template < class _TFilter, class _TVertex, class _TOutput >
30 fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode::
31 _TQueueNode( const _TVertex& v, const _TQueueNode& n )
32 {
33   this->Vertex = v;
34   this->Parent = n.Vertex;
35   this->Result = n.Result;
36   this->FrontId = n.FrontId;
37 }
38
39 // -------------------------------------------------------------------------
40 template < class _TFilter, class _TVertex, class _TOutput >
41 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
42 ClearSeeds( )
43 {
44   this->m_Seeds.clear( );
45   this->Modified( );
46 }
47
48 // -------------------------------------------------------------------------
49 template < class _TFilter, class _TVertex, class _TOutput >
50 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
51 AddSeed( const _TVertex& seed, const TOutput& value )
52 {
53   _TQueueNode node( seed );
54   node.FrontId = this->m_Seeds.size( ) + 1;
55   node.Result = value;
56   this->m_Seeds.push_back( node );
57   this->Modified( );
58 }
59
60 // -------------------------------------------------------------------------
61 template < class _TFilter, class _TVertex, class _TOutput >
62 fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
63 Algorithm( )
64   : Superclass( ),
65     m_InitResult( _TOutput( 0 ) ),
66     m_StopAtOneFront( false )
67 {
68 }
69
70 // -------------------------------------------------------------------------
71 template < class _TFilter, class _TVertex, class _TOutput >
72 fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
73 ~Algorithm( )
74 {
75 }
76
77 // -------------------------------------------------------------------------
78 template < class _TFilter, class _TVertex, class _TOutput >
79 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
80 GenerateData( )
81 {
82   this->InvokeEvent( TStartEvent( ) );
83   this->_BeforeGenerateData( );
84   this->m_NumberOfFronts = this->m_Seeds.size( );
85   if( this->m_NumberOfFronts > 0 )
86   {
87     // Prepare collisions
88     TCollision coll( TVertex( ), false );
89     TCollisionsRow row( this->m_NumberOfFronts, coll );
90     this->m_Collisions.clear( );
91     this->m_Collisions.resize( this->m_NumberOfFronts, row );
92
93     // Put seeds on queue
94     this->_QueueClear( );
95     for(
96       auto nIt = this->m_Seeds.begin( );
97       nIt != this->m_Seeds.end( );
98       ++nIt
99       )
100       this->_QueuePush( *nIt );
101
102     // Init marks and results
103     this->_InitMarks( );
104     this->_InitResults( this->m_InitResult );
105
106     // Main loop
107     do
108       this->_Loop( );
109     while( this->_ContinueGenerateData( ) );
110
111   } // fi
112   this->_AfterGenerateData( );
113   this->InvokeEvent( TEndEvent( ) );
114 }
115
116 // -------------------------------------------------------------------------
117 template < class _TFilter, class _TVertex, class _TOutput >
118 bool fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
119 _ContinueGenerateData( )
120 {
121   return( false );
122 }
123
124 // -------------------------------------------------------------------------
125 template < class _TFilter, class _TVertex, class _TOutput >
126 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
127 _Loop( )
128 {
129   this->InvokeEvent( TStartLoopEvent( ) );
130   this->_BeforeLoop( );
131   while( this->_ValidLoop( ) )
132   {
133     _TQueueNode node = this->_QueuePop( );
134     this->InvokeEvent( TPopEvent( node.Vertex, node.FrontId ) );
135
136     // Process actual vertex
137     if( this->_IsMarked( node.Vertex ) )
138       continue;
139     this->_Mark( node );
140     this->_UpdateResult( node );
141     this->InvokeEvent( TMarkEvent( node.Vertex, node.FrontId ) );
142
143     // Add neighbors to queue
144     TNeighborhood neighs = this->m_NeighborhoodFunction->Evaluate( node.Vertex );
145     for( auto it = neighs.begin( ); it != neighs.end( ); ++it )
146     {
147       if( !( this->_IsMarked( *it ) ) )
148       {
149         _TQueueNode neigh( *it, node );
150         if( this->_UpdateValue( neigh, node ) )
151         {
152           this->_QueuePush( neigh );
153           this->InvokeEvent( TPushEvent( node.Vertex, node.FrontId ) );
154
155         } // fi
156       }
157       else
158         this->_UpdateCollisions( node.Vertex, *it );
159
160     } // rof
161
162   } // elihw
163   this->_AfterLoop( );
164   this->InvokeEvent( TEndLoopEvent( ) );
165 }
166
167 // -------------------------------------------------------------------------
168 template < class _TFilter, class _TVertex, class _TOutput >
169 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
170 _BeforeGenerateData( )
171 {
172 }
173
174 // -------------------------------------------------------------------------
175 template < class _TFilter, class _TVertex, class _TOutput >
176 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
177 _AfterGenerateData( )
178 {
179 }
180
181 // -------------------------------------------------------------------------
182 template < class _TFilter, class _TVertex, class _TOutput >
183 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
184 _BeforeLoop( )
185 {
186 }
187
188 // -------------------------------------------------------------------------
189 template < class _TFilter, class _TVertex, class _TOutput >
190 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
191 _AfterLoop( )
192 {
193 }
194
195 // -------------------------------------------------------------------------
196 template < class _TFilter, class _TVertex, class _TOutput >
197 bool fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
198 _ValidLoop( ) const
199 {
200   bool r = ( this->_QueueSize( ) > 0 );
201   if( this->m_StopAtOneFront )
202     r &= ( this->m_NumberOfFronts > 0 );
203   return( r );
204 }
205
206 // -------------------------------------------------------------------------
207 template < class _TFilter, class _TVertex, class _TOutput >
208 void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
209 _UpdateCollisions( const TVertex& a, const TVertex& b )
210 {
211   auto ma = this->_GetMark( a );
212   auto mb = this->_GetMark( b );
213   if( ma == mb || ma == 0 || mb == 0 )
214     return;
215
216   // Mark collision, if it is new
217   ma--; mb--;
218   bool ret = false;
219   bool exists = this->m_Collisions[ ma ][ mb ].second;
220   exists     &= this->m_Collisions[ mb ][ ma ].second;
221   if( !exists )
222   {
223     this->m_Collisions[ ma ][ mb ].first = a;
224     this->m_Collisions[ ma ][ mb ].second = true;
225     this->m_Collisions[ mb ][ ma ].first = b;
226     this->m_Collisions[ mb ][ ma ].second = true;
227
228     // Update number of fronts
229     unsigned long N = this->m_Seeds.size( );
230     unsigned long count = 0;
231     std::vector< bool > m( N, false );
232     std::queue< unsigned long > q;
233     q.push( 0 );
234     while( !q.empty( ) )
235     {
236       unsigned long f = q.front( );
237       q.pop( );
238
239       if( m[ f ] )
240         continue;
241       m[ f ] = true;
242       count++;
243
244       for( unsigned int n = 0; n < N; ++n )
245         if( this->m_Collisions[ f ][ n ].second && !m[ n ] )
246           q.push( n );
247
248     } // elihw
249     this->m_NumberOfFronts = N - count;
250
251   } // fi
252 }
253
254 // -------------------------------------------------------------------------
255 template < class _TFilter, class _TVertex, class _TOutput >
256 _TOutput fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::
257 _GetInputValue( const _TQueueNode& v, const _TQueueNode& p )
258 {
259   _TOutput res = this->m_InitResult;
260   if( this->m_VertexFunction.IsNotNull( ) )
261     res = this->m_VertexFunction->Evaluate( v.Vertex, p.Vertex );
262   if( this->m_ConversionFunction.IsNotNull( ) )
263     res = this->m_ConversionFunction->Evaluate( res );
264   return( res );
265 }
266
267 #endif // __fpa__Base__Algorithm__hxx__
268
269 // eof - $RCSfile$