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