X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=appli%2FImageMPR%2FImageMPR.cxx;h=402baff2c1b1c4a074f6da2af00f34b50fe3692b;hb=48363731d62d46ffad8ca257326cc147a92ab681;hp=c4729f65cc2efeeab9d18bdc90521b939147f8c9;hpb=e18f55af541dba9026284beb6f12ef06b12e6f47;p=cpPlugins.git diff --git a/appli/ImageMPR/ImageMPR.cxx b/appli/ImageMPR/ImageMPR.cxx index c4729f6..402baff 100644 --- a/appli/ImageMPR/ImageMPR.cxx +++ b/appli/ImageMPR/ImageMPR.cxx @@ -1,13 +1,12 @@ #include "ImageMPR.h" +#include "MementoState.h" #include "ui_ImageMPR.h" #include #include +#include -#include -#include #include -#include #include #ifdef _WIN32 @@ -26,13 +25,18 @@ ImageMPR::ImageMPR( QWidget* parent ) m_UI( new Ui::ImageMPR ), m_ImageReaderClass( "" ), m_ImageWriterClass( "" ), - m_InputImage( NULL ), - m_ParametersDlg( NULL ) + m_MeshReaderClass( "" ), + m_MeshWriterClass( "" ), + m_MeshCutterClass( "" ), + m_Image( NULL ), + m_state(0), + m_max_state(0) { this->m_UI->setupUi( this ); // Create and associate renderers - this->m_MPR = new TMPR( + this->m_MPRObjects = vtkSmartPointer< TMPRObjects >::New( ); + this->m_MPRObjects->SetRenderWindows( this->m_UI->m_XPlaneVTK->GetRenderWindow( ), this->m_UI->m_YPlaneVTK->GetRenderWindow( ), this->m_UI->m_ZPlaneVTK->GetRenderWindow( ), @@ -48,15 +52,32 @@ ImageMPR::ImageMPR( QWidget* parent ) this->m_UI->actionOpenInputImage, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionOpenInputImage( ) ) ); + QObject::connect( + this->m_UI->actionOpenSegmentation, SIGNAL( triggered( ) ), + this, SLOT( _triggered_actionOpenSegmentation( ) ) + ); QObject::connect( this->m_UI->actionOpenInputPolyData, SIGNAL( triggered( ) ), this, SLOT( _triggered_actionOpenInputPolyData( ) ) ); + QObject::connect( + this->m_UI->actionUndo, SIGNAL(triggered()), + this, SLOT(_triggered_actionUndo()) + ); + QObject::connect( + this->m_UI->actionRedo, SIGNAL(triggered()), + this, SLOT(_triggered_actionRedo()) + ); // Start: load all disponible plugins this->_LoadPlugins( std::string( PLUGIN_PREFIX ) + - std::string( "cpPlugins." ) + + std::string( "cpPluginsIO." ) + + std::string( PLUGIN_EXT ) + ); + this->_LoadPlugins( + std::string( PLUGIN_PREFIX ) + + std::string( "cpPluginsBasicFilters." ) + std::string( PLUGIN_EXT ) ); } @@ -70,34 +91,26 @@ ImageMPR:: // Delete objects delete this->m_UI; - delete this->m_MPR; - if( this->m_ParametersDlg != NULL ) - { - this->m_ParametersDlg->close( ); - delete this->m_ParametersDlg; - - } // fi } // ------------------------------------------------------------------------- bool ImageMPR:: _LoadPlugins( const std::string& filename ) { + QApplication::setOverrideCursor( Qt::WaitCursor ); + this->setEnabled( false ); + this->m_ImageReaderClass = ""; this->m_ImageWriterClass = ""; this->m_MeshReaderClass = ""; this->m_MeshWriterClass = ""; - this->m_ImageToImageFilters.clear( ); - this->m_ImageToMeshFilters.clear( ); + this->m_MeshCutterClass = ""; + this->m_UI->MenuImageToImage->clear( ); + this->m_UI->MenuImageToMesh->clear( ); - this->m_Plugins.UnloadAll( ); if( !( this->m_Plugins.Load( filename ) ) ) - { - this->m_Plugins.UnloadAll( ); return( false ); - } // fi - typedef TPluginsInterface::TClasses _TClasses; _TClasses::const_iterator cIt = this->m_Plugins.GetClasses( ).begin( ); for( ; cIt != this->m_Plugins.GetClasses( ).end( ); ++cIt ) @@ -114,9 +127,13 @@ _LoadPlugins( const std::string& filename ) this->m_MeshReaderClass = name; else if( category == "MeshWriter" ) this->m_MeshWriterClass = name; + else if( category == "MeshToMeshFilter" ) + { + if( name.find_last_of( "Cutter" ) != std::string::npos ) + this->m_MeshCutterClass = name; + } else if( category == "ImageToImageFilter" ) { - this->m_ImageToImageFilters.insert( name ); QAction* action = this->m_UI->MenuImageToImage->addAction( QString( name.c_str( ) ) ); QObject::connect( @@ -126,7 +143,6 @@ _LoadPlugins( const std::string& filename ) } else if( category == "ImageToMeshFilter" ) { - this->m_ImageToMeshFilters.insert( name ); QAction* action = this->m_UI->MenuImageToMesh->addAction( QString( name.c_str( ) ) ); QObject::connect( @@ -137,160 +153,98 @@ _LoadPlugins( const std::string& filename ) } // fi } // rof + QApplication::restoreOverrideCursor( ); + this->setEnabled( true ); + return( true ); } // ------------------------------------------------------------------------- -bool ImageMPR:: -_ParametersDialog( TPluginFilter* filter ) +std::string ImageMPR:: +_LoadImage( TPluginImage::Pointer& image ) { - if( this->m_ParametersDlg != NULL ) - { - this->m_ParametersDlg->close( ); - delete this->m_ParametersDlg; + std::string ret = ""; + image = NULL; - } // fi - this->m_ParametersDlg = new QDialog( NULL ); - this->m_ParametersDlg->setWindowFlags( Qt::FramelessWindowHint ); - this->m_ParametersDlg->setWindowFlags( Qt::WindowTitleHint ); - - QGridLayout* gridLayout = new QGridLayout( this->m_ParametersDlg ); - QVBoxLayout* verticalLayout = new QVBoxLayout( ); - - // Put a title - QLabel* title = new QLabel( this->m_ParametersDlg ); - title->setText( filter->GetClassName( ).c_str( ) ); - verticalLayout->addWidget( title ); - - // Put values - TParameters parameters = filter->GetDefaultParameters( ); - std::vector< std::string > names = parameters.GetParameters( ); - std::vector< std::string >::const_iterator nIt = names.begin( ); - for( ; nIt != names.end( ); ++nIt ) + // Get a reader from loaded plugins + TPluginFilter::Pointer reader = + this->m_Plugins.CreateProcessObject( this->m_ImageReaderClass ); + if( reader.IsNotNull( ) ) { - std::string par_name = *nIt; - TParameters::Type par_type = parameters.GetParameterType( par_name ); - - /* TODO - enum Type - { - String = 0, - Bool, - Int, - Uint, - Real, - Index, - Point, - StringList, - BoolList, - IntList, - UintList, - RealList, - IndexList, - PointList, - NoType - }; - */ - QHBoxLayout* horizontalLayout = new QHBoxLayout( ); - QLabel* label = new QLabel( this->m_ParametersDlg ); - label->setText( QString( par_name.c_str( ) ) ); - horizontalLayout->addWidget( label ); - - QWidget* w_input = NULL; - if( par_type == TParameters::Uint ) - { - QSpinBox* v_uint = - new QSpinBox( this->m_ParametersDlg ); - v_uint->setMinimum( -100 ); - v_uint->setMaximum( std::numeric_limits< int >::max( ) ); - v_uint->setValue( parameters.GetValueAsUint( par_name ) ); - v_uint->setObjectName( QString( par_name.c_str( ) ) ); - w_input = v_uint; - } - else if( par_type == TParameters::Int ) - { - QSpinBox* v_int = - new QSpinBox( this->m_ParametersDlg ); - v_int->setMinimum( -std::numeric_limits< int >::max( ) ); - v_int->setMaximum( std::numeric_limits< int >::max( ) ); - v_int->setValue( parameters.GetValueAsInt( par_name ) ); - v_int->setObjectName( QString( par_name.c_str( ) ) ); - w_input = v_int; - } - else if( par_type == TParameters::Real ) + if( reader->ExecConfigurationDialog( this ) ) { - QDoubleSpinBox* v_double = - new QDoubleSpinBox( this->m_ParametersDlg ); - v_double->setDecimals( 3 ); - v_double->setMinimum( -( std::numeric_limits< double >::max( ) ) ); - v_double->setMaximum( std::numeric_limits< double >::max( ) ); - v_double->setValue( parameters.GetValueAsReal( par_name ) ); - v_double->setObjectName( QString( par_name.c_str( ) ) ); - w_input = v_double; + // Block application + QApplication::setOverrideCursor( Qt::WaitCursor ); + this->setEnabled( false ); - } // fi + // Execute and get error message, if any + ret = reader->Update( ); - if( w_input != NULL ) - { - horizontalLayout->addWidget( w_input ); - verticalLayout->addLayout( horizontalLayout ); + // Assign fresh image, if any + if( ret == "" ) + { + image = reader->GetOutput< TPluginImage >( 0 ); + reader->DisconnectOutputs( ); + + } // fi + + // Unblock application + QApplication::restoreOverrideCursor( ); + this->setEnabled( true ); } // fi + } + else + ret = "No suitable reader object found in loaded plugins."; + + return( ret ); +} - } // rof +// ------------------------------------------------------------------------- +std::string ImageMPR:: +_ConfigureMeshActors( ) +{ + if( this->m_Mesh.IsNull( ) ) + return( "Valid mesh not found." ); - // Add buttons - QDialogButtonBox* bb = new QDialogButtonBox( - QDialogButtonBox::Ok | QDialogButtonBox::Cancel - ); - QObject::connect( - bb, SIGNAL( accepted( ) ), this->m_ParametersDlg, SLOT( accept( ) ) - ); - QObject::connect( - bb, SIGNAL( rejected( ) ), this->m_ParametersDlg, SLOT( reject( ) ) - ); - verticalLayout->addWidget( bb ); - gridLayout->addLayout( verticalLayout, 0, 0, 1, 1 ); + this->m_Mesh->CreateVTKActor( ); + vtkActor* vtk_actor = this->m_Mesh->GetVTKActor( ); + if( vtk_actor != NULL ) + { + this->m_MPRObjects->Get3DRenderer( )->AddActor( vtk_actor ); + this->m_MPRObjects->Render( 4 ); - // Execute - QMetaObject::connectSlotsByName( this->m_ParametersDlg ); - if( !( this->m_ParametersDlg->exec( ) ) ) - return( false ); + } // fi + + TMPRObjects::TMPRActors* mprActors = this->m_MPRObjects->GetMPRActors( ); - // Get values back - nIt = names.begin( ); - for( ; nIt != names.end( ); ++nIt ) + std::string err = ""; + for( unsigned int i = 0; i < 3; ++i ) { - std::string par_name = *nIt; - TParameters::Type par_type = parameters.GetParameterType( par_name ); - if( par_type == TParameters::Uint ) - { - QSpinBox* v_uint = - this->m_ParametersDlg->findChild< QSpinBox* >( par_name.c_str( ) ); - if( v_uint != NULL ) - parameters.SetValueAsUint( par_name, v_uint->value( ) ); - } - else if( par_type == TParameters::Int ) + this->m_Cutters[ i ] = this->m_Plugins.CreateProcessObject( this->m_MeshCutterClass ); + this->m_Planes[ i ] = TPluginImplicitFunction::New( ); + this->m_Planes[ i ]->SetFunction( mprActors->GetSliceActors( i )->GetPlaneFunction( ) ); + this->m_Cutters[ i ]->SetInput( 0, this->m_Mesh ); + this->m_Cutters[ i ]->SetInput( 1, this->m_Planes[ i ] ); + std::string lerr = this->m_Cutters[ i ]->Update( ); + if( lerr == "" ) { - QSpinBox* v_int = - this->m_ParametersDlg->findChild< QSpinBox* >( par_name.c_str( ) ); - if( v_int != NULL ) - parameters.SetValueAsInt( par_name, v_int->value( ) ); - } - else if( par_type == TParameters::Real ) - { - QDoubleSpinBox* v_double = - this->m_ParametersDlg->findChild< QDoubleSpinBox* >( - par_name.c_str( ) - ); - if( v_double != NULL ) - parameters.SetValueAsReal( par_name, v_double->value( ) ); + this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->CreateVTKActor( ); + vtkActor* actor = this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->GetVTKActor( ); + mprActors->GetSliceActors( i )->AddActor( this->m_Cutters[ i ]->GetVTK< vtkAlgorithm >( ), actor ); + if( i == 0 ) + this->m_MPRObjects->GetXRenderer( )->AddActor( actor ); + else if( i == 1 ) + this->m_MPRObjects->GetYRenderer( )->AddActor( actor ); + else if( i == 2 ) + this->m_MPRObjects->GetZRenderer( )->AddActor( actor ); } // fi + err += lerr; } // rof - filter->SetParameters( parameters ); - return( true ); + this->m_MPRObjects->RenderAll( ); + return( err ); } // ------------------------------------------------------------------------- @@ -319,42 +273,67 @@ _triggered_actionOpenPlugins( ) void ImageMPR:: _triggered_actionOpenInputImage( ) { - // Show dialog and check if it was accepted - QFileDialog dialog( this ); - dialog.setFileMode( QFileDialog::ExistingFiles ); - dialog.setDirectory( tr( "." ) ); - dialog.setNameFilter( - tr( "Medical image files (*.mhd *.bin *.dcm *.nrri);;All files (*)" ) - ); - dialog.setDefaultSuffix( tr( "mhd" ) ); - if( !( dialog.exec( ) ) ) - return; - - this->m_InputImage = NULL; + // Read image + std::string err = this->_LoadImage( this->m_Image ); + if( err == "" ) + { + vtkImageData* vtk_id = this->m_Image->GetVTK< vtkImageData >( ); + if( vtk_id != NULL ) + { + this->m_MPRObjects->SetImage( vtk_id ); + this->m_MPRObjects->ActivateInteractors( ); + this->m_MPRObjects->ResetCameras( ); + this->m_MPRObjects->RenderAll( ); - // Get a reader from plugins - TPluginFilter::Pointer reader = - this->m_Plugins.CreateProcessObject( this->m_ImageReaderClass ); + MementoState(m_state, this->m_Image); + this->m_state++; + } + else + QMessageBox::critical( + this, + tr( "Error message" ), + tr( "Read image does not have a valid VTK converter." ) + ); + } + else + QMessageBox::critical( + this, + tr( "Error reading single image" ), + tr( err.c_str( ) ) + ); +} - // Configure reader - TParameters reader_params = reader->GetDefaultParameters( ); - QStringList q_fnames = dialog.selectedFiles( ); - QStringList::const_iterator qIt = q_fnames.begin( ); - for( ; qIt != q_fnames.end( ); ++qIt ) - reader_params.AddValueToStringList( "FileNames", qIt->toStdString( ) ); - reader->SetParameters( reader_params ); +// ------------------------------------------------------------------------- +void ImageMPR:: +_triggered_actionOpenSegmentation( ) +{ + if( this->m_Image.IsNull( ) ) + { + QMessageBox::critical( + this, + tr( "Error message" ), + tr( "Before reading a segmentation, first load a raw image." ) + ); + return; - // Execute and get error message, if any - std::string err = reader->Update( ); + } // fi - // Assign fresh image, if any + // Read image + std::string err = this->_LoadImage( this->m_Segmentation ); if( err == "" ) { - this->m_InputImage = - dynamic_cast< TPluginImage* >( reader->GetOutput( 0 ) ); - reader->DisconnectOutputs( ); - if( this->m_InputImage.IsNotNull( ) ) - this->m_MPR->SetImage( this->m_InputImage->GetVTKImageData( ) ); + vtkImageData* vtk_id = this->m_Segmentation->GetVTK< vtkImageData >( ); + if( vtk_id != NULL ) + { + this->m_MPRObjects->AddAuxiliaryImage( vtk_id ); + this->m_MPRObjects->RenderAll( ); + } + else + QMessageBox::critical( + this, + tr( "Error message" ), + tr( "Read image does not have a valid VTK converter." ) + ); } else QMessageBox::critical( @@ -368,64 +347,59 @@ _triggered_actionOpenInputImage( ) void ImageMPR:: _triggered_actionOpenInputPolyData( ) { - /* - // Show dialog and check if it was accepted - QFileDialog dialog( this ); - dialog.setFileMode( QFileDialog::ExistingFile ); - dialog.setDirectory( "." ); - dialog.setNameFilter( tr( "VTK file (*.vtk);;All files (*)" ) ); - dialog.setDefaultSuffix( tr( "vtk" ) ); - if( !( dialog.exec( ) ) ) - return; - - std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( ); - - this->m_InputMesh = NULL; + this->m_Mesh = NULL; // Get a reader from plugins TPluginFilter::Pointer reader = - this->m_Plugins.CreateProcessObject( - this->m_BaseClasses[ "MeshReader" ] - ); + this->m_Plugins.CreateProcessObject( this->m_MeshReaderClass ); - // Configure plugin - TParameters reader_params = reader->GetDefaultParameters( ); - reader_params.SetValueAsString( "FileName", fname ); - reader->SetParameters( reader_params ); - - // Execute and get error message, if any - std::string err = reader->Update( ); - - // Assign fresh image, if any - if( err == "" ) + if( reader.IsNotNull( ) ) { - this->m_InputMesh = - dynamic_cast< TPluginMesh* >( reader->GetOutput( 0 ) ); - reader->DisconnectOutputs( ); - if( this->m_InputMesh.IsNotNull( ) ) + // Configure reader + if( reader->ExecConfigurationDialog( this ) ) { - this->m_InputMeshMapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); - this->m_InputMeshMapper->SetInputData( this->m_InputMesh->GetVTKPolyData( ) ); - this->m_InputMeshActor = vtkSmartPointer< vtkActor >::New( ); - this->m_InputMeshActor->SetMapper( this->m_InputMeshMapper ); - this->m_MPR->Add3DActor( this->m_InputMeshActor ); + // Execute and get error message, if any + QApplication::setOverrideCursor( Qt::WaitCursor ); + this->setEnabled( false ); + std::string err = reader->Update( ); + QApplication::restoreOverrideCursor( ); + this->setEnabled( true ); + + // Assign fresh mesh, if any + if( err == "" ) + { + this->m_Mesh = reader->GetOutput< TPluginMesh >( 0 ); + reader->DisconnectOutputs( ); + err = this->_ConfigureMeshActors( ); + if( err != "" ) + QMessageBox::critical( + this, + tr( "Error message" ), + tr( err.c_str( ) ) + ); + } + else + QMessageBox::critical( + this, + tr( "Error reading mesh" ), + tr( err.c_str( ) ) + ); } // fi } else QMessageBox::critical( this, - tr( "Error reading polydata" ), - tr( err.c_str( ) ) + tr( "Error reading single mesh" ), + tr( "No suitable mesh reader found in loaded plugins." ) ); - */ } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionImageToImage( ) { - if( this->m_InputImage.IsNull( ) ) + if( this->m_Image.IsNull( ) ) return; // Get filter name @@ -437,27 +411,51 @@ _triggered_actionImageToImage( ) // Configure filter TPluginFilter::Pointer filter = this->m_Plugins.CreateProcessObject( name ); - if( !( this->_ParametersDialog( filter ) ) ) + bool dlg_ok = filter->ExecConfigurationDialog( NULL ); + if( !dlg_ok ) return; // Execute filter - filter->SetInput( 0, this->m_InputImage ); - filter->Update( ); + QApplication::setOverrideCursor( Qt::WaitCursor ); + this->setEnabled( false ); + filter->SetInput( 0, this->m_Image ); + std::string err = filter->Update( ); + QApplication::restoreOverrideCursor( ); + this->setEnabled( true ); // Update image - TPluginImage* result = - dynamic_cast< TPluginImage* >( filter->GetOutput( 0 ) ); - result->DisconnectPipeline( ); - this->m_InputImage = result; - if( this->m_InputImage.IsNotNull( ) ) - this->m_MPR->SetImage( this->m_InputImage->GetVTKImageData( ) ); + if( err == "" ) + { + TPluginImage* result = filter->GetOutput< TPluginImage >( 0 ); + result->DisconnectPipeline( ); + this->m_Image = result; + if( this->m_Image.IsNotNull( ) ) + this->m_MPRObjects->SetImage( + this->m_Image->GetVTK< vtkImageData >( ) + + ); + + + MementoState(this->m_state, this->m_Image); + this->m_state++; + if (this->m_state > this->m_max_state) + { + this->m_max_state = this->m_state; + } + } + else + QMessageBox::critical( + this, + tr( "Error executing filter" ), + tr( err.c_str( ) ) + ); } // ------------------------------------------------------------------------- void ImageMPR:: _triggered_actionImageToMesh( ) { - if( this->m_InputImage.IsNull( ) ) + if( this->m_Image.IsNull( ) ) return; // Get filter name @@ -465,6 +463,88 @@ _triggered_actionImageToMesh( ) if( action == NULL ) return; std::string name = action->text( ).toStdString( ); + + // Configure filter + TPluginFilter::Pointer filter = + this->m_Plugins.CreateProcessObject( name ); + bool dlg_ok = filter->ExecConfigurationDialog( NULL ); + if( !dlg_ok ) + return; + + // Execute filter + QApplication::setOverrideCursor( Qt::WaitCursor ); + this->setEnabled( false ); + filter->SetInput( 0, this->m_Image ); + std::string err = filter->Update( ); + QApplication::restoreOverrideCursor( ); + this->setEnabled( true ); + + // Update image + if( err == "" ) + { + TPluginMesh* result = filter->GetOutput< TPluginMesh >( 0 ); + result->DisconnectPipeline( ); + this->m_Mesh = result; + err = this->_ConfigureMeshActors( ); + if( err != "" ) + QMessageBox::critical( + this, + tr( "Error message" ), + tr( err.c_str( ) ) + ); + } + else + QMessageBox::critical( + this, + tr( "Error executing filter" ), + tr( err.c_str( ) ) + ); +} + +// ------------------------------------------------------------------------- +void ImageMPR:: +_triggered_actionUndo() +{ + MementoState memento = MementoState(); + + if (this->m_state>1) + { + this->m_state--; + this->m_MPRObjects->SetImage( + memento.getMemento(this->m_state)->GetOutput() + ); + } else + { + QMessageBox::warning( + this, + tr("message"), + tr("No history to undo") + ); + } + +} + +// ------------------------------------------------------------------------- +void ImageMPR:: +_triggered_actionRedo() +{ + MementoState memento = MementoState(); + if (this->m_state + 1 <= m_max_state) + { + this->m_state++; + this->m_MPRObjects->SetImage( + memento.getMemento(this->m_state)->GetOutput() + ); + } else + { + QMessageBox::warning( + this, + tr("message"), + tr("No history to redo") + ); + } + } + // eof - $RCSfile$