]> Creatis software - cpMesh.git/commitdiff
Simple flood fill plugin added.
authorLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Tue, 16 Dec 2014 18:11:54 +0000 (19:11 +0100)
committerLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Tue, 16 Dec 2014 18:11:54 +0000 (19:11 +0100)
appli/InteractiveDeformableMeshSegmentation/MainWnd.cxx
appli/InteractiveDeformableMeshSegmentation/MainWnd.h
appli/InteractiveDeformableMeshSegmentation/MainWnd_ExecutePlugins.cxx
appli/InteractiveDeformableMeshSegmentation/MainWnd_LoadPlugins.cxx
lib/cpm/Plugins/SimpleFillRegion.cxx
lib/cpm/Plugins/SimpleFillRegion.h

index f6d38fafec60d25916e5e45c72b3264471bc4f08..8e55c5a2815c320e3a6f69ef3f5f107c5e292049 100644 (file)
@@ -30,7 +30,9 @@ MainWnd::MainWnd( QWidget* parent )
     m_InputImage( NULL ),
     m_SegmentedImage( NULL ),
     m_ActivePlugin( NULL ),
-    m_ActiveParameters( NULL )
+    m_ActiveParameters( NULL ),
+    m_ActivePluginType( Self::NonePluginType ),
+    m_ActivePluginCategory( Self::NonePluginCategory )
 {
   this->m_UI->setupUi( this );
 
@@ -47,6 +49,12 @@ MainWnd::MainWnd( QWidget* parent )
     this->m_UI->m_3DVTK->GetRenderWindow( )
     );
 
+  // Associate observer
+  this->m_DoubleClickCommand =
+    vtkSmartPointer< DoubleClickCommand >::New( );
+  this->m_DoubleClickCommand->SetMainWnd( this );
+  this->m_MPR->AddDoubleClickObserver( this->m_DoubleClickCommand );
+
   // Orientation marks
   /* TODO
      vtkSmartPointer< vtkAnnotatedCubeActor > oCube =
@@ -339,9 +347,9 @@ _triggered_actionOpenSegmentedImage( )
     */
 
     // Ok, start!
-    this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
-    this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
-    this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
+    this->m_MPR->Render( 0 );
+    this->m_MPR->Render( 1 );
+    this->m_MPR->Render( 2 );
     this->_UpdateEnabledFlags( );
 
   } // fi
index 3576ac576b44732f6ccdfc235f6d57e878379f82..45860bb3e171118fd1f5ae1f4987b444f6fe00ce 100644 (file)
@@ -10,6 +10,7 @@
 #include <QWidget>
 
 // vtk stuff
+#include <vtkCommand.h>
 #include <vtkOrientationMarkerWidget.h>
 #include <vtkRenderer.h>
 #include <vtkSmartPointer.h>
 #include <cpPlugins/Interface/DataObject.h>
 #include <cpPlugins/Extensions/Visualization/MPRWithDifferentWindows.h>
 
+// -------------------------------------------------------------------------
+class MainWnd;
+
+class DoubleClickCommand
+  : public vtkCommand
+{
+public:
+  typedef DoubleClickCommand Self;
+
+public:
+  vtkTypeMacro( DoubleClickCommand, vtkCommand );
+
+public:
+  static DoubleClickCommand* New( );
+
+  void SetMainWnd( MainWnd* wnd );
+  void Execute( vtkObject* caller, unsigned long eid, void* data );
+
+protected:
+  DoubleClickCommand( );
+  virtual ~DoubleClickCommand( );
+
+private:
+  // Purposely not implemented
+  DoubleClickCommand( const Self& );
+  Self& operator=( const Self& );
+
+protected:
+  MainWnd* m_MainWnd;
+};
+
 // -------------------------------------------------------------------------
 namespace Ui
 {
@@ -36,17 +68,38 @@ class MainWnd
   Q_OBJECT;
 
 public:
+  friend class DoubleClickCommand;
+
+  typedef MainWnd Self;
+
   // Plugins types
   typedef cpPlugins::Interface::Interface     TPluginsInterface;
   typedef cpPlugins::Interface::Object        TPluginObject;
   typedef cpPlugins::Interface::DataObject    TPluginData;
   typedef cpPlugins::Interface::Image         TPluginImage;
   typedef cpPlugins::Interface::ProcessObject TPlugin;
+  typedef TPlugin::TParameter                 TParameter;
   typedef TPlugin::TParameters                TParameters;
   typedef cpPlugins::Extensions::Visualization::MPRWithDifferentWindows TMPR;
 
   typedef std::map< std::string, std::string > TStringMap;
 
+  enum PluginType
+  {
+    GlobalPluginType = 0,
+    DoubleClickPluginType,
+    SpherePluginType,
+    NonePluginType
+  };
+
+  enum PluginCategory
+  {
+    SegmentationPluginCategory = 0,
+    SegmentationFilteringPluginCategory,
+    MeshProcessingPluginCategory,
+    NonePluginCategory
+  };
+
 public:
   explicit MainWnd( QWidget* parent = 0 );
   virtual ~MainWnd( );
@@ -64,6 +117,10 @@ protected:
   void _UpdateEnabledFlags( );
 
   bool _ParametersDialog( const TParameters& parameters );
+  void _ExecuteDoubleClickPlugin( const double* pnt );
+
+  template< class P >
+  void _JoinSegmentations( );
 
   /* TODO
      template< class I >
@@ -125,6 +182,10 @@ private:
   // Active plugin
   TPlugin* m_ActivePlugin;
   QWidget* m_ActiveParameters;
+  Self::PluginType m_ActivePluginType;
+  Self::PluginCategory m_ActivePluginCategory;
+
+  vtkSmartPointer< DoubleClickCommand > m_DoubleClickCommand;
 };
 
 #endif // __MAINWND__H__
index 8429a818d38ceb7c41dfa1f792359d1e30801dc4..cbbfac64d213a9884fbe31df39da5466529e14b0 100644 (file)
@@ -2,9 +2,16 @@
 #include "ui_MainWnd.h"
 
 #include <cstdlib>
+#include <sstream>
 
 #include <QDoubleSpinBox>
 #include <QLabel>
+#include <QMessageBox>
+
+#include <itkImageRegionIterator.h>
+#include <itkImageRegionConstIterator.h>
+#define ITK_MANUAL_INSTANTIATION
+#include <itkImage.h>
 
 // -------------------------------------------------------------------------
 bool MainWnd::
@@ -52,100 +59,105 @@ _ParametersDialog( const TParameters& parameters )
 
   } // rof
   gridLayout->addLayout( verticalLayout, 0, 0, 1, 1 );
+
+  // Infere plugin type
+  TParameters::const_iterator seedIt = parameters.find( "Seed" );
+  TParameters::const_iterator radiusIt = parameters.find( "Radius" );
+  TParameters::const_iterator endIt = parameters.end( );
+  if( seedIt == endIt && radiusIt == endIt )
+    this->m_ActivePluginType = Self::GlobalPluginType;
+  else if( seedIt != endIt && radiusIt == endIt )
+    this->m_ActivePluginType = Self::DoubleClickPluginType;
+  else if( seedIt != endIt && radiusIt != endIt )
+    this->m_ActivePluginType = Self::SpherePluginType;
+  else
+    this->m_ActivePluginType = Self::NonePluginType;
+
   QMetaObject::connectSlotsByName( this->m_ActiveParameters );
   this->m_ActiveParameters->show( );
 
-  /*
-    typedef std::map< std::string, QWidget* > _TWidgets;
-    _TWidgets widgets;
-    TParameters::const_iterator pIt = parameters.begin( );
-    for( ; pIt != parameters.end( ); ++pIt )
-    {
-    unsigned long pos = pIt->first.find_last_of( ":" );
-    std::string v_name = pIt->first.substr( 0, pos );
-    std::string v_type = pIt->first.substr( pos + 1 );
-    QHBoxLayout* horizontalLayout = new QHBoxLayout( );
-    QLabel* label = new QLabel( this->m_ActiveParameters );
-    label->setText( QString( v_name.c_str( ) ) );
-    horizontalLayout->addWidget( label );
-    if( v_type == "real" )
-    {
-    QDoubleSpinBox* v_double = new QDoubleSpinBox( this->m_ActiveParameters );
-    v_double->setDecimals( 3 );
-    v_double->setMinimum( -( std::numeric_limits< double >::max( ) ) );
-    v_double->setMaximum( std::numeric_limits< double >::max( ) );
-    v_double->setValue( std::atof( pIt->second.c_str( ) ) );
-    horizontalLayout->addWidget( v_double );
-    widgets[ pIt->first ] = v_double;
-    }
-    else if( v_type == "atomic_real" )
-    {
-    if( v_name == "MeshType" )
-    {
-    QLabel* info = new QLabel( this->m_ActiveParameters );
-    if( typeid( TScalar ) == typeid( float ) )
-    info->setText( QString( "float" ) );
-    else if( typeid( TScalar ) == typeid( double ) )
-    info->setText( QString( "double" ) );
-    horizontalLayout->addWidget( info );
-    widgets[ pIt->first ] = info;
-    } // fi
-    } // fi
-    verticalLayout.addLayout( horizontalLayout );
-    } // rof
-    gridLayout.addLayout( &verticalLayout, 0, 0, 1, 1 );
-    // Buttons box
-    QDialogButtonBox buttonBox( this->m_ActiveParameters );
-    buttonBox.setOrientation( Qt::Horizontal );
-    buttonBox.setStandardButtons(
-    QDialogButtonBox::Cancel | QDialogButtonBox::Ok
-    );
-    gridLayout.addWidget( &buttonBox, 1, 0, 1, 1 );
-    QObject::connect(
-    &buttonBox, SIGNAL( accepted( ) ),
-    this->m_ActiveParameters, SLOT( accept( ) )
-    );
-    QObject::connect(
-    &buttonBox, SIGNAL( rejected( ) ),
-    this->m_ActiveParameters, SLOT( reject( ) )
-    );
-    QMetaObject::connectSlotsByName( this->m_ActiveParameters );
-
-    // Execute dialog
-    if( dlg.exec( ) == QDialog::Accepted )
-    {
-    _TWidgets::const_iterator wIt = widgets.begin( );
-    for( ; wIt != widgets.end( ); ++wIt )
-    {
-    unsigned long pos = wIt->first.find_last_of( ":" );
-    std::string v_name = wIt->first.substr( 0, pos );
-    std::string v_type = wIt->first.substr( pos + 1 );
-    std::stringstream sstr;
-    if( v_type == "real" )
-    {
-    QDoubleSpinBox* v_double =
-    dynamic_cast< QDoubleSpinBox* >( wIt->second );
-    if( v_double != NULL )
-    sstr << v_double->value( );
-    }
-    else if( v_type == "atomic_real" )
-    {
-    if( v_name == "MeshType" )
+  return( false );
+}
+
+// -------------------------------------------------------------------------
+void MainWnd::
+_ExecuteDoubleClickPlugin( const double* pnt )
+{
+  if(
+    this->m_InputImage == NULL ||
+    this->m_SegmentedImage == NULL ||
+    this->m_ActivePlugin == NULL ||
+    this->m_ActiveParameters == NULL ||
+    this->m_ActivePluginType != Self::DoubleClickPluginType
+    )
+    return;
+
+  TParameters parameters = this->m_ActivePlugin->GetDefaultParameters( );
+
+  // Variable parameters
+  for(
+    TParameters::iterator pIt = parameters.begin( );
+    pIt != parameters.end( );
+    ++pIt
+    )
+  {
+    if( pIt->first != "Seed" )
     {
-    QLabel* info = dynamic_cast< QLabel* >( wIt->second );
-    if( info != NULL )
-    sstr << info->text( ).toStdString( );
+      if( pIt->second.first == "double" )
+      {
+        QDoubleSpinBox* v_double = this->m_ActiveParameters->
+          findChild< QDoubleSpinBox* >( pIt->first.c_str( ) );
+        if( v_double != NULL )
+          parameters[ pIt->first ] =
+            TParameter( "double", v_double->text( ).toStdString( ) );
+        
+      } // fi
 
     } // fi
 
-    } // fi
-    parameters[ wIt->first ] = sstr.str( );
+  } // rof
 
-    } // rof
-    return( true );
-    }
-  */
-  return( false );
+  // Seed
+  std::stringstream seed_str;
+  seed_str << pnt[ 0 ] << ":" << pnt[ 1 ] << ":" << pnt[ 2 ];
+  parameters[ "Seed" ] = TParameter( "point", seed_str.str( ) );
+
+  // Execute
+  this->m_ActivePlugin->SetParameters( parameters );
+  this->m_ActivePlugin->SetInput( 0, this->m_InputImage );
+  this->m_ActivePlugin->SetInput( 1, this->m_SegmentedImage );
+  std::string err = this->m_ActivePlugin->Update( );
+  if( err != "" )
+  {
+    QMessageBox::critical( this, tr( "Error caugth!" ), tr( err.c_str( ) ) );
+    return;
+
+  } // fi
+
+  // Join results
+  itk::DataObject* s = this->m_SegmentedImage->GetDataObject( );
+  if( dynamic_cast< itk::Image< char, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< char >( );
+  else if( dynamic_cast< itk::Image< short, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< short >( );
+  else if( dynamic_cast< itk::Image< int, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< int >( );
+  else if( dynamic_cast< itk::Image< long, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< long >( );
+  else if( dynamic_cast< itk::Image< unsigned char, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< unsigned char >( );
+  else if( dynamic_cast< itk::Image< unsigned short, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< unsigned short >( );
+  else if( dynamic_cast< itk::Image< unsigned int, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< unsigned int >( );
+  else if( dynamic_cast< itk::Image< unsigned long, 3 >* >( s ) != NULL )
+    this->_JoinSegmentations< unsigned long >( );
+
+  // Update visualization
+  this->m_SegmentedImage->UpdateVTKImageData( );
+  this->m_MPR->Render( 0 );
+  this->m_MPR->Render( 1 );
+  this->m_MPR->Render( 2 );
 }
 
 // -------------------------------------------------------------------------
@@ -174,6 +186,7 @@ _triggered_actionFilterSegmentation( )
         this->m_SegmentationFilterClasses[ filter_name ]
         )
       );
+  this->m_ActivePluginCategory = Self::SegmentationFilteringPluginCategory;
 
   // Show parameters dialog
   this->_ParametersDialog( this->m_ActivePlugin->GetDefaultParameters( ) );
@@ -185,4 +198,82 @@ _triggered_actionProcessMesh( )
 {
 }
 
+// -------------------------------------------------------------------------
+template< class P >
+void MainWnd::
+_JoinSegmentations( )
+{
+  typedef itk::Image< P, 3 > _TImage;
+
+  _TImage* old_segmentation =
+    dynamic_cast< _TImage* >( this->m_SegmentedImage->GetDataObject( ) );
+  _TImage* new_segmentation =
+    dynamic_cast< _TImage* >(
+      dynamic_cast< TPluginImage* >(
+        this->m_ActivePlugin->GetOutput( 0 )
+        )->GetDataObject( )
+      );
+
+  /* TODO: InPlaceOn does not execute correctly on input image
+     typedef itk::AndImageFilter< _TImage, _TImage, _TImage > _TFilter;
+     typename _TFilter::Pointer filter = _TFilter::New( );
+     filter->InPlaceOn( );
+     filter->SetInput( 0, old_segmentation );
+     filter->SetInput( 1, new_segmentation );
+     filter->Update( );
+     //old_segmentation->DisconnectPipeline( );
+
+     std::cout << old_segmentation->GetRequestedRegion( ) << std::endl;
+     std::cout << new_segmentation->GetRequestedRegion( ) << std::endl;
+     std::cout << old_segmentation->GetBufferedRegion( ) << std::endl;
+     std::cout << new_segmentation->GetBufferedRegion( ) << std::endl;
+  */
+  typedef itk::ImageRegionConstIterator< _TImage > _TConstIt;
+  typedef itk::ImageRegionIterator< _TImage > _TIt;
+  _TConstIt nIt( new_segmentation, new_segmentation->GetRequestedRegion( ) );
+  _TIt oIt( old_segmentation, old_segmentation->GetRequestedRegion( ) );
+  nIt.GoToBegin( );
+  oIt.GoToBegin( );
+  for( ; !nIt.IsAtEnd( ); ++nIt, ++oIt )
+    oIt.Set( nIt.Get( ) | oIt.Get( ) );
+}
+
+// -------------------------------------------------------------------------
+DoubleClickCommand* DoubleClickCommand::
+New( )
+{
+  return( new DoubleClickCommand( ) );
+}
+
+// -------------------------------------------------------------------------
+void DoubleClickCommand::
+SetMainWnd( MainWnd* wnd )
+{
+  this->m_MainWnd = wnd;
+}
+
+// -------------------------------------------------------------------------
+void DoubleClickCommand::
+Execute( vtkObject* caller, unsigned long eid, void* data )
+{
+  if( this->m_MainWnd != NULL )
+    this->m_MainWnd->_ExecuteDoubleClickPlugin(
+      reinterpret_cast< const double* >( data )
+      );
+}
+
+// -------------------------------------------------------------------------
+DoubleClickCommand::
+DoubleClickCommand( )
+  : Superclass( ),
+    m_MainWnd( NULL )
+{
+}
+
+// -------------------------------------------------------------------------
+DoubleClickCommand::
+~DoubleClickCommand( )
+{
+}
+
 // eof - $RCSfile$
index 8c01ef8e1b26fa212b6e54787da77202c58489b6..27fbfe2fab30bcaad8ded329f0107fb87856e97b 100644 (file)
@@ -111,126 +111,7 @@ _LoadPlugins( )
     );
 
   // Historic objects
-
-
-
-  /*
-    this->m_ImageReaderClassName = "";
-    this->m_ImageSeriesReaderClassName = "";
-    this->m_ImageWriterClassName = "";
-
-  if( in )
-  {
-    std::string plugin;
-    std::getline( in, plugin );
-    while( !( in.eof( ) ) )
-    {
-    if( this->m_Plugins.Load( plugin ) )
-      {
-        TPluginsInterface::TClassesIterator cIt =
-          this->m_Plugins.GetClasses( ).begin( );
-        TPluginsInterface::TClassesIterator end_cIt =
-          this->m_Plugins.GetClasses( ).end( );
-        for( ; cIt != end_cIt; ++cIt )
-        {
-          std::string c_name = cIt->first;
-          c_name = c_name.substr( c_name.find_last_of( ":" ) + 1 );
-          if( c_name == "ImageReader" )
-          {
-            this->m_ImageReaderClassName = cIt->first;
-          }
-          else if( c_name == "ImageSeriesReader" )
-          {
-            this->m_ImageSeriesReaderClassName = cIt->first;
-          }
-          else if( c_name == "ImageWriter" )
-          {
-            this->m_ImageWriterClassName = cIt->first;
-          }
-          else
-          {
-          } // fi
-          
-        } // rof
-
-           TFilterPlugins::TClassesIterator cIt =
-           this->m_Plugins.BeginClasses( );
-           for( ; cIt != this->m_Plugins.EndClasses( ); ++cIt )
-           {
-           TFilterObject* filter =
-           this->m_Plugins.CreateObject( cIt->first );
-           if( filter == NULL )
-           continue;
-           std::string cat = filter->GetCategory( );
-           std::string catType = cat.substr( cat.find_last_of( ":" ) );
-           if( catType == ":BinaryImageToBinaryImageFilter" )
-           {
-           QAction* action = this->m_UI->menuFilterSegmentedImage->
-           addAction( QString( cIt->first.c_str( ) ) );
-           QObject::connect(
-           action, SIGNAL( triggered( ) ),
-           this, SLOT( triggered_aFilterSegmentedImage( ) )
-           );
-           }
-           else if( catType == ":ImageToMeshFilter" )
-           {
-           QAction* action = this->m_UI->menuExtractMesh->
-           addAction( QString( cIt->first.c_str( ) ) );
-           QObject::connect(
-           action, SIGNAL( triggered( ) ),
-           this, SLOT( triggered_aSegmentedImageToMesh( ) )
-           );
-
-           } // fi
-           delete filter;
-           } // rof
-      }
-      else
-      {
-        QMessageBox::warning(
-          this,
-          tr( "Ignoring plugin" ),
-          tr( plugin.c_str( ) )
-          );
-
-      } // fi
-      std::getline( in, plugin );
-
-    } // elihw
-  }
-  else
-  {
-    QMessageBox::critical(
-      this,
-      tr( "No plugins file loaded!" ),
-      tr( this->m_PluginsConfigurationFile.c_str( ) )
-      );
-
-  } // fi
-  in.close( );
-
-  if( this->m_ImageReaderClassName == "" )
-  {
-    QMessageBox::critical(
-      this,
-      tr( "No ImageReader found in plugins!" ),
-      tr( this->m_PluginsConfigurationFile.c_str( ) )
-      );
-
-  } // fi
-
-  if( this->m_ImageWriterClassName == "" )
-  {
-    QMessageBox::critical(
-      this,
-      tr( "No ImageWriter found in plugins!" ),
-      tr( this->m_PluginsConfigurationFile.c_str( ) )
-      );
-
-  } // fi
-  this->_UpdateEnabledFlags( );
-  */
-       }
+}
 
 // -------------------------------------------------------------------------
 bool MainWnd::
index 167c9e040e5d2e1dab0b07464a27af7a88df0b87..5dd4911ec2216f930a3210226165afe98eb352c0 100644 (file)
@@ -1,4 +1,29 @@
 #include <cpm/Plugins/SimpleFillRegion.h>
+#include <cpPlugins/Interface/Image.h>
+
+#include <itkBinaryThresholdImageFunction.h>
+#include <itkFloodFilledImageFunctionConditionalConstIterator.h>
+
+#define ITK_MANUAL_INSTANTIATION
+#include <itkImage.h>
+
+// -------------------------------------------------------------------------
+#define cpmPlugins_SimpleFillRegion_Dimension( r, d, i1, i2, f )     \
+  if(                                                                \
+    dynamic_cast< itk::ImageBase< d >* >( i1 ) != NULL &&            \
+    dynamic_cast< itk::ImageBase< d >* >( i2 ) != NULL               \
+    )                                                                \
+    r = this->f< d >( )
+
+// -------------------------------------------------------------------------
+#define cpmPlugins_SimpleFillRegion_Pixel1( r, p, d, i, f )          \
+  if( dynamic_cast< itk::Image< p, d >* >( i ) != NULL )             \
+    r = this->f< p, d >( )
+
+// -------------------------------------------------------------------------
+#define cpmPlugins_SimpleFillRegion_Pixel2( r, p1, p2, d, i, f )     \
+  if( dynamic_cast< itk::Image< p2, d >* >( i ) != NULL )            \
+    r = this->f< p1, p2, d >( )
 
 // -------------------------------------------------------------------------
 cpm::Plugins::SimpleFillRegion::
@@ -6,6 +31,8 @@ SimpleFillRegion( )
   : Superclass( )
 {
   this->SetNumberOfInputs( 2 );
+  this->SetNumberOfOutputs( 1 );
+  this->_MakeOutput< cpPlugins::Interface::Image >( 0 );
 
   this->m_DefaultParameters[ "MinDelta" ] = TParameter( "double", "0" );
   this->m_DefaultParameters[ "MaxDelta" ] = TParameter( "double", "0" );
@@ -29,7 +56,211 @@ GetClassName( ) const
 std::string cpm::Plugins::SimpleFillRegion::
 _GenerateData( )
 {
-  std::cout << "Simple fill region" << std::endl;
+  itk::DataObject* i1 = this->_GetInput( 0 );
+  itk::DataObject* i2 = this->_GetInput( 1 );
+
+  std::string r =
+    "cpm::Plugins::SimpleFillRegion: itk::Image(s) dimensions not supported";
+  cpmPlugins_SimpleFillRegion_Dimension( r, 2, i1, i2, _GD0 );
+  else cpmPlugins_SimpleFillRegion_Dimension( r, 3, i1, i2, _GD0 );
+  return( r );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int D >
+std::string cpm::Plugins::SimpleFillRegion::
+_GD0( )
+{
+  typedef itk::ImageBase< D > _TImage;
+
+  _TImage* i1 = dynamic_cast< _TImage* >( this->_GetInput( 0 ) );
+
+  std::string r =
+    "cpm::Plugins::SimpleFillRegion: first image's pixel type not supported";
+  cpmPlugins_SimpleFillRegion_Pixel1( r, char, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, short, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, int, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, long, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned char, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned short, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned int, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned long, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, float, D, i1, _GD1 );
+  else cpmPlugins_SimpleFillRegion_Pixel1( r, double, D, i1, _GD1 );
+  return( r );
+}
+
+// -------------------------------------------------------------------------
+template< class P1, unsigned int D >
+std::string cpm::Plugins::SimpleFillRegion::
+_GD1( )
+{
+  typedef itk::ImageBase< D > _TImage;
+
+  _TImage* i2 = dynamic_cast< _TImage* >( this->_GetInput( 1 ) );
+
+  std::string r =
+    "cpm::Plugins::SimpleFillRegion: second image's pixel type not supported";
+  cpmPlugins_SimpleFillRegion_Pixel2( r, P1, char, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, short, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, int, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, long, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned char, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned short, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned int, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned long, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, float, D, i2, _GD2 );
+  else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, double, D, i2, _GD2 );
+  return( r );
+}
+
+// -------------------------------------------------------------------------
+template< typename I1, class I2, typename TCoordRep >
+class SimpleFillRegionFunction
+  : public itk::BinaryThresholdImageFunction< I1, TCoordRep >
+{
+public:
+  typedef SimpleFillRegionFunction                 Self;
+  typedef itk::BinaryThresholdImageFunction< I1, TCoordRep > Superclass;
+  typedef itk::SmartPointer< Self >                          Pointer;
+  typedef itk::SmartPointer< const Self >                    ConstPointer;
+
+  itkTypeMacro( SimpleFillRegionFunction, itkBinaryThresholdImageFunction );
+  itkNewMacro( Self );
+
+  itkSetConstObjectMacro( InputSegmentation, I2 );
+
+  typedef typename Superclass::InputImageType InputImageType;
+  typedef typename I1::PixelType PixelType;
+  itkStaticConstMacro(ImageDimension, unsigned int, Superclass::ImageDimension);
+  typedef typename Superclass::PointType PointType;
+  typedef typename Superclass::IndexType IndexType;
+  typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
+
+  virtual bool EvaluateAtIndex( const IndexType& index ) const
+    {
+      bool cont = true;
+      if( this->m_InputSegmentation.IsNotNull( ) )
+        cont = (
+          this->m_InputSegmentation->GetPixel( index ) ==
+          ( typename I2::PixelType )( 0 )
+          );
+      if( cont )
+        return( this->Superclass::EvaluateAtIndex( index ) );
+      else
+        return( false );
+    }
+
+protected:
+  SimpleFillRegionFunction( )
+    : Superclass( )
+    {
+    }
+  virtual ~SimpleFillRegionFunction( )
+    {
+    }
+
+private:
+  // Purposely not implemented
+  SimpleFillRegionFunction( const Self& );
+  Self& operator=( const Self& );
+
+protected:
+  typename I2::ConstPointer m_InputSegmentation;
+};
+
+// -------------------------------------------------------------------------
+template< class P1, class P2, unsigned int D >
+std::string cpm::Plugins::SimpleFillRegion::
+_GD2( )
+{
+  typedef itk::Image< P1, D > _TImage1;
+  typedef itk::Image< P2, D > _TImage2;
+
+  _TImage1* i1 = dynamic_cast< _TImage1* >( this->_GetInput( 0 ) );
+  _TImage2* i2 = dynamic_cast< _TImage2* >( this->_GetInput( 1 ) );
+
+  // Transform input seed
+  typename _TImage1::PointType pnt;
+  TParameters::const_iterator sIt;
+  sIt = this->m_Parameters.find( "Seed" );
+  if( sIt == this->m_Parameters.end( ) )
+    return( "cpm::Plugins::SimpleFillRegion: no seed given." );
+  char* buff = new char[ sIt->second.second.size( ) + 1 ];
+  std::memcpy( buff, sIt->second.second.c_str( ), sIt->second.second.size( ) );
+  buff[ sIt->second.second.size( ) ] = '\0';
+  char* tok = std::strtok( buff, ":" );
+  for( unsigned int d = 0; d < D; ++d )
+  {
+    pnt[ d ] = std::atof( tok );
+    tok = std::strtok( NULL, ":" );
+
+  } // rof
+  delete [] buff;
+  typename _TImage1::IndexType idx;
+  if( !( i1->TransformPhysicalPointToIndex( pnt, idx ) ) )
+    return( "cpm::Plugins::SimpleFillRegion: seed is outside image regions." );
+
+  // Check spatial compatilibity
+  if( i1->GetLargestPossibleRegion( ) != i2->GetLargestPossibleRegion( ) )
+    return( "cpm::Plugins::SimpleFillRegion: incompatible regions." );
+  if( i1->GetSpacing( ) != i2->GetSpacing( ) )
+    return( "cpm::Plugins::SimpleFillRegion: incompatible spacings." );
+  if( i1->GetOrigin( ) != i2->GetOrigin( ) )
+    return( "cpm::Plugins::SimpleFillRegion: incompatible origins." );
+  if( i1->GetDirection( ) != i2->GetDirection( ) )
+    return( "cpm::Plugins::SimpleFillRegion: incompatible directions." );
+
+  // Create output
+  cpPlugins::Interface::Image* out_obj =
+    dynamic_cast< cpPlugins::Interface::Image* >( this->GetOutput( 0 ) );
+  typename _TImage2::Pointer out =
+    dynamic_cast< _TImage2* >( out_obj->GetDataObject( ) );
+  if( out.IsNull( ) )
+  {
+    out = _TImage2::New( );
+    this->_SetOutput( 0, out );
+
+  } // fi
+
+  // Create memory, if needed
+  if(
+    i1->GetLargestPossibleRegion( ) != out->GetLargestPossibleRegion( ) ||
+    i1->GetSpacing( ) != out->GetSpacing( ) ||
+    i1->GetOrigin( ) != out->GetOrigin( ) ||
+    i1->GetDirection( ) != out->GetDirection( )
+    )
+  {
+    out->SetLargestPossibleRegion( i1->GetLargestPossibleRegion( ) );
+    out->SetRequestedRegion( i1->GetRequestedRegion( ) );
+    out->SetBufferedRegion( i1->GetBufferedRegion( ) );
+    out->SetDirection( i1->GetDirection( ) );
+    out->SetOrigin( i1->GetOrigin( ) );
+    out->SetSpacing( i1->GetSpacing( ) );
+    out->Allocate( );
+
+  } // fi
+  out->FillBuffer( P2( 0 ) );
+
+  P1 min_delta = P1( std::atof( this->m_Parameters[ "MinDelta" ].second.c_str( ) ) );
+  P1 max_delta = P1( std::atof( this->m_Parameters[ "MaxDelta" ].second.c_str( ) ) );
+  P1 lower = i1->GetPixel( idx ) - min_delta;
+  P1 upper = i1->GetPixel( idx ) + min_delta;
+
+  typedef SimpleFillRegionFunction< _TImage1, _TImage2, double > _TFunction;
+  typename _TFunction::Pointer f = _TFunction::New( );
+  f->SetInputImage( i1 );
+  f->SetInputSegmentation( i2 );
+  f->ThresholdBetween( lower, upper );
+
+  typedef
+    itk::FloodFilledImageFunctionConditionalConstIterator< _TImage1, _TFunction >
+    _TIterator;
+  _TIterator fIt( i1, f, idx );
+  for( fIt.GoToBegin( ); !fIt.IsAtEnd( ); ++fIt )
+    out->SetPixel( fIt.GetIndex( ), 1 );
+
+  return( "" );
 }
 
 // eof - $RCSfile$
index 1e84ef61ba37e219e9bb27ebdaf870782f6356f7..4b5cb9c385e66b35e61f91d3df5a5d5b3932c544 100644 (file)
@@ -28,6 +28,15 @@ namespace cpm
     protected:
       virtual std::string _GenerateData( );
 
+      template< unsigned int D >
+      std::string _GD0( );
+
+      template< class P1, unsigned int D >
+      std::string _GD1( );
+
+      template< class P1, class P2, unsigned int D >
+      std::string _GD2( );
+
     protected:
       itk::ProcessObject::Pointer m_Filter;
     };