]> Creatis software - cpPlugins.git/blob - appli/ImageMPR/ImageMPR.cxx
402baff2c1b1c4a074f6da2af00f34b50fe3692b
[cpPlugins.git] / appli / ImageMPR / ImageMPR.cxx
1 #include "ImageMPR.h"
2 #include "MementoState.h"
3 #include "ui_ImageMPR.h"
4
5 #include <vtkProperty.h>
6 #include <vtkRenderWindow.h>
7 #include <vtkMetaImageReader.h>
8
9 #include <QFileDialog>
10 #include <QMessageBox>
11
12 #ifdef _WIN32
13 #  define PLUGIN_PREFIX ""
14 #  define PLUGIN_EXT "dll"
15 #  define PLUGIN_REGEX "Plugins file (*.dll);;All files (*)"
16 #else
17 #  define PLUGIN_PREFIX "lib"
18 #  define PLUGIN_EXT "so"
19 #  define PLUGIN_REGEX "Plugins file (*.so);;All files (*)"
20 #endif // _WIN32
21
22 // -------------------------------------------------------------------------
23 ImageMPR::ImageMPR( QWidget* parent )
24   : QMainWindow( parent ),
25     m_UI( new Ui::ImageMPR ),
26     m_ImageReaderClass( "" ),
27     m_ImageWriterClass( "" ),
28     m_MeshReaderClass( "" ),
29     m_MeshWriterClass( "" ),
30     m_MeshCutterClass( "" ),
31     m_Image( NULL ),
32         m_state(0),
33         m_max_state(0)
34 {
35   this->m_UI->setupUi( this );
36
37   // Create and associate renderers
38   this->m_MPRObjects = vtkSmartPointer< TMPRObjects >::New( );
39   this->m_MPRObjects->SetRenderWindows(
40     this->m_UI->m_XPlaneVTK->GetRenderWindow( ),
41     this->m_UI->m_YPlaneVTK->GetRenderWindow( ),
42     this->m_UI->m_ZPlaneVTK->GetRenderWindow( ),
43     this->m_UI->m_3DVTK->GetRenderWindow( )
44     );
45
46   // signals <-> slots
47   QObject::connect(
48     this->m_UI->actionOpenPlugins, SIGNAL( triggered( ) ),
49     this, SLOT( _triggered_actionOpenPlugins( ) )
50     );
51   QObject::connect(
52     this->m_UI->actionOpenInputImage, SIGNAL( triggered( ) ),
53     this, SLOT( _triggered_actionOpenInputImage( ) )
54     );
55   QObject::connect(
56     this->m_UI->actionOpenSegmentation, SIGNAL( triggered( ) ),
57     this, SLOT( _triggered_actionOpenSegmentation( ) )
58     );
59   QObject::connect(
60     this->m_UI->actionOpenInputPolyData, SIGNAL( triggered( ) ),
61     this, SLOT( _triggered_actionOpenInputPolyData( ) )
62     );
63   QObject::connect(
64         this->m_UI->actionUndo, SIGNAL(triggered()),
65         this, SLOT(_triggered_actionUndo())
66         );
67   QObject::connect(
68         this->m_UI->actionRedo, SIGNAL(triggered()),
69         this, SLOT(_triggered_actionRedo())
70         );
71
72   // Start: load all disponible plugins
73   this->_LoadPlugins(
74     std::string( PLUGIN_PREFIX ) +
75     std::string( "cpPluginsIO." ) +
76     std::string( PLUGIN_EXT )
77     );
78   this->_LoadPlugins(
79     std::string( PLUGIN_PREFIX ) +
80     std::string( "cpPluginsBasicFilters." ) +
81     std::string( PLUGIN_EXT )
82     );
83 }
84
85 // -------------------------------------------------------------------------
86 ImageMPR::
87 ~ImageMPR( )
88 {
89   // Close all connections
90   this->m_Plugins.UnloadAll( );
91
92   // Delete objects
93   delete this->m_UI;
94 }
95
96 // -------------------------------------------------------------------------
97 bool ImageMPR::
98 _LoadPlugins( const std::string& filename )
99 {
100   QApplication::setOverrideCursor( Qt::WaitCursor );
101   this->setEnabled( false );
102
103   this->m_ImageReaderClass = "";
104   this->m_ImageWriterClass = "";
105   this->m_MeshReaderClass = "";
106   this->m_MeshWriterClass = "";
107   this->m_MeshCutterClass = "";
108   this->m_UI->MenuImageToImage->clear( );
109   this->m_UI->MenuImageToMesh->clear( );
110
111   if( !( this->m_Plugins.Load( filename ) ) )
112     return( false );
113
114   typedef TPluginsInterface::TClasses _TClasses;
115   _TClasses::const_iterator cIt = this->m_Plugins.GetClasses( ).begin( );
116   for( ; cIt != this->m_Plugins.GetClasses( ).end( ); ++cIt )
117   {
118     TPluginFilter::Pointer o =
119       this->m_Plugins.CreateProcessObject( cIt->first );
120     std::string name = o->GetClassName( );
121     std::string category = o->GetClassCategory( );
122     if( category == "ImageReader" )
123       this->m_ImageReaderClass = name;
124     else if( category == "ImageWriter" )
125       this->m_ImageWriterClass = name;
126     else if( category == "MeshReader" )
127       this->m_MeshReaderClass = name;
128     else if( category == "MeshWriter" )
129       this->m_MeshWriterClass = name;
130     else if( category == "MeshToMeshFilter" )
131     {
132       if( name.find_last_of( "Cutter" ) != std::string::npos )
133         this->m_MeshCutterClass = name;
134     }
135     else if( category == "ImageToImageFilter" )
136     {
137       QAction* action =
138         this->m_UI->MenuImageToImage->addAction( QString( name.c_str( ) ) );
139       QObject::connect(
140         action, SIGNAL( triggered( ) ),
141         this, SLOT( _triggered_actionImageToImage( ) )
142         );
143     }
144     else if( category == "ImageToMeshFilter" )
145     {
146       QAction* action =
147         this->m_UI->MenuImageToMesh->addAction( QString( name.c_str( ) ) );
148       QObject::connect(
149         action, SIGNAL( triggered( ) ),
150         this, SLOT( _triggered_actionImageToMesh( ) )
151         );
152
153     } // fi
154
155   } // rof
156   QApplication::restoreOverrideCursor( );
157   this->setEnabled( true );
158
159   return( true );
160 }
161
162 // -------------------------------------------------------------------------
163 std::string ImageMPR::
164 _LoadImage( TPluginImage::Pointer& image )
165 {
166   std::string ret = "";
167   image = NULL;
168
169   // Get a reader from loaded plugins
170   TPluginFilter::Pointer reader =
171     this->m_Plugins.CreateProcessObject( this->m_ImageReaderClass );
172   if( reader.IsNotNull( ) )
173   {
174     if( reader->ExecConfigurationDialog( this ) )
175     {
176       // Block application
177       QApplication::setOverrideCursor( Qt::WaitCursor );
178       this->setEnabled( false );
179
180       // Execute and get error message, if any
181       ret = reader->Update( );
182
183       // Assign fresh image, if any
184       if( ret == "" )
185       {
186         image = reader->GetOutput< TPluginImage >( 0 );
187         reader->DisconnectOutputs( );
188
189       } // fi
190
191       // Unblock application
192       QApplication::restoreOverrideCursor( );
193       this->setEnabled( true );
194
195     } // fi
196   }
197   else
198     ret = "No suitable reader object found in loaded plugins.";
199   
200   return( ret );
201 }
202
203 // -------------------------------------------------------------------------
204 std::string ImageMPR::
205 _ConfigureMeshActors( )
206 {
207   if( this->m_Mesh.IsNull( ) )
208     return( "Valid mesh not found." );
209
210   this->m_Mesh->CreateVTKActor( );
211   vtkActor* vtk_actor = this->m_Mesh->GetVTKActor( );
212   if( vtk_actor != NULL )
213   {
214     this->m_MPRObjects->Get3DRenderer( )->AddActor( vtk_actor );
215     this->m_MPRObjects->Render( 4 );
216
217   } // fi
218
219   TMPRObjects::TMPRActors* mprActors = this->m_MPRObjects->GetMPRActors( );
220
221   std::string err = "";
222   for( unsigned int i = 0; i < 3; ++i )
223   {
224     this->m_Cutters[ i ] = this->m_Plugins.CreateProcessObject( this->m_MeshCutterClass );
225     this->m_Planes[ i ] = TPluginImplicitFunction::New( );
226     this->m_Planes[ i ]->SetFunction( mprActors->GetSliceActors( i )->GetPlaneFunction( ) );
227     this->m_Cutters[ i ]->SetInput( 0, this->m_Mesh );
228     this->m_Cutters[ i ]->SetInput( 1, this->m_Planes[ i ] );
229     std::string lerr = this->m_Cutters[ i ]->Update( );
230     if( lerr == "" )
231     {
232       this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->CreateVTKActor( );
233       vtkActor* actor = this->m_Cutters[ i ]->GetOutput< TPluginMesh >( 0 )->GetVTKActor( );
234       mprActors->GetSliceActors( i )->AddActor( this->m_Cutters[ i ]->GetVTK< vtkAlgorithm >( ), actor );
235       if( i == 0 )
236         this->m_MPRObjects->GetXRenderer( )->AddActor( actor );
237       else if( i == 1 )
238         this->m_MPRObjects->GetYRenderer( )->AddActor( actor );
239       else if( i == 2 )
240         this->m_MPRObjects->GetZRenderer( )->AddActor( actor );
241
242     } // fi
243     err += lerr;
244
245   } // rof
246   this->m_MPRObjects->RenderAll( );
247   return( err );
248 }
249
250 // -------------------------------------------------------------------------
251 void ImageMPR::
252 _triggered_actionOpenPlugins( )
253 {
254   // Show dialog and check if it was accepted
255   QFileDialog dialog( this );
256   dialog.setFileMode( QFileDialog::ExistingFile );
257   dialog.setDirectory( "." );
258   dialog.setNameFilter( tr( PLUGIN_REGEX ) );
259   dialog.setDefaultSuffix( tr( PLUGIN_EXT ) );
260   if( !( dialog.exec( ) ) )
261     return;
262   
263   std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( );
264   if( !( _LoadPlugins( fname ) ) )
265     QMessageBox::critical(
266       this,
267       tr( "Ignoring plugin" ),
268       tr( fname.c_str( ) )
269       );
270 }
271
272 // -------------------------------------------------------------------------
273 void ImageMPR::
274 _triggered_actionOpenInputImage( )
275 {
276   // Read image
277   std::string err = this->_LoadImage( this->m_Image );
278   if( err == "" )
279   {
280     vtkImageData* vtk_id = this->m_Image->GetVTK< vtkImageData >( );
281     if( vtk_id != NULL )
282     {
283       this->m_MPRObjects->SetImage( vtk_id );
284       this->m_MPRObjects->ActivateInteractors( );
285       this->m_MPRObjects->ResetCameras( );
286       this->m_MPRObjects->RenderAll( );
287
288           MementoState(m_state, this->m_Image);  
289           this->m_state++;
290     }
291     else
292       QMessageBox::critical(
293         this,
294         tr( "Error message" ),
295         tr( "Read image does not have a valid VTK converter." )
296         );
297   }
298   else
299     QMessageBox::critical(
300       this,
301       tr( "Error reading single image" ),
302       tr( err.c_str( ) )
303       );
304 }
305
306 // -------------------------------------------------------------------------
307 void ImageMPR::
308 _triggered_actionOpenSegmentation( )
309 {
310   if( this->m_Image.IsNull( ) )
311   {
312     QMessageBox::critical(
313       this,
314       tr( "Error message" ),
315       tr( "Before reading a segmentation, first load a raw image." )
316       );
317     return;
318
319   } // fi
320
321   // Read image
322   std::string err = this->_LoadImage( this->m_Segmentation );
323   if( err == "" )
324   {
325     vtkImageData* vtk_id = this->m_Segmentation->GetVTK< vtkImageData >( );
326     if( vtk_id != NULL )
327     {
328       this->m_MPRObjects->AddAuxiliaryImage( vtk_id );
329       this->m_MPRObjects->RenderAll( );
330     }
331     else
332       QMessageBox::critical(
333         this,
334         tr( "Error message" ),
335         tr( "Read image does not have a valid VTK converter." )
336         );
337   }
338   else
339     QMessageBox::critical(
340       this,
341       tr( "Error reading single image" ),
342       tr( err.c_str( ) )
343       );
344 }
345
346 // -------------------------------------------------------------------------
347 void ImageMPR::
348 _triggered_actionOpenInputPolyData( )
349 {
350   this->m_Mesh = NULL;
351
352   // Get a reader from plugins
353   TPluginFilter::Pointer reader =
354     this->m_Plugins.CreateProcessObject( this->m_MeshReaderClass );
355
356   if( reader.IsNotNull( ) )
357   {
358     // Configure reader
359     if( reader->ExecConfigurationDialog( this ) )
360     {
361       // Execute and get error message, if any
362       QApplication::setOverrideCursor( Qt::WaitCursor );
363       this->setEnabled( false );
364       std::string err = reader->Update( );
365       QApplication::restoreOverrideCursor( );
366       this->setEnabled( true );
367
368       // Assign fresh mesh, if any
369       if( err == "" )
370       {
371         this->m_Mesh = reader->GetOutput< TPluginMesh >( 0 );
372         reader->DisconnectOutputs( );
373         err = this->_ConfigureMeshActors( );
374         if( err != "" )
375           QMessageBox::critical(
376             this,
377             tr( "Error message" ),
378             tr( err.c_str( ) )
379             );
380       }
381       else
382         QMessageBox::critical(
383           this,
384           tr( "Error reading mesh" ),
385           tr( err.c_str( ) )
386           );
387
388     } // fi
389   }
390   else
391     QMessageBox::critical(
392       this,
393       tr( "Error reading single mesh" ),
394       tr( "No suitable mesh reader found in loaded plugins." )
395       );
396 }
397
398 // -------------------------------------------------------------------------
399 void ImageMPR::
400 _triggered_actionImageToImage( )
401 {
402   if( this->m_Image.IsNull( ) )
403     return;
404
405   // Get filter name
406   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
407   if( action == NULL )
408     return;
409   std::string name = action->text( ).toStdString( );
410
411   // Configure filter
412   TPluginFilter::Pointer filter =
413     this->m_Plugins.CreateProcessObject( name );
414   bool dlg_ok = filter->ExecConfigurationDialog( NULL );
415   if( !dlg_ok )
416     return;
417
418   // Execute filter
419   QApplication::setOverrideCursor( Qt::WaitCursor );
420   this->setEnabled( false );
421   filter->SetInput( 0, this->m_Image );
422   std::string err = filter->Update( );
423   QApplication::restoreOverrideCursor( );
424   this->setEnabled( true );
425
426   // Update image
427   if( err == "" )
428   {
429     TPluginImage* result = filter->GetOutput< TPluginImage >( 0 );
430     result->DisconnectPipeline( );
431     this->m_Image = result;
432     if( this->m_Image.IsNotNull( ) )
433       this->m_MPRObjects->SetImage(
434         this->m_Image->GetVTK< vtkImageData >( )
435
436                 );
437         
438         
439         MementoState(this->m_state, this->m_Image);
440         this->m_state++;
441         if (this->m_state > this->m_max_state)
442         {
443                 this->m_max_state = this->m_state;
444         }
445   }
446   else
447     QMessageBox::critical(
448       this,
449       tr( "Error executing filter" ),
450       tr( err.c_str( ) )
451       );
452 }
453
454 // -------------------------------------------------------------------------
455 void ImageMPR::
456 _triggered_actionImageToMesh( )
457 {
458   if( this->m_Image.IsNull( ) )
459     return;
460
461   // Get filter name
462   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
463   if( action == NULL )
464     return;
465   std::string name = action->text( ).toStdString( );
466
467   // Configure filter
468   TPluginFilter::Pointer filter =
469     this->m_Plugins.CreateProcessObject( name );
470   bool dlg_ok = filter->ExecConfigurationDialog( NULL );
471   if( !dlg_ok )
472     return;
473
474   // Execute filter
475   QApplication::setOverrideCursor( Qt::WaitCursor );
476   this->setEnabled( false );
477   filter->SetInput( 0, this->m_Image );
478   std::string err = filter->Update( );
479   QApplication::restoreOverrideCursor( );
480   this->setEnabled( true );
481
482   // Update image
483   if( err == "" )
484   {
485     TPluginMesh* result = filter->GetOutput< TPluginMesh >( 0 );
486     result->DisconnectPipeline( );
487     this->m_Mesh = result;
488     err = this->_ConfigureMeshActors( );
489     if( err != "" )
490       QMessageBox::critical(
491         this,
492         tr( "Error message" ),
493         tr( err.c_str( ) )
494         );
495   }
496   else
497     QMessageBox::critical(
498       this,
499       tr( "Error executing filter" ),
500       tr( err.c_str( ) )
501       );
502 }
503
504 // -------------------------------------------------------------------------
505 void ImageMPR::
506 _triggered_actionUndo()
507 {
508         MementoState memento = MementoState();
509     
510         if (this->m_state>1)
511         {
512                 this->m_state--;
513                 this->m_MPRObjects->SetImage(
514                         memento.getMemento(this->m_state)->GetOutput()
515                         );
516         } else
517         {
518                 QMessageBox::warning(
519                         this,
520                         tr("message"),
521                         tr("No history to undo")
522                         );
523         }
524
525 }
526
527 // -------------------------------------------------------------------------
528 void ImageMPR::
529 _triggered_actionRedo()
530 {
531         MementoState memento = MementoState();
532                 if (this->m_state + 1 <= m_max_state)
533                 {
534                         this->m_state++;
535                         this->m_MPRObjects->SetImage(
536                                 memento.getMemento(this->m_state)->GetOutput()
537                                 );
538                 } else
539                 {
540                         QMessageBox::warning(
541                                 this,
542                                 tr("message"),
543                                 tr("No history to redo")
544                                 );
545                 }
546         
547 }
548         
549
550 // eof - $RCSfile$