]> Creatis software - cpMesh.git/blob - appli/InteractiveDeformableMeshSegmentation/MainWnd.cxx
bde4b4a9fb7db8274b42c919958df94cc5b50269
[cpMesh.git] / appli / InteractiveDeformableMeshSegmentation / MainWnd.cxx
1 #include "MainWnd.h"
2 #include "ui_MainWnd.h"
3
4 #include <algorithm>
5 #include <cctype>
6 #include <fstream>
7
8 #include <QFileDialog>
9 #include <QMessageBox>
10
11 #include <vtkAnnotatedCubeActor.h>
12 #include <vtkAxesActor.h>
13 #include <vtkPropAssembly.h>
14 #include <vtkProperty.h>
15 #include <vtkRenderWindow.h>
16
17 #include <cpPlugins/Interface/Image.h>
18
19 // -------------------------------------------------------------------------
20 #define IDMS_QT_ACTION( name )                                         \
21   QObject::connect(                                                    \
22     this->m_UI->action##name, SIGNAL( triggered( ) ),                  \
23     this, SLOT( _triggered_action##name( ) )                           \
24     )
25
26 // -------------------------------------------------------------------------
27 MainWnd::MainWnd( QWidget* parent )
28   : QMainWindow( parent ),
29     m_UI( new Ui::MainWnd ),
30     m_InputImage( NULL ),
31     m_SegmentedImage( NULL )
32 {
33   this->m_UI->setupUi( this );
34
35   // Configuration files
36   this->m_ApplicationPreferencesFile = "idms.config";
37   this->m_PluginsConfigurationFile = "idms.plugins";
38   this->_LoadApplicationPreferences( );
39
40   // Create and associate renderers
41   this->m_3DRenderer = vtkSmartPointer< vtkRenderer >::New( );
42   this->m_XPlaneRenderer = vtkSmartPointer< vtkRenderer >::New( );
43   this->m_YPlaneRenderer = vtkSmartPointer< vtkRenderer >::New( );
44   this->m_ZPlaneRenderer = vtkSmartPointer< vtkRenderer >::New( );
45   this->m_AuxRenderer = vtkSmartPointer< vtkRenderer >::New( );
46   this->m_3DRenderer->SetBackground( 0.2, 0.2, 0.2 );
47   this->m_XPlaneRenderer->SetBackground( 0.1, 0.3, 0.8 );
48   this->m_YPlaneRenderer->SetBackground( 0.1, 0.3, 0.8 );
49   this->m_ZPlaneRenderer->SetBackground( 0.1, 0.3, 0.8 );
50   this->m_AuxRenderer->SetBackground( 0.1, 0.3, 0.8 );
51   this->m_UI->m_3DVTK->GetRenderWindow( )->
52     AddRenderer( this->m_3DRenderer );
53   this->m_UI->m_XPlaneVTK->GetRenderWindow( )->
54     AddRenderer( this->m_XPlaneRenderer );
55   this->m_UI->m_YPlaneVTK->GetRenderWindow( )->
56     AddRenderer( this->m_YPlaneRenderer );
57   this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->
58     AddRenderer( this->m_ZPlaneRenderer );
59   this->m_UI->m_AuxVTK->GetRenderWindow( )->
60     AddRenderer( this->m_AuxRenderer );
61
62   // Configure MPR actors
63   this->m_ImageActors = vtkSmartPointer< idms::VolumeActors >::New( );
64
65   // Interaction styles
66   this->m_XStyle = vtkSmartPointer< idms::InteractorStyleImage >::New( );
67   this->m_YStyle = vtkSmartPointer< idms::InteractorStyleImage >::New( );
68   this->m_ZStyle = vtkSmartPointer< idms::InteractorStyleImage >::New( );
69   this->m_XStyle->Configure( this->m_ImageActors, 0 );
70   this->m_YStyle->Configure( this->m_ImageActors, 1 );
71   this->m_ZStyle->Configure( this->m_ImageActors, 2 );
72   this->m_UI->m_XPlaneVTK->GetInteractor( )->
73     SetInteractorStyle( this->m_XStyle );
74   this->m_UI->m_YPlaneVTK->GetInteractor( )->
75     SetInteractorStyle( this->m_YStyle );
76   this->m_UI->m_ZPlaneVTK->GetInteractor( )->
77     SetInteractorStyle( this->m_ZStyle );
78
79   // Orientation marks
80   vtkSmartPointer< vtkAnnotatedCubeActor > oCube =
81     vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
82   oCube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
83   oCube->GetTextEdgesProperty( )->SetLineWidth( 1 );
84   oCube->GetTextEdgesProperty( )->SetDiffuse( 0 );
85   oCube->GetTextEdgesProperty( )->SetAmbient( 1 );
86   oCube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
87   oCube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
88   oCube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
89   oCube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
90   oCube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
91   oCube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
92   oCube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
93   oCube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
94   oCube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
95   oCube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
96   oCube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
97   oCube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
98   oCube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
99
100   vtkSmartPointer< vtkAxesActor > oAxes =
101     vtkSmartPointer< vtkAxesActor >::New( );
102   oAxes->AxisLabelsOff( );
103   oAxes->SetShaftTypeToCylinder( );
104   oAxes->SetTotalLength( 2.5, 2.5, 2.5 );
105
106   vtkSmartPointer< vtkPropAssembly > oActors =
107     vtkSmartPointer< vtkPropAssembly >::New( );
108   oActors->AddPart( oCube );
109   oActors->AddPart( oAxes );
110
111   this->m_3DOrientationWidget =
112     vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
113   this->m_3DOrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
114   this->m_3DOrientationWidget->SetOrientationMarker( oActors );
115   this->m_3DOrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
116
117   // Add actors, widgets, stuff, ...
118   this->m_3DOrientationWidget->
119     SetInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
120   this->m_3DOrientationWidget->SetEnabled( 1 );
121   this->m_3DOrientationWidget->InteractiveOff( );
122
123   // Qt signals <-> slots
124   IDMS_QT_ACTION( ReloadPlugins );
125   IDMS_QT_ACTION( OpenInputImage );
126   IDMS_QT_ACTION( OpenSegmentedImage );
127   QObject::connect(
128     this->m_UI->actionNavigation, SIGNAL( triggered( ) ),
129     this, SLOT( _triggered_actionSwitchMode( ) )
130     );
131   QObject::connect(
132     this->m_UI->actionSegmentationInteractiveDeformation,
133     SIGNAL( triggered( ) ),
134     this, SLOT( _triggered_actionSwitchMode( ) )
135     );
136
137   // Historic configuration
138   this->m_LastOpenedFile = ".";
139
140   // Start: load all disponible plugins
141   this->_triggered_actionReloadPlugins( );
142 }
143
144 // -------------------------------------------------------------------------
145 MainWnd::
146 ~MainWnd( )
147 {
148   delete this->m_UI;
149   if( this->m_InputImage != NULL ) delete this->m_InputImage;
150   if( this->m_SegmentedImage != NULL ) delete this->m_SegmentedImage;
151 }
152
153 // -------------------------------------------------------------------------
154 void MainWnd::
155 _LoadApplicationPreferences( )
156 {
157   this->m_ApplicationPreferences.clear( );
158   std::ifstream in( this->m_ApplicationPreferencesFile.c_str( ) );
159   if( in )
160   {
161     std::string line;
162     std::getline( in, line );
163     while( !( in.eof( ) ) )
164     {
165       long pos = line.find_last_of( "=" );
166       std::string key = line.substr( 0, pos );
167       std::string value = line.substr( pos + 1 );
168       key.erase(
169         std::remove_if( key.begin( ), key.end( ), isspace ), key.end( )
170         );
171       value.erase(
172         std::remove_if( value.begin( ), value.end( ), isspace ), value.end( )
173         );
174       this->m_ApplicationPreferences[ key ] = value;
175       std::getline( in, line );
176
177     } // elihw
178   }
179   else
180   {
181     this->m_ApplicationPreferences[ "data_dimensions" ] = "3";
182     this->m_ApplicationPreferences[ "input_image_type" ]  = "short";
183     this->m_ApplicationPreferences[ "segmented_image_type" ]  = "uchar";
184     this->m_ApplicationPreferences[ "mesh_type" ]  = "double";
185
186   } // fi
187   in.close( );
188 }
189
190 // -------------------------------------------------------------------------
191 MainWnd::
192 TPluginData* MainWnd::
193 _LoadImage( const std::string& image_type, const std::string& image_dim )
194 {
195   // Show dialog and check if it was accepted
196   QFileDialog dialog( this );
197   dialog.setFileMode( QFileDialog::ExistingFiles );
198   dialog.setDirectory( tr( this->m_LastOpenedFile.c_str( ) ) );
199   dialog.setNameFilter(
200     tr( "Medical image files (*.mhd *.bin *.dcm);;All files (*)" )
201     );
202   dialog.setDefaultSuffix( tr( "mhd" ) );
203   if( !( dialog.exec( ) ) )
204     return( NULL );
205
206   TPluginData* ret = NULL;
207   unsigned int nFiles = dialog.selectedFiles( ).size( );
208   if( nFiles == 1 )
209   {
210     if( this->m_ImageReaderClassName == "" )
211     {
212       QMessageBox::critical(
213         this,
214         tr( "No plugin to read a single image file found!" ),
215         tr( "No plugin to read a single image file found!" )
216         );
217       return( ret );
218
219     } // fi
220
221     std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( );
222     this->m_LastOpenedFile = fname;
223
224     TPlugin* reader =
225       dynamic_cast< TPlugin* >(
226         this->m_Plugins.CreateObject( this->m_ImageReaderClassName )
227         );
228
229     TParameters reader_params = reader->GetDefaultParameters( );
230     reader_params[ "FileName" ].second = fname;
231     reader_params[ "PixelType" ].second = image_type;
232     reader_params[ "ImageDimension" ].second = image_dim;
233     reader_params[ "IsColorImage" ].second = "0";
234     reader->SetParameters( reader_params );
235     std::string err = reader->Update( );
236
237     if( err == "" )
238     {
239       ret = reader->GetOutput( 0 );
240       reader->DisconnectOutputs( );
241     }
242     else
243       QMessageBox::critical(
244         this,
245         tr( "Error reading single image" ),
246         tr( err.c_str( ) )
247         );
248     delete reader;
249     return( ret );
250   }
251   else if( nFiles > 1 )
252   {
253     if( this->m_ImageSeriesReaderClassName == "" )
254     {
255       QMessageBox::critical(
256         this,
257         tr( "No plugin to read an image series found!" ),
258         tr( "No plugin to read an image series found!" )
259         );
260       return( ret );
261
262     } // fi
263
264     /* TODO
265        std::string fname = dialog.selectedFiles( ).at( 0 ).toStdString( );
266        this->m_LastOpenedFile = fname;
267     */
268     return( ret );
269
270   } // fi
271   return( ret );
272 }
273
274 // -------------------------------------------------------------------------
275 void MainWnd::
276 _UpdateEnabledFlags( )
277 {
278   bool img = ( this->m_InputImage != NULL );
279   this->m_UI->menuSegmentInputImage->setEnabled( img );
280   this->m_UI->actionOpenSegmentedImage->setEnabled( img );
281   this->m_UI->m_3DVTK->setEnabled( img );
282   this->m_UI->m_XPlaneVTK->setEnabled( img );
283   this->m_UI->m_YPlaneVTK->setEnabled( img );
284   this->m_UI->m_ZPlaneVTK->setEnabled( img );
285   this->m_UI->m_AuxVTK->setEnabled( img );
286
287   /* TODO
288      bool seg = this->m_Segmentation.IsNotNull( );
289      this->m_UI->menuFilterSegmentedImage->setEnabled( seg );
290      this->m_UI->menuExtractMesh->setEnabled( seg );
291      this->m_UI->actionOpenMesh->setEnabled( seg );
292
293      this->m_UI->actionNavigation->setEnabled( img && seg );
294      this->m_UI->actionSegmentationInteractiveDeformation->
295      setEnabled( img && seg );
296   */
297 }
298
299 // -------------------------------------------------------------------------
300 void MainWnd::
301 _triggered_actionReloadPlugins( )
302 {
303   this->m_Plugins.UnloadAll( );
304
305   this->m_ImageReaderClassName = "";
306   this->m_ImageSeriesReaderClassName = "";
307   this->m_ImageWriterClassName = "";
308
309   std::ifstream in( this->m_PluginsConfigurationFile.c_str( ) );
310   if( in )
311   {
312     std::string plugin;
313     std::getline( in, plugin );
314     while( !( in.eof( ) ) )
315     {
316       if( this->m_Plugins.Load( plugin ) )
317       {
318         TPluginsInterface::TClassesIterator cIt =
319           this->m_Plugins.GetClasses( ).begin( );
320         TPluginsInterface::TClassesIterator end_cIt =
321           this->m_Plugins.GetClasses( ).end( );
322         for( ; cIt != end_cIt; ++cIt )
323         {
324           std::string c_name = cIt->first;
325           c_name = c_name.substr( c_name.find_last_of( ":" ) + 1 );
326           if( c_name == "ImageReader" )
327           {
328             this->m_ImageReaderClassName = cIt->first;
329           }
330           else if( c_name == "ImageWriter" )
331           {
332             this->m_ImageWriterClassName = cIt->first;
333           }
334           else
335           {
336           } // fi
337           
338         } // rof
339
340         /* TODO
341            TFilterPlugins::TClassesIterator cIt =
342            this->m_Plugins.BeginClasses( );
343            for( ; cIt != this->m_Plugins.EndClasses( ); ++cIt )
344            {
345            TFilterObject* filter =
346            this->m_Plugins.CreateObject( cIt->first );
347            if( filter == NULL )
348            continue;
349            std::string cat = filter->GetCategory( );
350            std::string catType = cat.substr( cat.find_last_of( ":" ) );
351            if( catType == ":BinaryImageToBinaryImageFilter" )
352            {
353            QAction* action = this->m_UI->menuFilterSegmentedImage->
354            addAction( QString( cIt->first.c_str( ) ) );
355            QObject::connect(
356            action, SIGNAL( triggered( ) ),
357            this, SLOT( triggered_aFilterSegmentedImage( ) )
358            );
359            }
360            else if( catType == ":ImageToMeshFilter" )
361            {
362            QAction* action = this->m_UI->menuExtractMesh->
363            addAction( QString( cIt->first.c_str( ) ) );
364            QObject::connect(
365            action, SIGNAL( triggered( ) ),
366            this, SLOT( triggered_aSegmentedImageToMesh( ) )
367            );
368
369            } // fi
370            delete filter;
371            } // rof
372         */
373       }
374       else
375       {
376         QMessageBox::warning(
377           this,
378           tr( "Ignoring plugin" ),
379           tr( plugin.c_str( ) )
380           );
381
382       } // fi
383       std::getline( in, plugin );
384
385     } // elihw
386   }
387   else
388   {
389     QMessageBox::critical(
390       this,
391       tr( "No plugins file loaded!" ),
392       tr( this->m_PluginsConfigurationFile.c_str( ) )
393       );
394
395   } // fi
396   in.close( );
397
398   if( this->m_ImageReaderClassName == "" )
399   {
400     QMessageBox::critical(
401       this,
402       tr( "No ImageReader found in plugins!" ),
403       tr( this->m_PluginsConfigurationFile.c_str( ) )
404       );
405
406   } // fi
407
408   if( this->m_ImageWriterClassName == "" )
409   {
410     QMessageBox::critical(
411       this,
412       tr( "No ImageWriter found in plugins!" ),
413       tr( this->m_PluginsConfigurationFile.c_str( ) )
414       );
415
416   } // fi
417   this->_UpdateEnabledFlags( );
418 }
419
420 // -------------------------------------------------------------------------
421 void MainWnd::
422 _triggered_actionOpenInputImage( )
423 {
424   if( this->m_InputImage != NULL )
425     delete this->m_InputImage;
426   this->m_InputImage =
427     this->_LoadImage(
428       this->m_ApplicationPreferences[ "input_image_type" ],
429       this->m_ApplicationPreferences[ "data_dimensions" ]
430       );
431   if( this->m_InputImage != NULL )
432   {
433     cpPlugins::Interface::Image* img = 
434       dynamic_cast< cpPlugins::Interface::Image* >( this->m_InputImage );
435     this->m_ImageActors->Configure(
436       img->GetVTKImageData( ),
437       this->m_UI->m_XPlaneVTK->GetInteractor( ),
438       this->m_UI->m_YPlaneVTK->GetInteractor( ),
439       this->m_UI->m_ZPlaneVTK->GetInteractor( )
440       );
441     this->m_ImageActors->
442       AddAuxiliaryInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
443
444     // Associate actors
445     this->m_3DRenderer->AddActor(
446       this->m_ImageActors->GetImageOutlineActor( )
447       );
448     this->m_3DRenderer->AddActor(
449       this->m_ImageActors->GetXBoundsActor( )
450       );
451     this->m_3DRenderer->AddActor(
452       this->m_ImageActors->GetYBoundsActor( )
453       );
454     this->m_3DRenderer->AddActor(
455       this->m_ImageActors->GetZBoundsActor( )
456       );
457
458     // Reset all cameras
459     this->m_3DRenderer->ResetCamera( );
460     this->m_ImageActors->ResetCameras( );
461
462     // Ok, start!
463     this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
464     this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
465     this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
466     this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
467
468     // Update activations
469     this->_UpdateEnabledFlags( );
470     this->m_UI->actionNavigation->setChecked( true );
471     this->_triggered_actionSwitchMode( );
472
473   } // fi
474 }
475
476 // -------------------------------------------------------------------------
477 void MainWnd::
478 _triggered_actionOpenSegmentedImage( )
479 {
480   if( this->m_SegmentedImage != NULL )
481     delete this->m_SegmentedImage;
482   this->m_SegmentedImage =
483     this->_LoadImage(
484       this->m_ApplicationPreferences[ "segmented_image_type" ],
485       this->m_ApplicationPreferences[ "data_dimensions" ]
486       );
487   if( this->m_SegmentedImage != NULL )
488   {
489     cpPlugins::Interface::Image* img = 
490       dynamic_cast< cpPlugins::Interface::Image* >( this->m_SegmentedImage );
491     this->m_ImageActors->SetSegmentation( img->GetVTKImageData( ) );
492
493     // Ok, start!
494     this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
495     this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
496     this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
497     this->_UpdateEnabledFlags( );
498
499     /*
500     this->m_ImageActors->Configure(
501     img->GetVTKImageData( ),
502       this->m_UI->m_XPlaneVTK->GetInteractor( ),
503       this->m_UI->m_YPlaneVTK->GetInteractor( ),
504       this->m_UI->m_ZPlaneVTK->GetInteractor( )
505       );
506     this->m_ImageActors->
507       AddAuxiliaryInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
508
509     // Associate actors
510     this->m_3DRenderer->AddActor(
511       this->m_ImageActors->GetImageOutlineActor( )
512       );
513     this->m_3DRenderer->AddActor(
514       this->m_ImageActors->GetXBoundsActor( )
515       );
516     this->m_3DRenderer->AddActor(
517       this->m_ImageActors->GetYBoundsActor( )
518       );
519     this->m_3DRenderer->AddActor(
520       this->m_ImageActors->GetZBoundsActor( )
521       );
522
523     // Reset all cameras
524     this->m_3DRenderer->ResetCamera( );
525     this->m_ImageActors->ResetCameras( );
526
527     // Ok, start!
528     this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
529     this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
530     this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
531     this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
532
533     // Update activations
534     this->_UpdateEnabledFlags( );
535     this->m_UI->actionNavigation->setChecked( true );
536     this->_triggered_actionSwitchMode( );
537     */
538
539   } // fi
540 }
541
542 // -------------------------------------------------------------------------
543 void MainWnd::
544 _triggered_actionSwitchMode( )
545 {
546   QAction* snd = dynamic_cast< QAction* >( this->sender( ) );
547   if( snd == this->m_UI->actionNavigation )
548   {
549     this->m_UI->actionSegmentationInteractiveDeformation->setChecked(
550       !( this->m_UI->actionNavigation->isChecked( ) )
551       );
552   }
553   else if( snd == this->m_UI->actionSegmentationInteractiveDeformation )
554   {
555     this->m_UI->actionNavigation->setChecked(
556       !( this->m_UI->actionSegmentationInteractiveDeformation->isChecked( ) )
557       );
558   }
559   else
560   {
561     this->m_UI->actionNavigation->setChecked( true );
562     this->m_UI->actionSegmentationInteractiveDeformation->setChecked( false );
563
564   } // fi
565
566   /* TODO
567      if( this->m_UI->aNavigation->isChecked( ) )
568      {
569      this->m_XStyle->SetModeToNavigation( );
570      this->m_YStyle->SetModeToNavigation( );
571      this->m_ZStyle->SetModeToNavigation( );
572      this->m_ImageActors->HideRegion( 0 );
573      this->m_ImageActors->HideRegion( 1 );
574      this->m_ImageActors->HideRegion( 2 );
575      this->m_3DRenderer->RemoveActor(
576      this->m_ImageActors->GetCursorActor( )
577      );
578      this->m_3DRenderer->RemoveActor(
579      this->m_ImageActors->GetRegionActor( )
580      );
581      this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
582      }
583      else if( this->m_UI->aSegmentationInteractiveDeformation->isChecked( ) )
584      {
585      this->m_XStyle->SetModeToDeformation( );
586      this->m_YStyle->SetModeToDeformation( );
587      this->m_ZStyle->SetModeToDeformation( );
588      this->m_ImageActors->ShowRegion( 0 );
589      this->m_ImageActors->ShowRegion( 1 );
590      this->m_ImageActors->ShowRegion( 2 );
591      this->m_3DRenderer->AddActor(
592      this->m_ImageActors->GetCursorActor( )
593      );
594      this->m_3DRenderer->AddActor(
595      this->m_ImageActors->GetRegionActor( )
596      );
597      this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
598
599      } // fi
600   */
601 }
602
603 // -------------------------------------------------------------------------
604 /* TODO
605
606 // -------------------------------------------------------------------------
607 bool MainWnd::
608 _ParametersDialog( TParameters& parameters )
609 {
610   QDialog dlg( this );
611   QGridLayout gridLayout( &dlg );
612   QVBoxLayout verticalLayout;
613
614   // Put values
615   typedef std::map< std::string, QWidget* > _TWidgets;
616   _TWidgets widgets;
617   TParameters::const_iterator pIt = parameters.begin( );
618   for( ; pIt != parameters.end( ); ++pIt )
619   {
620     unsigned long pos = pIt->first.find_last_of( ":" );
621     std::string v_name = pIt->first.substr( 0, pos );
622     std::string v_type = pIt->first.substr( pos + 1 );
623
624     QHBoxLayout* horizontalLayout = new QHBoxLayout( );
625     QLabel* label = new QLabel( &dlg );
626     label->setText( QString( v_name.c_str( ) ) );
627     horizontalLayout->addWidget( label );
628     if( v_type == "real" )
629     {
630       QDoubleSpinBox* v_double = new QDoubleSpinBox( &dlg );
631       v_double->setDecimals( 3 );
632       v_double->setMinimum( -( std::numeric_limits< double >::max( ) ) );
633       v_double->setMaximum( std::numeric_limits< double >::max( ) );
634       v_double->setValue( std::atof( pIt->second.c_str( ) ) );
635       horizontalLayout->addWidget( v_double );
636       widgets[ pIt->first ] = v_double;
637     }
638     else if( v_type == "atomic_real" )
639     {
640       if( v_name == "MeshType" )
641       {
642         QLabel* info = new QLabel( &dlg );
643         if( typeid( TScalar ) == typeid( float ) )
644           info->setText( QString( "float" ) );
645         else if( typeid( TScalar ) == typeid( double ) )
646           info->setText( QString( "double" ) );
647         horizontalLayout->addWidget( info );
648         widgets[ pIt->first ] = info;
649
650       } // fi
651
652     } // fi
653     verticalLayout.addLayout( horizontalLayout );
654
655   } // rof
656   gridLayout.addLayout( &verticalLayout, 0, 0, 1, 1 );
657
658   // Buttons box
659   QDialogButtonBox buttonBox( &dlg );
660   buttonBox.setOrientation( Qt::Horizontal );
661   buttonBox.setStandardButtons(
662     QDialogButtonBox::Cancel | QDialogButtonBox::Ok
663     );
664   gridLayout.addWidget( &buttonBox, 1, 0, 1, 1 );
665   QObject::connect(
666     &buttonBox, SIGNAL( accepted( ) ),
667     &dlg, SLOT( accept( ) )
668     );
669   QObject::connect(
670     &buttonBox, SIGNAL( rejected( ) ),
671     &dlg, SLOT( reject( ) )
672     );
673   QMetaObject::connectSlotsByName( &dlg );
674
675   // Execute dialog
676   if( dlg.exec( ) == QDialog::Accepted )
677   {
678     _TWidgets::const_iterator wIt = widgets.begin( );
679     for( ; wIt != widgets.end( ); ++wIt )
680     {
681       unsigned long pos = wIt->first.find_last_of( ":" );
682       std::string v_name = wIt->first.substr( 0, pos );
683       std::string v_type = wIt->first.substr( pos + 1 );
684       std::stringstream sstr;
685       if( v_type == "real" )
686       {
687         QDoubleSpinBox* v_double =
688           dynamic_cast< QDoubleSpinBox* >( wIt->second );
689         if( v_double != NULL )
690           sstr << v_double->value( );
691       }
692       else if( v_type == "atomic_real" )
693       {
694         if( v_name == "MeshType" )
695         {
696           QLabel* info = dynamic_cast< QLabel* >( wIt->second );
697           if( info != NULL )
698             sstr << info->text( ).toStdString( );
699
700         } // fi
701
702       } // fi
703       parameters[ wIt->first ] = sstr.str( );
704
705     } // rof
706     return( true );
707   }
708   return( false );
709   }
710
711   // -------------------------------------------------------------------------
712   template< class I >
713   bool MainWnd::
714   _LoadImage( typename I::Pointer& image )
715   {
716   QStringList qList =
717   QFileDialog::getOpenFileNames(
718   this,
719   tr( "Open an image" ),
720   tr( this->m_LastOpenedFile.c_str( ) ),
721   tr( "Medical image files (*.mhd *.bin *.dcm);;All files (*)" )
722   );
723   if( qList.size( ) == 0 )
724   return( false );
725
726   bool ret = true;
727   QStringList::Iterator fIt = qList.begin( );
728   if( qList.size( ) == 1 )
729   {
730   // Read a single image
731   std::string fn = fIt->toStdString( );
732   this->m_LastOpenedFile = fn;
733
734   typename itk::ImageFileReader< I >::Pointer reader =
735   itk::ImageFileReader< I >::New( );
736   reader->SetFileName( fn );
737   try
738   {
739   reader->Update( );
740   }
741   catch( itk::ExceptionObject& err )
742   {
743   QMessageBox::critical(
744   this,
745   tr( "Error opening single image!" ),
746   tr( err.GetDescription( ) )
747   );
748   ret = false;
749
750   } // yrt
751   image = reader->GetOutput( );
752   image->DisconnectPipeline( );
753   }
754   else if( qList.size( ) > 1 )
755   {
756   typedef std::set< std::string > _TOrderedStringList;
757
758   // Read a slice set
759   _TOrderedStringList filenames;
760   for( ; fIt != qList.end( ); ++fIt )
761   filenames.insert( fIt->toStdString( ) );
762   typename itk::ImageSeriesReader< I >::Pointer reader =
763   itk::ImageSeriesReader< I >::New( );
764   reader->SetImageIO( itk::GDCMImageIO::New( ) );
765   _TOrderedStringList::const_iterator oIt = filenames.begin( );
766   for( ; oIt != filenames.end( ); ++oIt )
767   {
768   reader->AddFileName( *oIt );
769   this->m_LastOpenedFile = *oIt;
770
771   } // rof
772   try
773   {
774   reader->Update( );
775   }
776   catch( itk::ExceptionObject& err )
777   {
778   QMessageBox::critical(
779   this,
780   tr( "Error opening image series!" ),
781   tr( err.GetDescription( ) )
782   );
783   ret = false;
784
785   } // yrt
786   image = reader->GetOutput( );
787   image->DisconnectPipeline( );
788
789   } // fi
790   return( ret );
791   }
792
793 // -------------------------------------------------------------------------
794 void MainWnd::
795 triggered_aReloadPlugins( )
796 {
797 }
798
799 // -------------------------------------------------------------------------
800 void MainWnd::
801 triggered_aOpenInputImage( )
802 {
803   if( this->_LoadImage< TImage >( this->m_Image ) )
804   {
805     // Connect image to VTK
806     this->m_VTKImage = TVTKImage::New( );
807     this->m_VTKImage->SetInput( this->m_Image );
808     this->m_VTKImage->Update( );
809
810     this->m_ImageActors->Configure(
811       this->m_VTKImage->GetOutput( ),
812       this->m_UI->m_XPlaneVTK->GetInteractor( ),
813       this->m_UI->m_YPlaneVTK->GetInteractor( ),
814       this->m_UI->m_ZPlaneVTK->GetInteractor( )
815       );
816     this->m_ImageActors->
817       AddAuxiliaryInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
818
819     // Associate actors
820     this->m_3DRenderer->AddActor(
821       this->m_ImageActors->GetImageOutlineActor( )
822       );
823     this->m_3DRenderer->AddActor(
824       this->m_ImageActors->GetXBoundsActor( )
825       );
826     this->m_3DRenderer->AddActor(
827       this->m_ImageActors->GetYBoundsActor( )
828       );
829     this->m_3DRenderer->AddActor(
830       this->m_ImageActors->GetZBoundsActor( )
831       );
832
833     // Reset all cameras
834     this->m_3DRenderer->ResetCamera( );
835     this->m_ImageActors->ResetCameras( );
836
837     // Ok, start!
838     this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
839     this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
840     this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
841     this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
842     this->_UpdateEnabledFlags( );
843     this->m_UI->aNavigation->setChecked( true );
844     this->triggered_aSwitchMode( );
845
846   } // fi
847 }
848
849 // -------------------------------------------------------------------------
850 void MainWnd::
851 triggered_aOpenSegmentedImage( )
852 {
853   if( this->_LoadImage< TImage >( this->m_Segmentation ) )
854   {
855     // Connect image to VTK
856     this->m_VTKSegmentation = TVTKImage::New( );
857     this->m_VTKSegmentation->SetInput( this->m_Segmentation );
858     this->m_VTKSegmentation->Update( );
859
860     this->m_ImageActors->SetSegmentation(
861       this->m_VTKSegmentation->GetOutput( )
862       );
863
864     // Ok, start!
865     this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
866     this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
867     this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
868     this->_UpdateEnabledFlags( );
869
870   } // fi
871 }
872
873 // -------------------------------------------------------------------------
874 void MainWnd::
875 triggered_aFilterSegmentedImage( )
876 {
877   // Get filter name
878   if( this->m_Segmentation.IsNull( ) )
879     return;
880   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
881   if( action == NULL )
882     return;
883   std::string filter_name = action->text( ).toStdString( );
884
885   // Create filter
886   TFilterObject* filter = this->m_Plugins.CreateObject( filter_name );
887   if( filter == NULL )
888     return;
889
890   TParameters parameters = filter->GetDefaultParameters( );
891   if( !( this->_ParametersDialog( parameters ) ) )
892     return;
893   filter->SetInput( this->m_Segmentation );
894   filter->SetParameters( parameters );
895   std::string result = filter->Update( );
896
897   // Get modified segmentation
898      this->m_Mesh = filter->GetCastedOutput< TMesh >( );
899      if( this->m_Mesh.IsNotNull( ) )
900      {
901      this->m_Mesh->DisconnectPipeline( );
902
903      } // fi
904   // Ok, it seems to have runned fine
905   delete filter;
906 }
907
908 // -------------------------------------------------------------------------
909 void MainWnd::
910 triggered_aSegmentedImageToMesh( )
911 {
912   // Get filter name
913   if( this->m_Segmentation.IsNull( ) )
914     return;
915   QAction* action = dynamic_cast< QAction* >( this->sender( ) );
916   if( action == NULL )
917     return;
918   std::string filter_name = action->text( ).toStdString( );
919
920   // Create filter
921   TFilterObject* filter = this->m_Plugins.CreateObject( filter_name );
922   if( filter == NULL )
923     return;
924
925   TParameters parameters = filter->GetDefaultParameters( );
926   if( !( this->_ParametersDialog( parameters ) ) )
927     return;
928   filter->SetInput( this->m_Segmentation );
929   filter->SetParameters( parameters );
930   std::string result = filter->Update( );
931
932   // Get mesh
933   this->m_Mesh = filter->GetCastedOutput< TMesh >( );
934   if( this->m_Mesh.IsNotNull( ) )
935   {
936     this->m_Mesh->DisconnectPipeline( );
937
938   } // fi
939
940   // Ok, it seems to have runned fine
941   delete filter;
942 }
943 */
944
945 // -------------------------------------------------------------------------
946 /*
947   void MainWnd::
948   _SliceMesh( int axis )
949   {
950   TCutter* cutter = NULL;
951   if( axis == 2 ) cutter = this->m_ZCutter;
952
953   if( cutter == NULL )
954   return;
955
956   vtkPlane* vplane = this->m_ImageActors->GetSlicePlane( axis );
957   double vorigin[ 3 ], vnormal[ 3 ];
958   vplane->GetOrigin( vorigin );
959   vplane->GetNormal( vnormal );
960
961   TCutter::TVector corigin, cnormal;
962   corigin[ 0 ] = TScalar( vorigin[ 0 ] );
963   corigin[ 1 ] = TScalar( vorigin[ 1 ] );
964   corigin[ 2 ] = TScalar( vorigin[ 2 ] );
965   cnormal[ 0 ] = TScalar( vnormal[ 0 ] );
966   cnormal[ 1 ] = TScalar( vnormal[ 1 ] );
967   cnormal[ 2 ] = TScalar( vnormal[ 2 ] );
968
969   cutter->SetPlanePoint( corigin );
970   cutter->SetPlaneNormal( cnormal );
971   cutter->Update( );
972   }
973
974   // -------------------------------------------------------------------------
975   void MainWnd::
976   _SliceEventCallback(
977   vtkObject* caller,
978   long unsigned int eventId,
979   void* clientData, void* callData
980   )
981   {
982   if( clientData == NULL || callData == NULL )
983   return;
984   MainWnd* wnd = reinterpret_cast< MainWnd* >( clientData );
985   int axis = *( reinterpret_cast< int* >( callData ) );
986   if( wnd == NULL )
987   return;
988   if( eventId == idms::InteractorStyleImage::SliceEvent )
989   wnd->_SliceMesh( axis );
990   }
991
992   // -------------------------------------------------------------------------
993   void MainWnd::
994   triggered_aLoadImage( )
995   {
996   if( this->_LoadImage< TImage >( this->m_Image ) )
997   {
998   // Connect image to VTK
999   this->m_VTKImage->SetInput( this->m_Image );
1000   this->m_VTKImage->Update( );
1001   this->m_ImageActors->Configure(
1002   this->m_VTKImage->GetOutput( ),
1003   this->m_UI->m_XPlaneVTK->GetInteractor( ),
1004   this->m_UI->m_YPlaneVTK->GetInteractor( ),
1005   this->m_UI->m_ZPlaneVTK->GetInteractor( )
1006   );
1007   this->m_ImageActors->
1008   AddAuxiliaryInteractor( this->m_UI->m_3DVTK->GetInteractor( ) );
1009
1010   // Associate actors
1011   this->m_3DRenderer->AddActor(
1012   this->m_ImageActors->GetImageOutlineActor( )
1013   );
1014   this->m_3DRenderer->AddActor(
1015   this->m_ImageActors->GetXBoundsActor( )
1016   );
1017   this->m_3DRenderer->AddActor(
1018   this->m_ImageActors->GetYBoundsActor( )
1019   );
1020   this->m_3DRenderer->AddActor(
1021   this->m_ImageActors->GetZBoundsActor( )
1022   );
1023
1024   // Reset all cameras
1025   this->m_3DRenderer->ResetCamera( );
1026   this->m_ImageActors->ResetCameras( );
1027
1028   // Ok, start!
1029   this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
1030   this->m_UI->m_XPlaneVTK->GetRenderWindow( )->Render( );
1031   this->m_UI->m_YPlaneVTK->GetRenderWindow( )->Render( );
1032   this->m_UI->m_ZPlaneVTK->GetRenderWindow( )->Render( );
1033
1034   // Activate controls
1035   this->m_UI->aLoadSegmentedImage->setEnabled( true );
1036   this->m_UI->aSegmentImage->setEnabled( true );
1037   this->m_UI->m_3DVTK->setEnabled( true );
1038   this->m_UI->m_XPlaneVTK->setEnabled( true );
1039   this->m_UI->m_YPlaneVTK->setEnabled( true );
1040   this->m_UI->m_ZPlaneVTK->setEnabled( true );
1041
1042   } // fi
1043   }
1044
1045   // -------------------------------------------------------------------------
1046   void MainWnd::
1047   triggered_aLoadSegmentedImage( )
1048   {
1049   if( this->m_Mesh.IsNotNull( ) )
1050   {
1051   QMessageBox::critical(
1052   this,
1053   tr( "Mesh already loaded!" ),
1054   tr( "Mesh already loaded!" )
1055   );
1056   return;
1057
1058   } // fi
1059
1060   if( this->_LoadImage< TImage >( this->m_Segmentation ) )
1061   {
1062   // Compute segmentation values
1063   itk::MinimumMaximumImageCalculator< TImage >::Pointer minmax =
1064   itk::MinimumMaximumImageCalculator< TImage >::New( );
1065   minmax->SetImage( this->m_Segmentation );
1066   minmax->Compute( );
1067   TPixel min_v = minmax->GetMinimum( );
1068   TPixel max_v = minmax->GetMaximum( );
1069   double thr = double( max_v + min_v ) / double( 2 );
1070
1071   typedef itk::Image< TScalar, Dimension > _TScalarImage;
1072   typedef
1073   itk::BinaryMinMaxCurvatureFlowImageFilter< TImage, _TScalarImage >
1074   _TFilter;
1075   typedef _TFilter::TimeStepType    _TTimeStep;
1076   typedef _TFilter::RadiusValueType _TRadius;
1077
1078   _TFilter::Pointer filter = _TFilter::New( );
1079   filter->SetInput( this->m_Segmentation );
1080   filter->SetTimeStep( _TTimeStep( 0.0625 ) );
1081   filter->SetNumberOfIterations( 10 );
1082   filter->SetStencilRadius( _TRadius( 3 ) );
1083   filter->SetThreshold( thr );
1084   filter->Update( );
1085
1086   itk::ImageFileWriter< _TScalarImage >::Pointer w =
1087   itk::ImageFileWriter< _TScalarImage >::New( );
1088   w->SetInput( filter->GetOutput( ) );
1089   w->SetFileName( "no_noise.mhd" );
1090   w->Update( );
1091   std::exit( 1 );
1092
1093   typedef
1094   itk::LaplacianRecursiveGaussianImageFilter< TImage, _TScalarImage >
1095   _TFilter;
1096   _TFilter::Pointer filter = _TFilter::New( );
1097   filter->SetInput( this->m_Segmentation );
1098   filter->SetSigma( 3 ); // in spacing units
1099   filter->SetNormalizeAcrossScale( false );
1100
1101   typedef itk::ThresholdImageFilter< _TScalarImage > _TThreshold;
1102   _TThreshold::Pointer threshold = _TThreshold::New( );
1103   threshold->SetInput( filter->GetOutput( ) );
1104   threshold->ThresholdAbove( TScalar( 0 ) );
1105   threshold->InPlaceOff( );
1106   threshold->Update( );
1107
1108   itk::MinimumMaximumImageCalculator< _TScalarImage >::Pointer t_minmax =
1109   itk::MinimumMaximumImageCalculator< _TScalarImage >::New( );
1110   t_minmax->SetImage( threshold->GetOutput( ) );
1111   t_minmax->Compute( );
1112   TScalar min_t = t_minmax->GetMinimum( );
1113
1114   std::cout << min_t << " " << t_minmax->GetMaximum( ) << std::endl;
1115
1116   itk::SubtractImageFilter< _TScalarImage >::Pointer subtract =
1117   itk::SubtractImageFilter< _TScalarImage >::New( );
1118   subtract->SetInput1( threshold->GetOutput( ) );
1119   subtract->SetConstant2( min_t );
1120
1121   itk::ImageFileWriter< _TScalarImage >::Pointer w =
1122   itk::ImageFileWriter< _TScalarImage >::New( );
1123   w->SetInput( subtract->GetOutput( ) );
1124   w->SetFileName( "no_noise_laplace_2.mhd" );
1125   w->Update( );
1126   std::exit( 1 );
1127
1128   // Pass segmentation to VTK
1129   this->m_VTKSegmentation = TVTKImage::New( );
1130   this->m_VTKSegmentation->SetInput( this->m_Segmentation );
1131   this->m_VTKSegmentation->Update( );
1132
1133   // Use VTK's marching cubes (it is smoother)
1134   vtkSmartPointer< vtkImageMarchingCubes > segmentation_mc =
1135   vtkSmartPointer< vtkImageMarchingCubes >::New( );
1136   segmentation_mc->SetInputData( this->m_VTKSegmentation->GetOutput( ) );
1137   segmentation_mc->SetValue( 0, thr );
1138   segmentation_mc->Update( );
1139
1140   // Go back to ITK world
1141   typedef cpm::VTK::PolyDataToMeshFilter< TTriangulation > _TVTKPDataToMesh;
1142   _TVTKPDataToMesh::Pointer itk_mc = _TVTKPDataToMesh::New( );
1143   itk_mc->SetInput( segmentation_mc->GetOutput( ) );
1144   itk_mc->Update( );
1145   this->m_Mesh = itk_mc->GetOutput( );
1146   this->m_Mesh->DisconnectPipeline( );
1147
1148   this->m_MeshMapper = vtkSmartPointer< TTriangulationMapper >::New( );
1149   this->m_MeshActor = vtkSmartPointer< vtkActor >::New( );
1150
1151   this->m_MeshMapper->SetInputData( this->m_Mesh );
1152   this->m_MeshActor->SetMapper( this->m_MeshMapper );
1153   this->m_MeshActor->GetProperty( )->SetColor( 1, 1, 0 );
1154   this->m_MeshActor->GetProperty( )->SetRepresentationToWireframe( );
1155   this->m_3DRenderer->AddActor( this->m_MeshActor );
1156   this->m_3DRenderer->ResetCamera( );
1157   this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
1158
1159   unsigned int reduction = 20;
1160
1161   typedef TImage::SpacingType::ValueType _TValue;
1162
1163
1164   // Compute downsize parameters
1165   TImage::SizeType o_size =
1166   segmentation->GetLargestPossibleRegion( ).GetSize( );
1167   TImage::SpacingType o_spac = segmentation->GetSpacing( );
1168   _TValue min_spac = std::numeric_limits< _TValue >::max( );
1169   for( unsigned int d = 0; d < Dimension; ++d )
1170   min_spac = ( o_spac[ d ] < min_spac )? o_spac[ d ]: min_spac;
1171   min_spac *= _TValue( reduction );
1172   TImage::SpacingType n_spac( min_spac );
1173   TImage::SizeType n_size;
1174   for( unsigned int d = 0; d < Dimension; ++d )
1175   n_size[ d ] = ( unsigned long )(
1176   _TValue( o_size[ d ] ) * o_spac[ d ] / min_spac
1177   );
1178
1179   // Downsize image
1180   typedef itk::Image< TScalar, Dimension > _TScalarImage;
1181   typedef itk::IdentityTransform< TScalar, Dimension > _TTransform;
1182   typedef
1183   itk::LinearInterpolateImageFunction< TImage, TScalar >
1184   _TInterpolator;
1185   typedef
1186   itk::ResampleImageFilter< TImage, _TScalarImage, TScalar, TScalar >
1187   _TResample;
1188   _TResample::Pointer resample = _TResample::New( );
1189   resample->SetInput( segmentation );
1190   resample->SetSize( n_size );
1191   resample->SetOutputDirection( segmentation->GetDirection( ) );
1192   resample->SetOutputOrigin( segmentation->GetOrigin( ) );
1193   resample->SetOutputSpacing( n_spac );
1194   resample->SetTransform( _TTransform::New( ) );
1195   resample->SetInterpolator( _TInterpolator::New( ) );
1196   resample->UpdateLargestPossibleRegion( );
1197
1198   // Try to smooth
1199   typedef
1200   itk::SignedDanielssonDistanceMapImageFilter< _TScalarImage, _TScalarImage >
1201   _TDanielsson;
1202   _TDanielsson::Pointer danielsson = _TDanielsson::New( );
1203   danielsson->SetInput( resample->GetOutput( ) );
1204   danielsson->Update( );
1205
1206   // Go back to ITK world
1207   typedef cpm::VTK::PolyDataToMeshFilter< TTriangulation > TVTKPDataToMesh;
1208   TVTKPDataToMesh::Pointer itk_mc = TVTKPDataToMesh::New( );
1209   itk_mc->SetInput( danielsson_mc->GetOutput( ) );
1210   itk_mc->Update( );
1211   this->m_Mesh = itk_mc->GetOutput( );
1212   this->m_Mesh->DisconnectPipeline( );
1213
1214   this->m_ZCutter = TCutter::New( );
1215   this->m_ZCutter->SetInput( this->m_Mesh );
1216
1217   this->m_MeshMapper = vtkSmartPointer< TTriangulationMapper >::New( );
1218   this->m_MeshActor = vtkSmartPointer< vtkActor >::New( );
1219
1220   this->m_MeshMapper->SetInputData( this->m_Mesh );
1221   this->m_MeshActor->SetMapper( this->m_MeshMapper );
1222   this->m_MeshActor->GetProperty( )->SetColor( 1, 1, 0 );
1223   this->m_MeshActor->GetProperty( )->SetRepresentationToWireframe( );
1224   this->m_3DRenderer->AddActor( this->m_MeshActor );
1225   this->m_3DRenderer->ResetCamera( );
1226   this->m_UI->m_3DVTK->GetRenderWindow( )->Render( );
1227
1228   } // fi
1229   }
1230 */
1231
1232 // eof - $RCSfile$