Orfeo Toolbox  3.16
itkQuadEdgeMeshEdgeMergeDecimationFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkQuadEdgeMeshEdgeMergeDecimationFilter.txx,v $
5  Language: C++
6  Date: $Date: 2010-03-24 21:51:55 $
7  Version: $Revision: 1.12 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 
18 #ifndef __itkQuadEdgeMeshEdgeMergeDecimationFilter_txx
19 #define __itkQuadEdgeMeshEdgeMergeDecimationFilter_txx
20 
22 
23 namespace itk
24 {
25 
26 template< class TInput, class TOutput, class TCriterion >
29  m_Relocate( true ), m_CheckOrientation( false )
30 {
33 }
34 
35 template< class TInput, class TOutput, class TCriterion >
38 {
39  OutputQEType* edge;
40 
41  while( !m_PriorityQueue->Empty() )
42  {
43  edge = m_PriorityQueue->Peek()->m_Element;
44  m_PriorityQueue->Pop();
45 
46  QueueMapIterator it = m_QueueMapper.find( edge );
47  delete it->second;
48  m_QueueMapper.erase( it );
49  }
50 }
51 
52 template< class TInput, class TOutput, class TCriterion >
53 void
56 {
57  OutputMeshPointer output = this->GetOutput();
58  m_JoinVertexFunction->SetInput( output );
59 
60  OutputCellsContainerIterator it = output->GetEdgeCells()->Begin();
61  OutputCellsContainerIterator end = output->GetEdgeCells()->End();
62 
63  OutputEdgeCellType* edge;
64 
65  while( it != end )
66  {
67  edge = dynamic_cast< OutputEdgeCellType* >( it.Value( ) );
68 
69  if ( edge )
70  {
71  PushElement( edge->GetQEGeom( ) );
72  }
73  ++it;
74  }
75 }
76 
77 template< class TInput, class TOutput, class TCriterion >
78 void
81 {
82  OutputPointIdentifier id_org = iEdge->GetOrigin();
83  OutputPointIdentifier id_dest = iEdge->GetDestination();
84 
85  OutputQEType* temp = ( id_org < id_dest ) ? iEdge : iEdge->GetSym();
86  MeasureType measure = MeasureEdge( temp );
87 
89  PriorityType( false, measure ) );
90 
91  m_QueueMapper[ temp ] = qi;
92  m_PriorityQueue->Push( qi );
93 }
94 
95 template< class TInput, class TOutput, class TCriterion >
96 bool
98 #ifdef NDEBUG
99 IsEdgeOKToBeProcessed( OutputQEType* iEdge )
100 #else
101 IsEdgeOKToBeProcessed( OutputQEType* )
102 #endif
103 {
104 #ifdef NDEBUG
105  if ( iEdge == 0 )
106  {
107  itkDebugMacro( "iEdge == 0, at iteration: " <<this->m_Iteration );
108  return false;
109  }
110 
111  OutputPointIdentifier id_org = iEdge->GetOrigin();
112  if ( id_org == iEdge->m_NoPoint )
113  {
114  itkDebugMacro( "id_org == iEdge->m_NoPoint, at iteration: "
115  <<this->m_Iteration );
116  return false;
117  }
118 
119  OutputMeshPointer output = this->GetOutput();
120  if ( output->FindEdge( id_org ) == 0 )
121  {
122  itkDebugMacro( "output->FindEdge( id_org ) == 0, at iteration: "
123  <<this->m_Iteration );
124  return false;
125  }
126  if ( iEdge->GetSym() == 0 )
127  {
128  itkDebugMacro( "iEdge->GetSym() == 0, at iteration: "
129  <<this->m_Iteration );
130  return false;
131  }
132 
133  OutputPointIdentifier id_dest = iEdge->GetDestination();
134  if ( id_dest == iEdge->m_NoPoint )
135  {
136  itkDebugMacro( "id_dest == iEdge->m_NoPoint, at iteration: "
137  <<this->m_Iteration );
138  return false;
139  }
140  if ( output->FindEdge( id_dest ) == 0 )
141  {
142  itkDebugMacro( "output->FindEdge( id_dest ) == 0, at iteration: "
143  <<this->m_Iteration );
144  return false;
145  }
146  if ( output->FindEdge( id_org, id_dest ) == 0 )
147  {
148  itkDebugMacro( "output->FindEdge( id_org, id_dest ) == 0, at iteration: "
149  <<this->m_Iteration );
150  return false;
151  }
152 #endif
153 
154  return true;
155 }
156 
157 template< class TInput, class TOutput, class TCriterion >
158 void
161 {
162  OutputMeshPointer output = this->GetOutput();
163 
164  do
165  {
166  m_Element = m_PriorityQueue->Peek( )->m_Element;
167  m_Priority = m_PriorityQueue->Peek( )->m_Priority;
168 
169  m_PriorityQueue->Pop();
170  QueueMapIterator it = m_QueueMapper.find( m_Element );
171  delete it->second;
172  m_QueueMapper.erase( it );
173  } while ( !IsEdgeOKToBeProcessed( m_Element ) );
174 }
175 
176 template< class TInput, class TOutput, class TCriterion >
177 void
180 {
181  if ( iEdge ) // this test can be removed
182  {
183  OutputQEType* temp = ( iEdge->GetOrigin() < iEdge->GetDestination() ) ?
184  iEdge : iEdge->GetSym();
185 
186  QueueMapIterator map_it = m_QueueMapper.find( temp );
187  if ( map_it != m_QueueMapper.end() )
188  {
189  if( !map_it->second->m_Priority.first )
190  {
191  m_PriorityQueue->DeleteElement( map_it->second );
192  delete map_it->second;
193  m_QueueMapper.erase( map_it );
194  }
195  }
196  }
197 }
198 
199 template< class TInput, class TOutput, class TCriterion >
200 void
203 {
204  OutputQEType* temp = iEdge;
205 
206  if ( temp->GetOrigin() > temp->GetDestination() )
207  {
208  temp = temp->GetSym();
209  }
210 
211  QueueMapIterator map_it = m_QueueMapper.find( temp );
212 
213  MeasureType measure = MeasureEdge( temp );
214  if ( map_it != m_QueueMapper.end() )
215  {
216  if( !map_it->second->m_Priority.first )
217  {
218  map_it->second->m_Priority.second = measure;
219  m_PriorityQueue->Update( map_it->second );
220  }
221  }
222  else
223  {
225  PriorityType( false, measure ) );
226  m_QueueMapper[ temp ] = qi;
227  m_PriorityQueue->Push( qi );
228  }
229 }
230 
231 
232 template< class TInput, class TOutput, class TCriterion >
233 void
236 {
238  status = m_JoinVertexFunction->GetEdgeStatus();
239  switch( status )
240  {
241  default:
242  case OperatorType::EDGE_NULL:
243  case OperatorType::MESH_NULL:
244  case OperatorType::FACE_ISOLATED:
245  break;
246  case OperatorType::EDGE_ISOLATED:
247  itkDebugMacro( "EDGE_ISOLATED, at iteration: " <<this->m_Iteration );
248  TagElementOut( m_Element );
249  break;
250  // more than 2 common vertices in 0-ring of org and dest respectively
251  case OperatorType::TOO_MANY_COMMON_VERTICES:
252  itkDebugMacro( "TOO_MANY_COMMON_VERTICES, at iteration "
253  <<this->m_Iteration );
254  itkDebugMacro( <<m_Element->GetOrigin() << " -> "
255  <<m_Element->GetDestination() );
256  this->TagElementOut( m_Element );
257  break;
258  // ******************************************************************
259  // Tetrahedron case
260  case OperatorType::TETRAHEDRON_CONFIG:
261  itkDebugMacro( "TETRAHEDRON_CONFIG, at iteration " << this->m_Iteration );
262 
263  this->TagElementOut( m_Element );
264  this->TagElementOut( m_Element->GetOnext() );
265  this->TagElementOut( m_Element->GetOprev() );
266  this->TagElementOut( m_Element->GetSym() );
267  this->TagElementOut( m_Element->GetSym()->GetOnext() );
268  this->TagElementOut( m_Element->GetSym()->GetOprev() );
269  this->TagElementOut( m_Element->GetOnext()->GetLnext() );
270  break;
271  // ******************************************************************
272  // Samosa case
273  case OperatorType::SAMOSA_CONFIG:
274  itkDebugMacro( "SAMOSA_CONFIG, at iteration " << this->m_Iteration );
275  this->RemoveSamosa();
276  break;
277  // ******************************************************************
278  // Eye case
279  case OperatorType::EYE_CONFIG:
280  itkDebugMacro( "EYE_CONFIG, at iteration " << this->m_Iteration );
281  this->RemoveEye();
282  break;
283  case OperatorType::EDGE_JOINING_DIFFERENT_BORDERS:
284  itkDebugMacro( "EDGE_JOINING_DIFFERENT_BORDERS, at iteration " <<
285 this->m_Iteration );
286  this->TagElementOut( m_Element );
287  break;
288  }
289 }
290 
291 template< class TInput, class TOutput, class TCriterion >
292 void
294 DeletePoint( const OutputPointIdentifier& iIdToBeDeleted,
295  const OutputPointIdentifier& iRemaining )
296 {
297  (void)iRemaining;
298  this->GetOutput()->DeletePoint( iIdToBeDeleted );
299 }
300 
301 template< class TInput, class TOutput, class TCriterion >
302 bool
305 {
306  OutputMeshPointer output = this->GetOutput();
307  OutputPointType pt;
308 
309  OutputPointIdentifier id_org = m_Element->GetOrigin();
310  OutputPointIdentifier id_dest = m_Element->GetDestination();
311  OutputPointIdentifier idx = ( id_org < id_dest ) ? id_org : id_dest;
312 
313  bool to_be_processed( true );
314 
315  if ( m_Relocate )
316  {
317  pt = Relocate( m_Element );
318  }
319  else
320  {
321  pt = output->GetPoint( idx );
322  }
323 
325 // if( m_CheckOrientation )
326 // to_be_processed = CheckOrientation( m_Element, idx, pt );
327 
328  if( !to_be_processed )
329  {
330  return false;
331  }
332 
333  std::list< OutputQEType* > list_qe_to_be_deleted;
334  OutputQEType* temp = m_Element->GetOnext();
335 
336  while( temp != m_Element )
337  {
338  list_qe_to_be_deleted.push_back( temp );
339  temp = temp->GetOnext();
340  }
341 
342  temp = m_Element->GetSym()->GetOnext();
343  while( temp != m_Element->GetSym() )
344  {
345  list_qe_to_be_deleted.push_back( temp );
346  temp = temp->GetOnext();
347  }
348 
349  typename std::list< OutputQEType* >::iterator
350  it = list_qe_to_be_deleted.begin();
351 
352  while( it != list_qe_to_be_deleted.end() )
353  {
354  DeleteElement( *it );
355  ++it;
356  }
357 
358  if ( !m_JoinVertexFunction->Evaluate( m_Element ) )
359  {
360  it = list_qe_to_be_deleted.begin();
361 
362  while( it != list_qe_to_be_deleted.end() )
363  {
364  PushOrUpdateElement( *it );
365  ++it;
366  }
367 
368  JoinVertexFailed();
369  }
370  else
371  {
372  OutputPointIdentifier old_id = m_JoinVertexFunction->GetOldPointID();
373 
374  OutputPointIdentifier new_id = ( old_id == id_dest ) ? id_org : id_dest;
375  DeletePoint( old_id, new_id );
376 
377  OutputQEType* edge = output->FindEdge( new_id );
378  if ( edge == 0 )
379  {
380  itkDebugMacro( "edge == 0, at iteration " <<this->m_Iteration );
381  return false;
382  }
383 
384  if ( m_Relocate )
385  {
386  pt.SetEdge( edge );
387  output->SetPoint( new_id, pt );
388  }
389 
390  temp = edge;
391 
392  do
393  {
394  PushOrUpdateElement( temp );
395  temp = temp->GetOnext();
396  }
397  while ( temp != edge );
398  }
399  return false;
400 }
401 
402 
403 template< class TInput, class TOutput, class TCriterion >
404 unsigned int
407 {
408  OutputQEType* qe = m_Element;
409  OutputQEType* qe_sym = qe->GetSym( );
410 
411  bool LeftIsTriangle = qe->IsLnextOfTriangle( );
412  bool RightIsTriangle = qe->GetSym( )->IsLnextOfTriangle( );
413 
414  if( LeftIsTriangle || RightIsTriangle )
415  {
416  if( LeftIsTriangle && RightIsTriangle )
417  {
418  // two triangles
419  bool OriginOrderIsTwo = ( qe->GetOrder( ) == 2 );
420  bool DestinationOrderIsTwo = ( qe_sym->GetOrder( ) == 2 );
421 
422  if( OriginOrderIsTwo || DestinationOrderIsTwo )
423  {
424  if( OriginOrderIsTwo && DestinationOrderIsTwo )
425  {
426  // isolated component made of two triangles
427  // sharing same points but with opposite orientation
428  // looks like a samosa
429  itkDebugMacro( "RemoveSamosa" );
430  return 1;
431  } // end if( OriginOrderIsTwo && DestinationOrderIsTwo )
432  else
433  {
434  // two triangles share three points and two edges
435  // the last edge is duplicated = two edge cells
436  // having the same points. It is a valid manifold case
437  // but you have to decimate it the right way.
438  // from the top the drawing of that case looks like an Eye
439  itkDebugMacro( "RemoveEye" );
440  return 2;
441  } // end else if( OriginOrderIsTwo && DestinationOrderIsTwo )
442  } // end if( OriginOrderIsTwo || DestinationOrderIsTwo )
443  else // if( OriginOrderIsTwo || DestinationOrderIsTwo )
444  {
445  if( NumberOfCommonVerticesIn0Ring( ) > 2 )
446  {
447  // both points have more than 2 edges on their O-ring
448  itkDebugMacro( "NumberOfCommonVerticesIn0Ring( ) > 2" );
449  return 3;
450  } //end if( NumberOfCommonVerticesIn0Ring( ) > 2 )
451  else
452  {
453  return 0;
454  }
455  } // end else if( OriginOrderIsTwo || DestinationOrderIsTwo )
456  } // end if( LeftIsTriangle && RightIsTriangle )
457  else // if( LeftIsTriangle && RightIsTriangle )
458  {
459  if( NumberOfCommonVerticesIn0Ring( ) > 1 )
460  {
461  itkDebugMacro( "NumberOfCommonVerticesIn0Ring( ) > 1" );
462  return 4;
463  } // end if( NumberOfCommonVerticesIn0Ring( ) > 1 )
464  else // if( NumberOfCommonVerticesIn0Ring( ) > 1 )
465  {
466  if( RightIsTriangle )
467  {
468  return 5;
469  }
470  else
471  {
472  return 6;
473  }
474  } // end else if( NumberOfCommonVerticesIn0Ring( ) > 1 )
475  } // end else if( LeftIsTriangle && RightIsTriangle )
476  } // end if( LeftIsTriangle || RightIsTriangle )
477  else // if( LeftIsTriangle || RightIsTriangle )
478  {
479  if( NumberOfCommonVerticesIn0Ring( ) > 0 )
480  {
481  return 7;
482  }
483  else
484  {
485  return 0;
486  }
487  } // end if( LeftIsTriangle || RightIsTriangle )
488 
489  // return 0;
490 }
491 
492 template< class TInput, class TOutput, class TCriterion >
493 bool
496 {
497  if( m_Priority.first )
498  {
499  return true;
500  }
501 
502  ProcessWithoutAnyTopologicalGuarantee();
503  return false;
504 }
505 
506 template< class TInput, class TOutput, class TCriterion >
507 size_t
510 {
511  OutputQEType* qe = m_Element;
512  OutputQEType* e_it = qe->GetOnext( );
513 
514  std::list< OutputPointIdentifier > dir_list, sym_list, intersection_list;
515  do
516  {
517  dir_list.push_back( e_it->GetDestination() );
518  e_it = e_it->GetOnext();
519  } while( e_it != qe );
520 
521  qe = qe->GetSym();
522  e_it = qe;
523 
524  do
525  {
526  sym_list.push_back( e_it->GetDestination() );
527  e_it = e_it->GetOnext();
528  } while( e_it != qe );
529 
530  dir_list.sort();
531  sym_list.sort();
532 
533  std::set_intersection( dir_list.begin(), dir_list.end(),
534  sym_list.begin(), sym_list.end(),
535  std::back_inserter( intersection_list ) );
536 
537  return intersection_list.size();
538 }
539 
540 
541 template< class TInput, class TOutput, class TCriterion >
542 void
545 {
546  DeleteElement( m_Element->GetLnext( ) );
547  DeleteElement( m_Element->GetLprev( ) );
548  DeleteElement( m_Element->GetRnext( ) );
549  DeleteElement( m_Element->GetRprev( ) );
550 }
551 
552 template< class TInput, class TOutput, class TCriterion >
553 void
556 {
557  QueueMapIterator map_it = m_QueueMapper.find( iEdge );
558 
559  if( map_it != m_QueueMapper.end() )
560  {
561  map_it->second->m_Priority.first = true;
562  map_it->second->m_Priority.second = static_cast< MeasureType >( 0. );
563  m_PriorityQueue->Update( map_it->second );
564  }
565  else
566  {
568  PriorityType( true, static_cast< MeasureType >( 0. ) ) );
569 
570  m_QueueMapper[ iEdge ] = qi;
571  m_PriorityQueue->Push( qi );
572  }
573 }
574 
575 template< class TInput, class TOutput, class TCriterion >
576 void
579 {
580  OutputQEType* qe = m_Element;
581  OutputQEType* qe_sym = m_Element->GetSym( );
582 
583  if( qe->GetSym( )->GetOrder( ) == 2 )
584  {
585  qe = qe_sym;
586  }
587 
588  TagElementOut( qe );
589  TagElementOut( qe->GetOnext( ) );
590  TagElementOut( qe->GetSym( )->GetOnext( ) );
591  TagElementOut( qe->GetSym( )->GetOprev( ) );
592 }
593 
594 template< class TInput, class TOutput, class TCriterion >
595 bool
598 {
599  if( m_PriorityQueue->Empty() )
600  {
601  return true;
602  }
603  else
604  {
605  return this->m_Criterion->is_satisfied( this->GetOutput(), 0, m_Priority.second );
606  }
607 }
608 
609 }
610 #endif

Generated at Sun May 19 2013 00:01:25 for Orfeo Toolbox with doxygen 1.8.3.1