2 #include "ui_ImageMPR.h"
6 // -------------------------------------------------------------------------
7 #define ImageMPR_ConnectAction( ACTION ) \
9 this->m_UI->a##ACTION, SIGNAL( triggered( ) ), \
10 this, SLOT( _a##ACTION( ) ) \
13 // -------------------------------------------------------------------------
15 ImageMPR( QWidget* parent )
16 : QMainWindow( parent ),
17 m_UI( new Ui::ImageMPR ),
18 m_Plugins( new TPlugins )
20 this->m_UI->setupUi( this );
21 this->m_Plugins->SetWidget( this );
24 ImageMPR_ConnectAction( OpenImage );
25 ImageMPR_ConnectAction( OpenDICOMSeries );
26 ImageMPR_ConnectAction( OpenSegmentation );
27 ImageMPR_ConnectAction( OpenPolyData );
28 ImageMPR_ConnectAction( SaveImage );
29 ImageMPR_ConnectAction( SaveSegmentation );
30 ImageMPR_ConnectAction( SavePolyData );
31 ImageMPR_ConnectAction( Undo );
32 ImageMPR_ConnectAction( Redo );
33 ImageMPR_ConnectAction( LoadPlugins );
34 ImageMPR_ConnectAction( ShowPlugins );
36 // Try to load default plugins
38 this->m_Plugins->LoadPlugins("cpPluginsIO.dll");
39 this->m_Plugins->LoadPlugins("cpPluginsBasicFilters.dll");
41 this->m_Plugins->LoadPluginsConfigurationFile("Plugins.cfg");
43 this->m_Plugins->AssociatePluginsToMenu(
44 this->m_UI->MenuFilters, this, SLOT( _execPlugin( ) )
48 // -------------------------------------------------------------------------
53 delete this->m_Plugins;
56 // -------------------------------------------------------------------------
60 // Read and show image, if possible
61 TPlugins::TImage::Pointer image;
62 if( this->m_Plugins->ReadImage( image, true ) )
64 vtkImageData* vimage = image->GetVTK< vtkImageData >( );
67 QMessageBox::critical(
69 QMessageBox::tr( "Error showing image." ),
71 "Image was read, but no valid VTK conversion was found."
78 // Since we are opening an image, clear all
79 this->m_UI->MPR->DeleteAllData( );
80 this->m_Objects.clear( );
83 std::string name = image->GetName( );
84 this->m_Objects[ name ] = TTreeNode( "", image.GetPointer( ) );
85 this->m_UI->MPR->AddImage( vimage, name );
86 this->m_UI->MPR->ShowData( name );
93 // -------------------------------------------------------------------------
97 // Read and show image, if possible
98 TPlugins::TImage::Pointer image;
99 if( this->m_Plugins->ReadDicomSeries( image ) )
101 vtkImageData* vimage = image->GetVTK< vtkImageData >( );
104 QMessageBox::critical(
106 QMessageBox::tr( "Error showing image." ),
108 "Image was read, but no valid VTK conversion was found."
115 // Since we are opening an image, clear all
116 this->m_UI->MPR->DeleteAllData( );
117 this->m_Objects.clear( );
120 std::string name = image->GetName( );
121 this->m_Objects[ name ] = TTreeNode( "", image.GetPointer( ) );
122 this->m_UI->MPR->AddImage( vimage, name );
123 this->m_UI->MPR->ShowData( name );
130 // -------------------------------------------------------------------------
132 _aOpenSegmentation( )
135 if( this->m_ImageLoaded != "" )
136 this->m_ImageLoaded = this->m_UI->MPR->LoadImage( );
140 // -------------------------------------------------------------------------
146 // -------------------------------------------------------------------------
150 std::string data_name = this->m_UI->MPR->GetSelectedData( );
151 TPlugins::TImage* image = dynamic_cast< TPlugins::TImage* >(
152 this->m_Objects[ data_name ].second.GetPointer( )
156 this->m_Plugins->WriteImage( image, true );
159 // -------------------------------------------------------------------------
161 _aSaveSegmentation( )
165 // -------------------------------------------------------------------------
169 std::string data_name = this->m_UI->MPR->GetSelectedData( );
170 TPlugins::TMesh* mesh = dynamic_cast< TPlugins::TMesh* >(
171 this->m_Objects[ data_name ].second.GetPointer( )
175 this->m_Plugins->WriteMesh( mesh, true );
178 // -------------------------------------------------------------------------
184 // -------------------------------------------------------------------------
190 // -------------------------------------------------------------------------
194 this->m_Plugins->DialogLoadPlugins( );
195 this->m_Plugins->AssociatePluginsToMenu(
196 this->m_UI->MenuFilters, this, SLOT( _execPlugin( ) )
200 // -------------------------------------------------------------------------
206 // -------------------------------------------------------------------------
210 // Get filter's name and category
211 QAction* action = dynamic_cast< QAction* >( this->sender( ) );
214 QMenu* menu = dynamic_cast< QMenu* >( action->parentWidget( ) );
217 std::string filter_cate = menu->title( ).toStdString( );
218 std::string filter_name = action->text( ).toStdString( );
221 if( !( this->m_Plugins->CreateFilter( this->m_ActiveFilter, filter_name ) ) )
223 QMessageBox::critical(
225 tr( "Error creating filter" ),
227 std::string( "No valid filter \"" ) +
229 std::string( "\"defined." )
232 this->m_ActiveFilter = NULL;
238 this->m_ActiveFilter->AddInteractor( this->m_UI->MPR->GetInteractor( 0 ) );
239 this->m_ActiveFilter->AddInteractor( this->m_UI->MPR->GetInteractor( 1 ) );
240 this->m_ActiveFilter->AddInteractor( this->m_UI->MPR->GetInteractor( 2 ) );
241 this->m_ActiveFilter->AddInteractor( this->m_UI->MPR->GetInteractor( 3 ) );
243 TPlugins::TProcessObject::DialogResult res =
244 this->m_ActiveFilter->ExecConfigurationDialog( this );
245 if( res == TPlugins::TProcessObject::DialogResult_Cancel )
247 this->m_ActiveFilter = NULL;
253 std::string data_name = this->m_UI->MPR->GetSelectedData( );
254 std::vector< std::string > inputs_names =
255 this->m_ActiveFilter->GetInputsNames( );
256 if( inputs_names.size( ) == 1 )
258 TTree::iterator iIt = this->m_Objects.find( data_name );
259 if( iIt == this->m_Objects.end( ) )
261 QMessageBox::critical(
263 tr( "Error configuring filter" ),
264 tr( "No valid input found. Please select a valid input." )
266 this->m_ActiveFilter = NULL;
270 this->m_ActiveFilter->SetInput( inputs_names[ 0 ], iIt->second.second );
272 else if( inputs_names.size( ) > 1 )
274 QMessageBox::critical(
276 tr( "Error executing" ),
277 tr( "Filter has multiple inputs: NOT YET IMPLEMENTED!!!" )
285 if( res == TPlugins::TProcessObject::DialogResult_NoModal )
288 std::string filter_err = this->m_ActiveFilter->Update( );
290 if( filter_err != "" )
292 QMessageBox::critical(
294 tr( "Error executing" ),
295 tr( filter_err.c_str( ) )
297 this->m_ActiveFilter = NULL;
303 std::vector< std::string > outputs_names = filter->GetOutputsNames( );
305 auto oIt = outputs_names.begin( );
306 oIt != outputs_names.end( );
310 std::string out_name = filter_name + "_" + *oIt;
312 TPlugins::TImage* image =
313 this->m_ActiveFilter->GetOutput< TPlugins::TImage >( *oIt );
316 if( filter_cate == "ImageToBinaryImageFilter" )
318 this->m_UI->MPR->ShowImage(
319 image->GetVTK< vtkImageData >( ),
324 else if( filter_cate == "ImageToImageFilter" )
328 // Keep a track on a local data tree and go to next output
329 this->m_Objects[ out_name ] = TTreeNode( data_name, image );
334 TPlugins::TMesh* mesh = filter->GetOutput< TPlugins::TMesh >( *oIt );
339 this->m_UI->MPR->ShowMesh(
340 mesh->GetVTK< vtkPolyData >( ),
346 // Keep a track on a local data tree and go to next output
347 this->m_Objects[ out_name ] = TTreeNode( data_name, mesh );
354 // No-modal filters just exists for one usage
355 this->m_ActiveFilter = NULL;
361 // -------------------------------------------------------------------------
364 _CursorCommand( double* pos, int axis, void* data )
366 Self* app = reinterpret_cast< Self* >( data );
369 if( !( app->m_Flooding ) )
372 cpPlugins::Interface::ProcessObject::Pointer filter =
373 app->m_UI->MPR->CreateFilter(
374 "cpPlugins::BasicFilters::FloodFillImageFilter"
376 if( filter.IsNull( ) )
379 cpPlugins::Interface::Parameters* params = filter->GetParameters( );
380 params->SetPoint( "Seed", 3, pos );
381 params->SetReal( "Window", app->m_UI->MPR->GetWindow( ) );
382 params->SetReal( "Level", app->m_UI->MPR->GetLevel( ) );
383 params->SetUint( "InsideValue", 1 );
384 params->SetUint( "OutsideValue", 0 );
385 filter->SetInput( "Input", app->m_UI->MPR->GetImage( app->m_ImageLoaded ) );
386 app->m_UI->MPR->Block( );
387 std::string err = filter->Update( );
388 cpPlugins::Interface::BaseMPRWindow::TImage::Pointer image = filter->GetOutput< cpPlugins::Interface::BaseMPRWindow::TImage >( "Output" );
389 filter->DisconnectOutputs( );
390 app->m_UI->MPR->AddImage( "Segmentation", image );
391 app->m_UI->MPR->Unblock( );
394 << "CursorCommand ==> "
399 << data << std::endl;
404 #include "MementoState.h"
406 #include <vtkProperty.h>
407 #include <vtkRenderWindow.h>
408 #include <vtkMetaImageReader.h>
410 #include <QFileDialog>
411 #include <QMessageBox>
414 # define PLUGIN_PREFIX ""
415 # define PLUGIN_EXT "dll"
416 # define PLUGIN_REGEX "Plugins file (*.dll);;All files (*)"
418 # define PLUGIN_PREFIX "lib"
419 # define PLUGIN_EXT "so"
420 # define PLUGIN_REGEX "Plugins file (*.so);;All files (*)"
423 // -------------------------------------------------------------------------
424 ImageMPR::ImageMPR( QWidget* parent )
425 : QMainWindow( parent ),
426 m_UI( new Ui::ImageMPR ),
427 m_ImageReaderClass( "" ),
428 m_ImageWriterClass( "" ),
429 m_MeshReaderClass( "" ),
430 m_MeshWriterClass( "" ),
431 m_MeshCutterClass( "" ),
436 this->m_UI->setupUi( this );
438 // Create and associate renderers
439 this->m_MPRObjects = vtkSmartPointer< TMPRObjects >::New( );
440 this->m_MPRObjects->SetRenderWindows(
441 this->m_UI->m_XPlaneVTK->GetRenderWindow( ),
442 this->m_UI->m_YPlaneVTK->GetRenderWindow( ),
443 this->m_UI->m_ZPlaneVTK->GetRenderWindow( ),
444 this->m_UI->m_3DVTK->GetRenderWindow( )
449 this->m_UI->actionOpenPlugins, SIGNAL( triggered( ) ),
450 this, SLOT( _triggered_actionOpenPlugins( ) )
453 this->m_UI->actionOpenInputImage, SIGNAL( triggered( ) ),
454 this, SLOT( _triggered_actionOpenInputImage( ) )
457 this->m_UI->actionOpenSegmentation, SIGNAL( triggered( ) ),
458 this, SLOT( _triggered_actionOpenSegmentation( ) )
461 this->m_UI->actionOpenInputPolyData, SIGNAL( triggered( ) ),
462 this, SLOT( _triggered_actionOpenInputPolyData( ) )
465 this->m_UI->actionUndo, SIGNAL(triggered()),
466 this, SLOT(_triggered_actionUndo())
469 this->m_UI->actionRedo, SIGNAL(triggered()),
470 this, SLOT(_triggered_actionRedo())
473 // Start: load all disponible plugins
475 std::string( PLUGIN_PREFIX ) +
476 std::string( "cpPluginsIO." ) +
477 std::string( PLUGIN_EXT )
480 std::string( PLUGIN_PREFIX ) +
481 std::string( "cpPluginsBasicFilters." ) +
482 std::string( PLUGIN_EXT )
486 // -------------------------------------------------------------------------
490 // Close all connections
491 this->m_Plugins.UnloadAll( );
497 // -------------------------------------------------------------------------
499 _LoadPlugins( const std::string& filename )
501 QApplication::setOverrideCursor( Qt::WaitCursor );
502 this->setEnabled( false );
504 this->m_ImageReaderClass = "";
505 this->m_ImageWriterClass = "";
506 this->m_MeshReaderClass = "";
507 this->m_MeshWriterClass = "";
508 this->m_MeshCutterClass = "";
509 this->m_UI->MenuImageToImage->clear( );
510 this->m_UI->MenuImageToMesh->clear( );
512 if( !( this->m_Plugins.Load( filename ) ) )
515 typedef TPluginsInterface::TClasses _TClasses;
516 _TClasses::const_iterator cIt = this->m_Plugins.GetClasses( ).begin( );
517 for( ; cIt != this->m_Plugins.GetClasses( ).end( ); ++cIt )
519 TPluginFilter::Pointer o =
520 this->m_Plugins.CreateProcessObject( cIt->first );
521 std::string name = o->GetClassName( );
522 std::string category = o->GetClassCategory( );
523 if( category == "ImageReader" )
524 this->m_ImageReaderClass = name;
525 else if( category == "ImageWriter" )
526 this->m_ImageWriterClass = name;
527 else if( category == "MeshReader" )
528 this->m_MeshReaderClass = name;
529 else if( category == "MeshWriter" )
530 this->m_MeshWriterClass = name;
531 else if( category == "MeshToMeshFilter" )
533 if( name.find_last_of( "Cutter" ) != std::string::npos )
534 this->m_MeshCutterClass = name;
536 else if( category == "ImageToImageFilter" )
539 this->m_UI->MenuImageToImage->addAction( QString( name.c_str( ) ) );
541 action, SIGNAL( triggered( ) ),
542 this, SLOT( _triggered_actionImageToImage( ) )
545 else if( category == "ImageToMeshFilter" )
548 this->m_UI->MenuImageToMesh->addAction( QString( name.c_str( ) ) );
550 action, SIGNAL( triggered( ) ),
551 this, SLOT( _triggered_actionImageToMesh( ) )
557 QApplication::restoreOverrideCursor( );
558 this->setEnabled( true );
563 // -------------------------------------------------------------------------
564 std::string ImageMPR::
565 _LoadImage( TPluginImage::Pointer& image )
567 std::string ret = "";
570 // Get a reader from loaded plugins
571 TPluginFilter::Pointer reader =
572 this->m_Plugins.CreateProcessObject( this->m_ImageReaderClass );
573 if( reader.IsNotNull( ) )
575 if( reader->ExecConfigurationDialog( this ) )
578 QApplication::setOverrideCursor( Qt::WaitCursor );
579 this->setEnabled( false );
581 // Execute and get error message, if any
582 ret = reader->Update( );
584 // Assign fresh image, if any
587 image = reader->GetOutput< TPluginImage >( 0 );
588 reader->DisconnectOutputs( );
592 // Unblock application
593 QApplication::restoreOverrideCursor( );
594 this->setEnabled( true );
599 ret = "No suitable reader object found in loaded plugins.";
604 // -------------------------------------------------------------------------
605 std::string ImageMPR::
606 _ConfigureMeshActors( )
608 if( this->m_Mesh.IsNull( ) )
609 return( "Valid mesh not found." );
611 this->m_Mesh->CreateVTKActor( );
612 vtkActor* vtk_actor = this->m_Mesh->GetVTKActor( );
613 if( vtk_actor != NULL )
615 this->m_MPRObjects->Get3DRenderer( )->AddActor( vtk_actor );
616 this->m_MPRObjects->Render( 4 );
620 TMPRObjects::TMPRActors* mprActors = this->m_MPRObjects->GetMPRActors( );
622 std::string err = "";
623 for( unsigned int i = 0; i < 3; ++i )
625 this->m_Cutters[ i ] = this->m_Plugins.CreateProcessObject( this->m_MeshCutterClass );
626 this->m_Planes[ i ] = TPluginImplicitFunction::New( );
627 this->m_Planes[ i ]->SetFunction( mprActors->GetSliceActors( i )->GetPlaneFunction( ) );
628 this->m_Cutters[ i ]->SetInput( 0, this->m_Mesh );
629 this->m_Cutters[ i ]->SetInput( 1, this->m_Planes[ i ] );
630 std::string lerr = this->m_Cutters[ i ]->Update( );
633 this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->CreateVTKActor( );
634 vtkActor* actor = this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->GetVTKActor( );
635 mprActors->GetSliceActors( i )->AddActor( this->m_Cutters[ i ]->GetVTK< vtkAlgorithm >( ), actor );
637 this->m_MPRObjects->GetXRenderer( )->AddActor( actor );
639 this->m_MPRObjects->GetYRenderer( )->AddActor( actor );
641 this->m_MPRObjects->GetZRenderer( )->AddActor( actor );
647 this->m_MPRObjects->RenderAll( );
651 // -------------------------------------------------------------------------
653 _triggered_actionOpenPlugins( )
655 // Show dialog and check if it was accepted
656 QFileDialog dialog( this );
657 dialog.setFileMode( QFileDialog::ExistingFile );
658 dialog.setDirectory( "." );
659 dialog.setNameFilter( tr( PLUGIN_REGEX ) );
660 dialog.setDefaultSuffix( tr( PLUGIN_EXT ) );
661 if( !( dialog.exec( ) ) )
664 std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( );
665 if( !( _LoadPlugins( fname ) ) )
666 QMessageBox::critical(
668 tr( "Ignoring plugin" ),
673 // -------------------------------------------------------------------------
675 _triggered_actionOpenInputImage( )
678 std::string err = this->_LoadImage( this->m_Image );
681 vtkImageData* vtk_id = this->m_Image->GetVTK< vtkImageData >( );
684 this->m_MPRObjects->SetImage( vtk_id );
685 this->m_MPRObjects->ActivateInteractors( );
686 this->m_MPRObjects->ResetCameras( );
687 this->m_MPRObjects->RenderAll( );
689 MementoState(m_state, this->m_Image);
693 QMessageBox::critical(
695 tr( "Error message" ),
696 tr( "Read image does not have a valid VTK converter." )
700 QMessageBox::critical(
702 tr( "Error reading single image" ),
707 // -------------------------------------------------------------------------
709 _triggered_actionOpenSegmentation( )
711 if( this->m_Image.IsNull( ) )
713 QMessageBox::critical(
715 tr( "Error message" ),
716 tr( "Before reading a segmentation, first load a raw image." )
723 std::string err = this->_LoadImage( this->m_Segmentation );
726 vtkImageData* vtk_id = this->m_Segmentation->GetVTK< vtkImageData >( );
729 this->m_MPRObjects->AddAuxiliaryImage( vtk_id );
730 this->m_MPRObjects->RenderAll( );
733 QMessageBox::critical(
735 tr( "Error message" ),
736 tr( "Read image does not have a valid VTK converter." )
740 QMessageBox::critical(
742 tr( "Error reading single image" ),
747 // -------------------------------------------------------------------------
749 _triggered_actionOpenInputPolyData( )
753 // Get a reader from plugins
754 TPluginFilter::Pointer reader =
755 this->m_Plugins.CreateProcessObject( this->m_MeshReaderClass );
757 if( reader.IsNotNull( ) )
760 if( reader->ExecConfigurationDialog( this ) )
762 // Execute and get error message, if any
763 QApplication::setOverrideCursor( Qt::WaitCursor );
764 this->setEnabled( false );
765 std::string err = reader->Update( );
766 QApplication::restoreOverrideCursor( );
767 this->setEnabled( true );
769 // Assign fresh mesh, if any
772 this->m_Mesh = reader->GetOutput< TPluginMesh >( 0 );
773 reader->DisconnectOutputs( );
774 err = this->_ConfigureMeshActors( );
776 QMessageBox::critical(
778 tr( "Error message" ),
783 QMessageBox::critical(
785 tr( "Error reading mesh" ),
792 QMessageBox::critical(
794 tr( "Error reading single mesh" ),
795 tr( "No suitable mesh reader found in loaded plugins." )
799 // -------------------------------------------------------------------------
801 _triggered_actionImageToImage( )
803 if( this->m_Image.IsNull( ) )
807 QAction* action = dynamic_cast< QAction* >( this->sender( ) );
810 std::string name = action->text( ).toStdString( );
813 TPluginFilter::Pointer filter =
814 this->m_Plugins.CreateProcessObject( name );
815 bool dlg_ok = filter->ExecConfigurationDialog( NULL );
820 QApplication::setOverrideCursor( Qt::WaitCursor );
821 this->setEnabled( false );
822 filter->SetInput( 0, this->m_Image );
823 std::string err = filter->Update( );
824 QApplication::restoreOverrideCursor( );
825 this->setEnabled( true );
830 TPluginImage* result = filter->GetOutput< TPluginImage >( 0 );
831 result->DisconnectPipeline( );
832 this->m_Image = result;
833 if( this->m_Image.IsNotNull( ) )
834 this->m_MPRObjects->SetImage(
835 this->m_Image->GetVTK< vtkImageData >( )
840 MementoState(this->m_state, this->m_Image);
842 if (this->m_state > this->m_max_state)
844 this->m_max_state = this->m_state;
848 QMessageBox::critical(
850 tr( "Error executing filter" ),
855 // -------------------------------------------------------------------------
857 _triggered_actionImageToMesh( )
859 if( this->m_Image.IsNull( ) )
863 QAction* action = dynamic_cast< QAction* >( this->sender( ) );
866 std::string name = action->text( ).toStdString( );
869 TPluginFilter::Pointer filter =
870 this->m_Plugins.CreateProcessObject( name );
871 bool dlg_ok = filter->ExecConfigurationDialog( NULL );
876 QApplication::setOverrideCursor( Qt::WaitCursor );
877 this->setEnabled( false );
878 filter->SetInput( 0, this->m_Image );
879 std::string err = filter->Update( );
880 QApplication::restoreOverrideCursor( );
881 this->setEnabled( true );
886 TPluginMesh* result = filter->GetOutput< TPluginMesh >( 0 );
887 result->DisconnectPipeline( );
888 this->m_Mesh = result;
889 err = this->_ConfigureMeshActors( );
891 QMessageBox::critical(
893 tr( "Error message" ),
898 QMessageBox::critical(
900 tr( "Error executing filter" ),
905 // -------------------------------------------------------------------------
907 _triggered_actionUndo()
909 MementoState memento = MementoState();
914 this->m_MPRObjects->SetImage(
915 memento.getMemento(this->m_state)->GetOutput()
919 QMessageBox::warning(
922 tr("No history to undo")
928 // -------------------------------------------------------------------------
930 _triggered_actionRedo()
932 MementoState memento = MementoState();
933 if (this->m_state + 1 <= m_max_state)
936 this->m_MPRObjects->SetImage(
937 memento.getMemento(this->m_state)->GetOutput()
941 QMessageBox::warning(
944 tr("No history to redo")