From 003b7bc4f88cbe4aa6cc27fcd16b8cda94eba9be Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Tue, 17 Nov 2015 18:52:08 -0500 Subject: [PATCH] Machete filter with interactive plane: it now supports images and meshes. Not yet executable, but it is visible. --- lib/cpPlugins/Interface/DataObject.h | 1 + lib/cpPlugins/Interface/Parameters.cxx | 4 + lib/cpPlugins/Interface/Parameters.h | 34 +++- lib/cpPlugins/Interface/Parameters.hxx | 123 ++++++++++++ .../Interface/ParametersQtDialog.cxx | 16 ++ lib/cpPlugins/Interface/ParametersQtDialog.h | 6 +- lib/cpPlugins/Interface/ProcessObject.cxx | 1 + lib/cpPlugins/Interface/ProcessObject.h | 2 + .../Plugins/BasicFilters/MacheteFilter.cxx | 187 ++++++++++++++++++ .../Plugins/BasicFilters/MacheteFilter.h | 73 +++++++ 10 files changed, 440 insertions(+), 7 deletions(-) create mode 100644 lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.cxx create mode 100644 lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.h diff --git a/lib/cpPlugins/Interface/DataObject.h b/lib/cpPlugins/Interface/DataObject.h index 4668219..d90f8e9 100644 --- a/lib/cpPlugins/Interface/DataObject.h +++ b/lib/cpPlugins/Interface/DataObject.h @@ -26,6 +26,7 @@ namespace cpPlugins typedef itk::SmartPointer< const Self > ConstPointer; public: + itkNewMacro( Self ); itkTypeMacro( DataObject, Object ); cpPlugins_Id_Macro( DataObject, "BasicObject" ); diff --git a/lib/cpPlugins/Interface/Parameters.cxx b/lib/cpPlugins/Interface/Parameters.cxx index 8312246..c85aeee 100644 --- a/lib/cpPlugins/Interface/Parameters.cxx +++ b/lib/cpPlugins/Interface/Parameters.cxx @@ -87,6 +87,7 @@ cpPlugins_Parameters_List_Configure( Uint ); cpPlugins_Parameters_List_Configure( Real ); cpPlugins_Parameters_List_Configure( Index ); cpPlugins_Parameters_List_Configure( Point ); +cpPlugins_Parameters_List_Configure( Vector ); // ------------------------------------------------------------------------- void cpPlugins::Interface::Parameters:: @@ -148,6 +149,7 @@ cpPlugins_Parameters_Has( Uint ); cpPlugins_Parameters_Has( Real ); cpPlugins_Parameters_Has( Index ); cpPlugins_Parameters_Has( Point ); +cpPlugins_Parameters_Has( Vector ); cpPlugins_Parameters_Has( StringList ); cpPlugins_Parameters_Has( BoolList ); cpPlugins_Parameters_Has( IntList ); @@ -155,6 +157,7 @@ cpPlugins_Parameters_Has( UintList ); cpPlugins_Parameters_Has( RealList ); cpPlugins_Parameters_Has( IndexList ); cpPlugins_Parameters_Has( PointList ); +cpPlugins_Parameters_Has( VectorList ); cpPlugins_Parameters_Has( Choices ); // ------------------------------------------------------------------------- @@ -427,6 +430,7 @@ cpPlugins_Parameters_Clear( Uint ); cpPlugins_Parameters_Clear( Real ); cpPlugins_Parameters_Clear( Index ); cpPlugins_Parameters_Clear( Point ); +cpPlugins_Parameters_Clear( Vector ); // ------------------------------------------------------------------------- bool cpPlugins::Interface::Parameters:: diff --git a/lib/cpPlugins/Interface/Parameters.h b/lib/cpPlugins/Interface/Parameters.h index ef8e3b3..56cb5fd 100644 --- a/lib/cpPlugins/Interface/Parameters.h +++ b/lib/cpPlugins/Interface/Parameters.h @@ -31,12 +31,12 @@ namespace cpPlugins enum Type { - String , Bool , Int , - Uint , Real , Index , - Point , StringList , BoolList , - IntList , UintList , RealList , - IndexList , PointList , Choices , - NoType + String , Bool , Int , + Uint , Real , Index , + Point , Vector , StringList , + BoolList , IntList , UintList , + RealList , IndexList , PointList , + VectorList , Choices , NoType }; typedef bool TBool; @@ -78,6 +78,10 @@ namespace cpPlugins inline void ConfigureAsPoint( const TString& name, const TUint& dim, const P& v ); + template< class V > + inline void ConfigureAsVector( + const TString& name, const TUint& dim, const V& v + ); void ConfigureAsStringList( const TString& name ); void ConfigureAsBoolList( const TString& name ); @@ -86,6 +90,7 @@ namespace cpPlugins void ConfigureAsRealList( const TString& name ); void ConfigureAsIndexList( const TString& name ); void ConfigureAsPointList( const TString& name ); + void ConfigureAsVectorList( const TString& name ); void ConfigureAsChoices( const TString& name, const std::vector< TString >& choices ); @@ -101,6 +106,7 @@ namespace cpPlugins bool HasReal( const TString& name ) const; bool HasIndex( const TString& name ) const; bool HasPoint( const TString& name ) const; + bool HasVector( const TString& name ) const; bool HasStringList( const TString& name ) const; bool HasBoolList( const TString& name ) const; bool HasIntList( const TString& name ) const; @@ -108,6 +114,7 @@ namespace cpPlugins bool HasRealList( const TString& name ) const; bool HasIndexList( const TString& name ) const; bool HasPointList( const TString& name ) const; + bool HasVectorList( const TString& name ) const; bool HasChoices( const TString& name ) const; TString GetString( const TString& name ) const; @@ -141,6 +148,8 @@ namespace cpPlugins inline I GetIndex( const TString& name, const TUint& dim ) const; template< class P > inline P GetPoint( const TString& name, const TUint& dim ) const; + template< class V > + inline V GetVector( const TString& name, const TUint& dim ) const; template< class I > inline void GetIndexList( @@ -150,6 +159,10 @@ namespace cpPlugins inline void GetPointList( std::vector< P >& lst, const TString& name, const TUint& dim ) const; + template< class V > + inline void GetVectorList( + std::vector< V >& lst, const TString& name, const TUint& dim + ) const; // Set methods void SetString( const TString& name, const TString& v ); @@ -166,6 +179,10 @@ namespace cpPlugins inline void SetPoint( const TString& name, const TUint& dim, const P& v ); + template< class V > + inline void SetVector( + const TString& name, const TUint& dim, const V& v + ); void AddToStringList( const TString& name, const TString& v ); void AddToBoolList( const TString& name, const TBool& v ); @@ -181,6 +198,10 @@ namespace cpPlugins inline void AddToPointList( const TString& name, const TUint& dim, const P& v ); + template< class P > + inline void AddToVectorList( + const TString& name, const TUint& dim, const P& v + ); void ClearStringList( const TString& name ); void ClearBoolList( const TString& name ); @@ -189,6 +210,7 @@ namespace cpPlugins void ClearRealList( const TString& name ); void ClearIndexList( const TString& name ); void ClearPointList( const TString& name ); + void ClearVectorList( const TString& name ); bool SetSelectedChoice( const TString& name, const TString& choice ); diff --git a/lib/cpPlugins/Interface/Parameters.hxx b/lib/cpPlugins/Interface/Parameters.hxx index 4b4e342..0bb20c7 100644 --- a/lib/cpPlugins/Interface/Parameters.hxx +++ b/lib/cpPlugins/Interface/Parameters.hxx @@ -31,6 +31,21 @@ ConfigureAsPoint( const TString& name, const TUint& dim, const P& v ) this->Modified( ); } +// ------------------------------------------------------------------------- +template< class V > +void cpPlugins::Interface::Parameters:: +ConfigureAsVector( const TString& name, const TUint& dim, const V& v ) +{ + std::stringstream str; + str << v[ 0 ]; + for( unsigned int d = 1; d < dim; ++d ) + str << ";" << v[ d ]; + std::string s = str.str( ); + this->m_Parameters[ name ] = + TParameter( Self::Vector, TValues( s, s ) ); + this->Modified( ); +} + // ------------------------------------------------------------------------- template< class I > I cpPlugins::Interface::Parameters:: @@ -95,6 +110,38 @@ GetPoint( const TString& name, const TUint& dim ) const return( v ); } +// ------------------------------------------------------------------------- +template< class V > +V cpPlugins::Interface::Parameters:: +GetVector( const TString& name, const TUint& dim ) const +{ + V v; + TParameters::const_iterator i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == Self::Vector ) + { + std::istringstream str( i->second.second.second ); + std::string token; + unsigned int d = 0; + while( std::getline( str, token, ';' ) && d < dim ) + { + v[ d ] = std::atof( token.c_str( ) ); + d++; + + } // elihw + return( v ); + + } // fi + + } // fi + + // If parameter not found + for( unsigned int d = 0; d < dim; ++d ) + v[ d ] = float( 0 ); + return( v ); +} + // ------------------------------------------------------------------------- template< class I > void cpPlugins::Interface::Parameters:: @@ -165,6 +212,41 @@ GetPointList( } // elihw } +// ------------------------------------------------------------------------- +template< class V > +void cpPlugins::Interface::Parameters:: +GetVectorList( + std::vector< V >& lst, const TString& name, const TUint& dim + ) const +{ + lst.clear( ); + + TParameters::const_iterator i = this->m_Parameters.find( name ); + if( i == this->m_Parameters.end( ) ) + return; + if( i->second.first == Self::VectorList ) + return; + + std::istringstream str( i->second.second.second ); + std::string token; + unsigned int d = 0; + while( std::getline( str, token, '#' ) ) + { + std::istringstream str2( token ); + std::string token2; + unsigned int d = 0; + V v; + while( std::getline( str2, token2, ';' ) && d < dim ) + { + v[ d ] = std::atof( token.c_str( ) ); + d++; + + } // elihw + lst.push_back( v ); + + } // elihw +} + // ------------------------------------------------------------------------- template< class I > void cpPlugins::Interface::Parameters:: @@ -203,6 +285,25 @@ SetPoint( const TString& name, const TUint& dim, const P& v ) this->Modified( ); } +// ------------------------------------------------------------------------- +template< class V > +void cpPlugins::Interface::Parameters:: +SetVector( const TString& name, const TUint& dim, const V& v ) +{ + TParameters::iterator i = this->m_Parameters.find( name ); + if( i == this->m_Parameters.end( ) ) + return; + if( i->second.first != Self::Vector ) + return; + + std::stringstream str; + str << v[ 0 ]; + for( unsigned int d = 1; d < dim; ++d ) + str << ";" << v[ d ]; + i->second.second.second = str.str( ); + this->Modified( ); +} + // ------------------------------------------------------------------------- template< class I > void cpPlugins::Interface::Parameters:: @@ -247,6 +348,28 @@ AddToPointList( const TString& name, const TUint& dim, const P& v ) this->Modified( ); } +// ------------------------------------------------------------------------- +template< class V > +void cpPlugins::Interface::Parameters:: +AddToVectorList( const TString& name, const TUint& dim, const V& v ) +{ + TParameters::iterator i = this->m_Parameters.find( name ); + if( i == this->m_Parameters.end( ) ) + return; + if( i->second.first != Self::VectorList ) + return; + + std::stringstream str; + if( i->second.second.second == "" ) + str << v[ 0 ]; + else + str << "#" << v[ 0 ]; + for( unsigned int d = 1; d < dim; ++d ) + str << ";" << v[ d ]; + i->second.second.second += str.str( ); + this->Modified( ); +} + #endif // __CPPLUGINS__INTERFACE__PARAMETERS__HXX__ // eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/ParametersQtDialog.cxx b/lib/cpPlugins/Interface/ParametersQtDialog.cxx index cbe4484..90393ff 100644 --- a/lib/cpPlugins/Interface/ParametersQtDialog.cxx +++ b/lib/cpPlugins/Interface/ParametersQtDialog.cxx @@ -132,6 +132,22 @@ addInteractor( vtkRenderWindowInteractor* interactor ) this->m_Interactors.insert( interactor ); } +// ------------------------------------------------------------------------- +cpPlugins::Interface::ParametersQtDialog:: +TInteractors& cpPlugins::Interface::ParametersQtDialog:: +getInteractors( ) +{ + return( this->m_Interactors ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface::ParametersQtDialog:: +TInteractors& cpPlugins::Interface::ParametersQtDialog:: +getInteractors( ) const +{ + return( this->m_Interactors ); +} + // ------------------------------------------------------------------------- bool cpPlugins::Interface::ParametersQtDialog:: setParameters( Parameters* parameters ) diff --git a/lib/cpPlugins/Interface/ParametersQtDialog.h b/lib/cpPlugins/Interface/ParametersQtDialog.h index 9e9b73a..d19d314 100644 --- a/lib/cpPlugins/Interface/ParametersQtDialog.h +++ b/lib/cpPlugins/Interface/ParametersQtDialog.h @@ -32,6 +32,8 @@ namespace cpPlugins public: typedef cpExtensions::Interaction::ImageInteractorStyle TStyle; + typedef std::set< vtkRenderWindowInteractor* > TInteractors; + public: ParametersQtDialog( QWidget* parent = 0, Qt::WindowFlags f = 0 ); virtual ~ParametersQtDialog( ); @@ -39,6 +41,8 @@ namespace cpPlugins bool IsModal( ) const; Parameters* getParameters( ) const; void addInteractor( vtkRenderWindowInteractor* interactor ); + TInteractors& getInteractors( ); + const TInteractors& getInteractors( ) const; bool setParameters( Parameters* parameters ); void setTitle( const std::string& title ); @@ -53,7 +57,7 @@ namespace cpPlugins QVBoxLayout* m_ToolsLayout; bool m_IsModal; - std::set< vtkRenderWindowInteractor* > m_Interactors; + TInteractors m_Interactors; }; } // ecapseman diff --git a/lib/cpPlugins/Interface/ProcessObject.cxx b/lib/cpPlugins/Interface/ProcessObject.cxx index 1e89c85..7552e5e 100644 --- a/lib/cpPlugins/Interface/ProcessObject.cxx +++ b/lib/cpPlugins/Interface/ProcessObject.cxx @@ -121,6 +121,7 @@ AddInteractor( vtkRenderWindowInteractor* interactor ) this->m_ParametersDialog = new ParametersQtDialog( ); this->m_ParametersDialog->addInteractor( interactor ); #endif // cpPlugins_Interface_QT4 + this->m_Interactors.insert( interactor ); } // ------------------------------------------------------------------------- diff --git a/lib/cpPlugins/Interface/ProcessObject.h b/lib/cpPlugins/Interface/ProcessObject.h index 3dfe118..6578beb 100644 --- a/lib/cpPlugins/Interface/ProcessObject.h +++ b/lib/cpPlugins/Interface/ProcessObject.h @@ -42,6 +42,7 @@ namespace cpPlugins typedef itk::SmartPointer< const Self > ConstPointer; typedef Parameters TParameters; + typedef std::set< vtkRenderWindowInteractor* > TInteractors; enum DialogResult { @@ -137,6 +138,7 @@ namespace cpPlugins Parameters::Pointer m_Parameters; ParametersQtDialog* m_ParametersDialog; + TInteractors m_Interactors; Plugins* m_Plugins; bool m_Interactive; diff --git a/lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.cxx b/lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.cxx new file mode 100644 index 0000000..3eb6006 --- /dev/null +++ b/lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.cxx @@ -0,0 +1,187 @@ +#include "MacheteFilter.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::MacheteFilter:: +DialogResult cpPlugins::BasicFilters::MacheteFilter:: +ExecConfigurationDialog( QWidget* parent ) +{ + typedef cpExtensions::Interaction::ImageInteractorStyle _TImageStyle; + + // Choose a valid 3D interactor + vtkRenderWindowInteractor* iren = NULL; + auto iIt = this->m_Interactors.begin( ); + for( ; iIt != this->m_Interactors.end( ) && iren == NULL; ++iIt ) + { + _TImageStyle* istyle = + dynamic_cast< _TImageStyle* >( + ( *iIt )->GetInteractorStyle( ) + ); + if( istyle == NULL ) + iren = *iIt; + + } // rof + if( iren == NULL ) + return( Self::DialogResult_Cancel ); + + // Get bounding box + double bbox[ 6 ]; + cpPlugins::Interface::Image* image = + this->GetInput< cpPlugins::Interface::Image >( "Input" ); + bool input_found = false; + if( image != NULL ) + { + image->GetVTK< vtkImageData >( )->GetBounds( bbox ); + input_found = true; + + } // fi + cpPlugins::Interface::Mesh* mesh = + this->GetInput< cpPlugins::Interface::Mesh >( "Input" ); + if( mesh != NULL ) + { + mesh->GetVTK< vtkPolyData >( )->GetBounds( bbox ); + input_found = true; + + } // fi + if( !input_found ) + return( Self::DialogResult_Cancel ); + + // Create plane widget + if( this->m_PlaneWidget != NULL ) + this->m_PlaneWidget->Delete( ); + this->m_PlaneWidget = vtkPlaneWidget::New( ); + this->m_PlaneWidget->NormalToXAxisOn( ); + this->m_PlaneWidget->SetCenter( + ( bbox[ 1 ] + bbox[ 0 ] ) * double( 0.5 ), + ( bbox[ 3 ] + bbox[ 2 ] ) * double( 0.5 ), + ( bbox[ 5 ] + bbox[ 4 ] ) * double( 0.5 ) + ); + this->m_PlaneWidget->SetOrigin( + ( bbox[ 1 ] + bbox[ 0 ] ) * double( 0.5 ), + bbox[ 2 ], + bbox[ 4 ] + ); + this->m_PlaneWidget->SetPoint1( + ( bbox[ 1 ] + bbox[ 0 ] ) * double( 0.5 ), + bbox[ 3 ], + bbox[ 4 ] + ); + this->m_PlaneWidget->SetPoint2( + ( bbox[ 1 ] + bbox[ 0 ] ) * double( 0.5 ), + bbox[ 2 ], + bbox[ 5 ] + ); + this->m_PlaneWidget->SetResolution( 15 ); + this->m_PlaneWidget->SetRepresentationToWireframe( ); + this->m_PlaneWidget->SetInteractor( iren ); + this->m_PlaneWidget->PlaceWidget( ); + this->m_PlaneWidget->On( ); + + return( Self::DialogResult_Modal ); +} + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::MacheteFilter:: +MacheteFilter( ) + : Superclass( ), + m_PlaneWidget( NULL ) +{ + this->_AddInput( "Input" ); + this->_MakeOutput< cpPlugins::Interface::DataObject >( "Output" ); + + itk::Point< double, 3 > center; + itk::Vector< double, 3 > normal; + + center.Fill( double( 0 ) ); + normal.Fill( double( 0 ) ); + normal[ 0 ] = double( 1 ); + + this->m_Parameters->ConfigureAsPoint( "PlaneCenter", 3, center ); + this->m_Parameters->ConfigureAsVector( "PlaneNormal", 3, normal ); +} + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::MacheteFilter:: +~MacheteFilter( ) +{ + if( this->m_PlaneWidget != NULL ) + this->m_PlaneWidget->Delete( ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::BasicFilters::MacheteFilter:: +_GenerateData( ) +{ + cpPlugins::Interface::Image* image = + this->GetInput< cpPlugins::Interface::Image >( "Input" ); + if( image != NULL ) + return( this->_FromImage( image ) ); + cpPlugins::Interface::Mesh* mesh = + this->GetInput< cpPlugins::Interface::Mesh >( "Input" ); + if( mesh == NULL ) + return( this->_FromMesh( mesh ) ); + return( "MacheteFilter: No valid input." ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::BasicFilters::MacheteFilter:: +_FromImage( cpPlugins::Interface::Image* image ) +{ + itk::DataObject* itk_image = NULL; + std::string r = ""; + cpPlugins_Image_Demangle_AllScalarTypes( 2, image, itk_image, r, _RealImage ); + else cpPlugins_Image_Demangle_AllScalarTypes( 3, image, itk_image, r, _RealImage ); + else r = "MacheteFilter: Input image type not supported."; + return( r ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::BasicFilters::MacheteFilter:: +_FromMesh( cpPlugins::Interface::Mesh* mesh ) +{ + return( "" ); +} + +#include + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPlugins::BasicFilters::MacheteFilter:: +_RealImage( itk::DataObject* dobj ) +{ + typedef typename I::PixelType _TPixel; + typedef itk::PlaneSpatialObject< I::ImageDimension > _TPlane; + typedef itk::SpatialObjectToImageFilter< _TPlane, I > _TMaskFilter; + + I* image = dynamic_cast< I* >( dobj ); + + typename _TMaskFilter::Pointer mask = _TMaskFilter::New( ); + mask->SetDirection( image->GetDirection( ) ); + mask->SetOrigin( image->GetOrigin( ) ); + mask->SetSize( image->GetRequestedRegion( ).GetSize( ) ); + mask->SetSpacing( image->GetSpacing( ) ); + mask->SetInsideValue( _TPixel( 1 ) ); + mask->SetOutsideValue( _TPixel( 0 ) ); + + typename itk::ImageFileWriter< I >::Pointer w = + itk::ImageFileWriter< I >::New( ); + w->SetInput( mask->GetOutput( ) ); + w->SetFileName( "mask.mhd" ); + w->Update( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.h b/lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.h new file mode 100644 index 0000000..ad6669c --- /dev/null +++ b/lib/cpPlugins/Plugins/BasicFilters/MacheteFilter.h @@ -0,0 +1,73 @@ +#ifndef __CPPLUGINS__PLUGINS__MACHETEFILTER__H__ +#define __CPPLUGINS__PLUGINS__MACHETEFILTER__H__ + +#include +#include + +// Some forward declarations +class vtkPlaneWidget; + +namespace cpPlugins +{ + // Some forward declarations + namespace Interface + { + class Image; + class Mesh; + + } // ecapseman + + namespace BasicFilters + { + /** + */ + class cpPluginsBasicFilters_EXPORT MacheteFilter + : public cpPlugins::Interface::FilterObject + { + public: + typedef MacheteFilter Self; + typedef cpPlugins::Interface::FilterObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( MacheteFilter, FilterObject ); + cpPlugins_Id_Macro( + cpPlugins::BasicFilters::MacheteFilter, "FilterObject" + ); + + public: + virtual DialogResult ExecConfigurationDialog( QWidget* parent ); + + protected: + MacheteFilter( ); + virtual ~MacheteFilter( ); + + virtual std::string _GenerateData( ); + + std::string _FromImage( cpPlugins::Interface::Image* image ); + std::string _FromMesh( cpPlugins::Interface::Mesh* mesh ); + + template< class I > + inline std::string _RealImage( itk::DataObject* dobj ); + + private: + // Purposely not implemented + MacheteFilter( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkPlaneWidget* m_PlaneWidget; + }; + + // --------------------------------------------------------------------- + CPPLUGINS_INHERIT_PROVIDER( MacheteFilter ); + + } // ecapseman + +} // ecapseman + +#endif // __CPPLUGINS__PLUGINS__MACHETEFILTER__H__ + +// eof - $RCSfile$ -- 2.45.2