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