From: Leonardo Flórez-Valencia Date: Thu, 2 Feb 2017 18:44:54 +0000 (-0500) Subject: yet another refactoring X-Git-Tag: v0.1~19 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=3c250e0e573d7f08276aefd93a5336f128e6b1a7;p=cpPlugins.git yet another refactoring --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d584f6e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,50 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.0) + +## ======================== +## == Project definition == +## ======================== + +SET(prj_NAME cpPlugins) +SET(prj_MAJ_VERSION 0) +SET(prj_MIN_VERSION 1) +SET(prj_REL_VERSION 0) +SET(_subdirs cmake bash lib tools plugins appli) +SET(_policies CMP0015 CMP0020 CMP0042) + +## ========================== +## == Some useful policies == +## ========================== + +FOREACH(_p ${_policies}) + IF(POLICY ${_p}) + CMAKE_POLICY(SET ${_p} NEW) + ENDIF(POLICY ${_p}) +ENDFOREACH(_p) + +## =========================== +## == Project configuration == +## =========================== + +PROJECT(${prj_NAME}) +SET(prj_VERSION"${prj_MAJ_VERSION}.${prj_MIN_VERSION}.${prj_REL_VERSION}") +SET(prj_SHORT_VERSION "${prj_MAJ_VERSION}") + +## ===================================== +## == Functions, packages and options == +## ===================================== + +INCLUDE(cmake/BaseConfig.cmake) +INCLUDE(cmake/Options.cmake) +INCLUDE(cmake/KitwareTools.cmake) +INCLUDE(cmake/QtTools.cmake) +INCLUDE(cmake/Functions.cmake) + +## =========================== +## == Build different parts == +## =========================== + +FOREACH(_s ${_subdirs}) + SUBDIRS(${_s}) +ENDFOREACH(_s) + +## eof - $RCSfile$ diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt new file mode 100644 index 0000000..414db20 --- /dev/null +++ b/appli/CMakeLists.txt @@ -0,0 +1,10 @@ + +## =================================== +## == One directory per application == +## =================================== + +SUBDIRS( + PipelineEditor + ) + +## eof - $RCSfile$ diff --git a/appli/PipelineEditor/CMakeLists.txt b/appli/PipelineEditor/CMakeLists.txt new file mode 100644 index 0000000..11b7d77 --- /dev/null +++ b/appli/PipelineEditor/CMakeLists.txt @@ -0,0 +1,14 @@ +IF(BUILD_QT4_COMPONENTS) + INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_BINARY_DIR}/lib + ${PROJECT_SOURCE_DIR}/appli/PipelineEditor + ${PROJECT_BINARY_DIR}/appli/PipelineEditor + ) + cpPlugins_BuildApplication(PipelineEditor ${CMAKE_CURRENT_SOURCE_DIR}) + IF(BUILD_PipelineEditor) + TARGET_LINK_LIBRARIES(PipelineEditor cpBaseQtApplication) + ENDIF(BUILD_PipelineEditor) +ENDIF(BUILD_QT4_COMPONENTS) + +## eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditor.cxx b/appli/PipelineEditor/PipelineEditor.cxx new file mode 100644 index 0000000..c55920f --- /dev/null +++ b/appli/PipelineEditor/PipelineEditor.cxx @@ -0,0 +1,157 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +PipelineEditor:: +PipelineEditor( int argc, char* argv[], QWidget* parent ) + : Superclass( argc, argv, parent ), + m_UI( new Ui::PipelineEditor ) +{ + // Basic configuration + this->m_BaseWindowTitle = "PipelineEditor - "; + this->m_UI->setupUi( this ); + this->setCanvas( this->m_UI->Canvas ); + this->setNavigator( this->m_UI->Navigator ); + this->m_UI->Navigator->Update( ); + + // Connect slots <-> signals + cpBaseQtApplication_ConnectAction( actionLoadDirectory, _loadPluginsFromPath ); + cpBaseQtApplication_ConnectAction( actionLoadLibrary, _loadPlugins ); + cpBaseQtApplication_ConnectAction( actionOpenWorkspace, _loadWorkspace ); + cpBaseQtApplication_ConnectAction( actionSaveWorkspace, _saveWorkspace ); + cpBaseQtApplication_ConnectAction( actionSaveWorkspaceAs, _saveWorkspace ); + cpBaseQtApplication_ConnectAction( actionActorsProperties, _actorsProperties ); + this->m_UI->Canvas->connectOutputPortSlot( + this, SLOT( _slotView( const std::string&, bool ) ) + ); + this->connect( + this->m_UI->actionPrintExecutionInformation, SIGNAL( triggered( bool ) ), + this, SLOT( _slotPrintExecutionInformation( bool ) ) + ); + + // Load command-line given workspace (if any) + if( argc > 1 ) + this->_loadWorkspace( argv[ 1 ] ); +} + +// ------------------------------------------------------------------------- +PipelineEditor:: +~PipelineEditor( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_slotView( const std::string& name, bool show ) +{ + typedef cpExtensions::QT::ActorsWidgetInterface _TViewer; + + // Get filter parameters + std::vector< std::string > tokens = + cpPlugins::OS::String::Tokenize( name, "@" ); + if( tokens.size( ) != 2 ) + return; + auto filter_name = tokens[ 1 ]; + auto output_name = tokens[ 0 ]; + + // Process data + if( show ) + { + try + { + auto ws = this->workspace( ); + auto filter = ws->GetFilter( filter_name ); + cpBaseQtApplication_Execute( filter->Update( ) ); + auto image = filter->GetOutputData< vtkImageData >( output_name ); + auto mesh = filter->GetOutputData< vtkPolyData >( output_name ); + _TViewer* viewer = NULL; + if( image != NULL ) + { + int dim = image->GetDataDimension( ); + if( dim == 2 ) + viewer = + this->_configureViewer< cpExtensions::QT::ImageWidget >( + this->m_UI->Viewer + ); + else if( dim == 3 ) + viewer = + this->_configureViewer< cpExtensions::QT::SimpleMPRWidget >( + this->m_UI->Viewer + ); + } + else if( mesh != NULL ) + { + viewer = + this->_configureViewer< cpExtensions::QT::SimpleMPRWidget >( + this->m_UI->Viewer + ); + + } // fi + if( + dynamic_cast< QWidget* >( viewer ) != + dynamic_cast< QWidget* >( this->m_UI->Viewer ) && + viewer != NULL + ) + { + delete this->m_UI->Viewer; + this->m_UI->Viewer = dynamic_cast< QWidget* >( viewer ); + this->m_UI->MainSplitter->insertWidget( 0, this->m_UI->Viewer ); + this->setViewer( viewer ); + + } // fi + if( image != NULL ) + { + this->m_Blocker.block( ); + auto mpr = dynamic_cast< cpExtensions::QT::SimpleMPRWidget* >( viewer ); + auto imv = dynamic_cast< cpExtensions::QT::ImageWidget* >( viewer ); + if( mpr != NULL ) + mpr->SetImage( image, name ); + else if( imv != NULL ) + imv->SetImage( image, name ); + this->m_Blocker.unblock( ); + } + else if( mesh != NULL ) + { + this->m_Blocker.block( ); + auto mpr = dynamic_cast< cpExtensions::QT::SimpleMPRWidget* >( viewer ); + if( mpr != NULL ) + mpr->Add( mesh, name ); + this->m_Blocker.unblock( ); + + } // fi + } + catch( std::exception& err ) + { + QMessageBox::critical( + NULL, + QMessageBox::tr( "Error showing data" ), + QMessageBox::tr( err.what( ) ) + ); + + } // yrt + + } // fi +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_slotPrintExecutionInformation( bool show ) +{ + if( this->m_Workspace.IsNotNull( ) ) + this->m_Workspace->SetPrintExecution( show ); +} + +// ------------------------------------------------------------------------- +#include +cpBaseQtApplication_Main( PipelineEditor ); +cpBaseQtApplication_MainComplement; + +// eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditor.h b/appli/PipelineEditor/PipelineEditor.h new file mode 100644 index 0000000..1b6674e --- /dev/null +++ b/appli/PipelineEditor/PipelineEditor.h @@ -0,0 +1,36 @@ +#ifndef __PipelineEditor__h__ +#define __PipelineEditor__h__ + +#include +#include + +namespace Ui { class PipelineEditor; } + +/** + */ +class PipelineEditor + : public cpBaseQtApplication::MainWindow +{ + Q_OBJECT; +public: + typedef PipelineEditor Self; + typedef cpBaseQtApplication::MainWindow Superclass; + +public: + explicit PipelineEditor( + int argc, char* argv[], + QWidget* parent = NULL + ); + virtual ~PipelineEditor( ); + +protected slots: + void _slotView( const std::string& name, bool show ); + void _slotPrintExecutionInformation( bool show ); + +private: + Ui::PipelineEditor* m_UI; +}; + +#endif // __PipelineEditor__h__ + +// eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditor.ui b/appli/PipelineEditor/PipelineEditor.ui new file mode 100644 index 0000000..0e61512 --- /dev/null +++ b/appli/PipelineEditor/PipelineEditor.ui @@ -0,0 +1,188 @@ + + + PipelineEditor + + + + 0 + 0 + 800 + 600 + + + + PipelineEditor + + + + + 2 + + + 2 + + + + + Qt::Vertical + + + + + Qt::Horizontal + + + + + + + + + + + + 0 + 0 + 800 + 25 + + + + + &File + + + + + + + + + + &Properties + + + + + + Plu&gins + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + E&xit + + + + + &Open workspace + + + Ctrl+O + + + + + &Save workspace + + + Ctrl+S + + + + + Sa&ve workspace as... + + + Ctrl+Shift+S + + + + + &Actors + + + Ctrl+Shift+P + + + + + Load &library + + + Ctrl+Shift+L + + + + + Load &directory + + + Ctrl+Shift+D + + + + + true + + + Print execution information? + + + Print execution information? + + + + + + cpBaseQtApplication::Plugins::Navigator + QWidget +
cpBaseQtApplication/Plugins/Navigator.h
+ 1 +
+ + cpBaseQtApplication::Pipeline::Canvas + QWidget +
cpBaseQtApplication/Pipeline/Canvas.h
+ 1 +
+
+ + + + actionExit + triggered() + PipelineEditor + close() + + + -1 + -1 + + + 399 + 299 + + + + +
diff --git a/bash/CMakeLists.txt b/bash/CMakeLists.txt new file mode 100644 index 0000000..36c5075 --- /dev/null +++ b/bash/CMakeLists.txt @@ -0,0 +1,25 @@ +CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/Config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/Config.h + @ONLY + ) +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} + ) +SET( + _progs + CreateDemanglers + CreateInstances + CreateRealConfig + HostCreator + ) +FOREACH(_p ${_progs}) + ADD_EXECUTABLE(cpPlugins_bash_${_p} ${_p}) + SET( + cpPlugins_bash_${_p}_APP cpPlugins_bash_${_p} + CACHE INTERNAL "bash program cpPlugins_bash_${_p}" + ) +ENDFOREACH(_p) + +## eof - $RCSfile$ diff --git a/bash/Config.h.in b/bash/Config.h.in new file mode 100644 index 0000000..1d53531 --- /dev/null +++ b/bash/Config.h.in @@ -0,0 +1,274 @@ +#ifndef __cpPlugins__bash__Config__h__ +#define __cpPlugins__bash__Config__h__ + +// ------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpPlugins_PROCESS_DIMS "@cpPlugins_PROCESS_DIMS@" +#define cpPlugins_VISUAL_DIMS "@cpPlugins_VISUAL_DIMS@" +#define cpPlugins_ALL_CONFIGS "@cpPlugins_ALL_CONFIGS@" +#define cpPlugins_NUMBER_OF_FILES @cpPlugins_NUMBER_OF_FILES@ + +// ------------------------------------------------------------------------- +#define cpPlugins_bash_OS_@CMAKE_SYSTEM_NAME@ +#ifdef cpPlugins_bash_OS_Windows +# define cpPlugins_bash_STRTOK( A, B, N ) strtok_s( A, B, N ) +# define cpPlugins_bash_SPRINTF( B, S, O ) sprintf_s( B, S, "%s", O ); +#else // cpPlugins_bash_OS_Windows +# define cpPlugins_bash_STRTOK( A, B, N ) std::strtok( A, B ) +# define cpPlugins_bash_SPRINTF( B, S, O ) std::sprintf( B, "%s", O ); +#endif // cpPlugins_bash_OS_Windows + +// ------------------------------------------------------------------------- +typedef std::deque< std::string > TStrings; +typedef std::map< std::string, TStrings > TCommands; + +/** + */ +namespace cpPlugins_bash +{ + // ----------------------------------------------------------------------- + template< class _TTokens > + inline void Tokenize( + _TTokens& tokens, const std::string& str, const std::string& delims + ) + { + tokens.clear( ); + if( str.size( ) > 0 ) + { + auto ssize = str.size( ); + char* buffer = new char[ ssize + 1 ]; + for( unsigned long i = 0; i < ssize; ++i ) + buffer[ i ] = str[ i ]; + buffer[ ssize ] = '\0'; + char* next; + char* it = cpPlugins_bash_STRTOK( buffer, delims.c_str( ), &next ); + while( it != NULL ) + { + tokens.push_back( std::string( it ) ); + it = cpPlugins_bash_STRTOK( NULL, delims.c_str( ), &next ); + + } // elihw + delete [] buffer; + + } // fi + } + + // ----------------------------------------------------------------------- + inline std::string Replace( + const std::string& str, const std::string& sub, const std::string& nsub + ) + { + std::string res = str; + size_t index; + while( ( index = res.find( sub ) ) != std::string::npos ) + res.replace( index, sub.size( ), nsub ); + return( res ); + } + + // ----------------------------------------------------------------------- + inline bool Read( std::string& buffer, const std::string& fname ) + { + buffer = ""; + std::ifstream file_stream( fname.c_str( ) ); + if( !file_stream ) + return( false ); + file_stream.seekg( 0, std::ios::end ); + buffer.reserve( ( unsigned int )( file_stream.tellg( ) ) ); + file_stream.seekg( 0, std::ios::beg ); + buffer.assign( + ( std::istreambuf_iterator< char >( file_stream ) ), + std::istreambuf_iterator< char >( ) + ); + file_stream.close( ); + return( true ); + } + + // ----------------------------------------------------------------------- + inline bool Write( const std::string& buffer, const std::string& fname ) + { + std::ofstream file_stream( fname.c_str( ), std::ofstream::binary ); + if( !file_stream ) + return( false ); + file_stream.write( buffer.c_str( ), buffer.size( ) ); + return( true ); + } + + // ----------------------------------------------------------------------- + inline void Parse( TCommands& commands, const TStrings& lines ) + { + for( auto l = lines.begin( ); l != lines.end( ); ++l ) + { + auto line = l->substr( l->find_first_not_of( " " ) ); + if( line != "" ) + { + if( line[ 0 ] != '*' ) + { + auto cmd = line.substr( 0, line.find( " " ) ); + auto args = line.substr( line.find( " " ) + 1 ); + commands[ cmd ].push_back( args ); + + } // fi + + } // fi + + } // rof + } + + // ----------------------------------------------------------------------- + inline void LoadDefinitions( TCommands& commands ) + { + // Dimensions + commands[ "define" ].push_back( + std::string( "pdims=" ) + + std::string( cpPlugins_PROCESS_DIMS ) + ); + commands[ "define" ].push_back( + std::string( "vdims=" ) + + std::string( cpPlugins_VISUAL_DIMS ) + ); + + // Base c++ types + commands[ "define" ].push_back( + std::string( "int_types=char;short;int;long" ) + ); + commands[ "define" ].push_back( + std::string( "uint_types=unsigned #int_types#" ) + ); + commands[ "define" ].push_back( + std::string( "sint_types=signed char" ) + ); + commands[ "define" ].push_back( + std::string( "real_types=float;double" ) + ); + commands[ "define" ].push_back( + std::string( + "scalar_types=#int_types#;#uint_types#;#real_types#" + ) + ); + } + + // ----------------------------------------------------------------------- + inline void ExpandDefinitions( + TCommands& definitions, const TCommands& commands + ) + { + definitions.clear( ); + auto defs = commands.find( "define" ); + if( defs == commands.end( ) ) + return; + + std::map< std::string, std::string > values; + for( auto dIt = defs->second.begin( ); dIt != defs->second.end( ); ++dIt ) + { + TStrings toks; + cpPlugins_bash::Tokenize( toks, *dIt, "=" ); + if( toks.size( ) == 2 ) + { + auto name = toks[ 0 ].substr( toks[ 0 ].find_first_not_of( " " ) ); + auto val = toks[ 1 ].substr( toks[ 1 ].find_first_not_of( " " ) ); + values[ name ] = val; + + } // fi + + } // rof + for( auto vIt = values.begin( ); vIt != values.end( ); ++vIt ) + { + TStrings toks; + cpPlugins_bash::Tokenize( toks, vIt->second, ";" ); + for( auto tIt = toks.begin( ); tIt != toks.end( ); ++tIt ) + definitions[ vIt->first ].push_back( *tIt ); + + } // rof + for( auto dIt = definitions.begin( ); dIt != definitions.end( ); ++dIt ) + { + auto name = std::string( "#" ) + dIt->first + std::string( "#" ); + for( auto eIt = definitions.begin( ); eIt != definitions.end( ); ++eIt ) + { + if( eIt != dIt ) + { + auto vIt = eIt->second.begin( ); + while( vIt != eIt->second.end( ) ) + { + if( vIt->find( name ) != std::string::npos ) + { + for( + auto wIt = dIt->second.begin( ); + wIt != dIt->second.end( ); + ++wIt + ) + eIt->second.push_back( + cpPlugins_bash::Replace( *vIt, name, *wIt ) + ); + vIt = eIt->second.erase( vIt ); + } + else + ++vIt; + + } // elihw + + } // fi + + } // rof + + } // rof + } + + // ----------------------------------------------------------------------- + inline void Expand( + TStrings& tfiles, + const TCommands& definitions, + const TCommands& commands, + const std::string& cmd + ) + { + tfiles.clear( ); + auto tIt = commands.find( cmd ); + if( tIt == commands.end( ) ) + return; + + for( auto fIt = tIt->second.begin( ); fIt != tIt->second.end( ); ++fIt ) + { + std::queue< std::string > q; + q.push( *fIt ); + while( q.size( ) > 0 ) + { + auto value = q.front( ); + q.pop( ); + auto spos = value.find( "#" ); + if( spos != std::string::npos ) + { + auto name = value.substr( spos + 1 ); + auto epos = name.find( "#" ); + name = name.substr( 0, epos ); + auto dIt = definitions.find( name ); + if( dIt != definitions.end( ) ) + { + name = std::string( "#" ) + name + std::string( "#" ); + for( auto vIt = dIt->second.begin( ); vIt != dIt->second.end( ); ++vIt ) + q.push( cpPlugins_bash::Replace( value, name, *vIt ) ); + + } // fi + } + else + tfiles.push_back( value ); + + } // rof + + } // rof + } + +} // ecapseman + +#endif // __cpPlugins__bash__Config__h__ + +// eof - $RCSfile$ diff --git a/bash/CreateDemanglers.cxx b/bash/CreateDemanglers.cxx new file mode 100644 index 0000000..a68117f --- /dev/null +++ b/bash/CreateDemanglers.cxx @@ -0,0 +1,121 @@ +#include + +#define MAX_NUMBER_OF_INPUTS 9 + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get inputs + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " definitons_file object_name output_file" + << std::endl; + return( 1 ); + + } // fi + std::string definitions_filename = argv[ 1 ]; + std::string object_name = argv[ 2 ]; + std::string output_filename = argv[ 3 ]; + + // Read inputs + std::string definitions_buffer; + if( !( cpPlugins_bash::Read( definitions_buffer, definitions_filename ) ) ) + { + std::cerr + << argv[ 0 ] + << ": Error reading definitions file \"" << definitions_filename + << "\"" << std::endl; + return( 1 ); + + } // fi + + // Put it in a line-by-line structure + TStrings definitions_lines; + cpPlugins_bash::Tokenize( definitions_lines, definitions_buffer, "\n" ); + + // Parse input file + TCommands commands; + cpPlugins_bash::Parse( commands, definitions_lines ); + + // Load pre-compiled definitions + cpPlugins_bash::LoadDefinitions( commands ); + + // Expand definitions + TCommands definitions; + cpPlugins_bash::ExpandDefinitions( definitions, commands ); + + // Expand data + std::stringstream data; + data + << "#ifndef __cpPlugins__Demanglers__" << object_name << "__h__" << std::endl + << "#define __cpPlugins__Demanglers__" << object_name << "__h__" << std::endl + << std::endl; + + for( auto cIt = commands.begin( ); cIt != commands.end( ); ++cIt ) + { + if( cIt->first == "define" ) + continue; + + TStrings instances; + cpPlugins_bash::Expand( instances, definitions, commands, cIt->first ); + TStrings toks; + cpPlugins_bash::Tokenize( toks, cIt->first, "|" ); + for( unsigned int nIns = 1; nIns <= MAX_NUMBER_OF_INPUTS; ++nIns ) + { + if( toks.size( ) > 1 ) + { + data + << "#define cpPlugins_Demangle_" << object_name << "_" + << toks[ 0 ] << "_" << nIns << "( o, f"; + for( unsigned int i = 1; i < toks.size( ); ++i ) + data << ", " << toks[ i ]; + } + else + data + << "#define cpPlugins_Demangle_" << object_name << "_" + << toks[ 0 ] << "_" << nIns << "( o, f"; + + for( unsigned int i = 1; i < nIns; ++i ) + data << ", X" << i; + data << " ) \\"; + + data << std::endl; + std::string prefix = ""; + for( auto iIt = instances.begin( ); iIt != instances.end( ); ++iIt ) + { + data + << " " << prefix + << "if( dynamic_cast< " << *iIt << "* >( o ) != NULL ) \\" + << std::endl + << " this->f( dynamic_cast< " << *iIt << "* >( o )"; + + for( unsigned int i = 1; i < nIns; ++i ) + data << ", X" << i; + data + << " ); \\" + << std::endl; + prefix = "else "; + + } // rof + data << " " << prefix << std::endl << std::endl; + + } // rof + + } // rof + + data + << "#endif // __cpPlugins__Demanglers__" << object_name << "__h__" + << std::endl; + if( !( cpPlugins_bash::Write( data.str( ), output_filename ) ) ) + { + std::cerr << "Error writing file." << std::endl; + return( 1 ); + + } // fi + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/bash/CreateInstances.cxx b/bash/CreateInstances.cxx new file mode 100644 index 0000000..a107c26 --- /dev/null +++ b/bash/CreateInstances.cxx @@ -0,0 +1,168 @@ +#include + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get inputs + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " definitons_file library_name output_prefix" + << std::endl; + return( 1 ); + + } // fi + std::string definitions_filename = argv[ 1 ]; + std::string library_name = argv[ 2 ]; + std::string output_prefix = argv[ 3 ]; + unsigned int number_of_sources = cpPlugins_NUMBER_OF_FILES; + + // Read inputs + std::string definitions_buffer; + if( !( cpPlugins_bash::Read( definitions_buffer, definitions_filename ) ) ) + { + std::cerr + << argv[ 0 ] + << ": Error reading definitions file \"" << definitions_filename + << "\"" << std::endl; + return( 1 ); + + } // fi + + // Put it in a line-by-line structure + TStrings definitions_lines; + cpPlugins_bash::Tokenize( definitions_lines, definitions_buffer, "\n" ); + + // Parse input file + TCommands commands; + cpPlugins_bash::Parse( commands, definitions_lines ); + + // Load pre-compiled definitions + cpPlugins_bash::LoadDefinitions( commands ); + + // Expand definitions + TCommands definitions; + cpPlugins_bash::ExpandDefinitions( definitions, commands ); + definitions[ "_export_" ].clear( ); + definitions[ "_export_" ].push_back( library_name + std::string( "_EXPORT" ) ); + + // Expand data + TStrings tfiles, cfiles, instances, minstances; + cpPlugins_bash::Expand( tfiles, definitions, commands, "tinclude" ); + cpPlugins_bash::Expand( cfiles, definitions, commands, "cinclude" ); + cpPlugins_bash::Expand( instances, definitions, commands, "instances" ); + cpPlugins_bash::Expand( minstances, definitions, commands, "minstances" ); + + // Build all instances + TStrings all_instances; + for( auto iIt = instances.begin( ); iIt != instances.end( ); ++iIt ) + { + std::stringstream str; + str << "template class " << library_name << "_EXPORT " << *iIt; + all_instances.push_back( str.str( ) ); + + } // rof + for( auto iIt = minstances.begin( ); iIt != minstances.end( ); ++iIt ) + { + std::stringstream str; + str << "template " << *iIt; + all_instances.push_back( str.str( ) ); + + } // rof + + // Write source code + unsigned int instances_per_file = + ( unsigned int )( + std::floor( double( all_instances.size( ) ) / double( number_of_sources ) ) + ); + if( instances_per_file == 0 ) + instances_per_file = 1; + std::vector< std::vector< std::string > > all_lines( 1 ); + for( unsigned int c_id = 0; c_id < all_instances.size( ); ++c_id ) + { + all_lines[ all_lines.size( ) - 1 ].push_back( all_instances[ c_id ] ); + if( c_id % instances_per_file == instances_per_file - 1 ) + all_lines.push_back( std::vector< std::string >( ) ); + + } // rof + + // Paranoiac code + while( all_lines.size( ) > number_of_sources ) + { + all_lines[ all_lines.size( ) - 2 ].insert( + all_lines[ all_lines.size( ) - 2 ].end( ), + all_lines[ all_lines.size( ) - 1 ].begin( ), + all_lines[ all_lines.size( ) - 1 ].end( ) + ); + all_lines.pop_back( ); + + } // elihw + while( all_lines.size( ) < number_of_sources ) + all_lines.push_back( std::vector< std::string >( ) ); + + // Real write + for( unsigned int f_id = 0; f_id < all_lines.size( ); ++f_id ) + { + std::stringstream source; + source + << "#include <" << library_name << "_Export.h>" + << std::endl; + auto hIt = commands.find( "header" ); + if( hIt != commands.end( ) ) + { + source << std::endl; + for( auto vIt = hIt->second.begin( ); vIt != hIt->second.end( ); ++vIt ) + source << *vIt << std::endl; + source << std::endl; + + } // fi + + if( tfiles.size( ) > 0 ) + { + for( auto tIt = tfiles.begin( ); tIt != tfiles.end( ); ++tIt ) + { + TStrings toks; + cpPlugins_bash::Tokenize( toks, *tIt, ":|" ); + if( toks.size( ) == 3 ) + { + source << "#include <" << toks[ 0 ] << "." << toks[ 1 ] << ">" << std::endl; + source << "#include <" << toks[ 0 ] << "." << toks[ 2 ] << ">" << std::endl; + + } // fi + + } // rof + source << std::endl; + + } // fi + + if( cfiles.size( ) > 0 ) + { + for( auto cIt = cfiles.begin( ); cIt != cfiles.end( ); ++cIt ) + source << "#include <" << *cIt << ">" << std::endl; + source << std::endl; + + } // fi + + for( + auto c_it = all_lines[ f_id ].begin( ); + c_it != all_lines[ f_id ].end( ); + ++c_it + ) + source << *c_it << ";" << std::endl; + source << std::endl << "// eof" << std::endl; + std::stringstream source_file; + source_file + << output_prefix << "_" << f_id << ".cxx"; + if( !( cpPlugins_bash::Write( source.str( ), source_file.str( ) ) ) ) + { + std::cerr << "Error writing source code." << std::endl; + return( 1 ); + + } // fi + + } // rof + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/bash/CreateRealConfig.cxx b/bash/CreateRealConfig.cxx new file mode 100644 index 0000000..e9737d5 --- /dev/null +++ b/bash/CreateRealConfig.cxx @@ -0,0 +1,37 @@ +#include + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get inputs + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " output_file" << std::endl; + return( 1 ); + + } // fi + std::string output_filename = argv[ 1 ]; + + std::stringstream data; + data + << "#ifndef __cpPlugins__RealConfig__h__" << std::endl + << "#define __cpPlugins__RealConfig__h__" << std::endl + << std::endl; + + TStrings tokens; + cpPlugins_bash::Tokenize( tokens, cpPlugins_ALL_CONFIGS, ";" ); + for( auto t = tokens.begin( ); t != tokens.end( ); ++t ) + data << "#define " << *t << std::endl; + + data << std::endl << "#endif // __cpPlugins__RealConfig__h__" << std::endl; + if( !( cpPlugins_bash::Write( data.str( ), output_filename ) ) ) + { + std::cerr << "Error writing file." << std::endl; + return( 1 ); + + } // fi + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/bash/HostCreator.cxx b/bash/HostCreator.cxx new file mode 100644 index 0000000..8e6f274 --- /dev/null +++ b/bash/HostCreator.cxx @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +typedef std::pair< std::string, std::string > TPair; +typedef std::map< std::string, TPair > TInfo; + +// ------------------------------------------------------------------------- +bool is_valid_class( const std::string& str ) +{ + return( str.find( "cpPluginsObject" ) != std::string::npos ); +} + +// ------------------------------------------------------------------------- +void process_header( TInfo& info, const std::string& file_name ) +{ + std::string buffer; + if( !( cpPlugins_bash::Read( buffer, file_name ) ) ) + return; + + auto prev_pos = std::string::npos; + prev_pos = 0; + auto pos = buffer.find( "cpPluginsObject" ); + while( pos != std::string::npos ) + { + // Get class names + auto op = buffer.find( "(", pos ); + auto cl = buffer.find( ")", pos ); + std::vector< std::string > tokens; + cpPlugins_bash::Tokenize( + tokens, + buffer.substr( op + 1, cl - op - 2 ), + ",\n " + ); + + std::string namespace_name = ""; + auto preamble = buffer.substr( prev_pos, pos ); + auto napos = preamble.find( "namespace" ); + while( napos != std::string::npos ) + { + auto enapos = preamble.find( "{", napos + 1 ); + auto tmp = preamble.substr( napos, enapos - napos + 1 ); + std::vector< std::string > tokens2; + cpPlugins_bash::Tokenize( tokens2, tmp, " \n\t{" ); + namespace_name = tokens2.back( ); + napos = preamble.find( "namespace", napos + 1 ); + + } // elihw + + auto class_name = tokens[ 0 ]; + auto superclass_name = tokens[ 1 ]; + auto category_name = tokens[ 2 ]; + if( info.find( class_name ) == info.end( ) ) + info[ class_name ] = TPair( category_name, namespace_name ); + prev_pos = pos; + pos = buffer.find( "cpPluginsObject", pos + 1 ); + + } // elihw +} + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " plugins_name output_file header_file_0.h header_file_0.h ..." + << std::endl; + return( 1 ); + + } // fi + std::string plugins_name = argv[ 1 ]; + std::string output_filename = argv[ 2 ]; + + // Parse all header files + TInfo info; + for( int i = 3; i < argc; ++i ) + process_header( info, argv[ i ] ); + if( info.size( ) == 0 ) + { + std::cerr << "ERROR: No valid input headers." << std::endl; + return( 1 ); + + } // fi + + // Prepare prefixes +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + std::string export_prefix = "__declspec(dllexport)"; +#else // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + std::string export_prefix = "__attribute__((visibility(\"default\")))"; +#endif // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + + // Output data + std::stringstream out; + + // Include section + out + << "#include " << std::endl + << "#include " << std::endl + << "#include " << std::endl + << "#include " << std::endl + << std::endl; + for( int i = 3; i < argc; ++i ) + out << "#include \"" << argv[ i ] << "\"" < " + << plugins_name << "_Data;" << std::endl + << std::endl + << "// -------------------------------------------------------------------------" << std::endl + << "extern \"C\" void __attribute__ ((constructor))" << std::endl + << plugins_name << "_Init( )" << std::endl + << "{" << std::endl + << "}" << std::endl + << std::endl + << "// -------------------------------------------------------------------------" << std::endl + << "extern \"C\" void __attribute__ ((destructor))" << std::endl + << plugins_name << "_Finish( )" << std::endl + << "{" << std::endl + << " // " << plugins_name << "_Data.clear( );" << std::endl + << "}" << std::endl + << std::endl + << "// -------------------------------------------------------------------------" << std::endl + << "extern \"C\" " << export_prefix << std::endl + << "void " << plugins_name << "_LoadContents( )" << std::endl + << "{" << std::endl + << " if( " << plugins_name << "_Data.size( ) == 0 )" << std::endl + << " {" << std::endl + << " std::string sep = \"@\";" << std::endl; + + // Classes + int id = 1; + for( auto iIt = info.begin( ); iIt != info.end( ); ++iIt, ++id ) + { + std::string class_name = iIt->second.second; + if( class_name != "" ) + class_name += std::string( "::" ); + class_name += iIt->first; + out + << " " << class_name << "::Pointer ptr" << id << " =" << std::endl + << " " << class_name << "::New( );" << std::endl + << " std::string id" << id << " = ptr" << id << "->GetClassName( )" + << " + sep + ptr" << id << "->GetClassCategory( );" << std::endl + << " " << plugins_name << "_Data[ id" << id << " ] = ptr" << id << ";" + << std::endl; + + } // rof + + // Remaining header + out + << std::endl << " } // fi" << std::endl << "}" << std::endl << std::endl + << "// -------------------------------------------------------------------------" << std::endl + << "extern \"C\" " << export_prefix << std::endl + << "void cpPlugins_Contents( std::vector< std::string >* c )" << std::endl + << "{" << std::endl + << " " << plugins_name << "_LoadContents( );" << std::endl + << " for( auto d : " << plugins_name << "_Data )" << std::endl + << " c->push_back( d.first );" << std::endl + << "}" << std::endl + << std::endl + << "// -------------------------------------------------------------------------" << std::endl + << "extern \"C\" " << export_prefix << std::endl + << "void cpPlugins_Creator( itk::LightObject::Pointer& ptr, const std::string& c, const std::string& f )" << std::endl + << "{" << std::endl + << " " << plugins_name << "_LoadContents( );" << std::endl + << " ptr = NULL;" << std::endl + << " std::string id = f + \"@\" + c;" << std::endl + << " auto fIt = " << plugins_name << "_Data.find( id );" << std::endl + << " if( fIt != " << plugins_name << "_Data.end( ) )" << std::endl + << " ptr = fIt->second->CreateAnother( );" << std::endl + << "}" << std::endl << std::endl + << "// eof - $Automatic generated file$" + << std::endl; + + // Real write + if( !( cpPlugins_bash::Write( out.str( ), output_filename ) ) ) + { + std::cerr << "ERROR: Could not write file." << std::endl; + return( 1 ); + + } // fi + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/cmake/BaseConfig.cmake b/cmake/BaseConfig.cmake new file mode 100644 index 0000000..d177604 --- /dev/null +++ b/cmake/BaseConfig.cmake @@ -0,0 +1,51 @@ +## ======================================================================= +## == Force c++11 language version == +## == NOTE: It seems that by default on Visual Studio Compiler supports == +## == c++11, so it only need to be tested on other OS. == +## ======================================================================= + +IF(NOT MSVC) + INCLUDE(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + IF(COMPILER_SUPPORTS_CXX11) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + ELSE(COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + IF(COMPILER_SUPPORTS_CXX0X) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + ELSE(COMPILER_SUPPORTS_CXX0X) + MESSAGE( + FATAL_ERROR + "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support." + ) + ENDIF(COMPILER_SUPPORTS_CXX0X) + ENDIF(COMPILER_SUPPORTS_CXX11) +ENDIF(NOT MSVC) + +## =================================================== +## == Prepare header generator to build shared libs == +## =================================================== + +INCLUDE(GenerateExportHeader) + +## ================================================== +## == Do not allow to build inside the source tree == +## ================================================== + +IF(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR}) + MESSAGE(FATAL_ERROR "Building in the source tree is not allowed.") +ENDIF(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR}) + +## ================================================= +## == Where to put targets (executables and libs) == +## ================================================= + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) +SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) +MARK_AS_ADVANCED( + CMAKE_BACKWARDS_COMPATIBILITY + EXECUTABLE_OUTPUT_PATH + LIBRARY_OUTPUT_PATH + ) + +## eof - $RCSfile$ diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt new file mode 100644 index 0000000..e942ae9 --- /dev/null +++ b/cmake/CMakeLists.txt @@ -0,0 +1,11 @@ +## ===================== +## == Configure files == +## ===================== + +CONFIGURE_FILE( + cpPluginsConfig.cmake.in + ${PROJECT_BINARY_DIR}/cpPluginsConfig.cmake + @ONLY + ) + +## eof - $RCSfile$ diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake new file mode 100644 index 0000000..d755587 --- /dev/null +++ b/cmake/Functions.cmake @@ -0,0 +1,328 @@ +## ------------------------------------------------------------------------- +FUNCTION(NormPaths output_files) +SET(_out) +FOREACH(_f ${ARGN}) + SET(_d) + FILE(TO_CMAKE_PATH ${_f} _d) + LIST(APPEND _out ${_d}) +ENDFOREACH(_f) +SET(${output_files} "${_out}" PARENT_SCOPE) +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION(Wrap_Qt_CPP output_files) +SET(_out) +FOREACH(_f ${ARGN}) + IF(EXISTS ${_f}) + FILE(READ ${_f} _txt) + STRING(FIND "${_txt}" "Q_OBJECT" _pos) + IF(NOT ${_pos} EQUAL -1) + SET(_s) + QT4_WRAP_CPP(_s ${_f}) + SET(_out ${_out} ${_s}) + ENDIF(NOT ${_pos} EQUAL -1) + ENDIF(EXISTS ${_f}) +ENDFOREACH(_f) +SET(${output_files} "${_out}" PARENT_SCOPE) +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION(Wrap_Qt_UI output_files) +NormPaths(_source_dir ${PROJECT_SOURCE_DIR}) +NormPaths(_binary_dir ${PROJECT_BINARY_DIR}) +SET(_out) +FOREACH(_f ${ARGN}) + IF(EXISTS ${_f}) + GET_FILENAME_COMPONENT(_name ${_f} NAME_WE) + GET_FILENAME_COMPONENT(_dir ${_f} DIRECTORY) + SET(_base_dir ${_source_dir}) + STRING(FIND "${_dir}" "${_base_dir}" _pos) + IF(${_pos} EQUAL -1) + SET(_base_dir ${_binary_dir}) + STRING(FIND "${_dir}" "${_base_dir}" _pos) + ENDIF(${_pos} EQUAL -1) + IF(NOT ${_pos} EQUAL -1) + STRING(REPLACE "${_base_dir}/" "" _dir ${_dir}) + SET(_out_f ${_binary_dir}/${_dir}/ui_${_name}.h) + LIST(APPEND _out ${_out_f}) + ADD_CUSTOM_COMMAND( + OUTPUT ${_out_f} + COMMAND Qt4::uic + ARGS -o ${_out_f} ${_f} + MAIN_DEPENDENCY ${_f} VERBATIM + ) + ENDIF(NOT ${_pos} EQUAL -1) + ENDIF(EXISTS ${_f}) +ENDFOREACH(_f) +SET(${output_files} "${_out}" PARENT_SCOPE) +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION( + PrepareSourceFiles + lib_name + out_sources_list + out_headers_list + out_headers_paths + ) +SET(_config_extensions .c.in .cpp.in .cxx.in .h.in .hpp.in .hxx.in .ui.in) +SET(_sources_extensions .c .cpp .cxx) +SET(_headers_extensions .h .hpp .hxx) +SET(_qt_ui_extensions .ui) +SET(_demangler_extensions .d) +SET(_instances_extensions .i) + +## -- Configure inputs +SET(_all_files) +FOREACH(_file ${ARGN}) + GET_FILENAME_COMPONENT(_ext ${_file} EXT) + LIST(FIND _config_extensions ${_ext} _cfg) + IF(NOT ${_cfg} EQUAL -1) + STRING( + REPLACE + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} + _file_bin + ${_file} + ) + STRING(LENGTH ${_file_bin} _file_bin_len) + MATH(EXPR _file_bin_len "${_file_bin_len}-3") + STRING(SUBSTRING ${_file_bin} 0 ${_file_bin_len} _file_bin) + CONFIGURE_FILE(${_file} ${_file_bin} @ONLY) + LIST(APPEND _all_files ${_file_bin}) + ELSE(NOT ${_cfg} EQUAL -1) + LIST(APPEND _all_files ${_file}) + ENDIF(NOT ${_cfg} EQUAL -1) +ENDFOREACH(_file) + +## -- Separate files +SET(_srcs) +SET(_hdrs) +SET(_qts) +SET(_demanglers) +SET(_instances) +FOREACH(_file ${_all_files}) + GET_FILENAME_COMPONENT(_ext ${_file} EXT) + LIST(FIND _sources_extensions ${_ext} _src) + LIST(FIND _headers_extensions ${_ext} _hdr) + LIST(FIND _qt_ui_extensions ${_ext} _ui) + LIST(FIND _demangler_extensions ${_ext} _dem) + LIST(FIND _instances_extensions ${_ext} _ins) + IF(NOT ${_src} EQUAL -1) + LIST(APPEND _srcs ${_file}) + ENDIF(NOT ${_src} EQUAL -1) + IF(NOT ${_hdr} EQUAL -1) + LIST(APPEND _hdrs ${_file}) + ENDIF(NOT ${_hdr} EQUAL -1) + IF(NOT ${_ui} EQUAL -1) + LIST(APPEND _qts ${_file}) + ENDIF(NOT ${_ui} EQUAL -1) + IF(NOT ${_dem} EQUAL -1) + LIST(APPEND _demanglers ${_file}) + ENDIF(NOT ${_dem} EQUAL -1) + IF(NOT ${_ins} EQUAL -1) + LIST(APPEND _instances ${_file}) + ENDIF(NOT ${_ins} EQUAL -1) +ENDFOREACH(_file) + +# -- Prepare Qt4-based code +IF(Qt4_FOUND) + ## -- Guess what headers sould be qt-moc'ed + Wrap_Qt_CPP(_moc ${_hdrs}) + IF(_moc) + LIST(APPEND _srcs ${_moc}) + ENDIF(_moc) + + ## -- Guess what qt-ui's sould be qt-uic'ed + ## -- Wrap qt-ui headers: this is equivalent to QT4_WRAP_UI except to change + ## -- the output file + Wrap_Qt_UI(_qt_hdrs ${_qts}) + IF(_qt_hdrs) + LIST(APPEND _hdrs ${_qt_hdrs}) + ENDIF(_qt_hdrs) +ENDIF(Qt4_FOUND) + +## -- Create demanglers +FOREACH(_d ${_demanglers}) + STRING( + REPLACE + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} + _d_bin + ${_d} + ) + GET_FILENAME_COMPONENT(_d_path ${_d_bin} DIRECTORY) + GET_FILENAME_COMPONENT(_out_name ${_d_bin} NAME_WE) + SET(_d_out ${_d_path}/${_out_name}_Demanglers.h) + ADD_CUSTOM_COMMAND( + OUTPUT ${_d_out} + COMMAND ${CMAKE_COMMAND} -E make_directory ${_d_path} + COMMAND ${cpPlugins_bash_CreateDemanglers_APP} ${_d} ${_out_name} ${_d_out} + DEPENDS ${cpPlugins_bash_CreateDemanglers_APP} ${_d} + ) + LIST(APPEND _hdrs ${_d_out}) +ENDFOREACH(_d) + +## -- Create instances +FOREACH(_i ${_instances}) + STRING( + REPLACE + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} + _i_bin + ${_i} + ) + GET_FILENAME_COMPONENT(_i_path ${_i_bin} DIRECTORY) + GET_FILENAME_COMPONENT(_out_name ${_i} NAME_WE) + + ## -- Infere source code filenames + MATH(EXPR _last_range "${cpPlugins_NUMBER_OF_FILES}-1") + SET(_out_code) + FOREACH(_n RANGE 0 ${_last_range}) + LIST(APPEND _out_code ${_i_path}/${_out_name}_${_n}.cxx) + LIST(APPEND _srcs ${_i_path}/${_out_name}_${_n}.cxx) + ENDFOREACH(_n) + + ## -- Command to write source code + ADD_CUSTOM_COMMAND( + OUTPUT ${_out_code} + DEPENDS ${cpPlugins_bash_CreateInstances_APP} ${_i} + COMMAND ${CMAKE_COMMAND} -E make_directory ${_i_path} + COMMAND ${cpPlugins_bash_CreateInstances_APP} ${_i} ${lib_name} ${_i_path}/${_out_name} + ) +ENDFOREACH(_i) + +## -- Real compilation +SET(_hdrs_paths) +FOREACH(_hdr ${_hdrs}) + GET_FILENAME_COMPONENT(_path ${_hdr} DIRECTORY) + LIST(FIND _hdrs_paths ${_path} _path_idx) + IF(${_path_idx} EQUAL -1) + LIST(APPEND _hdrs_paths ${_path}) + ENDIF(${_path_idx} EQUAL -1) +ENDFOREACH(_hdr) + +SET(${out_sources_list} ${_srcs} PARENT_SCOPE) +SET(${out_headers_list} ${_hdrs} PARENT_SCOPE) +SET(${out_headers_paths} ${_hdrs_paths} PARENT_SCOPE) + +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION(cpPlugins_BuildLibrary lib_name lib_type) +# -- Detect all source files +SET(_all_files) +FOREACH(_c ${ARGN}) + GET_FILENAME_COMPONENT(_cname ${_c} ABSOLUTE) + SET(_files) + IF(IS_DIRECTORY ${_cname}) + FILE(GLOB_RECURSE _files "${_cname}/*") + ELSE(IS_DIRECTORY ${_cname}) + SET(_files ${_cname}) + ENDIF(IS_DIRECTORY ${_cname}) + LIST(APPEND _all_files ${_files}) +ENDFOREACH(_c ${ARGN}) + +## -- Prepare sources by types +PrepareSourceFiles(${lib_name} _srcs _hdrs _paths ${_all_files}) + +## -- Build library +IF(_srcs) + INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) + ADD_LIBRARY(${lib_name} ${lib_type} ${_srcs} ${_hdrs}) + GENERATE_EXPORT_HEADER( + ${lib_name} + BASE_NAME ${lib_name} + EXPORT_MACRO_NAME ${lib_name}_EXPORT + EXPORT_FILE_NAME ${lib_name}_Export.h + STATIC_DEFINE ${lib_name}_BUILT_AS_STATIC + ) +ENDIF(_srcs) + +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION(cpPlugins_BuildPluginsLibrary lib_name) +# -- Detect all source files +SET(_all_files) +FOREACH(_c ${ARGN}) + GET_FILENAME_COMPONENT(_cname ${_c} ABSOLUTE) + SET(_files) + IF(IS_DIRECTORY ${_cname}) + FILE(GLOB_RECURSE _files "${_cname}/*") + ELSE(IS_DIRECTORY ${_cname}) + SET(_files ${_cname}) + ENDIF(IS_DIRECTORY ${_cname}) + LIST(APPEND _all_files ${_files}) +ENDFOREACH(_c ${ARGN}) + +## -- Prepare sources by types +PrepareSourceFiles(${lib_name} _srcs _hdrs _paths ${_all_files}) + +## -- Check which headers need to be wrapped to build host code +SET(_hdrs_to_wrap) +FOREACH(_hdr ${_hdrs}) + IF(EXISTS ${_hdr}) + FILE(READ ${_hdr} _txt) + STRING(FIND "${_txt}" "cpPluginsObject" _res) + IF(NOT ${_res} EQUAL -1) + LIST(APPEND _hdrs_to_wrap ${_hdr}) + ENDIF(NOT ${_res} EQUAL -1) + ENDIF(EXISTS ${_hdr}) +ENDFOREACH(_hdr) + +## -- Wrap headers +IF(_hdrs_to_wrap) + SET(_host ${CMAKE_CURRENT_BINARY_DIR}/${lib_name}_host.cxx) + ADD_CUSTOM_COMMAND( + OUTPUT ${_host} + DEPENDS ${cpPlugins_bash_HostCreator_APP} ${_hdrs_to_wrap} + COMMAND ${cpPlugins_bash_HostCreator_APP} ${lib_name} ${_host} ${_hdrs_to_wrap} + ) + LIST(APPEND _all_files ${_host}) +ENDIF(_hdrs_to_wrap) + +cpPlugins_BuildLibrary(${lib_name} SHARED ${_all_files}) +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION(cpPlugins_BuildApplication app_name) +OPTION(BUILD_${app_name} "Build \"${app_name}\" application?" OFF) +IF(BUILD_${app_name}) + # -- Detect all source files + SET(_all_files) + FOREACH(_c ${ARGN}) + GET_FILENAME_COMPONENT(_cname ${_c} ABSOLUTE) + SET(_files) + IF(IS_DIRECTORY ${_cname}) + FILE(GLOB_RECURSE _files "${_cname}/*") + ELSE(IS_DIRECTORY ${_cname}) + SET(_files ${_cname}) + ENDIF(IS_DIRECTORY ${_cname}) + LIST(APPEND _all_files ${_files}) + ENDFOREACH(_c ${ARGN}) + + ## -- Prepare sources by types + PrepareSourceFiles(${app_name} _srcs _hdrs _paths ${_all_files}) + + ## -- Build library + IF(_srcs) + INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) + SET(_app_os_target) + IF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + SET(_app_os_target WIN32) + ELSEIF(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + SET(_app_os_target MACOSX_BUNDLE) + ENDIF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + ADD_EXECUTABLE(${app_name} ${_app_os_target} ${_srcs} ${_hdrs}) + ENDIF(_srcs) +ENDIF(BUILD_${app_name}) +ENDFUNCTION() + +## eof - $RCSfile$ diff --git a/cmake/KitwareTools.cmake b/cmake/KitwareTools.cmake new file mode 100644 index 0000000..b4493d2 --- /dev/null +++ b/cmake/KitwareTools.cmake @@ -0,0 +1,19 @@ +# ====================== +# == Find ITK and VTK == +# ====================== + +FIND_PACKAGE(ITK REQUIRED) +FIND_PACKAGE(VTK REQUIRED) + +INCLUDE(${ITK_USE_FILE}) +INCLUDE(${VTK_USE_FILE}) + +# =================================================== +# == Do not use itk-vtk glue --> problems ahead!!! == +# =================================================== + +IF(ITKVtkGlue_LOADED) + MESSAGE(FATAL_ERROR "ITKVtkGlue module is available. Please re-compile your ITK without it. It could lead to nasty compilation problems... Just waiting for Kitware to solve it.") +ENDIF(ITKVtkGlue_LOADED) + +## eof - $RCSfile$ diff --git a/cmake/Options.cmake b/cmake/Options.cmake new file mode 100644 index 0000000..6800c63 --- /dev/null +++ b/cmake/Options.cmake @@ -0,0 +1,25 @@ +## =============================== +## == Some configurable options == +## =============================== + +SET(cpPlugins_NUMBER_OF_FILES "10" CACHE STRING "Number of compiled files.") +SET(cpPlugins_PROCESS_DIMS "1;2;3" CACHE STRING "Accepted processing dimensions.") +SET(cpPlugins_VISUAL_DIMS "2;3" CACHE STRING "Accepted visual dimensions.") + +OPTION(BUILD_EXAMPLES "Build examples" OFF) +OPTION(BUILD_QT4_COMPONENTS "Build Qt4-based code" OFF) + +SET( + _all_configs + cpPlugins_PROCESS_DIMS + cpPlugins_VISUAL_DIMS + ) +SET(_real_configs) +FOREACH(_cfg ${_all_configs}) + FOREACH(_type ${${_cfg}}) + LIST(APPEND _real_configs "${_cfg}_${_type}") + ENDFOREACH(_type) +ENDFOREACH(_cfg) +SET(cpPlugins_ALL_CONFIGS "${_real_configs}" CACHE INTERNAL "All valid configurations." FORCE) + +## eof - $RCSfile$ diff --git a/cmake/QtTools.cmake b/cmake/QtTools.cmake new file mode 100644 index 0000000..4f1e574 --- /dev/null +++ b/cmake/QtTools.cmake @@ -0,0 +1,28 @@ +## ================================================== +## == Find Qt4 and check if it was well configured == +## ================================================== + +IF(BUILD_QT4_COMPONENTS) + FIND_PACKAGE(Qt4 REQUIRED) + INCLUDE(${QT_USE_FILE}) + SET( + _modules + vtkGUISupportQt + ) + FOREACH(_m ${_modules}) + IF(NOT ${_m}_LOADED) + MESSAGE(FATAL_ERROR "${_m} module is required but not available.") + BREAK() + ENDIF(NOT ${_m}_LOADED) + ENDFOREACH(_m) + SET( + cpPlugins_Qt4_VTKWidget + QVTKWidget + CACHE STRING "Base Qt4-based vtkRenderWindow" + ) + # ADD_DEFINITIONS(-DcpPlugins_QT4 -DcpExtensions_QT4) +ELSE(BUILD_QT4_COMPONENTS) + # ADD_DEFINITIONS(-UcpPlugins_QT4 -UcpExtensions_QT4) +ENDIF(BUILD_QT4_COMPONENTS) + +## eof - $RCSfile$ diff --git a/cmake/cpPluginsConfig.cmake.in b/cmake/cpPluginsConfig.cmake.in new file mode 100644 index 0000000..2f2fdd2 --- /dev/null +++ b/cmake/cpPluginsConfig.cmake.in @@ -0,0 +1,119 @@ +## ================================ +## == Find cpPlugins-cmake tools == +## ================================ + +SET(ITK_DIR "@ITK_DIR@") +SET(VTK_DIR "@VTK_DIR@") +IF("@Qt4_FOUND@" STREQUAL "TRUE") + SET(USE_QT4 ON) + SET(QT_QMAKE_EXECUTABLE "@QT_QMAKE_EXECUTABLE@") +ENDIF("@Qt4_FOUND@" STREQUAL "TRUE") + +## ==================== +## == Find libraries == +## ==================== + +SET( + cpPlugins_AllInstances + cpInstances_BaseObjects + cpInstances_Images + cpInstances_Geometries + cpInstances_Extensions + CACHE STRING "All instances from templated code" + ) +MARK_AS_ADVANCED(FORCE cpPlugins_AllInstances) + +SET( + _all_libs + cpExtensions + cpPlugins + cpPluginsDataObjects + ) +IF(USE_QT4) + LIST(APPEND _all_libs cpBaseQtApplication) +ENDIF(USE_QT4) +SET(cpPlugins_Libraries ${_all_libs} CACHE STRING "cpPlugins base libraries") +MARK_AS_ADVANCED(FORCE cpPlugins_Libraries) + +SET(_all_libs ${cpPlugins_AllInstances} ${cpPlugins_Libraries}) +SET(_l_locations) +FOREACH(_l ${_all_libs}) + FIND_LIBRARY( + ${_l}_LIB NAMES ${_l} + PATHS + @PROJECT_BINARY_DIR@ + @CMAKE_INSTALL_PREFIX@/bin + @CMAKE_INSTALL_PREFIX@/lib + ${_l_locations} + ) + IF(${_l}_LIB) + MARK_AS_ADVANCED(FORCE ${_l}_LIB) + GET_FILENAME_COMPONENT(_dir ${${_l}_LIB} DIRECTORY) + LIST(APPEND _l_locations ${_dir}) + LIST(REMOVE_DUPLICATES _l_locations) + ENDIF(${_l}_LIB) +ENDFOREACH(_l) +IF(_l_locations) + LINK_DIRECTORIES(${_l_locations}) +ENDIF(_l_locations) + +## ============================== +## == Find include directories == +## ============================== + +## TODO: this is not completely correct!!! +INCLUDE_DIRECTORIES( + @CMAKE_INSTALL_PREFIX@/include + @CMAKE_INSTALL_PREFIX@/include/cpPlugins/cpInstances + @PROJECT_SOURCE_DIR@ + @PROJECT_BINARY_DIR@ + @PROJECT_SOURCE_DIR@/lib + @PROJECT_BINARY_DIR@/lib + @PROJECT_SOURCE_DIR@/lib/cpInstances + @PROJECT_BINARY_DIR@/lib/cpInstances + ) + +## ============================ +## == Find bash applications == +## ============================ + +SET( + _exec_programs + "@cpPlugins_bash_CreateRealConfig_APP@" + "@cpPlugins_bash_CreateInstances_APP@" + "@cpPlugins_bash_CreateDemanglers_APP@" + "@cpPlugins_bash_CreatePlugins_APP@" + "@cpPlugins_bash_HostCreator_APP@" + ) + +SET(_b_locations) +FOREACH(_p ${_exec_programs}) + FIND_PROGRAM( + ${_p}_APP + NAMES ${_p} + HINTS /usr /usr/local + PATHS @CMAKE_INSTALL_PREFIX@/bin @PROJECT_BINARY_DIR@ ${_b_locations} + PATH_SUFFIXES bin sbin + DOC "Where is ${_prog}?" + ) + IF(${_p}_APP) + MARK_AS_ADVANCED(FORCE ${_p}_APP) + GET_FILENAME_COMPONENT(_dir ${${_p}_APP} DIRECTORY) + LIST(APPEND _b_locations ${_dir}) + LIST(REMOVE_DUPLICATES _b_locations) + ENDIF(${_p}_APP) +ENDFOREACH(_p) + +## ========================== +## == Configuration values == +## ========================== + +SET(cpPlugins_NUMBER_OF_FILES "@cpPlugins_NUMBER_OF_FILES@" CACHE STRING "Internal") +SET(cpPlugins_PROCESS_DIMS "@cpPlugins_PROCESS_DIMS@" CACHE STRING "Internal") +SET(cpPlugins_VISUAL_DIMS "@cpPlugins_VISUAL_DIMS@" CACHE STRING "Internal") + +MARK_AS_ADVANCED(FORCE cpPlugins_NUMBER_OF_FILES) +MARK_AS_ADVANCED(FORCE cpPlugins_PROCESS_DIMS) +MARK_AS_ADVANCED(FORCE cpPlugins_VISUAL_DIMS) + +## eof - $RCSfile$ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..52132e6 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,73 @@ + +## ====================== +## == Helper libraries == +## ====================== + +SET( + _cpExtensions_components + cpExtensions/Config.h.in + cpExtensions/DataStructures + cpExtensions/Algorithms + cpExtensions/Interaction + cpExtensions/Visualization + ) + +IF(BUILD_QT4_COMPONENTS) + LIST(APPEND _cpExtensions_components "cpExtensions/QT") +ENDIF(BUILD_QT4_COMPONENTS) +cpPlugins_BuildLibrary(cpExtensions SHARED ${_cpExtensions_components}) +TARGET_LINK_LIBRARIES( + cpExtensions + ${QT_LIBRARIES} ${ITK_LIBRARIES} ${VTK_LIBRARIES} + ) + +## ============================================ +## == Explicit instances from templated code == +## ============================================ + +SUBDIRS( + cpInstances + ) + +## ================== +## == Base library == +## ================== + +SET(_real_config ${CMAKE_CURRENT_BINARY_DIR}/cpPlugins/RealConfig.h) +ADD_CUSTOM_COMMAND( + OUTPUT ${_real_config} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/cpPlugins + COMMAND ${cpPlugins_bash_CreateRealConfig_APP} ${_real_config} + DEPENDS ${cpPlugins_bash_CreateRealConfig_APP} + ) +SET( + _cpPlugins_components + ${_real_config} + cpPlugins/Config.h.in + cpPlugins/tinyxml2 + cpPlugins/OS + cpPlugins/Pipeline + cpPlugins/Interface + ) +IF(BUILD_QT4_COMPONENTS) + LIST(APPEND _cpPlugins_components "cpPlugins/QT") +ENDIF(BUILD_QT4_COMPONENTS) +cpPlugins_BuildLibrary(cpPlugins SHARED ${_cpPlugins_components}) +TARGET_LINK_LIBRARIES(cpPlugins ${ITK_LIBRARIES} ${VTK_LIBRARIES}) +IF(BUILD_QT4_COMPONENTS) + TARGET_LINK_LIBRARIES(cpPlugins ${QT_LIBRARIES}) +ENDIF(BUILD_QT4_COMPONENTS) + +## =================================== +## == Base library for applications == +## =================================== + +IF(BUILD_QT4_COMPONENTS) + cpPlugins_BuildLibrary(cpBaseQtApplication SHARED cpBaseQtApplication) + TARGET_LINK_LIBRARIES( + cpBaseQtApplication + cpExtensions cpPlugins + ) +ENDIF(BUILD_QT4_COMPONENTS) + +## eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Blocker.cxx b/lib/cpBaseQtApplication/Blocker.cxx new file mode 100644 index 0000000..634f25b --- /dev/null +++ b/lib/cpBaseQtApplication/Blocker.cxx @@ -0,0 +1,67 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Blocker:: +Blocker( ) + : QObject( ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Blocker:: +~Blocker( ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Blocker:: +block( ) +{ + QApplication* app = + dynamic_cast< QApplication* >( QApplication::instance( ) ); + if( app != NULL ) + { + app->setOverrideCursor( Qt::WaitCursor ); + app->installEventFilter( this ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Blocker:: +unblock( ) +{ + QApplication* app = + dynamic_cast< QApplication* >( QApplication::instance( ) ); + if( app != NULL ) + { + while( app->overrideCursor( ) ) + app->restoreOverrideCursor( ); + app->removeEventFilter( this ); + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Blocker:: +eventFilter( QObject* obj, QEvent* event ) +{ + return( true ); // -> Block all events + /* NOTE: this should be the correct implementation: + switch( event->type( ) ) + { + //list event you want to prevent here ... + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonDblClick: + //... + return( true ); + } // hctiws + return( this->QObject::eventFilter( obj, event ) ); + */ +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Blocker.h b/lib/cpBaseQtApplication/Blocker.h new file mode 100644 index 0000000..6e7abf8 --- /dev/null +++ b/lib/cpBaseQtApplication/Blocker.h @@ -0,0 +1,30 @@ +#ifndef __cpBaseQtApplication__Blocker__h__ +#define __cpBaseQtApplication__Blocker__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpBaseQtApplication +{ + /** + */ + class cpBaseQtApplication_EXPORT Blocker + : public QObject + { + public: + Blocker( ); + virtual ~Blocker( ); + + void block( ); + void unblock( ); + + protected: + virtual bool eventFilter( QObject* obj, QEvent* event ); + }; + +} // ecapseman + +#endif // __cpBaseQtApplication__Blocker__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/MainHelper.h b/lib/cpBaseQtApplication/MainHelper.h new file mode 100644 index 0000000..d850b25 --- /dev/null +++ b/lib/cpBaseQtApplication/MainHelper.h @@ -0,0 +1,90 @@ +#ifndef __cpBaseQtApplication__MainHelper__h__ +#define __cpBaseQtApplication__MainHelper__h__ + +#include +#include + +// ------------------------------------------------------------------------- +#define cpBaseQtApplication_Main( _window_class_ ) \ + int main( int argc, char* argv[] ) \ + { \ + QApplication a( argc, argv ); \ + _window_class_ w( argc, argv ); \ + w.show( ); \ + return( a.exec( ) ); \ + } + +// ------------------------------------------------------------------------- +#include + +#ifdef cpPlugins_OS_Windows + +# include +# include +# include +# include + +// ------------------------------------------------------------------------- +namespace cpBaseQtApplication +{ + /** + */ + class Win32CommandLineConverter + { + private: + std::unique_ptr< char*[ ] > argv_; + std::vector< std::unique_ptr< char[ ] > > storage_; + + public: + Win32CommandLineConverter( ) + { + LPWSTR cmd_line = GetCommandLineW( ); + int argc; + LPWSTR* w_argv = CommandLineToArgvW( cmd_line, &argc ); + argv_ = std::unique_ptr< char*[ ] >( new char*[ argc ] ); + storage_.reserve( argc ); + for( int i = 0; i < argc; ++i ) + { + storage_.push_back( ConvertWArg( w_argv[ i ] ) ); + argv_[ i ] = storage_.back( ).get( ); + + } // rof + LocalFree( w_argv ); + } + int argc( ) const + { + return( static_cast< int >(storage_.size( ) ) ); + } + char** argv( ) const + { + return( argv_.get( ) ); + } + static std::unique_ptr< char[ ] > ConvertWArg( LPWSTR w_arg ) + { + int size = WideCharToMultiByte( + CP_UTF8, 0, w_arg, -1, nullptr, 0, nullptr, nullptr + ); + std::unique_ptr< char[ ] > ret( new char[ size ] ); + WideCharToMultiByte( + CP_UTF8, 0, w_arg, -1, ret.get( ), size, nullptr, nullptr + ); + return( ret ); + } + }; + +} // ecapseman + +// ------------------------------------------------------------------------- +# define cpBaseQtApplication_MainComplement \ + int CALLBACK WinMain( HINSTANCE i, HINSTANCE p, LPSTR c, int s ) \ + { \ + cpBaseQtApplication::Win32CommandLineConverter cmd_line; \ + return( main( cmd_line.argc( ), cmd_line.argv( ) ) ); \ + } +#else // cpPlugins_OS_Windows +# define cpBaseQtApplication_MainComplement +#endif // cpPlugins_OS_Windows + +#endif // __cpBaseQtApplication__MainHelper__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/MainWindow.cxx b/lib/cpBaseQtApplication/MainWindow.cxx new file mode 100644 index 0000000..668eb3b --- /dev/null +++ b/lib/cpBaseQtApplication/MainWindow.cxx @@ -0,0 +1,309 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::MainWindow:: +MainWindow( int argc, char* argv[], QWidget* parent ) + : Superclass( parent ), + m_LastSaveFileName( "" ), + m_BaseWindowTitle( "cpBaseQtApplication" ), + m_Canvas( NULL ), + m_Navigator( NULL ), + m_Viewer( NULL ) +{ + this->m_RunPath = QDir( "." ).canonicalPath( ).toStdString( ); + this->m_Loader.GuessEnvironment( this->m_RunPath ); + this->m_Loader.SaveEnvironment( this->m_RunPath ); + this->_clearWorkspace( ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::MainWindow:: +~MainWindow( ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::MainWindow:: +TWorkspace* cpBaseQtApplication::MainWindow:: +workspace( ) +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::MainWindow:: +TWorkspace* cpBaseQtApplication::MainWindow:: +workspace( ) const +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Canvas* +cpBaseQtApplication::MainWindow:: +canvas( ) +{ + return( this->m_Canvas ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Pipeline::Canvas* +cpBaseQtApplication::MainWindow:: +canvas( ) const +{ + return( this->m_Canvas ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +setCanvas( cpBaseQtApplication::Pipeline::Canvas* c ) +{ + this->m_Canvas = c; + if( this->m_Canvas != NULL ) + this->m_Canvas->setWorkspace( this->m_Workspace ); + +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Plugins::Navigator* +cpBaseQtApplication::MainWindow:: +navigator( ) +{ + return( this->m_Navigator ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Plugins::Navigator* +cpBaseQtApplication::MainWindow:: +navigator( ) const +{ + return( this->m_Navigator ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +setNavigator( cpBaseQtApplication::Plugins::Navigator* n ) +{ + this->m_Navigator = n; +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::ActorsWidgetInterface* +cpBaseQtApplication::MainWindow:: +viewer( ) +{ + return( this->m_Viewer ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::QT::ActorsWidgetInterface* +cpBaseQtApplication::MainWindow:: +viewer( ) const +{ + return( this->m_Viewer ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +setViewer( cpExtensions::QT::ActorsWidgetInterface* v ) +{ + this->m_Viewer = v; + if( this->m_Viewer != NULL ) + { + auto interactors = this->m_Viewer->GetInteractors( ); + for( auto i : interactors ) + this->m_Workspace->AddInteractor( i ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_loadPlugins( const std::string& filename ) +{ + try + { + this->m_Loader.Register( filename ); + if( this->m_Navigator != NULL ) + this->m_Navigator->Update( ); + } + catch( std::exception& err ) + { + QMessageBox::critical( + this, + "Error loading plugins path", + err.what( ) + ); + + } // yrt +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_loadPlugins( ) +{ + QFileDialog dlg( this ); + dlg.setFileMode( QFileDialog::ExistingFiles ); + + std::stringstream filter; + std::string suffix = std::string( cpPlugins_LIB_EXT ); + filter << "Plugins file (*" << cpPlugins_LIB_EXT << ");;All files (*)"; + dlg.setNameFilter( filter.str( ).c_str( ) ); + dlg.setDefaultSuffix( suffix.c_str( ) ); + if( !( dlg.exec( ) ) ) + return; + QStringList names = dlg.selectedFiles( ); + for( auto qIt = names.begin( ); qIt != names.end( ); ++qIt ) + this->_loadPlugins( qIt->toStdString( ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_loadPluginsFromPath( const std::string& path ) +{ + try + { + this->m_Loader.RegisterFromDirectory( path ); + this->m_Loader.SaveEnvironment( this->m_RunPath ); + if( this->m_Navigator != NULL ) + this->m_Navigator->Update( ); + } + catch( std::exception& err ) + { + QMessageBox::critical( + this, + "Error loading plugins path", + err.what( ) + ); + + } // yrt +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_loadPluginsFromPath( ) +{ + QFileDialog d( this ); + d.setFileMode( QFileDialog::DirectoryOnly ); + if( !( d.exec( ) ) ) + return; + this->_loadPluginsFromPath( d.selectedFiles( ).begin( )->toStdString( ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_clearWorkspace( ) +{ + this->setWindowTitle( this->m_BaseWindowTitle.c_str( ) ); + this->m_Workspace = TWorkspace::New( ); + if( this->m_Canvas != NULL ) + { + this->m_Canvas->clear( ); + this->m_Canvas->setWorkspace( this->m_Workspace ); + + } // fi + if( this->m_Viewer != NULL ) + { + // TODO: this->m_Viewer->clear( ); + auto interactors = this->m_Viewer->GetInteractors( ); + for( auto i : interactors ) + this->m_Workspace->AddInteractor( i ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_saveWorkspace( const std::string& fname ) +{ + this->m_LastSaveFileName = fname; + this->m_Workspace->Save( this->m_LastSaveFileName ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_saveWorkspace( ) +{ + if( this->m_LastSaveFileName == "" ) + { + QFileDialog dlg( this ); + dlg.setFileMode( QFileDialog::AnyFile ); + dlg.setDirectory( "." ); + dlg.setAcceptMode( QFileDialog::AcceptSave ); + dlg.setNameFilter( + QFileDialog::tr( "Workspace file (*.wxml);;All files (*)" ) + ); + dlg.setDefaultSuffix( QFileDialog::tr( "wxml" ) ); + dlg.setWindowTitle( "Saving workspace" ); + if( dlg.exec( ) ) + this->_saveWorkspace( dlg.selectedFiles( ).begin( )->toStdString( ) ); + } + else + this->_saveWorkspace( this->m_LastSaveFileName ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_loadWorkspace( const std::string& fname ) +{ + try + { + this->_clearWorkspace( ); + this->m_Workspace->Load( fname ); + this->m_LastSaveFileName = ""; + if( this->m_Canvas != NULL ) + this->m_Canvas->setWorkspace( this->m_Workspace ); + } + catch( std::exception& err ) + { + QMessageBox::critical( + this, + QMessageBox::tr( "Error loading workspace" ), + QMessageBox::tr( err.what( ) ) + ); + + } // yrt +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_loadWorkspace( ) +{ + QFileDialog dlg( this ); + dlg.setFileMode( QFileDialog::ExistingFile ); + dlg.setDirectory( "." ); + dlg.setNameFilter( + QFileDialog::tr( "Workspace file (*.wxml);;All files (*)" ) + ); + dlg.setDefaultSuffix( QFileDialog::tr( "wxml" ) ); + if( !( dlg.exec( ) ) ) + return; + this->_loadWorkspace( dlg.selectedFiles( ).begin( )->toStdString( ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_actorsProperties( ) +{ + auto data = + dynamic_cast< cpExtensions::QT::ActorsWidgetInterface* >( + this->m_Viewer + ); + if( data != NULL ) + { + auto dlg = new cpExtensions::QT::ConfigurationChooser( this ); + dlg->setData( data ); + dlg->exec( ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/MainWindow.h b/lib/cpBaseQtApplication/MainWindow.h new file mode 100644 index 0000000..2e967d9 --- /dev/null +++ b/lib/cpBaseQtApplication/MainWindow.h @@ -0,0 +1,136 @@ +#ifndef __cpBaseQtApplication__MainWindow__h__ +#define __cpBaseQtApplication__MainWindow__h__ + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpBaseQtApplication_ConnectAction( _act_, _slt_ ) \ + this->connect( \ + this->m_UI->_act_, SIGNAL( triggered( ) ), this, SLOT( _slt_( ) ) \ + ) + +// ------------------------------------------------------------------------- +#define cpBaseQtApplication_Execute( _cmd_ ) \ + { \ + this->m_Blocker.block( ); \ + try \ + { \ + _cmd_; \ + this->m_Blocker.unblock( ); \ + } \ + catch( std::exception& err ) \ + { \ + this->m_Blocker.unblock( ); \ + QMessageBox::critical( \ + this, \ + QMessageBox::tr( "Error executing filter" ), \ + QMessageBox::tr( err.what( ) ) \ + ); \ + } \ + catch( ... ) \ + { \ + this->m_Blocker.unblock( ); \ + QMessageBox::critical( \ + this, \ + QMessageBox::tr( "Error executing filter" ), \ + QMessageBox::tr( "Unknown error" ) \ + ); \ + } \ + this->m_Blocker.unblock( ); \ + } + +// ------------------------------------------------------------------------- +namespace cpExtensions { namespace QT { class ActorsWidgetInterface; } } + +// ------------------------------------------------------------------------- +namespace cpBaseQtApplication +{ + namespace Pipeline { class Canvas; } + namespace Plugins { class Navigator; } + + /** + */ + class cpBaseQtApplication_EXPORT MainWindow + : public QMainWindow + { + Q_OBJECT; + + public: + typedef MainWindow Self; + typedef QMainWindow Superclass; + + typedef cpPlugins::Interface::Loader TLoader; + typedef cpPlugins::Interface::Workspace TWorkspace; + + public: + explicit MainWindow( + int argc, char* argv[], + QWidget* parent = NULL + ); + virtual ~MainWindow( ); + + TWorkspace* workspace( ); + const TWorkspace* workspace( ) const; + + Pipeline::Canvas* canvas( ); + const Pipeline::Canvas* canvas( ) const; + void setCanvas( Pipeline::Canvas* c ); + + Plugins::Navigator* navigator( ); + const Plugins::Navigator* navigator( ) const; + void setNavigator( Plugins::Navigator* n ); + + cpExtensions::QT::ActorsWidgetInterface* viewer( ); + const cpExtensions::QT::ActorsWidgetInterface* viewer( ) const; + void setViewer( cpExtensions::QT::ActorsWidgetInterface* v ); + + protected: + template< class _TViewer > + _TViewer* _configureViewer( QWidget* w ) + { + _TViewer* v = dynamic_cast< _TViewer* >( w ); + if( v == NULL ) + v = new _TViewer( ); + return( v ); + } + + protected slots: + void _loadPlugins( const std::string& filename ); + void _loadPlugins( ); + void _loadPluginsFromPath( const std::string& path ); + void _loadPluginsFromPath( ); + + void _clearWorkspace( ); + + void _saveWorkspace( const std::string& fname ); + void _saveWorkspace( ); + + void _loadWorkspace( const std::string& fname ); + void _loadWorkspace( ); + + void _actorsProperties( ); + + protected: + Blocker m_Blocker; + std::string m_RunPath; + TLoader m_Loader; + std::string m_LastSaveFileName; + TWorkspace::Pointer m_Workspace; + + std::string m_BaseWindowTitle; + + Pipeline::Canvas* m_Canvas; + Plugins::Navigator* m_Navigator; + cpExtensions::QT::ActorsWidgetInterface* m_Viewer; + }; + +} // ecapseman + +#endif // __cpBaseQtApplication__MainWindow__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Block.cxx b/lib/cpBaseQtApplication/Pipeline/Block.cxx new file mode 100644 index 0000000..3d235aa --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Block.cxx @@ -0,0 +1,418 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +QColor cpBaseQtApplication::Pipeline::Block:: +SelectedAndUpdated = Qt::green; +QColor cpBaseQtApplication::Pipeline::Block:: +NotSelectedAndUpdated = Qt::blue; +QColor cpBaseQtApplication::Pipeline::Block:: +SelectedAndNotUpdated = Qt::yellow; +QColor cpBaseQtApplication::Pipeline::Block:: +NotSelectedAndNotUpdated = Qt::lightGray; + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block::_TFilterObserver:: +Execute( const itk::Object* c, const itk::EventObject& e ) +{ + typedef cpPlugins::Pipeline::Events::Modified _TModified; + const _TModified* mod_evt = dynamic_cast< const _TModified* >( &e ); + if( mod_evt != NULL ) + { + std::stringstream str; + str + << "(" << mod_evt->Time << "/" + << double( mod_evt->Span ) / double( 1000 ) << "s)"; + this->ObservedBlock->setInfoPort( str.str( ).c_str( ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Block:: +Block( + TFilter* filter, + QGraphicsItem* parent, QGraphicsScene* scene + ) + : Superclass( parent, scene ), + m_HorzMargin( 20 ), + m_VertMargin( 5 ), + m_NamePort( NULL ), + m_InfoPort( NULL ), + m_Filter( filter ) +{ + QPainterPath p; + p.addRoundedRect( -50, -15, 100, 30, 5, 5 ); + + this->setPath( p ); + this->setPen( QPen( Qt::darkGreen ) ); + this->setBrush( Qt::green ); + this->setFlag( QGraphicsItem::ItemIsMovable ); + this->setFlag( QGraphicsItem::ItemIsSelectable ); + + this->m_Width = this->m_HorzMargin; + this->m_Height = this->m_VertMargin; + + // Configure names + this->setNamePort( filter->GetName( ) ); + this->setInfoPort( "(-/-)" ); + this->_setTypeInfo( + ( + std::string( this->m_Filter->GetClassCategory( ) ) + + std::string( "::" ) + + std::string( this->m_Filter->GetClassName( ) ) + ).c_str( ) + ); + + // Add input ports + auto inputs = this->m_Filter->GetInputsNames( ); + for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt ) + { + this->addInputPort( + iIt->c_str( ), + this->m_Filter->IsInputMultiple( iIt->c_str( ) ) + ); + + } // rof + + // Add output ports + auto outputs = this->m_Filter->GetOutputsNames( ); + for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt ) + this->addOutputPort( oIt->c_str( ) ); + + // Add obvserver + this->m_FilterObserver = _TFilterObserver::New( ); + this->m_FilterObserver->ObservedBlock = this; + this->m_FilterObserverId = + this->m_Filter->AddObserver( + cpPlugins::Pipeline::Events::Modified( ), this->m_FilterObserver + ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Block:: +~Block( ) +{ + this->m_Filter->RemoveObserver( this->m_FilterObserverId ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Block:: +TFilter* cpBaseQtApplication::Pipeline::Block:: +filter( ) +{ + return( this->m_Filter ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Pipeline::Block:: +TFilter* cpBaseQtApplication::Pipeline::Block:: +filter( ) const +{ + return( this->m_Filter ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +setNamePort( const QString& txt ) +{ + if( this->m_NamePort == NULL ) + this->m_NamePort = new NamePort( this ); + this->m_NamePort->setName( txt ); + this->_configPort( this->m_NamePort ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +setInfoPort( const QString& txt ) +{ + if( this->m_InfoPort == NULL ) + this->m_InfoPort = new InfoPort( this ); + this->m_InfoPort->setName( txt ); + this->_configPort( this->m_InfoPort ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::InputPort* +cpBaseQtApplication::Pipeline::Block:: +addInputPort( const QString& txt, bool multiple ) +{ + InputPort* ip = new InputPort( this, multiple ); + ip->setExtendedName( "" ); + ip->setName( txt ); + this->m_InputPorts[ txt.toStdString( ) ] = ip; + this->_configPort( ip ); + return( ip ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::OutputPort* +cpBaseQtApplication::Pipeline::Block:: +addOutputPort( const QString& txt ) +{ + OutputPort* op = new OutputPort( this ); + op->setExtendedName( "" ); + op->setName( txt ); + this->m_OutputPorts[ txt.toStdString( ) ] = op; + this->_configPort( op ); + return( op ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::InputPort* +cpBaseQtApplication::Pipeline::Block:: +inputPort( const QString& txt ) +{ + auto i = this->m_InputPorts.find( txt.toStdString( ) ); + if( i != this->m_InputPorts.end( ) ) + return( i->second ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::OutputPort* +cpBaseQtApplication::Pipeline::Block:: +outputPort( const QString& txt ) +{ + auto o = this->m_OutputPorts.find( txt.toStdString( ) ); + if( o != this->m_OutputPorts.end( ) ) + return( o->second ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +QString cpBaseQtApplication::Pipeline::Block:: +namePort( ) const +{ + return( this->m_NamePort->name( ) ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Pipeline::InputPort* +cpBaseQtApplication::Pipeline::Block:: +inputPort( const QString& txt ) const +{ + auto i = this->m_InputPorts.find( txt.toStdString( ) ); + if( i != this->m_InputPorts.end( ) ) + return( i->second ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Pipeline::OutputPort* +cpBaseQtApplication::Pipeline::Block:: +outputPort( const QString& txt ) const +{ + auto o = this->m_OutputPorts.find( txt.toStdString( ) ); + if( o != this->m_OutputPorts.end( ) ) + return( o->second ); + else + return( NULL ); +} + + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Pipeline::Block:: +connectOutputPortSlot( QObject* receiver, const char* slot ) +{ + bool ok = true; + for( auto p : this->m_OutputPorts ) + ok &= QObject::connect( + p.second, SIGNAL( viewData( const std::string&, bool ) ), + receiver, slot + ); + return( ok ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +setPos( const QPointF& pos ) +{ + this->m_Filter->SetViewCoords( pos.x( ), pos.y( ) ); + this->Superclass::setPos( pos ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +setPos( qreal x, qreal y ) +{ + this->m_Filter->SetViewCoords( x, y ); + this->Superclass::setPos( x, y ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +paint( + QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget + ) +{ + Q_UNUSED( option ); + Q_UNUSED( widget ); + + if( this->isSelected( ) ) + { + painter->setPen( QPen( Qt::darkYellow ) ); + painter->setBrush( Qt::yellow ); + } + else + { + painter->setPen( QPen( Qt::darkGreen ) ); + painter->setBrush( Qt::green ); + + } // fi + painter->drawPath( this->path( ) ); +} + +// ------------------------------------------------------------------------- +QVariant cpBaseQtApplication::Pipeline::Block:: +itemChange( GraphicsItemChange change, const QVariant& value ) +{ + return( value ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +_setTypeInfo( const QString& txt ) +{ + this->setToolTip( txt ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +_configPort( Port* port ) +{ + port->setBlock( this ); + + QFontMetrics fm( this->scene( )->font( ) ); + this->m_Width = 0; + foreach( QGraphicsItem* i, this->children( ) ) + { + Port* p = dynamic_cast< Port* >( i ); + if( p == NULL ) + continue; + int w = fm.width( p->name( ) ) + ( 4 * p->radius( ) ); + if( w > this->m_Width - this->m_HorzMargin ) + this->m_Width = w + this->m_HorzMargin; + + } // rof + int h = fm.height( ); + this->m_Height = this->m_InputPorts.size( ) + this->m_OutputPorts.size( ); + this->m_Height += 4; + this->m_Height *= h; + + QPainterPath pth; + pth.addRoundedRect( + -this->m_Width / 2, + -this->m_Height / 2, + this->m_Width, + this->m_Height, 5, 5 + ); + this->setPath( pth ); + + int y = -this->m_Height / 2 + this->m_VertMargin + port->radius( ); + foreach( QGraphicsItem* i, this->children( ) ) + { + Port* p = dynamic_cast< Port* >( i ); + if( p == NULL ) + continue; + + if( + dynamic_cast< NamePort* >( i ) != NULL || + dynamic_cast< InfoPort* >( i ) != NULL + ) + { + i->setPos( -this->m_Width / 2 + port->radius( ), y ); + y += h >> 1; + } + else if( dynamic_cast< InputPort* >( i ) != NULL ) + i->setPos( -this->m_Width / 2 - 2 * port->radius( ), y ); + else if( dynamic_cast< OutputPort* >( i ) != NULL ) + i->setPos( this->m_Width / 2, y ); + y += h; + + } // rof +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +mouseReleaseEvent( QGraphicsSceneMouseEvent* evt ) +{ + if( this->m_Filter.IsNotNull( ) ) + this->m_Filter->SetViewCoords( + this->scenePos( ).x( ), + this->scenePos( ).y( ) + ); + this->Superclass::mouseReleaseEvent( evt ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Block:: +contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ) +{ + QMenu menu; + QAction* configureAction = menu.addAction( "Configure" ); + QAction* updateAction = menu.addAction( "Update" ); + auto widget = + dynamic_cast< cpPlugins::Pipeline::Widget* >( + this->m_Filter.GetPointer( ) + ); + QAction* enableAction = NULL; + if( widget != NULL ) + enableAction = + menu.addAction( ( widget->GetEnabled( ) )? "Disable": "Enable" ); + + QAction* selectedAction = menu.exec( evt->screenPos( ) ); + if( selectedAction == configureAction ) + { + auto dlg = this->m_Filter->CreateQDialog( ); + if( dlg != NULL ) + dlg->exec( ); + } + else if( selectedAction == enableAction ) + { + if( widget != NULL ) + widget->SetEnabled( !( widget->GetEnabled( ) ) ); + } + else if( selectedAction == updateAction ) + { + cpBaseQtApplication::Blocker blocker; + blocker.block( ); + try + { + this->m_Filter->Update( ); + blocker.unblock( ); + } + catch( std::exception& err ) + { + blocker.unblock( ); + QMessageBox::critical( + NULL, + QMessageBox::tr( "Error updating filter" ), + QMessageBox::tr( err.what( ) ) + ); + + } // yrt + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Block.h b/lib/cpBaseQtApplication/Pipeline/Block.h new file mode 100644 index 0000000..a61e00e --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Block.h @@ -0,0 +1,120 @@ +#ifndef __cpBaseQtApplication__Pipeline__Block__h__ +#define __cpBaseQtApplication__Pipeline__Block__h__ + +#include +#include +#include +#include + +namespace cpBaseQtApplication +{ + namespace Pipeline + { + class Port; + class NamePort; + class InfoPort; + class InputPort; + class OutputPort; + + /** + */ + class cpBaseQtApplication_EXPORT Block + : public QGraphicsPathItem + { + public: + typedef Block Self; + typedef QGraphicsPathItem Superclass; + typedef cpPlugins::Pipeline::ProcessObject TFilter; + + protected: + /** + */ + class _TFilterObserver + : public itk::Command + { + public: + typedef itk::SmartPointer< _TFilterObserver > Pointer; + typedef itk::SmartPointer< const _TFilterObserver > ConstPointer; + itkNewMacro( _TFilterObserver ); + public: + void Execute( itk::Object* c, const itk::EventObject& e ) + { this->Execute( const_cast< const itk::Object* >( c ), e ); } + void Execute( const itk::Object* c, const itk::EventObject& e ); + public: + Block* ObservedBlock; + }; + + public: + enum { Type = QGraphicsItem::UserType + 6 }; + + Block( + TFilter* filter, + QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL + ); + virtual ~Block( ); + + TFilter* filter( ); + const TFilter* filter( ) const; + + void setNamePort( const QString& txt ); + void setInfoPort( const QString& txt ); + InputPort* addInputPort( const QString& txt, bool multiple ); + OutputPort* addOutputPort( const QString& txt ); + + InputPort* inputPort( const QString& txt ); + OutputPort* outputPort( const QString& txt ); + + QString namePort( ) const; + const InputPort* inputPort( const QString& txt ) const; + const OutputPort* outputPort( const QString& txt ) const; + + bool connectOutputPortSlot( QObject* receiver, const char* slot ); + + inline int type( ) const + { return( this->Type ); } + + virtual void setPos( const QPointF& pos ); + virtual void setPos( qreal x, qreal y ); + + virtual void paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ); + + protected: + QVariant itemChange( GraphicsItemChange change, const QVariant& value ); + void _setTypeInfo( const QString& txt ); + void _configPort( Port* port ); + + virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent* evt ); + virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ); + + private: + int m_HorzMargin; + int m_VertMargin; + int m_Width; + int m_Height; + + NamePort* m_NamePort; + InfoPort* m_InfoPort; + std::map< std::string, InputPort* > m_InputPorts; + std::map< std::string, OutputPort* > m_OutputPorts; + + TFilter::Pointer m_Filter; + _TFilterObserver::Pointer m_FilterObserver; + unsigned long m_FilterObserverId; + + static QColor SelectedAndUpdated; + static QColor NotSelectedAndUpdated; + static QColor SelectedAndNotUpdated; + static QColor NotSelectedAndNotUpdated; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpBaseQtApplication__Pipeline__Block__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Canvas.cxx b/lib/cpBaseQtApplication/Pipeline/Canvas.cxx new file mode 100644 index 0000000..8457187 --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Canvas.cxx @@ -0,0 +1,452 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Canvas:: +Canvas( QWidget* parent ) + : Superclass( parent ), + m_Workspace( NULL ), + m_ActualConnection( NULL ), + m_OutputPortReceiver( NULL ), + m_OutputPortSlot( "" ) +{ + this->m_Scene = new QGraphicsScene( this ); + this->setScene( this->m_Scene ); + this->setRenderHint( QPainter::Antialiasing ); + this->setAcceptDrops( true ); + + this->m_EventFilter = new EventFilter( this ); + this->m_EventFilter->setCanvas( this ); + this->m_EventFilter->install( this->m_Scene ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Canvas:: +~Canvas( ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +clear( ) +{ + qDeleteAll( this->m_Scene->items( ) ); + this->m_Blocks.clear( ); + this->m_ActualConnection = NULL; +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Canvas:: +TWorkspace* cpBaseQtApplication::Pipeline::Canvas:: +workspace( ) +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Pipeline::Canvas:: +TWorkspace* cpBaseQtApplication::Pipeline::Canvas:: +workspace( ) const +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +setWorkspace( TWorkspace* ws ) +{ + if( this->m_Workspace != ws ) + { + this->clear( ); + this->m_Workspace = ws; + + } // fi + this->_redrawWorkspace( ); +} + +// ------------------------------------------------------------------------- +std::string cpBaseQtApplication::Pipeline::Canvas:: +addFilter( const std::string& cat, const std::string& fil, const QPointF& pos ) +{ + auto filter = this->m_Workspace->CreateFilter( cat, fil ); + Block* b = new Block( filter, NULL, this->m_Scene ); + b->setPos( pos ); + if( this->m_OutputPortReceiver != NULL ) + b->connectOutputPortSlot( + this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( ) + ); + std::string name = filter->GetName( ); + this->m_Blocks[ name ] = b; + return( name ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Pipeline::Canvas:: +connectOutputPortSlot( QObject* receiver, const char* slot ) +{ + this->m_OutputPortReceiver = receiver; + this->m_OutputPortSlot = slot; + bool ok = true; + for( auto b : this->m_Blocks ) + ok &= b.second->connectOutputPortSlot( receiver, slot ); + return( ok ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +rename( QGraphicsItem* item ) +{ + if( this->m_Workspace == NULL ) + return; + + Block* b = dynamic_cast< Block* >( item ); + if( b != NULL ) + { + std::string old_n = b->filter( )->GetName( ); + bool ok; + std::string new_n = + QInputDialog::getText( + dynamic_cast< QWidget* >( this->parent( ) ), + "Change filter name", + "Filter name:", + QLineEdit::Normal, + old_n.c_str( ), + &ok + ).toStdString( ); + if( ok && new_n != "" && old_n != new_n ) + { + if( this->m_Workspace->RenameFilter( old_n, new_n ) ) + { + auto bIt = this->m_Blocks.find( old_n ); + this->m_Blocks[ new_n ] = bIt->second; + bIt->second->setNamePort( new_n.c_str( ) ); + this->m_Blocks.erase( bIt ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +exposePort( QGraphicsItem* item ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +moveConnection( const QPointF& pnt ) +{ + if( this->m_ActualConnection != NULL ) + { + if( this->m_ActualConnection->port1( ) == NULL ) + this->m_ActualConnection->setPos1( pnt ); + else if( this->m_ActualConnection->port2( ) == NULL ) + this->m_ActualConnection->setPos2( pnt ); + this->m_ActualConnection->updatePath( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +grab( const QPointF& pnt ) +{ + QGraphicsItem* item = this->m_Scene->itemAt( pnt ); + OutputPort* oport = dynamic_cast< OutputPort* >( item ); + if( oport != NULL ) + { + // Start new connection + this->m_ActualConnection = new Connection( 0, this->m_Scene ); + this->m_ActualConnection->setPort1( oport ); + this->m_ActualConnection->setPos1( oport->scenePos( ) ); + this->m_ActualConnection->setPos2( pnt ); + this->m_ActualConnection->updatePosFromPorts( ); + this->m_ActualConnection->updatePath( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +release( const QPointF& pnt ) +{ + if( this->m_ActualConnection == NULL || this->m_Workspace == NULL ) + return; + + QGraphicsItem* item = this->m_Scene->itemAt( pnt ); + InputPort* iport = dynamic_cast< InputPort* >( item ); + OutputPort* oport = + dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) ); + if( iport != NULL && oport != NULL ) + { + Block* iblock = iport->block( ); + Block* oblock = oport->block( ); + std::string ofil = oblock->namePort( ).toStdString( ); + std::string dfil = iblock->namePort( ).toStdString( ); + std::string oname = oport->name( ).toStdString( ); + std::string dname = iport->name( ).toStdString( ); + try + { + if( this->m_Workspace->Connect( ofil, oname, dfil, dname ) ) + { + this->m_ActualConnection->setPos2( iport->scenePos( ) ); + this->m_ActualConnection->setPort2( iport ); + this->m_ActualConnection->updatePosFromPorts( ); + this->m_ActualConnection->updatePath( ); + } + else + delete this->m_ActualConnection; + } + catch( std::exception& err ) + { + delete this->m_ActualConnection; + QMessageBox::critical( + NULL, + QMessageBox::tr( "Error connecting ports" ), + QMessageBox::tr( err.what( ) ) + ); + + } // yrt + this->m_ActualConnection = NULL; + } + else + { + delete this->m_ActualConnection; + this->m_ActualConnection = NULL; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +keyPressEvent( QKeyEvent* event ) +{ + static const int del_key = 16777223; + if( this->m_Workspace == NULL ) + return; + + switch( event->key( ) ) + { + case del_key: + { + // Get items to delete + auto _items = this->items( ); + auto i = _items.begin( ); + std::set< Block* > blocks_to_delete; + std::set< Connection* > connections_to_delete; + while( i != _items.end( ) ) + { + if( ( *i )->isSelected( ) ) + { + Block* b = dynamic_cast< Block* >( *i ); + Connection* c = dynamic_cast< Connection* >( *i ); + if( b != NULL ) + { + blocks_to_delete.insert( b ); + auto inputs = b->filter( )->GetInputsNames( ); + for( auto inIt : inputs ) + { + InputPort* p = b->inputPort( inIt.c_str( ) ); + for( unsigned int j = 0; j < p->numberOfConnections( ); ++j ) + connections_to_delete.insert( p->connection( j ) ); + + } // rof + auto outputs = b->filter( )->GetOutputsNames( ); + for( auto outIt : outputs ) + { + OutputPort* p = b->outputPort( outIt.c_str( ) ); + auto& conns = p->connections( ); + for( unsigned int j = 0; j < conns.size( ); ++j ) + connections_to_delete.insert( conns[ j ] ); + + } // rof + } + else if( c != NULL ) + connections_to_delete.insert( c ); + + } // fi + i++; + + } // elihw + + // Delete connections + for( auto conn : connections_to_delete ) + { + OutputPort* oport = conn->port1( ); + InputPort* iport = conn->port2( ); + Block* oblock = oport->block( ); + Block* iblock = iport->block( ); + if( + this->m_Workspace->Disconnect( + oblock->namePort( ).toStdString( ), + oport->name( ).toStdString( ), + iblock->namePort( ).toStdString( ), + iport->name( ).toStdString( ) + ) + ) + delete conn; + + } // rof + + // Delete blocks + for( auto block : blocks_to_delete ) + if( + this->m_Workspace->RemoveFilter( block->namePort( ).toStdString( ) ) + ) + delete block; + } + break; + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +wheelEvent( QWheelEvent* event ) +{ + this->_scaleView( + std::pow( double( 2 ), event->delta( ) / double( 240 ) ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +dragEnterEvent( QDragEnterEvent* event ) +{ + const QMimeData* mime = event->mimeData( ); + if( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) + event->acceptProposedAction( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +dragLeaveEvent( QDragLeaveEvent* event ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +dragMoveEvent( QDragMoveEvent* event ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +dropEvent( QDropEvent* event ) +{ + if( this->m_Workspace == NULL ) + return; + const QMimeData* mime = event->mimeData( ); + if( !( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) ) + return; + event->acceptProposedAction( ); + auto tree = dynamic_cast< QTreeWidget* >( event->source( ) ); + if( tree == NULL ) + return; + + QPointF p = this->mapToScene( event->pos( ) ); + QList< QTreeWidgetItem* > items = tree->selectedItems( ); + for( auto iIt = items.begin( ); iIt != items.end( ); ++iIt ) + { + auto parent = ( *iIt )->parent( ); + if( parent != NULL ) + this->addFilter( + parent->text( 0 ).toStdString( ), + ( *iIt )->text( 0 ).toStdString( ), + p + ); + + } // rof +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +_scaleView( qreal scaleFactor ) +{ + qreal factor = this->transform( ). + scale( scaleFactor, scaleFactor ). + mapRect( QRectF( 0, 0, 1, 1 ) ). + width( ); + if( factor < qreal( 0.07 ) || factor > qreal( 100 ) ) + return; + this->scale( scaleFactor, scaleFactor ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Canvas:: +_redrawWorkspace( ) +{ + // Get filters names + if( this->m_Workspace == NULL ) + return; + auto fnames = this->m_Workspace->GetFiltersNames( ); + + // Create blocks + for( auto fname : fnames ) + { + auto filter = this->m_Workspace->GetFilter( fname ); + Block* b = new Block( filter, NULL, this->m_Scene ); + b->setPos( filter->GetViewX( ), filter->GetViewY( ) ); + if( this->m_OutputPortReceiver != NULL ) + b->connectOutputPortSlot( + this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( ) + ); + this->m_Blocks[ filter->GetName( ) ] = b; + + } // rof + + // Create connections + for( auto b : this->m_Blocks ) + { + auto filter = b.second->filter( ); + auto inputs = filter->GetInputsNames( ); + for( auto in : inputs ) + { + for( unsigned int id = 0; id < filter->GetInputSize( in ); ++id ) + { + auto inData = filter->GetInput( in, id ); + if( inData != NULL ) + { + auto src = inData->GetSource( ); + auto outputs = src->GetOutputsNames( ); + std::string outName = ""; + for( auto out : outputs ) + if( src->GetOutput( out ) == inData ) + outName = out; + auto c = this->m_Blocks.find( src->GetName( ) ); + auto b_src = c->second; + auto b_des = b.second; + auto oport = b_src->outputPort( outName.c_str( ) ); + auto iport = b_des->inputPort( in.c_str( ) ); + + auto conn = new Connection( 0, this->m_Scene ); + conn->setPort1( oport ); + conn->setPort2( iport ); + conn->setPos1( oport->scenePos( ) ); + conn->setPos2( iport->scenePos( ) ); + conn->updatePosFromPorts( ); + conn->updatePath( ); + + } // fi + + } // rof + + } // rof + + } // rof +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Canvas.h b/lib/cpBaseQtApplication/Pipeline/Canvas.h new file mode 100644 index 0000000..bdd487c --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Canvas.h @@ -0,0 +1,83 @@ +#ifndef __cpBaseQtApplication__Pipeline__Canvas__h__ +#define __cpBaseQtApplication__Pipeline__Canvas__h__ + +#include +#include +#include + +class QGraphicsScene; + +namespace cpBaseQtApplication +{ + namespace Pipeline + { + // Some other forward declarations + class EventFilter; + class Block; + class Connection; + + /** + */ + class cpBaseQtApplication_EXPORT Canvas + : public QGraphicsView + { + Q_OBJECT; + + public: + typedef Canvas Self; + typedef QGraphicsView Superclass; + typedef cpPlugins::Interface::Workspace TWorkspace; + + public: + Canvas( QWidget* parent = 0 ); + virtual ~Canvas( ); + + void clear( ); + + TWorkspace* workspace( ); + const TWorkspace* workspace( ) const; + void setWorkspace( TWorkspace* ws ); + + std::string addFilter( + const std::string& cat, const std::string& fil, + const QPointF& pos = QPointF( 0, 0 ) + ); + bool connectOutputPortSlot( QObject* receiver, const char* slot ); + + void rename( QGraphicsItem* item ); + void exposePort( QGraphicsItem* item ); + void moveConnection( const QPointF& pnt ); + void grab( const QPointF& pnt ); + void release( const QPointF& pnt ); + + protected: + void keyPressEvent( QKeyEvent* event ); + void wheelEvent( QWheelEvent* event ); + + void dragEnterEvent( QDragEnterEvent* event ); + void dragLeaveEvent( QDragLeaveEvent* event ); + void dragMoveEvent( QDragMoveEvent* event ); + void dropEvent( QDropEvent* event ); + + void _scaleView( qreal scaleFactor ); + void _redrawWorkspace( ); + + protected: + QGraphicsScene* m_Scene; + EventFilter* m_EventFilter; + TWorkspace* m_Workspace; + std::map< std::string, Block* > m_Blocks; + + Connection* m_ActualConnection; + + QObject* m_OutputPortReceiver; + std::string m_OutputPortSlot; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpBaseQtApplication__Pipeline__Canvas__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Connection.cxx b/lib/cpBaseQtApplication/Pipeline/Connection.cxx new file mode 100644 index 0000000..28bd39c --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Connection.cxx @@ -0,0 +1,135 @@ +#include +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Connection:: +Connection( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ + this->setPen( QPen( Qt::black, 2 ) ); + this->setBrush( Qt::NoBrush ); + this->setZValue( -1 ); + this->m_Port1 = NULL; + this->m_Port2 = NULL; + this->setFlag( QGraphicsItem::ItemIsSelectable ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Connection:: +~Connection( ) +{ + if( this->m_Port1 != NULL ) + this->m_Port1->removeConnection( this ); + if( this->m_Port2 != NULL ) + this->m_Port2->removeConnection( this ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Connection:: +setPos1( const QPointF& p ) +{ + this->m_Pos1 = p; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Connection:: +setPos2( const QPointF& p ) +{ + this->m_Pos2 = p; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Connection:: +setPort1( OutputPort* p ) +{ + if( p != NULL ) + { + p->connections( ).push_back( this ); + this->m_Port1 = p; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Connection:: +setPort2( InputPort* p ) +{ + if( p != NULL ) + { + p->setConnection( this ); + this->m_Port2 = p; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Connection:: +updatePosFromPorts( ) +{ + if( this->m_Port1 != NULL ) + this->m_Pos1 = + this->m_Port1->scenePos( ) + + QPointF( this->m_Port1->radius( ), this->m_Port1->radius( ) ); + if( this->m_Port2 != NULL ) + this->m_Pos2 = + this->m_Port2->scenePos( ) + + QPointF( this->m_Port2->radius( ), this->m_Port2->radius( ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Connection:: +updatePath( ) +{ + QPainterPath p; + p.moveTo( this->m_Pos1 ); + + qreal dx = this->m_Pos2.x( ) - this->m_Pos1.x( ); + qreal dy = this->m_Pos2.y( ) - this->m_Pos1.y( ); + QPointF c1( this->m_Pos1.x( ) + dx * 0.25, this->m_Pos1.y( ) + dy * 0.1 ); + QPointF c2( this->m_Pos1.x( ) + dx * 0.75, this->m_Pos1.y( ) + dy * 0.9 ); + p.cubicTo( c1, c2, this->m_Pos2 ); + + this->setPath( p ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::OutputPort* +cpBaseQtApplication::Pipeline::Connection:: +port1( ) const +{ + return( this->m_Port1 ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::InputPort* +cpBaseQtApplication::Pipeline::Connection:: +port2( ) const +{ + return( this->m_Port2 ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Connection:: +paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ) +{ + Q_UNUSED( option ); + Q_UNUSED( widget ); + + if( this->isSelected( ) ) + painter->setPen( QPen( Qt::red, 5 ) ); + else + painter->setPen( QPen( Qt::black, 2 ) ); + this->setBrush( Qt::NoBrush ); + painter->drawPath( this->path( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Connection.h b/lib/cpBaseQtApplication/Pipeline/Connection.h new file mode 100644 index 0000000..ecfc8d2 --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Connection.h @@ -0,0 +1,60 @@ +#ifndef __cpBaseQtApplication__Pipeline__Connection__h__ +#define __cpBaseQtApplication__Pipeline__Connection__h__ + +#include +#include + +namespace cpBaseQtApplication +{ + namespace Pipeline + { + class InputPort; + class OutputPort; + + /** + */ + class cpBaseQtApplication_EXPORT Connection + : public QGraphicsPathItem + { + public: + typedef Connection Self; + typedef QGraphicsPathItem Superclass; + + public: + enum { Type = QGraphicsItem::UserType + 5 }; + + Connection( QGraphicsItem* parent = 0, QGraphicsScene* scene = 0 ); + virtual ~Connection( ); + + void setPos1( const QPointF& p ); + void setPos2( const QPointF& p ); + void setPort1( OutputPort* p ); + void setPort2( InputPort* p ); + void updatePosFromPorts( ); + void updatePath( ); + OutputPort* port1( ) const; + InputPort* port2( ) const; + + inline int type( ) const + { return( this->Type ); } + + virtual void paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ); + + private: + QPointF m_Pos1; + QPointF m_Pos2; + OutputPort* m_Port1; + InputPort* m_Port2; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpBaseQtApplication__Pipeline__Connection__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/EventFilter.cxx b/lib/cpBaseQtApplication/Pipeline/EventFilter.cxx new file mode 100644 index 0000000..5149c60 --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/EventFilter.cxx @@ -0,0 +1,227 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpBaseQtApplicationPipelineEventFilterCbckSWITCH( E, e ) \ + case QEvent::GraphicsScene##E: \ + { \ + QGraphicsScene##E##Event* evt = \ + dynamic_cast< QGraphicsScene##E##Event* >( e ); \ + if( evt != NULL ) \ + this->_##E##_cbk( evt ); \ + } \ + break; + +// ------------------------------------------------------------------------- +#define cpBaseQtApplicationPipelineEventFilterCallbackCODE( E ) \ + void cpBaseQtApplication::Pipeline::EventFilter:: \ + _##E##_cbk( QGraphicsScene##E##Event* evt ) + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::EventFilter:: +EventFilter( QObject* parent ) + : Superclass( parent ), + m_Scene( NULL ), + m_Canvas( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::EventFilter:: +~EventFilter( ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Canvas* +cpBaseQtApplication::Pipeline::EventFilter:: +canvas( ) +{ + return( this->m_Canvas ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Pipeline::Canvas* +cpBaseQtApplication::Pipeline::EventFilter:: +canvas( ) const +{ + return( this->m_Canvas ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::EventFilter:: +setCanvas( cpBaseQtApplication::Pipeline::Canvas* c ) +{ + this->m_Canvas = c; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::EventFilter:: +install( QGraphicsScene* s ) +{ + s->installEventFilter( this ); + this->m_Scene = s; +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Pipeline::EventFilter:: +eventFilter( QObject* o, QEvent* e ) +{ + // Event type + switch( int( e->type( ) ) ) + { + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( ContextMenu, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( DragEnter, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( DragLeave, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( DragMove, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Drop, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Help, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( HoverEnter, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( HoverLeave, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( HoverMove, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MouseDoubleClick, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MouseMove, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MousePress, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MouseRelease, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Move, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Resize, e ); + cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Wheel, e ); + default: + break; + } // hctiws + return( this->Superclass::eventFilter( o, e ) ); +} + +// ------------------------------------------------------------------------- +QGraphicsItem* cpBaseQtApplication::Pipeline::EventFilter:: +itemAt( const QPointF& pos ) +{ + QList< QGraphicsItem* > items = + this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) ); + QGraphicsItem* ret = NULL; + foreach( QGraphicsItem* item, items ) + if( item->type( ) > QGraphicsItem::UserType ) + ret = item; + return( ret ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( ContextMenu ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( DragEnter ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( DragLeave ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( DragMove ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( Drop ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( Help ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( HoverEnter ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( HoverLeave ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( HoverMove ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( MouseDoubleClick ) +{ + // Get clicked item + QGraphicsItem* item = this->itemAt( evt->scenePos( ) ); + if( item == NULL ) + return; + + if( evt->button( ) == Qt::LeftButton ) + { + if( evt->modifiers( ) == Qt::NoModifier ) + this->m_Canvas->rename( item ); + else if( evt->modifiers( ) == Qt::ControlModifier ) + this->m_Canvas->exposePort( item ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( MouseMove ) +{ + this->m_Canvas->moveConnection( evt->scenePos( ) ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( MousePress ) +{ + switch( evt->button( ) ) + { + case Qt::LeftButton: this->m_Canvas->grab( evt->scenePos( ) ); break; + default: break; + } // hctiws +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( MouseRelease ) +{ + switch( evt->button( ) ) + { + case Qt::LeftButton: this->m_Canvas->release( evt->scenePos( ) ); break; + default: break; + } // hctiws +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( Move ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( Resize ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplicationPipelineEventFilterCallbackCODE( Wheel ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/EventFilter.h b/lib/cpBaseQtApplication/Pipeline/EventFilter.h new file mode 100644 index 0000000..0243b7c --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/EventFilter.h @@ -0,0 +1,96 @@ +#ifndef __cpBaseQtApplication__Pipeline__EventFilter__h__ +#define __cpBaseQtApplication__Pipeline__EventFilter__h__ + +#include +#include +#include + +class QGraphicsScene; +class QGraphicsSceneMouseEvent; +class QGraphicsItem; +class QGraphicsSceneContextMenuEvent; +class QGraphicsSceneDragDropEvent; +class QGraphicsSceneHelpEvent; +class QGraphicsSceneHoverEvent; +class QGraphicsSceneMouseEvent; +class QGraphicsSceneMoveEvent; +class QGraphicsSceneResizeEvent; +class QGraphicsSceneWheelEvent; + +// ------------------------------------------------------------------------- +#define cpBaseQtApplicationPipelineEventFilterCallbackDCL( E ) \ + void _##E##_cbk( QGraphicsScene##E##Event* e ); + +namespace cpBaseQtApplication +{ + namespace Pipeline + { + class Canvas; + + /** + */ + class cpBaseQtApplication_EXPORT EventFilter + : public QObject + { + Q_OBJECT; + + public: + typedef EventFilter Self; + typedef QObject Superclass; + + public: + explicit EventFilter( QObject* parent = 0 ); + virtual ~EventFilter( ); + + Canvas* canvas( ); + const Canvas* canvas( ) const; + void setCanvas( Canvas* c ); + + void install( QGraphicsScene* s ); + bool eventFilter( QObject* o, QEvent* e ); + + private: + QGraphicsItem* itemAt( const QPointF& pos ); + + protected: + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragEnterEvent; + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragLeaveEvent; + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragMoveEvent; + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDropEvent; + typedef QGraphicsSceneHoverEvent QGraphicsSceneHoverEnterEvent; + typedef QGraphicsSceneHoverEvent QGraphicsSceneHoverMoveEvent; + typedef QGraphicsSceneHoverEvent QGraphicsSceneHoverLeaveEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMouseDoubleClickEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMouseMoveEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMousePressEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMouseReleaseEvent; + + cpBaseQtApplicationPipelineEventFilterCallbackDCL( ContextMenu ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( DragEnter ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( DragLeave ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( DragMove ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( Drop ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( Help ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( HoverEnter ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( HoverLeave ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( HoverMove ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( MouseDoubleClick ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( MouseMove ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( MousePress ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( MouseRelease ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( Move ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( Resize ); + cpBaseQtApplicationPipelineEventFilterCallbackDCL( Wheel ); + + private: + QGraphicsScene* m_Scene; + Canvas* m_Canvas; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpBaseQtApplication__Pipeline__EventFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Port.cxx b/lib/cpBaseQtApplication/Pipeline/Port.cxx new file mode 100644 index 0000000..f5b0b01 --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Port.cxx @@ -0,0 +1,358 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Port:: +Port( QGraphicsItem* parent, QGraphicsScene* scene ) + : QObject( ), + Superclass( parent, scene ), + m_Radius( 5 ), + m_Margin( 2 ) +{ + this->m_Label = new QGraphicsTextItem( this ); + this->m_ExtendedLabel = new QGraphicsTextItem( this ); + this->setExtend( false ); + + QPainterPath p; + p.addEllipse( 0, 0, 2 * this->m_Radius, 2 * this->m_Radius ); + + this->setPath( p ); + this->setPen( QPen( Qt::darkRed ) ); + this->setBrush( Qt::red ); + this->setFlag( QGraphicsItem::ItemSendsScenePositionChanges ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::Port:: +~Port( ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Port:: +setBlock( Block* b ) +{ + this->m_Block = b; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Port:: +setName( const QString& n ) +{ + this->m_Label->setPlainText( n ); + this->_updateLabels( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Port:: +setExtendedName( const QString& n ) +{ + this->m_ExtendedLabel->setPlainText( n ); + this->_updateLabels( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Port:: +setExtend( bool extend ) +{ + // Do nothing! + this->m_IsExtended = false; + this->m_ExtendedLabel->setVisible( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::Port:: +paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ) +{ + Q_UNUSED( option ); + Q_UNUSED( widget ); + + if( this->isExtended( ) ) + { + painter->setPen( QPen( Qt::darkBlue ) ); + painter->setBrush( Qt::blue ); + } + else + { + painter->setPen( QPen( Qt::darkRed ) ); + painter->setBrush( Qt::red ); + + } // fi + painter->drawPath( this->path( ) ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::NamePort:: +NamePort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::NamePort:: +~NamePort( ) +{ +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Pipeline::NamePort:: +isConnected( Port* other ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::NamePort:: +_updateLabels( ) +{ + QFont font( this->scene( )->font( ) ); + font.setBold( true ); + this->m_Label->setFont( font ); + this->m_ExtendedLabel->setFont( font ); + this->setPath( QPainterPath( ) ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::InfoPort:: +InfoPort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::InfoPort:: +~InfoPort( ) +{ +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Pipeline::InfoPort:: +isConnected( Port* other ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::InfoPort:: +_updateLabels( ) +{ + QFont font( this->scene( )->font( ) ); + font.setBold( false ); + this->m_Label->setFont( font ); + this->m_ExtendedLabel->setFont( font ); + this->setPath( QPainterPath( ) ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::InputPort:: +InputPort( QGraphicsItem* parent, bool multiple, QGraphicsScene* scene ) + : Superclass( parent, scene ), + m_IsMultiple( multiple ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::InputPort:: +~InputPort( ) +{ + this->m_Connection.clear( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::InputPort:: +_updateLabels( ) +{ + QFontMetrics fm( this->scene( )->font( ) ); + this->m_Label->setPos( this->m_Radius * 2, -fm.height( ) / 2 ); + this->m_ExtendedLabel->setPos( + -fm.width( this->extendedName( ) ) - this->m_Radius * 2, + -fm.height( ) / 2 + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::InputPort:: +setExtend( bool extend ) +{ + if( this->m_Connection.size( ) == 0 ) + { + this->m_IsExtended = extend; + this->m_ExtendedLabel->setVisible( extend ); + } + else + this->Superclass::setExtend( false ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Pipeline::InputPort:: +isConnected( Port* other ) +{ + bool conn = false; + auto i = this->m_Connection.begin( ); + for( ; i != this->m_Connection.end( ); ++i ) + conn |= ( ( *i )->port1( ) == other && ( *i )->port2( ) == this ); + return( conn ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::InputPort:: +setConnection( Connection* c ) +{ + if( this->m_IsMultiple || this->m_Connection.size( ) == 0 ) + this->m_Connection.push_back( c ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::InputPort:: +removeConnection( Connection* c ) +{ + auto i = std::find( + this->m_Connection.begin( ), + this->m_Connection.end( ), + c + ); + if( i != this->m_Connection.end( ) ) + { + *i = NULL; + this->m_Connection.erase( i ); + + } // fi +} + +// ------------------------------------------------------------------------- +QVariant cpBaseQtApplication::Pipeline::InputPort:: +itemChange( GraphicsItemChange change, const QVariant& value ) +{ + if( change == ItemScenePositionHasChanged ) + { + for( + auto i = this->m_Connection.begin( ); + i != this->m_Connection.end( ); + ++i + ) + { + ( *i )->updatePosFromPorts( ); + ( *i )->updatePath( ); + + } // fi + + } // fi + return( value ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::OutputPort:: +OutputPort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Pipeline::OutputPort:: +~OutputPort( ) +{ + foreach( Connection* conn, this->m_Connections ) + delete conn; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::OutputPort:: +_updateLabels( ) +{ + QFontMetrics fm( this->scene( )->font( ) ); + this->m_Label->setPos( + -fm.width( this->name( ) ) - this->m_Radius * 2, -fm.height( ) / 2 + ); + this->m_ExtendedLabel->setPos( this->m_Radius * 2, -fm.height( ) / 2 ); + +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::OutputPort:: +removeConnection( Connection* c ) +{ + auto i = std::find( + this->m_Connections.begin( ), + this->m_Connections.end( ), + c + ); + if( i != this->m_Connections.end( ) ) + { + *i = NULL; + this->m_Connections.erase( i ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::OutputPort:: +setExtend( bool extend ) +{ + this->m_IsExtended = extend; + this->m_ExtendedLabel->setVisible( extend ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Pipeline::OutputPort:: +isConnected( Port* other ) +{ + auto i = this->m_Connections.begin( ); + bool conn = false; + for( ; i != this->m_Connections.end( ) && !conn; ++i ) + conn |= ( ( *i )->port1( ) == this && ( *i )->port2( ) == other ); + return( conn ); +} + +// ------------------------------------------------------------------------- +QVariant cpBaseQtApplication::Pipeline::OutputPort:: +itemChange( GraphicsItemChange change, const QVariant& value ) +{ + if( change == ItemScenePositionHasChanged ) + { + foreach( Connection* conn, this->m_Connections ) + { + conn->updatePosFromPorts( ); + conn->updatePath( ); + + } // rof + + } // fi + return( value ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Pipeline::OutputPort:: +contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ) +{ + if( this->m_Block == NULL ) + return; + + QMenu menu; + QAction* showAction = menu.addAction( "Show" ); + QAction* hideAction = menu.addAction( "Hide" ); + QAction* selectedAction = menu.exec( evt->screenPos( ) ); + + if( selectedAction == showAction || selectedAction == hideAction ) + { + std::stringstream str; + str + << this->name( ).toStdString( ) << "@" + << this->m_Block->filter( )->GetName( ); + emit viewData( str.str( ), ( selectedAction == showAction ) ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Pipeline/Port.h b/lib/cpBaseQtApplication/Pipeline/Port.h new file mode 100644 index 0000000..0622925 --- /dev/null +++ b/lib/cpBaseQtApplication/Pipeline/Port.h @@ -0,0 +1,216 @@ +#ifndef __cpBaseQtApplication__Pipeline__Port__h__ +#define __cpBaseQtApplication__Pipeline__Port__h__ + +#include +#include + +namespace cpBaseQtApplication +{ + namespace Pipeline + { + class Block; + class Connection; + + /** + */ + class cpBaseQtApplication_EXPORT Port + : public QObject, + public QGraphicsPathItem + { + Q_OBJECT; + public: + typedef Port Self; + typedef QGraphicsPathItem Superclass; + + enum { Type = QGraphicsItem::UserType + 1 }; + + public: + Port( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~Port( ); + + void setBlock( Block* b ); + inline Block* block( ) const + { return( this->m_Block ); } + + virtual void setName( const QString& n ); + virtual void setExtendedName( const QString& n ); + inline QString name( ) const + { return( this->m_Label->toPlainText( ) ); } + inline QString extendedName( ) const + { return( this->m_ExtendedLabel->toPlainText( ) ); } + + inline int radius( ) const + { return( this->m_Radius ); } + + inline bool isExtended( ) const + { return( this->m_IsExtended ); } + virtual void setExtend( bool extend ); + + virtual bool isConnected( Port* other ) = 0; + inline int type( ) const + { return( this->Type ); } + + virtual void paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ); + + protected: + virtual void _updateLabels( ) { } + + protected: + Block* m_Block; + + int m_Radius; + int m_Margin; + bool m_IsExtended; + + QGraphicsTextItem* m_Label; + QGraphicsTextItem* m_ExtendedLabel; + }; + + /** + */ + class cpBaseQtApplication_EXPORT NamePort + : public Port + { + Q_OBJECT; + public: + typedef NamePort Self; + typedef Port Superclass; + + enum { Type = Superclass::Type + 1 }; + + public: + NamePort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~NamePort( ); + + virtual bool isConnected( Port* other ); + inline int type( ) const + { return( this->Type ); } + + protected: + virtual void _updateLabels( ); + }; + + /** + */ + class cpBaseQtApplication_EXPORT InfoPort + : public Port + { + Q_OBJECT; + public: + typedef InfoPort Self; + typedef Port Superclass; + + enum { Type = Superclass::Type + 2 }; + + public: + InfoPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~InfoPort( ); + + virtual bool isConnected( Port* other ); + inline int type( ) const + { return( this->Type ); } + + protected: + virtual void _updateLabels( ); + }; + + /** + */ + class cpBaseQtApplication_EXPORT InputPort + : public Port + { + Q_OBJECT; + public: + typedef InputPort Self; + typedef Port Superclass; + + enum { Type = Superclass::Type + 3 }; + + public: + InputPort( + QGraphicsItem* parent, + bool multiple, + QGraphicsScene* scene = NULL + ); + virtual ~InputPort( ); + + virtual void setExtend( bool extend ); + + virtual bool isConnected( Port* other ); + inline int type( ) const + { return( this->Type ); } + + void setConnection( Connection* c ); + void removeConnection( Connection* c ); + inline unsigned int numberOfConnections( ) const + { return( this->m_Connection.size( ) ); } + inline Connection* connection( unsigned int i ) + { return( this->m_Connection[ i ] ); } + inline const Connection* connection( unsigned int i ) const + { return( this->m_Connection[ i ] ); } + inline bool hasConnection( ) const + { return( this->m_Connection.size( ) > 0 ); } + inline bool isMultiple( ) const + { return( this->m_IsMultiple ); } + + protected: + QVariant itemChange( GraphicsItemChange change, const QVariant& value ); + virtual void _updateLabels( ); + + protected: + std::vector< Connection* > m_Connection; + bool m_IsMultiple; + }; + + /** + */ + class cpBaseQtApplication_EXPORT OutputPort + : public Port + { + Q_OBJECT; + public: + typedef OutputPort Self; + typedef Port Superclass; + + enum { Type = Superclass::Type + 4 }; + + public: + OutputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~OutputPort( ); + + void removeConnection( Connection* c ); + virtual void setExtend( bool extend ); + + virtual bool isConnected( Port* other ); + inline int type( ) const + { return( this->Type ); } + + inline std::vector< Connection* >& connections( ) + { return( this->m_Connections ); } + inline const std::vector< Connection* >& connections( ) const + { return( this->m_Connections ); } + + signals: + void viewData( const std::string& name, bool show ); + + protected: + QVariant itemChange( GraphicsItemChange change, const QVariant& value ); + virtual void _updateLabels( ); + + virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ); + + protected: + std::vector< Connection* > m_Connections; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpBaseQtApplication__Pipeline__Port__h__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Plugins/Navigator.cxx b/lib/cpBaseQtApplication/Plugins/Navigator.cxx new file mode 100644 index 0000000..8fa3048 --- /dev/null +++ b/lib/cpBaseQtApplication/Plugins/Navigator.cxx @@ -0,0 +1,92 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Plugins::Navigator:: +Navigator( QWidget* parent ) + : Superclass( parent ) +{ + this->setDragEnabled( true ); + this->setDragDropMode( QAbstractItemView::DragOnly ); + this->setAlternatingRowColors( true ); + this->_Clear( ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Plugins::Navigator:: +~Navigator( ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Plugins::Navigator:: +Update( ) +{ + this->_Clear( ); + this->_Update( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Plugins::Navigator:: +_Clear( ) +{ + this->clear( ); + this->setColumnCount( 1 ); + QString header_txt = "Loaded plugins"; + if( QTreeWidgetItem* header = this->headerItem( ) ) + header->setText( 0, header_txt ); + else + this->setHeaderLabel( header_txt ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Plugins::Navigator:: +_Update( ) +{ + typedef cpPlugins::Interface::Loader _TLoader; + _TLoader loader; + + // Iterate over categories and filters + auto filters = loader.GetFilters( ); + for( auto catIt : filters ) + { + const char* c_cat = catIt.first.c_str( ); + + // Create or get category + QList< QTreeWidgetItem* > cat_items = + this->findItems( c_cat, Qt::MatchExactly | Qt::MatchRecursive ); + QTreeWidgetItem* cat = NULL; + if( cat_items.size( ) == 0 ) + { + cat = new QTreeWidgetItem( + ( QTreeWidgetItem* )( NULL ), QStringList( c_cat ) + ); + this->addTopLevelItem( cat ); + } + else + cat = cat_items[ 0 ]; + + for( auto filIt : catIt.second ) + { + const char* c_fil = filIt.c_str( ); + QList< QTreeWidgetItem* > filter_items = + this->findItems( c_fil, Qt::MatchExactly | Qt::MatchRecursive ); + auto i = filter_items.begin( ); + auto found_i = filter_items.end( ); + for( ; i != filter_items.end( ); ++i ) + if( ( *i )->parent( ) == cat ) + found_i = i; + + // Add filter + if( found_i == filter_items.end( ) ) + QTreeWidgetItem* filter = new QTreeWidgetItem( + cat, QStringList( c_fil ) + ); + + } // rof + + } // rof + this->expandAll( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Plugins/Navigator.h b/lib/cpBaseQtApplication/Plugins/Navigator.h new file mode 100644 index 0000000..a4a745a --- /dev/null +++ b/lib/cpBaseQtApplication/Plugins/Navigator.h @@ -0,0 +1,39 @@ +#ifndef __cpBaseQtApplication__Plugins__Navigator__h__ +#define __cpBaseQtApplication__Plugins__Navigator__h__ + +#include +#include + +namespace cpBaseQtApplication +{ + namespace Plugins + { + /** + */ + class cpBaseQtApplication_EXPORT Navigator + : public QTreeWidget + { + Q_OBJECT; + + public: + typedef Navigator Self; + typedef QTreeWidget Superclass; + + public: + explicit Navigator( QWidget* parent = NULL ); + virtual ~Navigator( ); + + void Update( ); + + protected: + void _Clear( ); + void _Update( ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpBaseQtApplication__Plugins__Navigator__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/BezierCurveFunction.h b/lib/cpExtensions/Algorithms/BezierCurveFunction.h new file mode 100644 index 0000000..65c3af8 --- /dev/null +++ b/lib/cpExtensions/Algorithms/BezierCurveFunction.h @@ -0,0 +1,77 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + * Uses the De Casteljau's algorithm. + */ + template< class V > + class BezierCurveFunction + : public itk::FunctionBase< typename V::ValueType, V > + { + public: + typedef BezierCurveFunction Self; + typedef itk::FunctionBase< typename V::ValueType, V > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef V TVector; + typedef typename V::ValueType TScalar; + + typedef + itk::Matrix< TScalar, TVector::Dimension, TVector::Dimension > + TFrame; + typedef std::vector< TVector > TVectorsContainer; + + public: + itkNewMacro( Self ); + itkTypeMacro( BezierCurveFunction, itkFunctionBase ); + + public: + virtual void AddPoint( const TVector& v ); + virtual unsigned int GetNumberOfPoints( ) const; + + virtual TVector Evaluate( const TScalar& u ) const cpExtensions_OVERRIDE; + virtual TFrame EvaluateFrenetFrame( const TScalar& u ) const; + virtual TScalar EvaluateLength( ) const; + + protected: + BezierCurveFunction( ); + virtual ~BezierCurveFunction( ) { } + + void _UpdateDerivative( ) const; + + private: + // Purposely not implemented + BezierCurveFunction( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TVectorsContainer m_Vectors; + mutable Pointer m_Derivative; + mutable bool m_DerivativeUpdated; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/BezierCurveFunction.hxx b/lib/cpExtensions/Algorithms/BezierCurveFunction.hxx new file mode 100644 index 0000000..684360f --- /dev/null +++ b/lib/cpExtensions/Algorithms/BezierCurveFunction.hxx @@ -0,0 +1,155 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__HXX__ + +// ------------------------------------------------------------------------- +template< class V > +void cpExtensions::Algorithms::BezierCurveFunction< V >:: +AddPoint( const TVector& v ) +{ + this->m_Vectors.push_back( v ); + this->m_DerivativeUpdated = false; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class V > +unsigned int cpExtensions::Algorithms::BezierCurveFunction< V >:: +GetNumberOfPoints( ) const +{ + return( this->m_Vectors.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class V > +typename cpExtensions::Algorithms::BezierCurveFunction< V >:: +TVector cpExtensions::Algorithms::BezierCurveFunction< V >:: +Evaluate( const TScalar& u ) const +{ + TVectorsContainer Q = this->m_Vectors; + unsigned int n = Q.size( ); + TScalar _1u = TScalar( 1 ) - u; + + for( unsigned int k = 1; k < n; k++ ) + { + // CM Fixed a bug appearing under Windows : changed the stopping + // condition from <= to <. Otherwise, on the last step, an element out + // of the range of vector Q is accessed (Q[ i + 1 ])... + for( unsigned int i = 0; i < n - k; i++ ) + Q[ i ] = ( Q[ i ] * _1u ) + ( Q[ i + 1 ] * u ); + + } // rof + return( Q[ 0 ] ); +} + +// ------------------------------------------------------------------------- +template< class V > +typename cpExtensions::Algorithms::BezierCurveFunction< V >:: +TFrame cpExtensions::Algorithms::BezierCurveFunction< V >:: +EvaluateFrenetFrame( const TScalar& u ) const +{ + TFrame fr; + fr.Fill( TScalar( 0 ) ); + if( TVector::Dimension == 2 ) + { + this->_UpdateDerivative( ); + this->m_Derivative->_UpdateDerivative( ); + + TVector vT = this->m_Derivative->Evaluate( u ); + TScalar nvT = vT.GetNorm( ); + if( TScalar( 0 ) < nvT ) + vT /= nvT; + + fr[ 0 ][ 0 ] = vT[ 0 ]; + fr[ 1 ][ 0 ] = vT[ 1 ]; + + fr[ 0 ][ 1 ] = -vT[ 1 ]; + fr[ 1 ][ 1 ] = vT[ 0 ]; + } + else if( TVector::Dimension == 3 ) + { + this->_UpdateDerivative( ); + this->m_Derivative->_UpdateDerivative( ); + TVector vT = this->m_Derivative->Evaluate( u ); + TScalar nvT = vT.GetNorm( ); + if( nvT > TScalar( 0 ) ) + { + vT /= nvT; + TVector vN = this->m_Derivative->m_Derivative->Evaluate( u ); + TScalar nvN = vN.GetNorm( ); + if( nvT > TScalar( 0 ) ) + { + vN /= nvN; + TVector vB; + vB[ 0 ] = ( vT[ 1 ] * vN[ 2 ] ) - ( vT[ 2 ] * vN[ 1 ] ); + vB[ 1 ] = ( vT[ 2 ] * vN[ 0 ] ) - ( vT[ 0 ] * vN[ 2 ] ); + vB[ 2 ] = ( vT[ 0 ] * vN[ 1 ] ) - ( vT[ 1 ] * vN[ 0 ] ); + + for( unsigned int d = 0; d < 3; d++ ) + { + fr[ d ][ 0 ] = vT[ d ]; + fr[ d ][ 1 ] = vN[ d ]; + fr[ d ][ 2 ] = vB[ d ]; + + } // rof + } + else + std::cerr << "ERROR normal" << std::endl; + } + else + std::cerr << "ERROR tangent" << std::endl; + + } // fi + return( fr ); +} + +// ------------------------------------------------------------------------- +template< class V > +typename cpExtensions::Algorithms::BezierCurveFunction< V >:: +TScalar cpExtensions::Algorithms::BezierCurveFunction< V >:: +EvaluateLength( ) const +{ + unsigned int n = this->GetNumberOfPoints( ) << 1; + TScalar d = TScalar( 0 ); + TVector v0 = this->Evaluate( 0 ); + for( unsigned int i = 1; i < n; i++ ) + { + TVector v1 = this->Evaluate( TScalar( i ) / TScalar( n - 1 ) ); + d += ( v1 - v0 ).GetNorm( ); + v0 = v1; + + } // rof + return( d ); +} + +// ------------------------------------------------------------------------- +template< class V > +cpExtensions::Algorithms::BezierCurveFunction< V >:: +BezierCurveFunction( ) + : Superclass( ), + m_DerivativeUpdated( false ) +{ +} + +// ------------------------------------------------------------------------- +template< class V > +void cpExtensions::Algorithms::BezierCurveFunction< V >:: +_UpdateDerivative( ) const +{ + if( this->m_DerivativeUpdated ) + return; + + this->m_Derivative = Self::New( ); + unsigned int n = this->m_Vectors.size( ) - 1; + for( unsigned int i = 0; i < n; i++ ) + this->m_Derivative->AddPoint( + TScalar( n ) * ( this->m_Vectors[ i + 1 ] - this->m_Vectors[ i ] ) + ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/CPRImageFilter.h b/lib/cpExtensions/Algorithms/CPRImageFilter.h new file mode 100644 index 0000000..ed13da3 --- /dev/null +++ b/lib/cpExtensions/Algorithms/CPRImageFilter.h @@ -0,0 +1,76 @@ +#ifndef __cpExtensions__Algorithms__CPRImageFilter__h__ +#define __cpExtensions__Algorithms__CPRImageFilter__h__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TImage, class _TCurve > + class CPRImageFilter + : public itk::ImageToImageFilter< _TImage, _TImage > + { + public: + typedef CPRImageFilter Self; + typedef itk::ImageToImageFilter< _TImage, _TImage > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TImage TImage; + typedef _TCurve TCurve; + typedef typename TCurve::TScalar TScalar; + + typedef IsoImageSlicer< TImage, TScalar > TSlicer; + typedef typename TSlicer::TInterpolateFunction TInterpolateFunction; + typedef typename TSlicer::TSliceImage TSliceImage; + + typedef itk::JoinSeriesImageFilter< TSliceImage, TImage > TJoinFilter; + + public: + itkNewMacro( Self ); + itkTypeMacro( CPRImageFilter, itk::ImageToImageFilter ); + + itkGetConstMacro( SliceRadius, double ); + itkGetObjectMacro( Interpolator, TInterpolateFunction ); + + itkSetMacro( SliceRadius, double ); + itkSetObjectMacro( Interpolator, TInterpolateFunction ); + + public: + _TCurve* GetCurve( ); + const _TCurve* GetCurve( ) const; + void SetCurve( _TCurve* curve ); + + protected: + CPRImageFilter( ); + virtual ~CPRImageFilter( ); + + virtual void GenerateOutputInformation( ) cpExtensions_OVERRIDE; + virtual void GenerateInputRequestedRegion( ) cpExtensions_OVERRIDE; + virtual void GenerateData( ) cpExtensions_OVERRIDE; + + protected: + double m_SliceRadius; + typename TInterpolateFunction::Pointer m_Interpolator; + + std::vector< typename TSlicer::Pointer > m_Slicers; + typename TJoinFilter::Pointer m_Join; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__CPRImageFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/CPRImageFilter.hxx b/lib/cpExtensions/Algorithms/CPRImageFilter.hxx new file mode 100644 index 0000000..de76e7f --- /dev/null +++ b/lib/cpExtensions/Algorithms/CPRImageFilter.hxx @@ -0,0 +1,127 @@ +#ifndef __cpExtensions__Algorithms__CPRImageFilter__hxx__ +#define __cpExtensions__Algorithms__CPRImageFilter__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +_TCurve* cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +GetCurve( ) +{ + return( + dynamic_cast< _TCurve* >( this->itk::ProcessObject::GetInput( 1 ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +const _TCurve* cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +GetCurve( ) const +{ + return( + dynamic_cast< const _TCurve* >( this->itk::ProcessObject::GetInput( 1 ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +SetCurve( _TCurve* curve ) +{ + this->itk::ProcessObject::SetNthInput( 1, curve ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +CPRImageFilter( ) + : Superclass( ), + m_SliceRadius( 0 ) +{ + this->Superclass::SetNumberOfRequiredInputs( 2 ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +~CPRImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +GenerateOutputInformation( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +GenerateInputRequestedRegion( ) +{ + TImage* input = const_cast< TImage* >( this->GetInput( ) ); + if( input != NULL ) + input->SetRequestedRegionToLargestPossibleRegion( ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TCurve > +void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >:: +GenerateData( ) +{ + typedef itk::MinimumMaximumImageCalculator< _TImage > _TMinMax; + + auto input = this->GetInput( ); + auto curve = this->GetCurve( ); + auto output = this->GetOutput( ); + + // Compute image intensity range + typename _TMinMax::Pointer minmax = _TMinMax::New( ); + minmax->SetImage( input ); + minmax->Compute( ); + + // Main loop + this->m_Join = TJoinFilter::New( ); + this->m_Slicers.clear( ); + unsigned long N = curve->GetNumberOfPoints( ); + double len = 0; + typename _TCurve::TPoint p, q; + for( unsigned long n = 0; n < N; ++n ) + { + p = curve->GetPoint( n ); + if( n > 0 ) + len += p.EuclideanDistanceTo( q ); + q = p; + + // Prepare slicer + typename TSlicer::Pointer slicer = TSlicer::New( ); + slicer->SetInput( input ); + slicer->SetDefaultValue( minmax->GetMinimum( ) ); + slicer->SpacingFromMinimumOn( ); + if( this->m_Interpolator.IsNotNull( ) ) + slicer->SetInterpolator( this->m_Interpolator ); + slicer->SizeFromMaximumOff( ); + if( this->m_SliceRadius > double( 0 ) ) + { + slicer->SizeFromMinimumOff( ); + slicer->SetSize( this->m_SliceRadius ); + } + else + slicer->SizeFromMinimumOn( ); + slicer->SetTranslation( p ); + slicer->SetRotation( curve->GetFrame( n ) ); + slicer->Update( ); + + this->m_Join->SetInput( n, slicer->GetOutput( ) ); + this->m_Slicers.push_back( slicer ); + + } // rof + this->m_Join->SetSpacing( len / double( N ) ); + this->m_Join->Update( ); + this->GetOutput( )->Graft( this->m_Join->GetOutput( ) ); +} + +#endif // __cpExtensions__Algorithms__CPRImageFilter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/FluxMedialness.h b/lib/cpExtensions/Algorithms/FluxMedialness.h new file mode 100644 index 0000000..c25f5f4 --- /dev/null +++ b/lib/cpExtensions/Algorithms/FluxMedialness.h @@ -0,0 +1,74 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > > + class FluxMedialness + : public GradientImageFunctionBase< _TGradient, _TMask > + { + public: + typedef FluxMedialness Self; + typedef GradientImageFunctionBase< _TGradient, _TMask > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkStaticConstMacro( Dimension, unsigned int, Superclass::Dimension ); + + typedef typename Superclass::TOutput TOutput; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TIndex TIndex; + typedef typename Superclass::TVector TVector; + typedef typename Superclass::TPoint TPoint; + + typedef std::vector< double > TRCandidates; + + public: + itkNewMacro( Self ); + itkTypeMacro( FluxMedialness, GradientImageFunctionBase ); + + itkGetConstMacro( RadiusStep, double ); + itkGetConstMacro( MinRadius, double ); + itkGetConstMacro( MaxRadius, double ); + itkGetConstMacro( RadialSampling, unsigned int ); + + itkSetMacro( RadiusStep, double ); + itkSetMacro( MinRadius, double ); + itkSetMacro( MaxRadius, double ); + itkSetMacro( RadialSampling, unsigned int ); + + protected: + FluxMedialness( ); + virtual ~FluxMedialness( ); + + virtual TOutput _Evaluate( const TIndex& i ) const cpExtensions_OVERRIDE; + + private: + // Purposely not implemented. + FluxMedialness( const Self& ); + void operator=( const Self& ); + + protected: + double m_MinRadius; + double m_MaxRadius; + unsigned int m_RadialSampling; + double m_RadiusStep; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/FluxMedialness.hxx b/lib/cpExtensions/Algorithms/FluxMedialness.hxx new file mode 100644 index 0000000..4412292 --- /dev/null +++ b/lib/cpExtensions/Algorithms/FluxMedialness.hxx @@ -0,0 +1,108 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >:: +FluxMedialness( ) + : Superclass( ), + m_MinRadius( double( 0 ) ), + m_MaxRadius( double( 1 ) ), + m_RadialSampling( 4 ), + m_RadiusStep( double( 1 ) ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >:: +~FluxMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +typename cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >:: +TOutput cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >:: +_Evaluate( const TIndex& i ) const +{ + itk::Object::GlobalWarningDisplayOff( ); + + double pi2n = double( 2 ) * double( vnl_math::pi ); + pi2n /= int( this->m_RadialSampling ); + const _TGradient* img = this->GetInputImage( ); + // Gradient in central pixel + //TVector grad_idx = img->GetPixel( i ); + + double Flux1 = 0; + double Flux = 0; + + TRCandidates FluxFinal; + TRCandidates radiusGenerated; + double dR = double( 0 ); + double optR = double( 0 ); + TPoint center; + img->TransformIndexToPhysicalPoint( i, center ); + double radius = double(0); + + for( unsigned int cx = 0; cx < Self::Dimension - 1; cx++ ) + { + for( unsigned int cy = cx + 1; cy < Self::Dimension; cy++ ) + { + dR = double( 0 ); + FluxFinal.clear(); + radiusGenerated.clear(); + radius = this->m_MinRadius; + while( radius <= this->m_MaxRadius ) + { + Flux = 0; + for( unsigned int I_radial = 0; I_radial < this->m_RadialSampling ; I_radial++ ) + { + Flux1 = 0; + + // Direction of first profile + typename TPoint::VectorType dir1; + dir1.Fill( double( 0 ) ); + dir1[ cx ] = std::cos( pi2n * double( I_radial ) ); + dir1[ cy ] = std::sin( pi2n * double( I_radial ) ); + dir1 *= (radius); + TIndex rIdx; + if (img->TransformPhysicalPointToIndex( center + dir1, rIdx )) + { + TVector grad_rIdx = img->GetPixel( rIdx ); + TVector u_i1; + u_i1.SetVnlVector( ( center - ( center + dir1 ) ).GetVnlVector( ) ); + u_i1.Normalize( ); + // dot product + Flux1 = grad_rIdx * u_i1; + } + + Flux += Flux1; + + } // rof + //std::cout<<" radius:"<m_RadialSampling; + FluxFinal.push_back(Flux); + radiusGenerated.push_back(radius); + radius += this->m_RadiusStep; + + } //elihw + + dR= *( std::max_element( FluxFinal.begin(), FluxFinal.end() ) ); + optR= (dR>optR)? dR:optR; + + } // rof + + } // rof + return( TScalar(optR) ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h b/lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h new file mode 100644 index 0000000..308b3c5 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h @@ -0,0 +1,103 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TInputImage, class _TEstimator > + class GaussianDensityImageFilter + : public itk::ImageToImageFilter< _TInputImage, itk::Image< typename _TEstimator::TScalar, _TInputImage::ImageDimension > > + { + public: + typedef typename _TEstimator::TScalar TScalar; + typedef itk::Image< TScalar, _TInputImage::ImageDimension > TOutputImage; + typedef GaussianDensityImageFilter Self; + typedef itk::ImageToImageFilter< _TInputImage, TOutputImage > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInputImage TInputImage; + typedef _TEstimator TEstimator; + typedef typename TOutputImage::RegionType TRegion; + + public: + itkNewMacro( Self ); + itkTypeMacro( GaussianDensityImageFilter, itkImageToImageFilter ); + + itkGetConstObjectMacro( Estimator, TEstimator ); + itkSetConstObjectMacro( Estimator, TEstimator ); + + protected: + GaussianDensityImageFilter( ) + : Superclass( ) + { + } + virtual ~GaussianDensityImageFilter( ) + { + } + + virtual void ThreadedGenerateData( + const TRegion& region, + itk::ThreadIdType threadId + ) + { + const typename TRegion::SizeType& regionSize = region.GetSize( ); + if( regionSize[ 0 ] == 0 ) + return; + const TInputImage* in = this->GetInput( ); + TOutputImage* out = this->GetOutput( 0 ); + + const size_t nLines = region.GetNumberOfPixels( ) / regionSize[ 0 ]; + itk::ProgressReporter progress( this, threadId, nLines ); + + // Define the iterators + itk::ImageScanlineConstIterator< TInputImage > inIt( in, region ); + itk::ImageScanlineIterator< TOutputImage > outIt( out, region ); + + inIt.GoToBegin( ); + outIt.GoToBegin( ); + while( !inIt.IsAtEnd( ) ) + { + while( !inIt.IsAtEndOfLine( ) ) + { + if( this->m_Estimator.IsNotNull( ) ) + outIt.Set( this->m_Estimator->Density( inIt.Get( ) ) ); + ++inIt; + ++outIt; + + } // elihw + inIt.NextLine( ); + outIt.NextLine( ); + progress.CompletedPixel( ); + + } // elihw + } + + private: + // Purposely not implemented. + GaussianDensityImageFilter( const Self& ); + void operator=( const Self& ); + + protected: + typename TEstimator::ConstPointer m_Estimator; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/GradientImageFunctionBase.h b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.h new file mode 100644 index 0000000..7350495 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.h @@ -0,0 +1,79 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__ +#define __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + * Base class to compute values based on image gradients (vector). + */ + template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > > + class GradientImageFunctionBase + : public itk::ImageFunction< _TGradient, typename _TGradient::PixelType::ValueType, typename _TGradient::PixelType::ValueType > + { + public: + // Types from input arguments + typedef _TGradient TGradient; + typedef _TMask TMask; + typedef typename _TGradient::PixelType TVector; + typedef typename TVector::ValueType TScalar; + itkStaticConstMacro( + Dimension, unsigned int, _TGradient::ImageDimension + ); + + // Standard itk types + typedef GradientImageFunctionBase Self; + typedef itk::ImageFunction< _TGradient, TScalar, TScalar > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Types from base itk::ImageFunction + typedef typename Superclass::InputType TInput; + typedef typename Superclass::OutputType TOutput; + typedef typename Superclass::PointType TPoint; + typedef typename Superclass::ContinuousIndexType TContIndex; + typedef typename Superclass::IndexType TIndex; + + public: + itkTypeMacro( GradientImageFunctionBase, itkImageFunction ); + + itkGetConstObjectMacro( Mask, TMask ); + itkSetConstObjectMacro( Mask, TMask ); + + public: + virtual void Prepare( ) const; + virtual TOutput Evaluate( const TPoint& p ) const cpExtensions_OVERRIDE; + virtual TOutput EvaluateAtIndex( const TIndex& i ) const cpExtensions_OVERRIDE; + virtual TOutput EvaluateAtContinuousIndex( const TContIndex& i ) const cpExtensions_OVERRIDE; + + protected: + GradientImageFunctionBase( ); + virtual ~GradientImageFunctionBase( ); + + virtual TOutput _Evaluate( const TIndex& i ) const = 0; + + private: + // Purposely not implemented. + GradientImageFunctionBase( const Self& ); + void operator=( const Self& ); + + protected: + typename _TMask::ConstPointer m_Mask; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx new file mode 100644 index 0000000..a858650 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx @@ -0,0 +1,72 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__ + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +void +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +Prepare( ) const +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +typename +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +TOutput +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +Evaluate( const TPoint& p ) const +{ + TIndex i; + this->GetInputImage( )->TransformPhysicalPointToIndex( p, i ); + return( this->EvaluateAtIndex( i ) ); +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +typename +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +TOutput +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +EvaluateAtIndex( const TIndex& i ) const +{ + bool eval = true; + if( this->m_Mask.IsNotNull( ) ) + eval = ( ( unsigned long )( this->m_Mask->GetPixel( i ) ) > 0 ); + if( eval ) + return( this->_Evaluate( i ) ); + else + return( TOutput( -1 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +typename +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +TOutput +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +EvaluateAtContinuousIndex( const TContIndex& i ) const +{ + TPoint p; + this->GetInputImage( )->TransformContinuousIndexToPhysicalPoint( i, p ); + return( this->Evaluate( p ) ); +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +GradientImageFunctionBase( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >:: +~GradientImageFunctionBase( ) +{ +} + +#endif // __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/GulsunTekMedialness.h b/lib/cpExtensions/Algorithms/GulsunTekMedialness.h new file mode 100644 index 0000000..15add9e --- /dev/null +++ b/lib/cpExtensions/Algorithms/GulsunTekMedialness.h @@ -0,0 +1,76 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > > + class GulsunTekMedialness + : public GradientImageFunctionBase< _TGradient, _TMask > + { + public: + typedef GulsunTekMedialness Self; + typedef GradientImageFunctionBase< _TGradient, _TMask > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkStaticConstMacro( Dimension, unsigned int, Superclass::Dimension ); + + typedef typename Superclass::TOutput TOutput; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TIndex TIndex; + typedef typename Superclass::TVector TVector; + typedef typename Superclass::TPoint TPoint; + typedef typename TIndex::OffsetType TOffset; + + typedef std::vector< double > TProfile; + typedef std::vector< TOffset > TOffsets; + + public: + itkNewMacro( Self ); + itkTypeMacro( GulsunTekMedialness, GradientImageFunctionBase ); + + itkGetConstMacro( MinRadius, double ); + itkGetConstMacro( MaxRadius, double ); + itkGetConstMacro( ProfileSampling, unsigned int ); + itkGetConstMacro( RadialSampling, unsigned int ); + + itkSetMacro( MinRadius, double ); + itkSetMacro( MaxRadius, double ); + itkSetMacro( ProfileSampling, unsigned int ); + itkSetMacro( RadialSampling, unsigned int ); + + protected: + GulsunTekMedialness( ); + virtual ~GulsunTekMedialness( ); + + virtual TOutput _Evaluate( const TIndex& i ) const cpExtensions_OVERRIDE; + + private: + // Purposely not implemented. + GulsunTekMedialness( const Self& ); + void operator=( const Self& ); + + protected: + double m_MinRadius; + double m_MaxRadius; + unsigned int m_ProfileSampling; + unsigned int m_RadialSampling; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx b/lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx new file mode 100644 index 0000000..fc59929 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx @@ -0,0 +1,114 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >:: +GulsunTekMedialness( ) + : Superclass( ), + m_MinRadius( double( 0 ) ), + m_MaxRadius( double( 1 ) ), + m_ProfileSampling( 4 ), + m_RadialSampling( 10 ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >:: +~GulsunTekMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +typename cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >:: +TOutput cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >:: +_Evaluate( const TIndex& i ) const +{ + itk::Object::GlobalWarningDisplayOff( ); + + // Various values + const _TGradient* in = this->GetInputImage( ); + double pi2n = + double( 2 ) * double( vnl_math::pi ) / + double( this->m_ProfileSampling ); + double rOff = this->m_MaxRadius / double( this->m_RadialSampling - 1 ); + double optR = double( 0 ); + TPoint pnt; + in->TransformIndexToPhysicalPoint( i, pnt ); + + // Main loop + for( unsigned int cx = 0; cx < Self::Dimension - 1; cx++ ) + { + for( unsigned int cy = cx + 1; cy < Self::Dimension; cy++ ) + { + TProfile maxProfile( this->m_RadialSampling, double( 0 ) ); + for( unsigned int p = 0; p < this->m_ProfileSampling; p++ ) + { + double a = pi2n * double( p ); + + // Direction of this profile + TVector dir; + dir.Fill( TScalar( 0 ) ); + dir[ cx ] = TScalar( std::cos( a ) ); + dir[ cy ] = TScalar( std::sin( a ) ); + + double maxrise = double( 0 ); + double maxfall = double( -1 ); + TProfile profile; + for( unsigned int r = 0; r < this->m_RadialSampling; r++ ) + { + double radius = double( r ) * rOff; + TIndex idx; + typename TPoint::VectorType aux; + aux.SetVnlVector( dir.GetVnlVector( ) ); + if( + in->TransformPhysicalPointToIndex( pnt + ( aux * radius ), idx ) + ) + { + TVector g = in->GetPixel( idx ); + double b = double( g.GetNorm( ) ); + if( double( g * dir ) < double( 0 ) ) + b *= double( -1 ); + maxrise = ( b > maxrise )? b: maxrise; + if( radius >= this->m_MinRadius ) + maxfall = ( b < maxfall )? b: maxfall; + profile.push_back( -b - maxrise ); + } + else + profile.push_back( double( 0 ) ); + + } // rof + + for( unsigned int r = 0; r < this->m_RadialSampling; r++ ) + { + double E = profile[ r ] / -maxfall; + E = ( E < double( 0 ) )? double( 0 ): E; + E = ( E > double( 1 ) )? double( 1 ): E; + maxProfile[ r ] += E; + + } // rof + + } // rof + + for( unsigned int r = 0; r < this->m_RadialSampling; r++ ) + { + double E = maxProfile[ r ] / double( this->m_RadialSampling ); + optR = ( E > optR )? E: optR; + + } // rof + + } // rof + + } // rof + return( TScalar( optR ) ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageBlender.cxx b/lib/cpExtensions/Algorithms/ImageBlender.cxx new file mode 100644 index 0000000..5a12cd0 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageBlender.cxx @@ -0,0 +1,234 @@ +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Algorithms::ImageBlender:: +Self* cpExtensions::Algorithms::ImageBlender:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Algorithms::ImageBlender:: +GetNumberOfInputs( ) +{ + unsigned int np = this->GetNumberOfInputPorts( ); + unsigned int ni = 0; + for( unsigned int p = 0; p < np; ++p ) + ni += this->GetNumberOfInputConnections( p ); + return( ni ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Algorithms::ImageBlender:: +ImageBlender( ) + : Superclass( ) +{ + this->SetNumberOfInputPorts( 1 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Algorithms::ImageBlender:: +~ImageBlender( ) +{ +} + +// ------------------------------------------------------------------------- +int cpExtensions::Algorithms::ImageBlender:: +RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) +{ + if( this->GetNumberOfInputConnections( 0 ) == 0 ) + return( 0 ); + + vtkDataObject::SetPointDataActiveScalarInfo( + outputVector->GetInformationObject( 0 ), + VTK_UNSIGNED_CHAR, + 1 + ); + return( 1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Algorithms::ImageBlender:: +RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) +{ + this->m_Ranges.clear( ); + for( int i = 0; i < this->GetNumberOfInputPorts( ); ++i ) + { + vtkInformationVector* portInfo = inputVector[ i ]; + for( int j = 0; j < portInfo->GetNumberOfInformationObjects( ); ++j ) + { + vtkInformation* info = portInfo->GetInformationObject( j ); + vtkImageData* image = vtkImageData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + if( image != NULL ) + { + double r[ 2 ]; + image->GetScalarRange( r ); + this->m_Ranges.push_back( r[ 0 ] ); + this->m_Ranges.push_back( r[ 1 ] ); + } + else + { + this->m_Ranges.push_back( double( 0 ) ); + this->m_Ranges.push_back( double( 0 ) ); + + } // fi + + } // rof + + } // rof + return( + this->Superclass::RequestData( request, inputVector, outputVector ) + ); +} + +// ------------------------------------------------------------------------- +// Description: +// This templated function executes the filter for any type of data. +template< class T > +void cpExtensions_Algorithms_ImageBlender_Execute( + cpExtensions::Algorithms::ImageBlender* self, + vtkImageData** inDatas, int numInputs, + const std::vector< double >& ranges, vtkImageData* outData, + int outExt[ 6 ], int id, T* really_not_used + ) +{ + vtkImageIterator< T > inItsFast[ 256 ]; + T* inSIFast[ 256 ]; + vtkImageProgressIterator< T > outIt( outData, outExt, self, id ); + vtkImageIterator< T >* inIts; + T** inSI; + if( numInputs < 256 ) + { + inIts = inItsFast; + inSI = inSIFast; + } + else + { + inIts = new vtkImageIterator< T >[ numInputs ]; + inSI = new T*[ numInputs ]; + + } // fi + + // Loop through all input ImageData to initialize iterators + for( int i = 0; i < numInputs; ++i ) + inIts[ i ].Initialize( inDatas[ i ], outExt ); + + // Loop through output pixels + while( !outIt.IsAtEnd( ) ) + { + for( int j = 0; j < numInputs; ++j ) + inSI[ j ] = inIts[ j ].BeginSpan( ); + + T* outSI = outIt.BeginSpan( ); + T* outSIEnd = outIt.EndSpan( ); + + // Pixel operation + while( outSI != outSIEnd ) + { + // Input 0 is ignored: it is just used to guarantee sizes all over + // the result + int vmax = 0; + for( int k = 0; k < numInputs; ++k ) + if( double( *inSI[ k ] ) > ranges[ k << 1 ] && vmax <= k ) + vmax = k + 1; + *outSI = static_cast< T >( vmax ); + outSI++; + for( int l = 0; l < numInputs; ++l ) + inSI[ l ]++; + + } // elihw + for( int j = 0; j < numInputs; ++j ) + inIts[ j ].NextSpan( ); + outIt.NextSpan( ); + + } // elihw + + if( numInputs >= 256) + { + delete [] inIts; + delete [] inSI; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Algorithms::ImageBlender:: +ThreadedRequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData*** inData, vtkImageData** outData, + int outExt[ 6 ], int id + ) +{ + if( inData[ 0 ][ 0 ] == NULL ) + { + vtkErrorMacro( << "Input " << 0 << " must be specified." ); + return; + + } // fi + + int numInputs = this->GetNumberOfInputConnections( 0 ); + int scalarType = inData[ 0 ][ 0 ]->GetScalarType( ); + int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( ); + for( int i = 0; i < numInputs; ++i ) + { + int otherType = inData[ 0 ][ i ]->GetScalarType( ); + int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( ); + if( otherType != scalarType || otherComp != numComp ) + { + if( id == 0 ) + vtkErrorMacro( + "ThreadedRequestData: Input " << i + << " has " << otherComp << " components of type " + << otherType << ", but input 0 has " << numComp + << " components of type " << scalarType + ); + return; + + } // fi + + } // rof + + switch( scalarType ) + { + vtkTemplateMacro( + cpExtensions_Algorithms_ImageBlender_Execute( + this, inData[ 0 ], numInputs, this->m_Ranges, + outData[ 0 ], outExt, id, static_cast< VTK_TT* >( 0 ) + ) + ); + default: + if( id == 0 ) + vtkErrorMacro( << "Execute: Unknown ScalarType" ); + return; + } // hctiws +} + +// ------------------------------------------------------------------------- +int cpExtensions::Algorithms::ImageBlender:: +FillInputPortInformation( int i, vtkInformation* info ) +{ + info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 ); + return( this->Superclass::FillInputPortInformation( i,info ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageBlender.h b/lib/cpExtensions/Algorithms/ImageBlender.h new file mode 100644 index 0000000..4d82bcf --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageBlender.h @@ -0,0 +1,65 @@ +#ifndef __cpExtensions__Algorithms__ImageBlender__h__ +#define __cpExtensions__Algorithms__ImageBlender__h__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + * @note: Based on vtkImageWeightedSum + */ + class cpExtensions_EXPORT ImageBlender + : public vtkThreadedImageAlgorithm + { + public: + typedef ImageBlender Self; + vtkTypeMacro( ImageBlender, vtkThreadedImageAlgorithm ); + + public: + static Self* New( ); + + unsigned int GetNumberOfInputs( ); + + protected: + ImageBlender( ); + virtual ~ImageBlender( ); + + int RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ); + int RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ); + void ThreadedRequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData*** inData, vtkImageData** outData, + int outExt[ 6 ], int id + ); + int FillInputPortInformation( int i, vtkInformation* info ); + + private: + // Purposely not implemented. + ImageBlender( const Self& other ); + void operator=( const Self& other ); + + protected: + std::vector< double > m_Ranges; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Algorithms__ImageBlender__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageFunctionFilter.h b/lib/cpExtensions/Algorithms/ImageFunctionFilter.h new file mode 100644 index 0000000..503f791 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctionFilter.h @@ -0,0 +1,69 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TInput, class _TOutput, class _TFunction > + class ImageFunctionFilter + : public itk::ImageToImageFilter< _TInput, _TOutput > + { + public: + typedef ImageFunctionFilter Self; + typedef itk::ImageToImageFilter< _TInput, _TOutput > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInput TInput; + typedef _TOutput TOutput; + typedef _TFunction TFunction; + + typedef typename TOutput::RegionType TRegion; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageFunctionFilter, itkImageToImageFilter ); + + itkGetObjectMacro( Function, TFunction ); + itkSetObjectMacro( Function, TFunction ); + + protected: + ImageFunctionFilter( ); + virtual ~ImageFunctionFilter( ); + + virtual void BeforeThreadedGenerateData( ) cpExtensions_OVERRIDE; + virtual void ThreadedGenerateData( + const TRegion& region, + itk::ThreadIdType threadId + ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented. + ImageFunctionFilter( const Self& ); + void operator=( const Self& ); + + protected: + typename TFunction::Pointer m_Function; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx b/lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx new file mode 100644 index 0000000..c96c092 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx @@ -0,0 +1,67 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput, class _TFilter > +cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >:: +ImageFunctionFilter( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput, class _TFilter > +cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >:: +~ImageFunctionFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput, class _TFilter > +void cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >:: +BeforeThreadedGenerateData( ) +{ + if( this->m_Function.IsNull( ) ) + itkExceptionMacro( << "Please set a valid itk::ImageFunction" ); + this->m_Function->SetInputImage( this->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput, class _TFilter > +void cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >:: +ThreadedGenerateData( const TRegion& region, itk::ThreadIdType threadId ) +{ + const typename TRegion::SizeType& regionSize = region.GetSize( ); + if( regionSize[ 0 ] == 0 ) + return; + const _TInput* in = this->GetInput( ); + _TOutput* out = this->GetOutput( 0 ); + + itk::ProgressReporter pr( this, threadId, region.GetNumberOfPixels( ) ); + + // Define the iterators + itk::ImageRegionConstIteratorWithIndex< TInput > iIt( in, region ); + itk::ImageRegionIteratorWithIndex< TOutput > oIt( out, region ); + + iIt.GoToBegin( ); + oIt.GoToBegin( ); + for( ; !iIt.IsAtEnd( ) && !oIt.IsAtEnd( ); ++iIt, ++oIt ) + { + oIt.Set( this->m_Function->EvaluateAtIndex( iIt.GetIndex( ) ) ); + pr.CompletedPixel( ); + + } // rof +} + +#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageFunctorFilter.h b/lib/cpExtensions/Algorithms/ImageFunctorFilter.h new file mode 100644 index 0000000..d8a7eca --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctorFilter.h @@ -0,0 +1,102 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I, class O, class F > + class ImageFunctorFilter + : public itk::ImageToImageFilter< I, O > + { + public: + typedef ImageFunctorFilter Self; + typedef itk::ImageToImageFilter< I, O > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef I TInputImage; + typedef O TOutputImage; + typedef F TFunctor; + + typedef typename O::RegionType TRegion; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageFunctorFilter, itkImageToImageFilter ); + + itkGetMacro( Functor, F ); + itkGetConstMacro( Functor, F ); + + protected: + ImageFunctorFilter( ) + : Superclass( ) + { + } + virtual ~ImageFunctorFilter( ) + { + } + + virtual void ThreadedGenerateData( + const TRegion& region, + itk::ThreadIdType threadId + ) + { + const typename TRegion::SizeType& regionSize = region.GetSize( ); + if( regionSize[ 0 ] == 0 ) + return; + const I* in = this->GetInput( ); + O* out = this->GetOutput( 0 ); + + const size_t nLines = region.GetNumberOfPixels( ) / regionSize[ 0 ]; + itk::ProgressReporter progress( this, threadId, nLines ); + + // Define the iterators + itk::ImageScanlineConstIterator< I > inIt( in, region ); + itk::ImageScanlineIterator< O > outIt( out, region ); + + inIt.GoToBegin( ); + outIt.GoToBegin( ); + while( !inIt.IsAtEnd( ) ) + { + while( !inIt.IsAtEndOfLine( ) ) + { + outIt.Set( this->m_Functor( inIt.Get( ) ) ); + ++inIt; + ++outIt; + + } // elihw + inIt.NextLine( ); + outIt.NextLine( ); + progress.CompletedPixel( ); + + } // elihw + } + + private: + // Purposely not implemented. + ImageFunctorFilter( const Self& ); + void operator=( const Self& ); + + protected: + F m_Functor; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.h b/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.h new file mode 100644 index 0000000..b970df4 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.h @@ -0,0 +1,78 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__h__ +#define __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__h__ + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TImage > + class ImageToBoundingBoxFromThreshold + : public itk::Object + { + public: + typedef ImageToBoundingBoxFromThreshold Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TImage TImage; + typedef typename TImage::PixelType TPixel; + typedef typename TImage::IndexType TIndex; + typedef typename TImage::RegionType TRegion; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageToBoundingBoxFromThreshold, itkObject ); + + itkGetConstObjectMacro( Image, TImage ); + itkGetConstMacro( LowerThreshold, TPixel ); + itkGetConstMacro( UpperThreshold, TPixel ); + itkGetConstMacro( Region, TRegion ); + itkGetConstMacro( PAD, unsigned int ); + + itkSetConstObjectMacro( Image, TImage ); + itkSetMacro( LowerThreshold, TPixel ); + itkSetMacro( UpperThreshold, TPixel ); + itkSetMacro( Region, TRegion ); + itkSetMacro( PAD, unsigned int ); + + public: + void Compute( ); + + protected: + ImageToBoundingBoxFromThreshold( ); + virtual ~ImageToBoundingBoxFromThreshold( ); + + private: + // Purposely not implemented. + ImageToBoundingBoxFromThreshold( const Self& ); + void operator=( const Self& ); + + protected: + typename TImage::ConstPointer m_Image; + TPixel m_LowerThreshold; + TPixel m_UpperThreshold; + TRegion m_Region; + unsigned int m_PAD; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.hxx b/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.hxx new file mode 100644 index 0000000..55659eb --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.hxx @@ -0,0 +1,89 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__hxx__ +#define __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage >:: +Compute( ) +{ + typedef itk::ImageRegionConstIteratorWithIndex< _TImage > _TIt; + + TIndex min_idx, max_idx; + min_idx.Fill( 0 ); + max_idx.Fill( -1 ); + + if( this->m_Image.IsNotNull( ) ) + { + auto region = this->m_Image->GetRequestedRegion( ); + min_idx = max_idx = region.GetIndex( ); + min_idx += region.GetSize( ); + + _TIt i( this->m_Image, region ); + for( i.GoToBegin( ); !i.IsAtEnd( ); ++i ) + { + auto v = i.Get( ); + if( this->m_LowerThreshold <= v && v <= this->m_UpperThreshold ) + { + auto idx = i.GetIndex( ); + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + { + min_idx[ d ] = ( idx[ d ] < min_idx[ d ] )? idx[ d ]: min_idx[ d ]; + max_idx[ d ] = ( idx[ d ] > max_idx[ d ] )? idx[ d ]: max_idx[ d ]; + + } // rof + + } // fi + + } // rof + + // Fix indices + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + { + min_idx[ d ] -= long( this->m_PAD ); + max_idx[ d ] += long( this->m_PAD ); + + if( min_idx[ d ] < region.GetIndex( )[ d ] ) + min_idx[ d ] = region.GetIndex( )[ d ]; + if( max_idx[ d ] > region.GetIndex( )[ d ] + region.GetSize( )[ d ] ) + max_idx[ d ] = region.GetIndex( )[ d ] + region.GetSize( )[ d ]; + + } // rof + + } // fi + + typename _TImage::SizeType size; + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + size[ d ] = max_idx[ d ] - min_idx[ d ] + 1; + + this->m_Region.SetIndex( min_idx ); + this->m_Region.SetSize( size ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage >:: +ImageToBoundingBoxFromThreshold( ) + : Superclass( ), + m_LowerThreshold( std::numeric_limits< TPixel >::min( ) ), + m_UpperThreshold( std::numeric_limits< TPixel >::max( ) ), + m_PAD( 0 ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage >:: +~ImageToBoundingBoxFromThreshold( ) +{ +} + +#endif // __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/InertiaMedialness.h b/lib/cpExtensions/Algorithms/InertiaMedialness.h new file mode 100644 index 0000000..e385513 --- /dev/null +++ b/lib/cpExtensions/Algorithms/InertiaMedialness.h @@ -0,0 +1,215 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__ + +#include +#include + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I, class S = float > + class InertiaMedialness + : public itk::ImageFunction< I, S, S > + { + public: + // Standard itk types + typedef InertiaMedialness Self; + typedef itk::ImageFunction< I, S, S > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Types from base itk::ImageFunction + typedef typename Superclass::InputType TInput; + typedef typename Superclass::OutputType TOutput; + typedef typename Superclass::PointType TPoint; + typedef typename Superclass::ContinuousIndexType TContIndex; + typedef typename Superclass::IndexType TIndex; + typedef typename TIndex::OffsetType TOffset; + + // Sparse buffer + typedef std::map< TIndex, TOutput, typename TIndex::LexicographicCompare > TBuffer; + + typedef InertiaTensorFunction< S, I::ImageDimension > TInertia; + + public: + itkNewMacro( Self ); + itkTypeMacro( InertiaMedialness, itkImageFunction ); + + itkBooleanMacro( BufferResults ); + itkGetConstMacro( BufferResults, bool ); + itkGetConstMacro( MaxRadius, double ); + + itkSetMacro( BufferResults, bool ); + itkSetMacro( MaxRadius, double ); + + public: + virtual void ResetBuffer( ) + { + this->m_Buffer.clear( ); + } + + virtual TOutput Evaluate( const TPoint& p ) const + { + TIndex i; + this->GetInputImage( )->TransformPhysicalPointToIndex( p, i ); + return( this->EvaluateAtIndex( i ) ); + } + + virtual TOutput EvaluateAtIndex( const TIndex& i ) const + { + TOutput res = TOutput( 0 ); + bool computed = false; + if( this->m_BufferResults ) + { + typename TBuffer::const_iterator bIt = this->m_Buffer.find( i ); + computed = ( bIt != this->m_Buffer.end( ) ); + res = ( computed )? bIt->second: res; + + } // fi + + if( !computed ) + res = this->_Evaluate( i ); + + if( this->m_BufferResults ) + this->m_Buffer[ i ] = res; + return( res ); + } + + virtual TOutput EvaluateAtContinuousIndex( const TContIndex& i ) const + { + TPoint p; + this->GetInputImage( )->TransformContinuousIndexToPhysicalPoint( i, p ); + return( this->Evaluate( p ) ); + } + + protected: + InertiaMedialness( ) + : Superclass( ), + m_BufferResults( false ), + m_MaxRadius( double( 1 ) ) + { + this->m_Buffer.clear( ); + } + + virtual ~InertiaMedialness( ) + { + this->m_Buffer.clear( ); + } + + virtual TOutput _Evaluate( const TIndex& idx ) const + { + const I* image = this->GetInputImage( ); + + typename I::PointType p_i; + image->TransformIndexToPhysicalPoint( idx, p_i ); + + typename I::PointType max_p, min_p; + for( unsigned int d = 0; d < I::ImageDimension; ++d ) + { + max_p[ d ] = p_i[ d ] + this->m_MaxRadius; + min_p[ d ] = p_i[ d ] - this->m_MaxRadius; + + } // rof + TIndex max_i, min_i; + image->TransformPhysicalPointToIndex( max_p, max_i ); + image->TransformPhysicalPointToIndex( min_p, min_i ); + + typename I::RegionType in_region = image->GetRequestedRegion( ); + TIndex in_index = in_region.GetIndex( ); + TIndex in_last = in_index + in_region.GetSize( ); + typename I::SizeType size; + for( unsigned int d = 0; d < I::ImageDimension; ++d ) + { + if( min_i[ d ] < in_index[ d ] ) min_i[ d ] = in_index[ d ]; + if( max_i[ d ] < in_index[ d ] ) max_i[ d ] = in_index[ d ]; + if( min_i[ d ] >= in_last[ d ] ) min_i[ d ] = in_last[ d ]; + if( max_i[ d ] >= in_last[ d ] ) max_i[ d ] = in_last[ d ]; + + size[ d ] = max_i[ d ] - min_i[ d ]; + + } // rof + + typename I::RegionType region; + region.SetIndex( min_i ); + region.SetSize( size ); + + std::vector< typename TInertia::Pointer > inertias; + itk::ImageRegionConstIteratorWithIndex< I > it( image, region ); + for( it.GoToBegin( ); !it.IsAtEnd( ); ++it ) + { + TOffset off = it.GetIndex( ) - idx; + unsigned long l1dist = std::abs( off[ 0 ] ); + for( unsigned int d = 1; d < I::ImageDimension; ++d ) + l1dist = ( std::abs( off[ d ] ) > l1dist )? std::abs( off[ d ] ): l1dist; + + typename TInertia::TPoint i_pnt; + image->TransformIndexToPhysicalPoint( it.GetIndex( ), i_pnt ); + + for( unsigned long l = 0; l < l1dist; ++l ) + { + if( inertias.size( ) <= l ) + inertias.push_back( TInertia::New( ) ); + inertias[ l ]->AddMass( i_pnt.GetVectorFromOrigin( ), S( it.Get( ) ) ); + + /* TODO + typename TInertias::iterator inIt = inertias.find( l ); + if( inIt == inertias.end( ) ) + inIt = inertias.insert( std::pair< unsigned long, typename TInertia::Pointer >( l, TInertia::New( ) ) ).first; + */ + + } // rof + + } // rof + + if( inertias.size( ) > 0 ) + { + S res = S( 0 ); + for( unsigned int l = 0; l < inertias.size( ); ++l ) + { + typename TInertia::TVector pv, r; + typename TInertia::TMatrix pm; + inertias[ l ]->GetEigenAnalysis( pm, pv, r ); + S v = pv.GetNorm( ); + if( l == 0 || v > res ) + res = v; + + } // rof + return( res ); + } + else + return( TOutput( 0 ) ); + } + + private: + // Purposely not implemented. + InertiaMedialness( const Self& ); + void operator=( const Self& ); + + protected: + mutable TBuffer m_Buffer; + bool m_BufferResults; + + double m_MaxRadius; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +// TODO: #include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/InertiaTensorFunction.h b/lib/cpExtensions/Algorithms/InertiaTensorFunction.h new file mode 100644 index 0000000..ecb341d --- /dev/null +++ b/lib/cpExtensions/Algorithms/InertiaTensorFunction.h @@ -0,0 +1,180 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__ + +#include + +#include +#include +#include +#include + + +#include +#include + + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class S, unsigned int D > + class InertiaTensorFunction + : public itk::Object + { + public: + // Standard itk types + typedef InertiaTensorFunction Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef S TScalar; + typedef itk::Matrix< S, D, D > TMatrix; + typedef itk::Point< S, D > TPoint; + typedef typename TPoint::VectorType TVector; + + protected: + typedef TMatrix _TInternalMatrix; + typedef itk::Matrix< S, D, 1 > _TInternalVector; + + public: + itkNewMacro( Self ); + itkTypeMacro( InertiaTensorFunction, itkObject ); + + public: + inline void Reset( ) + { + this->m_M = S( 0 ); + this->m_MPP = S( 0 ); + this->m_MP.Fill( S( 0 ) ); + this->m_MPPT.Fill( S( 0 ) ); + this->Modified( ); + } + inline void AddMass( const TPoint& pnt, const S& mass = S( 1 ) ) + { + this->AddMass( pnt.GetVectorFromOrigin( ), mass ); + } + inline void AddMass( const S* data, const S& mass = S( 1 ) ) + { + this->AddMass( TVector( data ), mass ); + } + inline void AddMass( const TVector& vec, const S& mass = S( 1 ) ) + { + this->m_M += mass; + this->m_MPP += mass * ( vec * vec ); + + _TInternalVector mp; + for( unsigned int d = 0; d < D; ++d ) + { + this->m_MP[ d ][ 0 ] += mass * vec[ d ]; + mp[ d ][ 0 ] = vec[ d ]; + + } // rof + this->m_MPPT += + _TInternalMatrix( mp.GetVnlMatrix( ) * mp.GetTranspose( ) ) * + mass; + } + + inline S GetMass( ) const + { + return( this->m_M ); + } + + inline TMatrix GetInertia( ) const + { + TMatrix I; + if( S( 0 ) < this->m_M ) + { + I.SetIdentity( ); + I *= this->m_MPP - ( ( this->m_MP.GetTranspose( ) * this->m_MP.GetVnlMatrix( ) )[ 0 ][ 0 ] / this->m_M ); + I -= this->m_MPPT; + I += TMatrix( this->m_MP.GetVnlMatrix( ) * this->m_MP.GetTranspose( ) ) / this->m_M; + } + else + I.Fill( S( 0 ) ); + return( I ); + } + + inline TVector GetCenterOfGravity( ) const + { + TVector cog; + if( S( 0 ) < this->m_M ) + { + for( unsigned int d = 0; d < D; ++d ) + cog[ d ] = this->m_MP[ d ][ 0 ] / this->m_M; + } + else + cog.Fill( S( 0 ) ); + return( cog ); + } + + inline void GetEigenAnalysis( TMatrix& pm, TVector& pv, TVector& r ) const + { + TMatrix I = this->GetInertia( ); + + itk::SymmetricEigenAnalysis< TMatrix, TVector, TMatrix > eigen; + eigen.SetDimension( D ); + eigen.SetOrderEigenMagnitudes( true ); + eigen.SetOrderEigenValues( 1 ); + eigen.ComputeEigenValuesAndVectors( I, pv, pm ); + pm = TMatrix( pm.GetTranspose( ) ); + S det = vnl_determinant( pm.GetVnlMatrix( ) ); + for( unsigned int d = 0; d < D; ++d ) + pm[ d ][ D - 1 ] *= det; + + if( D == 2 ) + { + S coeff = S( 4 ) / this->m_M; + r[ 0 ] = std::sqrt( std::fabs( coeff * pv[ 1 ] ) ); + r[ 1 ] = std::sqrt( std::fabs( coeff * pv[ 0 ] ) ); + } + else if( D == 3 ) + { + S coeff = S( 2.5 ) / this->m_M; + r[ 0 ] = std::sqrt( std::fabs( coeff * ( pv[ 1 ] + pv[ 2 ] - pv[ 0 ] ) ) ); + r[ 1 ] = std::sqrt( std::fabs( coeff * ( pv[ 0 ] + pv[ 2 ] - pv[ 1 ] ) ) ); + r[ 2 ] = std::sqrt( std::fabs( coeff * ( pv[ 0 ] + pv[ 1 ] - pv[ 2 ] ) ) ); + } + else + r.Fill( S( 0 ) ); + } + + protected: + InertiaTensorFunction( ) + : Superclass( ) + { + this->Reset( ); + } + virtual ~InertiaTensorFunction( ) + { + } + + private: + // Purposely not implemented. + InertiaTensorFunction( const Self& ); + void operator=( const Self& ); + + protected: + S m_M; + S m_MPP; + _TInternalVector m_MP; + _TInternalMatrix m_MPPT; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +// #include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/IsoImageSlicer.h b/lib/cpExtensions/Algorithms/IsoImageSlicer.h new file mode 100644 index 0000000..9190430 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IsoImageSlicer.h @@ -0,0 +1,185 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__ +#define __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class R, class I > + class BaseImageSlicer + : public itk::ImageToImageFilter< typename R::InputImageType, itk::Image< typename R::InputImageType::PixelType, R::ImageDimension - 1 > > + { + public: + // Basic types + typedef BaseImageSlicer Self; + typedef R TSlicer; + typedef I TInterpolateFunction; + typedef typename R::InputImageType TImage; + typedef typename I::CoordRepType TScalar; + typedef typename TImage::PixelType TPixel; + enum + { + Dim = TImage::ImageDimension, + SliceDim = TImage::ImageDimension - 1 + }; + typedef itk::Image< TPixel, Self::SliceDim > TSliceImage; + + // itk types + typedef itk::ImageToImageFilter< TImage, TSliceImage > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Internal filters + typedef itk::ExtractImageFilter< TImage, TSliceImage > TCollapsor; + + // Various types + typedef typename TImage::IndexType TIndex; + typedef typename TImage::RegionType TRegion; + typedef typename TImage::SizeType TSize; + typedef typename TImage::SpacingType TSpacing; + typedef typename TSpacing::ValueType TSpacingValue; + + typedef itk::AffineTransform< TScalar, Self::Dim > TTransform; + typedef typename TTransform::MatrixType TMatrix; + typedef typename TTransform::OffsetType TVector; + + public: + itkNewMacro( Self ); + itkTypeMacro( BaseImageSlicer, itkImageToImageFilter ); + + itkBooleanMacro( SizeFromMaximum ); + itkBooleanMacro( SizeFromMinimum ); + itkBooleanMacro( SpacingFromMaximum ); + itkBooleanMacro( SpacingFromMinimum ); + + itkGetConstObjectMacro( Transform, TTransform ); + itkGetConstMacro( DefaultValue, TPixel ); + itkGetConstMacro( Size, TVector ); + itkGetConstMacro( SizeFromMaximum, bool ); + itkGetConstMacro( SizeFromMinimum, bool ); + itkGetConstMacro( Spacing, TSpacingValue ); + itkGetConstMacro( SpacingFromMaximum, bool ); + itkGetConstMacro( SpacingFromMinimum, bool ); + + itkSetObjectMacro( Transform, TTransform ); + itkSetMacro( Size, TVector ); + itkSetMacro( DefaultValue, TPixel ); + itkSetMacro( SizeFromMaximum, bool ); + itkSetMacro( SizeFromMinimum, bool ); + itkSetMacro( Spacing, TSpacingValue ); + itkSetMacro( SpacingFromMaximum, bool ); + itkSetMacro( SpacingFromMinimum, bool ); + + public: + virtual unsigned long GetMTime( ) const cpExtensions_OVERRIDE; + + const TInterpolateFunction* GetInterpolator( ) const; + const TMatrix& GetRotation( ) const; + const TVector& GetTranslation( ) const; + + void SetInterpolator( TInterpolateFunction* f ); + + template< class M > + void SetRotation( const M& r ); + + template< class V > + void SetTranslation( const V& t ); + void SetSize( TScalar s ); + + protected: + BaseImageSlicer( ); + virtual ~BaseImageSlicer( ); + + virtual void GenerateOutputInformation( ) cpExtensions_OVERRIDE; // TODO { } + virtual void GenerateInputRequestedRegion( ) cpExtensions_OVERRIDE; + virtual void GenerateData( ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + BaseImageSlicer( const Self& ); + void operator=( const Self& ); + + protected: + typename TSlicer::Pointer m_Slicer; + typename TCollapsor::Pointer m_Collapsor; + typename TTransform::Pointer m_Transform; + + TPixel m_DefaultValue; + + TVector m_Size; + bool m_SizeFromMaximum; + bool m_SizeFromMinimum; + + TSpacingValue m_Spacing; + bool m_SpacingFromMaximum; + bool m_SpacingFromMinimum; + }; + + } // ecapseman + +} // ecapseman + +// ------------------------------------------------------------------------- +#define CPPLUGINS_DEFINE_ISOIMAGESLICER( name, R, F ) \ + template< class I, class S = double > \ + class name \ + : public BaseImageSlicer< R< I, I, S >, F< I, S > > \ + { \ + public: \ + typedef BaseImageSlicer< R< I, I, S >, F< I, S > > Superclass; \ + typedef name Self; \ + typedef itk::SmartPointer< Self > Pointer; \ + typedef itk::SmartPointer< const Self > ConstPointer; \ + public: \ + itkNewMacro( Self ); \ + itkTypeMacro( name, BaseSlicer ); \ + protected: \ + name( ) : Superclass( ) { } \ + virtual ~name( ) { } \ + private: \ + name( const Self& ); \ + void operator=( const Self& ); \ + }; + +namespace cpExtensions +{ + namespace Algorithms + { + CPPLUGINS_DEFINE_ISOIMAGESLICER( + IsoImageSlicer, + itk::ResampleImageFilter, + itk::InterpolateImageFunction + ); + CPPLUGINS_DEFINE_ISOIMAGESLICER( + VectorIsoImageSlicer, + itk::VectorResampleImageFilter, + itk::VectorInterpolateImageFunction + ); + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/IsoImageSlicer.hxx b/lib/cpExtensions/Algorithms/IsoImageSlicer.hxx new file mode 100644 index 0000000..041d874 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IsoImageSlicer.hxx @@ -0,0 +1,234 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__HXX__ + +// ------------------------------------------------------------------------- +template< class R, class I > +unsigned long cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +GetMTime( ) const +{ + unsigned long t = this->Superclass::GetMTime( ); + unsigned long sT = this->m_Slicer->GetMTime( ); + unsigned long cT = this->m_Collapsor->GetMTime( ); + unsigned long tT = this->m_Transform->GetMTime( ); + t = ( sT > t )? sT: t; + t = ( cT > t )? cT: t; + t = ( tT > t )? tT: t; + return( t ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +const typename cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +TInterpolateFunction* +cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +GetInterpolator( ) const +{ + return( this->m_Slicer->GetInterpolator( ) ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +const typename cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +TMatrix& cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +GetRotation( ) const +{ + return( this->m_Transform->GetMatrix( ) ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +const typename cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +TVector& cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +GetTranslation( ) const +{ + return( this->m_Transform->GetOffset( ) ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +void cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +SetInterpolator( TInterpolateFunction* f ) +{ + this->m_Slicer->SetInterpolator( f ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +template< class M > +void cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +SetRotation( const M& r ) +{ + TMatrix rotation; + for( unsigned int i = 0; i < Self::Dim; ++i ) + for( unsigned int j = 0; j < Self::Dim; ++j ) + rotation[ i ][ j ] = r[ i ][ j ]; + this->m_Transform->SetMatrix( rotation ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +template< class V > +void cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +SetTranslation( const V& t ) +{ + TVector off; + for( unsigned int i = 0; i < Self::Dim; ++i ) + off[ i ] = t[ i ]; + this->m_Transform->SetOffset( off ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +void cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +SetSize( TScalar s ) +{ + this->m_Size.Fill( s ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +BaseImageSlicer( ) + : Superclass( ), + m_SizeFromMaximum( false ), + m_SizeFromMinimum( false ), + m_Spacing( TSpacingValue( 1 ) ), + m_SpacingFromMaximum( false ), + m_SpacingFromMinimum( false ) +{ + this->m_Size.Fill( TScalar( 1 ) ); + + // Slicer + this->m_Slicer = TSlicer::New( ); + + TIndex idx; + idx.Fill( 0 ); + this->m_Slicer->SetOutputStartIndex( idx ); + + // Dimension collapsor + this->m_Collapsor = TCollapsor::New( ); + this->m_Collapsor->SetInput( this->m_Slicer->GetOutput( ) ); + this->m_Collapsor->SetDirectionCollapseToIdentity( ); + + this->m_Transform = TTransform::New( ); + this->m_Transform->SetIdentity( ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +~BaseImageSlicer( ) +{ +} + +// ------------------------------------------------------------------------- +template< class R, class I > +void cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +GenerateOutputInformation( ) +{ +} + +// ------------------------------------------------------------------------- +template< class R, class I > +void cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +GenerateInputRequestedRegion( ) +{ + TImage* input = const_cast< TImage* >( this->GetInput( ) ); + if( input != NULL ) + input->SetRequestedRegionToLargestPossibleRegion( ); +} + +// ------------------------------------------------------------------------- +template< class R, class I > +void cpExtensions::Algorithms::BaseImageSlicer< R, I >:: +GenerateData( ) +{ + const TImage* input = this->GetInput( ); + + // Spacing + TSpacing spac; + if( this->m_SpacingFromMaximum || this->m_SpacingFromMinimum ) + { + spac = input->GetSpacing( ); + TSpacingValue minIso = spac[ 0 ]; + TSpacingValue maxIso = spac[ 0 ]; + for( unsigned int i = 1; i < Self::Dim; i++ ) + { + minIso = ( spac[ i ] < minIso )? spac[ i ]: minIso; + maxIso = ( spac[ i ] > maxIso )? spac[ i ]: maxIso; + + } // rof + this->m_Spacing = ( this->m_SpacingFromMinimum )? minIso: maxIso; + + } // fi + spac.Fill( this->m_Spacing ); + + // Size and origin + if( this->m_SizeFromMaximum || this->m_SizeFromMinimum ) + { + TSize iSize = input->GetRequestedRegion( ).GetSize( ); + TSpacing iSpac = input->GetSpacing( ); + TScalar minSize = TScalar( iSize[ 0 ] ) * TScalar( iSpac[ 0 ] ); + TScalar maxSize = minSize; + for( unsigned int i = 1; i < Self::Dim; i++ ) + { + TScalar v = TScalar( iSize[ i ] ) * TScalar( iSpac[ i ] ); + minSize = ( v < minSize )? v: minSize; + maxSize = ( v > maxSize )? v: maxSize; + + } // rof + if( this->m_SizeFromMaximum ) + this->m_Size.Fill( maxSize ); + else + this->m_Size.Fill( minSize ); + + } // fi + + TSize size; + typename TSlicer::OriginPointType origin; + size[ 0 ] = 1; + origin[ 0 ] = 0; + for( unsigned int i = 1; i < Self::Dim; i++ ) + { + double s = double( this->m_Size[ i ] ) / double( spac[ i ] ); + size[ i ] = ( unsigned int )( s ); + origin[ i ] = -( 0.5 * this->m_Size[ i ] ); + + } // rof + + // Prepare slicer + this->m_Slicer->SetInput( input ); + this->m_Slicer->SetTransform( this->m_Transform ); + this->m_Slicer->SetOutputSpacing( spac ); + this->m_Slicer->SetOutputOrigin( origin ); + this->m_Slicer->SetSize( size ); + this->m_Slicer->SetDefaultPixelValue( this->m_DefaultValue ); + + // Slice! + // Note: UpdateLargestPossibleRegion( ) is used since we need the + // output regions to be updated at each filter call. + this->m_Slicer->UpdateLargestPossibleRegion( ); + + // Collapse result + TRegion region = this->m_Slicer->GetOutput( )->GetRequestedRegion( ); + TSize regionSize = region.GetSize( ); + regionSize[ 0 ] = 0; + region.SetSize( regionSize ); + this->m_Collapsor->SetExtractionRegion( region ); + + this->m_Collapsor->GraftOutput( this->GetOutput( ) ); + this->m_Collapsor->UpdateLargestPossibleRegion( ); + this->GraftOutput( this->m_Collapsor->GetOutput( ) ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h new file mode 100644 index 0000000..b38e06e --- /dev/null +++ b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h @@ -0,0 +1,171 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__ +#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__ + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + * Recursive formulation taken from: + * http://lmb.informatik.uni-freiburg.de/lectures/mustererkennung/Englische_Folien/07_c_ME_en.pdf + */ + template< class _TScalar, unsigned int _VDimension > + class IterativeGaussianModelEstimator + : public itk::Object + { + public: + typedef IterativeGaussianModelEstimator Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TScalar TScalar; + itkStaticConstMacro( Dimension, unsigned int, _VDimension ); + + // Begin concept checking +#ifdef ITK_USE_CONCEPT_CHECKING + itkConceptMacro( + ScalarTypeHasFloatResolution, + ( itk::Concept::IsFloatingPoint< _TScalar > ) + ); +#endif + // End concept checking + + typedef itk::Matrix< TScalar, Dimension, Dimension > TMatrix; + typedef itk::Vector< TScalar, Dimension > TVector; + + public: + itkNewMacro( Self ); + itkTypeMacro( IterativeGaussianModelEstimator, itkObject ); + + itkGetConstMacro( Mean, TVector ); + itkGetConstMacro( Covariance, TMatrix ); + itkGetConstMacro( UnbiasedCovariance, TMatrix ); + itkGetConstMacro( NumberOfSamples, unsigned long ); + + itkSetMacro( Mean, TVector ); + itkSetMacro( Covariance, TMatrix ); + itkSetMacro( NumberOfSamples, unsigned long ); + + public: + void Clear( ); + + template< class _TOtherScalar > + void AddSample( const _TOtherScalar& x1, ... ); + + template< class _TOtherScalar > + void AddSample( const _TOtherScalar* array ); + + template< class _TOtherScalar > + void AddSample( const vnl_vector< _TOtherScalar >& v ); + + template< class _TOtherScalar > + void AddSample( + const itk::CovariantVector< _TOtherScalar, _VDimension >& v + ); + + template< class _TOtherScalar > + void AddSample( const itk::Point< _TOtherScalar, _VDimension >& p ); + + template< class _TOtherScalar > + void AddSample( const itk::Vector< _TOtherScalar, _VDimension >& v ); + + template< class _TOtherScalar > + _TScalar SquaredMahalanobis( const _TOtherScalar& x1, ... ) const; + + template< class _TOtherScalar > + _TScalar SquaredMahalanobis( const _TOtherScalar* array ) const; + + template< class _TOtherScalar > + _TScalar SquaredMahalanobis( + const vnl_vector< _TOtherScalar >& v + ) const; + + template< class _TOtherScalar > + _TScalar SquaredMahalanobis( + const itk::CovariantVector< _TOtherScalar, _VDimension >& v + ) const; + + template< class _TOtherScalar > + _TScalar SquaredMahalanobis( + const itk::Point< _TOtherScalar, _VDimension >& p + ) const; + + template< class _TOtherScalar > + _TScalar SquaredMahalanobis( + const itk::Vector< _TOtherScalar, _VDimension >& v + ) const; + + template< class _TOtherScalar > + _TScalar Density( const _TOtherScalar& x1, ... ) const; + + template< class _TOtherScalar > + _TScalar Density( const _TOtherScalar* array ) const; + + template< class _TOtherScalar > + _TScalar Density( + const vnl_vector< _TOtherScalar >& v + ) const; + + template< class _TOtherScalar > + _TScalar Density( + const itk::CovariantVector< _TOtherScalar, _VDimension >& v + ) const; + + template< class _TOtherScalar > + _TScalar Density( + const itk::Point< _TOtherScalar, _VDimension >& p + ) const; + + template< class _TOtherScalar > + _TScalar Density( + const itk::Vector< _TOtherScalar, _VDimension >& v + ) const; + + protected: + IterativeGaussianModelEstimator( ); + virtual ~IterativeGaussianModelEstimator( ); + + protected: + void _AddSample( const TVector& v ) const; + _TScalar _SquaredMahalanobis( const TVector& v ) const; + _TScalar _Density( const TVector& v ) const; + + private: + // Purposely not implemented + IterativeGaussianModelEstimator( const Self& other ); + void operator=( const Self& other ); + + protected: + // Recursive avg/cov values + mutable unsigned long m_NumberOfSamples; + mutable TVector m_Mean; + mutable TMatrix m_Covariance; + mutable TMatrix m_UnbiasedCovariance; + mutable bool m_InverseUpdated; + mutable TMatrix m_InverseUnbiasedCovariance; + }; + + } // ecapseman + +} // ecapseman + +#include + +#endif // __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx new file mode 100644 index 0000000..acd1da7 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx @@ -0,0 +1,365 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +Clear( ) +{ + this->m_NumberOfSamples = 0; + this->m_Mean.Fill( TScalar( 0 ) ); + this->m_Covariance.Fill( TScalar( 0 ) ); + this->m_InverseUpdated = false; + this->m_InverseUnbiasedCovariance.Fill( TScalar( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +AddSample( const _TOtherScalar& x1, ... ) +{ + TVector s; + std::va_list lst; + va_start( lst, x1 ); + s[ 0 ] = TScalar( x1 ); + for( unsigned int d = 1; d < _VDimension; ++d ) + s[ d ] = TScalar( va_arg( lst, double ) ); + va_end( lst ); + this->_AddSample( s ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +AddSample( const _TOtherScalar* array ) +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( array[ d ] ); + this->_AddSample( s ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +AddSample( const vnl_vector< _TOtherScalar >& v ) +{ + unsigned int len = ( v.size( ) < _VDimension )? v.size: _VDimension; + TVector s; + for( unsigned d = 0; d < len; ++d ) + s[ d ] = TScalar( v[ d ] ); + this->_AddSample( s ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +AddSample( const itk::CovariantVector< _TOtherScalar, _VDimension >& v ) +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( v[ d ] ); + this->_AddSample( s ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +AddSample( const itk::Point< _TOtherScalar, _VDimension >& p ) +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( p[ d ] ); + this->_AddSample( s ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +AddSample( const itk::Vector< _TOtherScalar, _VDimension >& v ) +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( v[ d ] ); + this->_AddSample( s ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +SquaredMahalanobis( const _TOtherScalar& x1, ... ) const +{ + TVector s; + std::va_list lst; + va_start( lst, x1 ); + s[ 0 ] = TScalar( x1 ); + for( unsigned int d = 1; d < _VDimension; ++d ) + s[ d ] = TScalar( va_arg( lst, double ) ); + va_end( lst ); + return( this->_SquaredMahalanobis( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +SquaredMahalanobis( const _TOtherScalar* array ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( array[ d ] ); + return( this->_SquaredMahalanobis( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +SquaredMahalanobis( const vnl_vector< _TOtherScalar >& v ) const +{ + unsigned int len = ( v.size( ) < _VDimension )? v.size: _VDimension; + TVector s; + for( unsigned d = 0; d < len; ++d ) + s[ d ] = TScalar( v[ d ] ); + return( this->_SquaredMahalanobis( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +SquaredMahalanobis( + const itk::CovariantVector< _TOtherScalar, _VDimension >& v + ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( v[ d ] ); + return( this->_SquaredMahalanobis( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +SquaredMahalanobis( const itk::Point< _TOtherScalar, _VDimension >& p ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( p[ d ] ); + return( this->_SquaredMahalanobis( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +SquaredMahalanobis( const itk::Vector< _TOtherScalar, _VDimension >& v ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( v[ d ] ); + return( this->_SquaredMahalanobis( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +Density( const _TOtherScalar& x1, ... ) const +{ + TVector s; + std::va_list lst; + va_start( lst, x1 ); + s[ 0 ] = TScalar( x1 ); + for( unsigned int d = 1; d < _VDimension; ++d ) + s[ d ] = TScalar( va_arg( lst, double ) ); + va_end( lst ); + return( this->_Density( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +Density( const _TOtherScalar* array ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( array[ d ] ); + return( this->_Density( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +Density( const vnl_vector< _TOtherScalar >& v ) const +{ + unsigned int len = ( v.size( ) < _VDimension )? v.size: _VDimension; + TVector s; + for( unsigned d = 0; d < len; ++d ) + s[ d ] = TScalar( v[ d ] ); + return( this->_Density( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +Density( + const itk::CovariantVector< _TOtherScalar, _VDimension >& v + ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( v[ d ] ); + return( this->_Density( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +Density( const itk::Point< _TOtherScalar, _VDimension >& p ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( p[ d ] ); + return( this->_Density( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +template< class _TOtherScalar > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +Density( const itk::Vector< _TOtherScalar, _VDimension >& v ) const +{ + TVector s; + for( unsigned d = 0; d < _VDimension; ++d ) + s[ d ] = TScalar( v[ d ] ); + return( this->_Density( s ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +IterativeGaussianModelEstimator( ) + : Superclass( ) +{ + this->Clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +~IterativeGaussianModelEstimator( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +void cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +_AddSample( const TVector& v ) const +{ + this->m_NumberOfSamples += 1; + TScalar a = TScalar( 1 ) / TScalar( this->m_NumberOfSamples ); + TScalar b = TScalar( 1 ) - a; + TVector c = v - this->m_Mean; + TMatrix m; + for( unsigned int i = 0; i < _VDimension; ++i ) + { + m[ i ][ i ] = c[ i ] * c[ i ]; + for( unsigned int j = i + 1; j < _VDimension; ++j ) + m[ i ][ j ] = m[ j ][ i ] = c[ i ] * c[ j ]; + + } // rof + this->m_Covariance = ( this->m_Covariance + ( m * a ) ) * b; + this->m_Mean = ( this->m_Mean * b ) + ( v * a ); + + TScalar u = + TScalar( this->m_NumberOfSamples ) / + TScalar( this->m_NumberOfSamples - 1 ); + this->m_UnbiasedCovariance = this->m_Covariance * u; + this->m_InverseUpdated = false; +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +_SquaredMahalanobis( const TVector& v ) const +{ + if( !this->m_InverseUpdated ) + { + double d = + double( + vnl_determinant( this->m_UnbiasedCovariance.GetVnlMatrix( ) ) + ); + if( std::fabs( d ) > double( 0 ) ) + this->m_InverseUnbiasedCovariance = + this->m_UnbiasedCovariance.GetInverse( ); + else + this->m_InverseUnbiasedCovariance.SetIdentity( ); + this->m_InverseUpdated = true; + + } // fi + TVector x = v - this->m_Mean; + return( x * ( this->m_InverseUnbiasedCovariance * x ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _VDimension > +_TScalar cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< _TScalar, _VDimension >:: +_Density( const TVector& v ) const +{ + static const double _2pik = + std::pow( double( 2 ) * double( vnl_math::pi ), _VDimension ); + + double s = double( this->_SquaredMahalanobis( v ) ) / double( 2 ); + double d = + double( + vnl_determinant( this->m_UnbiasedCovariance.GetVnlMatrix( ) ) + ); + return( _TScalar( std::exp( -s ) / std::sqrt( _2pik * d ) ) ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx b/lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx new file mode 100644 index 0000000..0fd5d6c --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx @@ -0,0 +1,49 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#include + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanConstantFilter< T >:: +Configure( unsigned int m ) +{ + this->Superclass::Configure( m, 1, m ); +} + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanConstantFilter< T >:: +Initialize( ) +{ + this->Superclass::Initialize( ); + + this->m_A.set_identity( ); + this->m_B.fill( TScalar( 0 ) ); + this->m_H.set_identity( ); +} + +// ------------------------------------------------------------------------- +template< typename T > +cpExtensions::Algorithms::KalmanConstantFilter< T >:: +KalmanConstantFilter( ) + : Superclass( ) +{ + this->Configure( 1 ); +} + +// ------------------------------------------------------------------------- +template< typename T > +cpExtensions::Algorithms::KalmanConstantFilter< T >:: +~KalmanConstantFilter( ) +{ +} + +// ------------------------------------------------------------------------- +// Explicit instantiations + +template class cpExtensions::Algorithms::KalmanConstantFilter< float >; +template class cpExtensions::Algorithms::KalmanConstantFilter< double >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/KalmanConstantFilter.h b/lib/cpExtensions/Algorithms/KalmanConstantFilter.h new file mode 100644 index 0000000..82cd263 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanConstantFilter.h @@ -0,0 +1,56 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< typename T > + class cpExtensions_EXPORT KalmanConstantFilter + : public KalmanFilter< T > + { + public: + typedef KalmanConstantFilter Self; + typedef KalmanFilter< T > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TMatrix TMatrix; + typedef typename Superclass::TVector TVector; + + public: + itkNewMacro( Self ); + itkTypeMacro( KalmanConstantFilter, KalmanFilter ); + + public: + void Configure( unsigned int m ); + + // Iteration methods + virtual void Initialize( ) cpExtensions_OVERRIDE; + + protected: + KalmanConstantFilter( ); + virtual ~KalmanConstantFilter( ); + + private: + // Purposely not implemented. + KalmanConstantFilter( const Self& ); + void operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/KalmanFilter.cxx b/lib/cpExtensions/Algorithms/KalmanFilter.cxx new file mode 100644 index 0000000..add2041 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanFilter.cxx @@ -0,0 +1,137 @@ +#include + +#include +#include + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanFilter< T >:: +Configure( unsigned int s, unsigned int i, unsigned int m ) +{ + this->m_StateSize = s; + this->m_InputSize = i; + this->m_MeasureSize = m; + + // Matrices + this->m_A.set_size( s, s ); + this->m_B.set_size( s, i ); + this->m_H.set_size( m, s ); + this->m_Id.set_size( s, s ); + this->m_Q.set_size( s, s ); + this->m_R.set_size( m, m ); + this->m_P0.set_size( s, s ); + this->m_K.set_size( s, m ); + this->m_Pm.set_size( s, s ); + this->m_Pp.set_size( s, s ); + + // Vectors + this->m_x0.set_size( s ); + this->m_u.set_size( i ); + this->m_m.set_size( m ); + this->m_xm.set_size( s ); + this->m_xp.set_size( s ); + + // Static values + this->m_Id.set_identity( ); +} + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanFilter< T >:: +Initialize( ) +{ + // Set all to the first iteration + this->m_I = 0; + this->m_Step = Self::StFilt; +} + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanFilter< T >:: +Predict( ) +{ + if( this->m_Step == Self::StFilt ) + { + if( this->m_I == 0 ) + { + this->m_xp = this->m_x0; + this->m_Pp = this->m_P0; + + } // fi + + // Project the state + this->m_xm = ( this->m_A * this->m_xp ) + ( this->m_B * this->m_u ); + + // Project the error + this->m_Pm = this->m_A * this->m_Pp * this->m_A.transpose( ); + this->m_Pm += this->m_Q; + + this->m_Step = Self::StPred; + + } // fi +} + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanFilter< T >:: +Innovate( ) +{ + typedef vnl_matrix_inverse< T > _TInv; + + if( this->m_Step == Self::StPred ) + { + // Kalman gain + this->m_K = this->m_Pm * this->m_H.transpose( ); + this->m_K *= + _TInv( + ( this->m_H * this->m_Pm * this->m_H.transpose( ) ) + this->m_R + ); + + this->m_Step = Self::StInno; + + } // fi +} + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanFilter< T >:: +Filtrate( ) +{ + if( this->m_Step == Self::StInno ) + { + // A posteriori state + this->m_xp = this->m_xm; + this->m_xp += this->m_K * ( this->m_m - ( this->m_H * this->m_xm ) ); + + // A posteriori error + this->m_Pp = ( this->m_Id - ( this->m_K * this->m_H ) ) * this->m_Pm; + + this->m_Step = Self::StFilt; + this->m_I++; + + } // fi +} + +// ------------------------------------------------------------------------- +template< typename T > +cpExtensions::Algorithms::KalmanFilter< T >:: +KalmanFilter( ) + : Superclass( ) +{ + this->Configure( 1, 1, 1 ); +} + +// ------------------------------------------------------------------------- +template< typename T > +cpExtensions::Algorithms::KalmanFilter< T >:: +~KalmanFilter( ) +{ +} + +// ------------------------------------------------------------------------- +// Explicit instantiations + +template class cpExtensions::Algorithms::KalmanFilter< float >; +template class cpExtensions::Algorithms::KalmanFilter< double >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/KalmanFilter.h b/lib/cpExtensions/Algorithms/KalmanFilter.h new file mode 100644 index 0000000..0039620 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanFilter.h @@ -0,0 +1,213 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__ + +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +#define kalmanGetSetMacro( type, name ) \ + itkGetConstMacro( name, type ); \ + itkSetMacro( name, type ); + +// ------------------------------------------------------------------------- +#define kalmanGetMatrixMacro( var, name ) \ + virtual const TMatrix& Get##name( ) const \ + { return( this->m_##var ); } + +// ------------------------------------------------------------------------- +#define kalmanSetMatrixMacro( var, name ) \ + virtual void Set##name( const TMatrix& m ) \ + { this->Set##var( m ); } + +// ------------------------------------------------------------------------- +#define kalmanGetSetMatrixMacro( var, name ) \ + kalmanGetMatrixMacro( var, name ); \ + kalmanSetMatrixMacro( var, name ); + +// ------------------------------------------------------------------------- +#define kalmanGetVectorMacro( var, name ) \ + virtual const TVector& Get##name( ) const \ + { return( this->m_##var ); } + +// ------------------------------------------------------------------------- +#define kalmanSetVectorMacro( var, name ) \ + virtual void Set##name( const TVector& v ) \ + { this->Set##var( v ); } + +// ------------------------------------------------------------------------- +#define kalmanGetSetVectorMacro( var, name ) \ + kalmanGetVectorMacro( var, name ); \ + kalmanSetVectorMacro( var, name ); + +namespace cpExtensions +{ + namespace Algorithms + { + /** + * Abstract class implementing the classical kalman filter. See + * http://www.cs.unc.edu/~welch/media/pdf/kalman_intro.pdf + * for a description of this algorithm. + */ + template< typename T > + class cpExtensions_EXPORT KalmanFilter + : public itk::Object + { + public: + typedef KalmanFilter Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Template parameters types + typedef T TScalar; + + // VNL types + typedef vnl_matrix< TScalar > TMatrix; + typedef vnl_vector< TScalar > TVector; + + // stage identificators + enum + { + StPred, + StInno, + StFilt + }; + + public: + itkNewMacro( Self ); + itkTypeMacro( KalmanFilter, itkObject ); + + // Values + itkGetConstMacro( StateSize, unsigned int ); + itkGetConstMacro( InputSize, unsigned int ); + itkGetConstMacro( MeasureSize, unsigned int ); + + // Matrices + kalmanGetSetMacro( TMatrix, A ); + kalmanGetSetMacro( TMatrix, B ); + kalmanGetSetMacro( TMatrix, H ); + kalmanGetSetMacro( TMatrix, Q ); + kalmanGetSetMacro( TMatrix, R ); + kalmanGetSetMacro( TMatrix, P0 ); + kalmanGetSetMacro( TMatrix, K ); + kalmanGetSetMacro( TMatrix, Pm ); + kalmanGetSetMacro( TMatrix, Pp ); + + // Vectors + kalmanGetSetMacro( TVector, x0 ); + kalmanGetSetMacro( TVector, u ); + kalmanGetSetMacro( TVector, m ); + kalmanGetSetMacro( TVector, xm ); + kalmanGetSetMacro( TVector, xp ); + + // Human-readable matrices + kalmanGetSetMatrixMacro( A, TransitionMatrix ); + kalmanGetSetMatrixMacro( B, InputControlMatrix ); + kalmanGetSetMatrixMacro( H, MeasureMatrix ); + kalmanGetSetMatrixMacro( Q, ProcessNoise ); + kalmanGetSetMatrixMacro( R, MeasureNoise ); + kalmanGetSetMatrixMacro( P0, InitialNoise ); + kalmanGetSetMatrixMacro( K, Gain ); + kalmanGetSetMatrixMacro( Pm, APrioriNoise ); + kalmanGetSetMatrixMacro( Pp, APosterioriNoise ); + + // Human-readable vectors + kalmanGetSetVectorMacro( x0, InitialState ); + kalmanGetSetVectorMacro( u, Input ); + kalmanGetSetVectorMacro( m, Measure ); + kalmanGetSetVectorMacro( xm, APrioriState ); + kalmanGetSetVectorMacro( xp, APosterioriState ); + + public: + + void Configure( unsigned int s, unsigned int i, unsigned int m ); + + // Iteration methods + virtual void Initialize( ); + virtual void Predict( ); + virtual void Innovate( ); + virtual void Filtrate( ); + virtual void OneStep( ) + { + this->Predict( ); + this->Innovate( ); + this->Filtrate( ); + } + virtual void NSteps( unsigned int n ) + { + for( unsigned int i = 0; i < n; i++ ) + this->OneStep( ); + } + unsigned int CurrentIteration( ) const + { return( this->m_I ); } + unsigned char CurrentStep( ) const + { return( this->m_Step ); } + + protected: + KalmanFilter( ); + virtual ~KalmanFilter( ); + + private: + // Purposely not implemented + KalmanFilter( const Self& ); + void operator=( const Self& ); + + protected: + // Filter dimensions + unsigned int m_StateSize; + unsigned int m_InputSize; + unsigned int m_MeasureSize; + + // Transition matrices + TMatrix m_A; // Transition + TMatrix m_B; // Input control + TMatrix m_H; // Measure + TMatrix m_Id; // Identity matrix + + // Noise matrices + TMatrix m_Q; // Process noise covariance + TMatrix m_R; // Measure noise covariance + + // Initial values + TVector m_x0; // Initial state + TMatrix m_P0; // Initial error covariance + + // Loop vectors + TVector m_u; // Last real input + TVector m_m; // Last real measure + TVector m_xm; // A priori state + TVector m_xp; // A posteriori state + + // Loop matrices + TMatrix m_K; // kalman gain + TMatrix m_Pm; // A priori error + TMatrix m_Pp; // A posteriori error + + // Loop values + unsigned int m_I; // Current iteration + unsigned char m_Step; // Current step within current iteration + + // ------------------------------------------------------------------- + // Classic kronecker product operator + // ------------------------------------------------------------------- + template< class M > + static void Kronecker( M& AkB, const M& A, const M& B ); + }; + + } // ecapseman + +} // ecapseman + +#include + +#endif // __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/KalmanFilter.hxx b/lib/cpExtensions/Algorithms/KalmanFilter.hxx new file mode 100644 index 0000000..e81cae2 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanFilter.hxx @@ -0,0 +1,37 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__HXX__ + +// ------------------------------------------------------------------------- +template< typename T > +template< class M > +void cpExtensions::Algorithms::KalmanFilter< T >:: +Kronecker( M& AkB, const M& A, const M& B ) +{ + unsigned int m = A.rows( ); unsigned int n = A.cols( ); + unsigned int p = B.rows( ); unsigned int q = B.cols( ); + AkB.set_size( m * p, n * q ); + + for( unsigned int i = 1; i <= m; ++i ) + { + for( unsigned int j = 1; j <= n; ++j ) + { + for( unsigned int k = 1; k <= p; ++k ) + { + for( unsigned int l = 1; l <= q; ++l ) + { + unsigned int al = ( ( p * ( i - 1 ) ) + k ) - 1; + unsigned int be = ( ( q * ( j - 1 ) ) + l ) - 1; + AkB[ al ][ be ] = A[ i - 1 ][ j - 1 ] * B[ k - 1 ][ l - 1 ]; + + } // rof + + } // rof + + } // rof + + } // rof +} + +#endif // __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx new file mode 100644 index 0000000..a725e16 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx @@ -0,0 +1,90 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#include +#include + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanVelocityFilter< T >:: +Configure( unsigned int m ) +{ + this->Superclass::Configure( m << 1, 1, m ); + + this->m_TimeOffset.set_size( 2, 2 ); + this->SetTimeOffset( TScalar( 1 ) ); + + this->m_Sigma.set_size( this->m_MeasureSize, this->m_MeasureSize ); + this->m_Sigma.set_identity( ); +} + +// ------------------------------------------------------------------------- +template< typename T > +typename cpExtensions::Algorithms::KalmanVelocityFilter< T >:: +TScalar cpExtensions::Algorithms::KalmanVelocityFilter< T >:: +GetTimeOffset( ) const +{ + return( TScalar( std::sqrt( double( this->m_TimeOffset[ 1 ][ 1 ] ) ) ) ); +} + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanVelocityFilter< T >:: +SetTimeOffset( TScalar t ) +{ + TScalar t2 = t * t; + TScalar t3 = t2 * t; + TScalar t4 = t3 * t; + this->m_TimeOffset[ 0 ][ 0 ] = t4 / TScalar( 4 ); + this->m_TimeOffset[ 1 ][ 1 ] = t2; + + this->m_TimeOffset[ 0 ][ 1 ] = t3 / TScalar( 2 ); + this->m_TimeOffset[ 1 ][ 0 ] = this->m_TimeOffset[ 0 ][ 1 ]; +} + +// ------------------------------------------------------------------------- +template< typename T > +void cpExtensions::Algorithms::KalmanVelocityFilter< T >:: +Initialize( ) +{ + this->Superclass::Initialize( ); + + Self::Kronecker( this->m_Q, this->m_Sigma, this->m_TimeOffset ); + + this->m_A.set_identity( ); + this->m_B.fill( TScalar( 0 ) ); + this->m_H.fill( TScalar( 0 ) ); + + TScalar tOff = this->GetTimeOffset( ); + for( unsigned int i = 0; i < this->m_MeasureSize; i++ ) + { + this->m_A[ i ][ this->m_MeasureSize + i ] = tOff; + this->m_H[ i ][ i ] = TScalar( 1 ); + + } // rof +} + +// ------------------------------------------------------------------------- +template< typename T > +cpExtensions::Algorithms::KalmanVelocityFilter< T >:: +KalmanVelocityFilter( ) + : Superclass( ) +{ + this->Configure( 1 ); +} + +// ------------------------------------------------------------------------- +template< typename T > +cpExtensions::Algorithms::KalmanVelocityFilter< T >:: +~KalmanVelocityFilter( ) +{ +} + +// ------------------------------------------------------------------------- +// Explicit instantiations + +template class cpExtensions::Algorithms::KalmanVelocityFilter< float >; +template class cpExtensions::Algorithms::KalmanVelocityFilter< double >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/KalmanVelocityFilter.h b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.h new file mode 100644 index 0000000..c32dde6 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.h @@ -0,0 +1,66 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< typename T > + class cpExtensions_EXPORT KalmanVelocityFilter + : public KalmanFilter< T > + { + public: + typedef KalmanVelocityFilter Self; + typedef KalmanFilter< T > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TMatrix TMatrix; + typedef typename Superclass::TVector TVector; + + public: + itkNewMacro( Self ); + itkTypeMacro( KalmanVelocityFilter, KalmanFilter ); + + kalmanGetSetMacro( TMatrix, Sigma ); + kalmanGetSetMatrixMacro( Sigma, AccelerationNoise ); + + public: + void Configure( unsigned int m ); + + TScalar GetTimeOffset( ) const; + void SetTimeOffset( TScalar t ); + + /// Iteration methods + virtual void Initialize( ) cpExtensions_OVERRIDE; + + protected: + KalmanVelocityFilter( ); + virtual ~KalmanVelocityFilter( ); + + private: + // Purposely not implemented. + KalmanVelocityFilter( const Self& ); + void operator=( const Self& ); + + protected: + TMatrix m_TimeOffset; + TMatrix m_Sigma; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/LightCompensationFilter.h b/lib/cpExtensions/Algorithms/LightCompensationFilter.h new file mode 100644 index 0000000..a3c28ff --- /dev/null +++ b/lib/cpExtensions/Algorithms/LightCompensationFilter.h @@ -0,0 +1,65 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I > + class LightCompensationFilter + : public itk::InPlaceImageFilter< I, I > + { + public: + typedef LightCompensationFilter Self; + typedef itk::InPlaceImageFilter< I, I > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef I TImage; + typedef typename I::RegionType TRegion; + + typedef cpExtensions::Algorithms::ParallelImageMean< I > TMeanCalculator; + typedef typename TMeanCalculator::TMean TMean; + + public: + itkNewMacro( Self ); + itkTypeMacro( LightCompensationFilter, itkInPlaceImageFilter ); + + itkGetConstMacro( Mean, TMean ); + + protected: + LightCompensationFilter( ); + virtual ~LightCompensationFilter( ); + + private: + virtual void BeforeThreadedGenerateData( ); + virtual void ThreadedGenerateData( + const TRegion& region, itk::ThreadIdType id + ); + virtual void AfterThreadedGenerateData( ); + + protected: + TMean m_Mean; + TMean m_Coefficient; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/LightCompensationFilter.hxx b/lib/cpExtensions/Algorithms/LightCompensationFilter.hxx new file mode 100644 index 0000000..f75ffcd --- /dev/null +++ b/lib/cpExtensions/Algorithms/LightCompensationFilter.hxx @@ -0,0 +1,96 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class I > +cpExtensions::Algorithms::LightCompensationFilter< I >:: +LightCompensationFilter( ) + : Superclass( ) +{ + this->SetNumberOfRequiredInputs( 1 ); + this->InPlaceOff( ); +} + +// ------------------------------------------------------------------------- +template< class I > +cpExtensions::Algorithms::LightCompensationFilter< I >:: +~LightCompensationFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I > +void cpExtensions::Algorithms::LightCompensationFilter< I >:: +BeforeThreadedGenerateData( ) +{ + this->Superclass::BeforeThreadedGenerateData( ); + + I* input = const_cast< I* >( this->GetInput( ) ); + + typename TMeanCalculator::Pointer mc = TMeanCalculator::New( ); + mc->Execute( input, input->GetRequestedRegion( ) ); + this->m_Mean = mc->GetMean( ); + + double gm = this->m_Mean[ 0 ] + this->m_Mean[ 1 ] + this->m_Mean[ 2 ]; + gm /= double( 3 ); + this->m_Coefficient = this->m_Mean; + this->m_Coefficient.Fill( gm ); + this->m_Coefficient[ 0 ] /= this->m_Mean[ 0 ]; + this->m_Coefficient[ 1 ] /= this->m_Mean[ 1 ]; + this->m_Coefficient[ 2 ] /= this->m_Mean[ 2 ]; +} + +// ------------------------------------------------------------------------- +template< class I > +void cpExtensions::Algorithms::LightCompensationFilter< I >:: +ThreadedGenerateData( const TRegion& region, itk::ThreadIdType id ) +{ + typedef itk::NumericTraits< typename I::PixelType > _TPixelTraits; + typedef typename _TPixelTraits::ValueType _TPixelChannel; + typedef itk::NumericTraits< _TPixelChannel > _TChannelTraits; + static const double max_value = double( _TChannelTraits::max( ) ); + + itk::ImageRegionConstIterator< I > iIt( this->GetInput( ), region ); + itk::ImageRegionIterator< I > oIt( this->GetOutput( ), region ); + + iIt.GoToBegin( ); + oIt.GoToBegin( ); + for( ; !iIt.IsAtEnd( ); ++iIt, ++oIt ) + { + double r = double( iIt.Get( )[ 0 ] ) * this->m_Coefficient[ 0 ]; + double g = double( iIt.Get( )[ 1 ] ) * this->m_Coefficient[ 1 ]; + double b = double( iIt.Get( )[ 2 ] ) * this->m_Coefficient[ 2 ]; + + if( r > max_value ) r = max_value; + if( g > max_value ) g = max_value; + if( b > max_value ) b = max_value; + + typename I::PixelType pix; + pix.SetRed( _TPixelChannel( r ) ); + pix.SetGreen( _TPixelChannel( g ) ); + pix.SetBlue( _TPixelChannel( b ) ); + + oIt.Set( pix ); + + } // rof +} + +// ------------------------------------------------------------------------- +template< class I > +void cpExtensions::Algorithms::LightCompensationFilter< I >:: +AfterThreadedGenerateData( ) +{ + this->Superclass::AfterThreadedGenerateData( ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/MFluxMedialness.h b/lib/cpExtensions/Algorithms/MFluxMedialness.h new file mode 100644 index 0000000..97bc44f --- /dev/null +++ b/lib/cpExtensions/Algorithms/MFluxMedialness.h @@ -0,0 +1,74 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > > + class MFluxMedialness + : public GradientImageFunctionBase< _TGradient, _TMask > + { + public: + typedef MFluxMedialness Self; + typedef GradientImageFunctionBase< _TGradient, _TMask > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkStaticConstMacro( Dimension, unsigned int, Superclass::Dimension ); + + typedef typename Superclass::TOutput TOutput; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TIndex TIndex; + typedef typename Superclass::TVector TVector; + typedef typename Superclass::TPoint TPoint; + + typedef std::vector< double > TRCandidates; + + public: + itkNewMacro( Self ); + itkTypeMacro( MFluxMedialness, GradientImageFunctionBase ); + + itkGetConstMacro( RadiusStep, double ); + itkGetConstMacro( MinRadius, double ); + itkGetConstMacro( MaxRadius, double ); + itkGetConstMacro( RadialSampling, unsigned int ); + + itkSetMacro( RadiusStep, double ); + itkSetMacro( MinRadius, double ); + itkSetMacro( MaxRadius, double ); + itkSetMacro( RadialSampling, unsigned int ); + + protected: + MFluxMedialness( ); + virtual ~MFluxMedialness( ); + + virtual TOutput _Evaluate( const TIndex& i ) const cpExtensions_OVERRIDE; + + private: + // Purposely not implemented. + MFluxMedialness( const Self& ); + void operator=( const Self& ); + + protected: + double m_MinRadius; + double m_MaxRadius; + unsigned int m_RadialSampling; + double m_RadiusStep; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/MFluxMedialness.hxx b/lib/cpExtensions/Algorithms/MFluxMedialness.hxx new file mode 100644 index 0000000..bc5db37 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MFluxMedialness.hxx @@ -0,0 +1,159 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >:: +MFluxMedialness( ) + : Superclass( ), + m_MinRadius( double( 0 ) ), + m_MaxRadius( double( 1 ) ), + m_RadialSampling( 4 ), + m_RadiusStep( double( 1 ) ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >:: +~MFluxMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient, class _TMask > +typename cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >:: +TOutput cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >:: +_Evaluate( const TIndex& i ) const +{ + itk::Object::GlobalWarningDisplayOff( ); + + double pi2n = double( 2 ) * double( vnl_math::pi ); + pi2n /= int( this->m_RadialSampling ); + const _TGradient* img = this->GetInputImage( ); + //const itk::Image::SpacingType& input_spacing = img->GetSpacing( ); + + double Flux1 = 0; + double Flux2 = 0; + double MFlux = 0; + + TRCandidates FluxFinal; + TRCandidates radiusGenerated; + double dR = double( 0 ); + double optR = double( 0 ); + TPoint center; + img->TransformIndexToPhysicalPoint( i, center ); + double radius; + + for( unsigned int cx = 0; cx < Self::Dimension - 1; cx++ ) + { + for( unsigned int cy = cx + 1; cy < Self::Dimension; cy++ ) + { + dR = double( 0 ); + FluxFinal.clear(); + radiusGenerated.clear(); + radius = this->m_MinRadius; + while( radius <= this->m_MaxRadius ) + { + MFlux = 0; + for( unsigned int I_radial = 0; I_radial < this->m_RadialSampling / 2; I_radial++ ) + { + Flux1 = 0; + Flux2 = 0; + + // Direction of first profile + typename TPoint::VectorType dir1; + dir1.Fill( double( 0 ) ); + dir1[ cx ] = std::cos( pi2n * double( I_radial ) ); + dir1[ cy ] = std::sin( pi2n * double( I_radial ) ); + //dir1 *= (radius); + + TIndex rIdx; + + if ( img->TransformPhysicalPointToIndex( center + (dir1*radius), rIdx ) ) + { + TVector grad_rIdx = img->GetPixel( rIdx ); + TVector u_i1; + u_i1.SetVnlVector( ( center - ( center + dir1 ) ).GetVnlVector( ) ); + u_i1.Normalize( ); + // dot product + Flux1 = grad_rIdx * u_i1; + } + else + { + //if (Self::Dimension==3) + //{ + //std::cout<<"Point Edge x:"<TransformPhysicalPointToIndex( center + (dir2*radius), rIdx2 ) ) + { + TVector grad_rIdx2 = img->GetPixel( rIdx2 ); + TVector u_i2; + u_i2.SetVnlVector( ( center - ( center + dir2 ) ).GetVnlVector( ) ); + u_i2.Normalize( ); + + Flux2 = grad_rIdx2 * u_i2; + } + else + { + //if (Self::Dimension==3) + //{ + //std::cout<<"Point Edge x:"<m_RadialSampling; + FluxFinal.push_back(MFlux); + radiusGenerated.push_back(radius); + + radius += this->m_RadiusStep; + + } //elihw + + dR= *( std::max_element( FluxFinal.begin(), FluxFinal.end() ) ); + optR= (dR>optR)? dR:optR; + + } // rof + + } // rof + return( TScalar(optR) ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/MacheteImageFilter.h b/lib/cpExtensions/Algorithms/MacheteImageFilter.h new file mode 100644 index 0000000..d9d3c32 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MacheteImageFilter.h @@ -0,0 +1,72 @@ +// ------------------------------------------------------------------------- +// @author Jose Luis Guzman (cycopepe@gmail.com) +// ------------------------------------------------------------------------- + + +#ifndef __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__ + +#include + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + template< class I, class O> + class MacheteImageFilter :public itk::ImageToImageFilter < I, O > + { + public: + /** Standard class typedefs. */ + typedef MacheteImageFilter Self; + + typedef itk::ImageToImageFilter< I, O > Superclass; + typedef itk::SmartPointer< Self > Pointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(MacheteImageFilter, ImageToImageFilter); + + typedef typename I::PixelType RadiusType; + //typedef typename I::SizeValueType RadiusValueType; + + itkGetConstReferenceMacro(Radius, RadiusType); + + + void SetRadius(const RadiusType & rad); + //void SetRadius(const RadiusValueType & rad); + + void SetPoint(itk::Point & point); + void SetPoint(const double & x, const double & y, const double & z); + + protected: + MacheteImageFilter(){} + ~MacheteImageFilter(){} + + /** Does the real work. */ + virtual void GenerateData(); + + RadiusType m_Radius; + itk::Point point; + + private: + MacheteImageFilter(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + + + }; + + } // ecapseman + +} // ecapseman + + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif + + +#endif // __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__ \ No newline at end of file diff --git a/lib/cpExtensions/Algorithms/MacheteImageFilter.hxx b/lib/cpExtensions/Algorithms/MacheteImageFilter.hxx new file mode 100644 index 0000000..a984df1 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MacheteImageFilter.hxx @@ -0,0 +1,92 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__HXX__ + +#include + +//filter stuff +#include "itkObjectFactory.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIterator.h" + +//typedef itk::Image ImageType; + +template< class I, class O> +void cpExtensions::Algorithms::MacheteImageFilter< I, O> +::GenerateData() +{ + //const typename Superclass::OutputImageRegionType& region; + + typename I::ConstPointer input = this->GetInput(); + + typename O::Pointer output = this->GetOutput(); + output->SetRegions(input->GetLargestPossibleRegion()); + output->Allocate(); + + itk::ImageRegionIterator outputIterator(output, output->GetLargestPossibleRegion()); + itk::ImageRegionConstIterator inputIterator(input, input->GetLargestPossibleRegion()); + + while (!outputIterator.IsAtEnd()) + { + auto p0 = inputIterator.GetIndex(); + itk::Point otherPoint; + otherPoint[0] = p0[0]; + otherPoint[1] = p0[1]; + otherPoint[2] = p0[2]; + //otherPoint[2] = this->point[2]; // TODO : Solve this hammer + + double dist = this->point.EuclideanDistanceTo(otherPoint); + if (dist <= this->m_Radius) + { + outputIterator.Set(0); + } + else + { + outputIterator.Set(inputIterator.Get()); + } + + ++inputIterator; + ++outputIterator; + } + + +} + +template< class I, class O> +void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetRadius(const RadiusType & rad) +{ + if (this->m_Radius != rad) + { + this->m_Radius = rad; + this->Modified(); + } +} + +//template< class I, class O> +//void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetRadius(const RadiusValueType & rad) +//{ +// RadiusType r; +// r.Fill(rad); +// this->SetRadius(r); +//} + +template< class I, class O> +void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetPoint(itk::Point & p){ + if (point != p) + { + this->point = p; + this->Modified(); + } +} + +template< class I, class O> +void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetPoint(const double & x, const double & y, const double & z) +{ + this->point[0] = x; + this->point[1] = y; + this->point[2] = z; + this->Modified(); +} + + + +#endif \ No newline at end of file diff --git a/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h new file mode 100644 index 0000000..63fb8a8 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h @@ -0,0 +1,86 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__h__ +#define __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__h__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I, class O > + class MultiScaleGaussianImageFilter + : public itk::ImageToImageFilter< I, O > + { + public: + typedef MultiScaleGaussianImageFilter Self; + typedef itk::ImageToImageFilter< I, O > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef I TInputImage; + typedef O TOutputImage; + + typedef std::set< double > TScalesContainer; + + protected: + /** + */ + class _Greater + { + public: + typedef typename O::PixelType _T; + + public: + _Greater( ); + virtual ~_Greater( ); + bool operator!=( const _Greater& b ) const; + bool operator==( const _Greater& b ) const; + inline _T operator()( const _T& a ) const; + inline _T operator()( const _T& a, const _T& b ) const; + }; + + public: + itkNewMacro( Self ); + itkTypeMacro( MultiScaleGaussianImageFilter, itkImageToImageFilter ); + + public: + void AddScale( const double& s ); + unsigned long GetNumberOfScales( ) const; + + protected: + MultiScaleGaussianImageFilter( ); + virtual ~MultiScaleGaussianImageFilter( ); + + virtual void GenerateData( ) cpExtensions_OVERRIDE; + + template< class F > + void _GenerateData( ); + + private: + // Purposely not implemented. + MultiScaleGaussianImageFilter( const Self& ); + void operator=( const Self& ); + + protected: + TScalesContainer m_Scales; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx new file mode 100644 index 0000000..985cbec --- /dev/null +++ b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx @@ -0,0 +1,226 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__hxx__ +#define __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__hxx__ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class I, class O > +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +_Greater( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +~_Greater( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +bool cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +operator!=( const _Greater& b ) const +{ + return( false ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +bool cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +operator==( const _Greater& b ) const +{ + return !( *this != b ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +typename cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +_T cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +operator()( const _T& a ) const +{ + return( a ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +typename cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +_T cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >::_Greater:: +operator()( const _T& a, const _T& b ) const +{ + typedef itk::NumericTraits< _T > _TTraits; + typedef typename _TTraits::ValueType _TValue; + typedef vnl_vector< _TValue > _TVector; + + _TVector va( _TTraits::GetLength( ) ); + _TVector vb( _TTraits::GetLength( ) ); + + _TTraits::AssignToArray( a, va ); + _TTraits::AssignToArray( b, vb ); + return( ( vb.magnitude( ) < va.magnitude( ) )? a: b ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +AddScale( const double& s ) +{ + if( this->m_Scales.insert( s ).second ) + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +unsigned long +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +GetNumberOfScales( ) const +{ + return( this->m_Scales.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +MultiScaleGaussianImageFilter( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +~MultiScaleGaussianImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +GenerateData( ) +{ + typedef itk::GradientRecursiveGaussianImageFilter< I, O > _TGF; + this->_GenerateData< _TGF >( ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +template< class F > +void +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +_GenerateData( ) +{ + // Some types + typedef itk::BinaryFunctorImageFilter< O, O, O, _Greater > _TMaxFilter; + typedef itk::UnaryFunctorImageFilter< O, O, _Greater > _TCopyFilter; + typedef itk::ImageRegionConstIterator< O > _TConstIt; + typedef itk::ImageRegionIterator< O > _TIt; + typedef itk::ProgressAccumulator _TProgress; + + // Some values + typename I::ConstPointer input = this->GetInput( ); + typename O::Pointer output = this->GetOutput( ); + unsigned int nThreads = this->GetNumberOfThreads( ); + float fw = float( 1 ) / float( this->m_Scales.size( ) << 1 ); + + // Progress accumulator + _TProgress::Pointer pg = _TProgress::New( ); + pg->SetMiniPipelineFilter( this ); + + // Copy image information + output->SetLargestPossibleRegion( input->GetLargestPossibleRegion( ) ); + output->SetRequestedRegion( input->GetRequestedRegion( ) ); + output->SetBufferedRegion( input->GetBufferedRegion( ) ); + output->SetSpacing( input->GetSpacing( ) ); + output->SetOrigin( input->GetOrigin( ) ); + output->SetDirection( input->GetDirection( ) ); + output->Allocate( ); + + // Intermediary buffer + typename O::Pointer buffer = O::New( ); + buffer->SetLargestPossibleRegion( input->GetLargestPossibleRegion( ) ); + buffer->SetRequestedRegion( input->GetRequestedRegion( ) ); + buffer->SetBufferedRegion( input->GetBufferedRegion( ) ); + buffer->SetSpacing( input->GetSpacing( ) ); + buffer->SetOrigin( input->GetOrigin( ) ); + buffer->SetDirection( input->GetDirection( ) ); + buffer->Allocate( ); + + // Perform all scales + _TIt gIt( output, output->GetRequestedRegion( ) ); + TScalesContainer::const_iterator sIt = this->m_Scales.begin( ); + for( ; sIt != this->m_Scales.end( ); sIt++ ) + { + // Single scale filter + typename F::Pointer filter = F::New( ); + filter->SetInput( input ); + filter->SetNormalizeAcrossScale( true ); + filter->SetNumberOfThreads( nThreads ); + filter->SetSigma( *sIt ); + pg->RegisterInternalFilter( filter, fw ); + filter->GraftOutput( buffer ); + filter->Update( ); + buffer->Graft( filter->GetOutput( ) ); + + // Get maximum response + if( sIt == this->m_Scales.begin( ) ) + { + // Copy first result + typename _TCopyFilter::Pointer copy = _TCopyFilter::New( ); + copy->SetInput( buffer ); + copy->InPlaceOff( ); + copy->SetNumberOfThreads( nThreads ); + pg->RegisterInternalFilter( copy, fw ); + copy->GraftOutput( output ); + copy->Update( ); + output->Graft( copy->GetOutput( ) ); + } + else + { + // Maximize results + typename _TMaxFilter::Pointer max = _TMaxFilter::New( ); + max->SetInput1( output ); + max->SetInput2( buffer ); + max->InPlaceOn( ); + max->SetNumberOfThreads( nThreads ); + pg->RegisterInternalFilter( max, fw ); + max->GraftOutput( output ); + max->Update( ); + output->Graft( max->GetOutput( ) ); + + } // fi + + } // rof +} + +#endif // __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ParallelImageMean.h b/lib/cpExtensions/Algorithms/ParallelImageMean.h new file mode 100644 index 0000000..6122ce3 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ParallelImageMean.h @@ -0,0 +1,70 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__ +#define __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I > + class ParallelImageMean + : public itk::DomainThreader< itk::ThreadedImageRegionPartitioner< I::ImageDimension >, I > + { + public: + // Standard ITK typedefs. + typedef itk::DomainThreader< itk::ThreadedImageRegionPartitioner< I::ImageDimension >, I > Superclass; + typedef ParallelImageMean Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::DomainType DomainType; + + typedef itk::Array< double > TMean; + + protected: + typedef itk::NumericTraits< typename I::PixelType > _TPixelTraits; + + + public: + itkNewMacro( Self ); + itkTypeMacro( ParallelImageMean, itkDomainThreader ); + + itkGetConstMacro( Mean, TMean ); + + protected: + ParallelImageMean( ); + virtual ~ParallelImageMean( ); + + private: + virtual void BeforeThreadedExecution( ); + virtual void ThreadedExecution( + const DomainType& region, const itk::ThreadIdType id + ); + virtual void AfterThreadedExecution( ); + + protected: + itk::Array< double > m_Mean; + unsigned long m_N; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ParallelImageMean.hxx b/lib/cpExtensions/Algorithms/ParallelImageMean.hxx new file mode 100644 index 0000000..b3e4716 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ParallelImageMean.hxx @@ -0,0 +1,65 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class I > +cpExtensions::Algorithms::ParallelImageMean< I >:: +ParallelImageMean( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I > +cpExtensions::Algorithms::ParallelImageMean< I >:: +~ParallelImageMean( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I > +void cpExtensions::Algorithms::ParallelImageMean< I >:: +BeforeThreadedExecution( ) +{ + this->m_Mean.SetSize( _TPixelTraits::GetLength( ) ); + this->m_Mean.Fill( double( 0 ) ); + this->m_N = 0; +} + +// ------------------------------------------------------------------------- +template< class I > +void cpExtensions::Algorithms::ParallelImageMean< I >:: +ThreadedExecution( const DomainType& region, const itk::ThreadIdType id ) +{ + itk::ImageRegionConstIterator< I > i( this->m_Associate, region ); + for( i.GoToBegin( ); !i.IsAtEnd( ); ++i ) + { + for( unsigned int d = 0; d < _TPixelTraits::GetLength( ); ++d ) + { + this->m_Mean.SetElement( + d, this->m_Mean.GetElement( d ) + double( i.Get( )[ d ] ) + ); + this->m_N++; + + } // rof + + } // rof +} + +// ------------------------------------------------------------------------- +template< class I > +void cpExtensions::Algorithms::ParallelImageMean< I >:: +AfterThreadedExecution( ) +{ + this->m_Mean /= double( this->m_N ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.cxx b/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.cxx new file mode 100644 index 0000000..9eecda1 --- /dev/null +++ b/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.cxx @@ -0,0 +1,94 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#include + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +_TPolyLine* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +GetInput( ) +{ + return( dynamic_cast< _TPolyLine* >( this->Superclass::GetInput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +const _TPolyLine* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +GetInput( ) const +{ + return( dynamic_cast< const _TPolyLine* >( this->Superclass::GetInput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +void cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +SetInput( _TPolyLine* pl ) +{ + this->Superclass::SetNthInput( 0, pl ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +_TCurve* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +GetOutput( ) +{ + return( dynamic_cast< _TCurve* >( this->Superclass::GetOutput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +const _TCurve* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +GetOutput( ) const +{ + return( dynamic_cast< const _TCurve* >( this->Superclass::GetOutput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +PolyLineParametricPathToSimple3DCurve( ) + : Superclass( ), + m_NumberOfSamples( 0 ) +{ + this->SetNumberOfRequiredInputs( 1 ); + this->SetNumberOfRequiredOutputs( 1 ); + typename _TCurve::Pointer curve = _TCurve::New( ); + this->Superclass::SetNthOutput( 0, curve ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +~PolyLineParametricPathToSimple3DCurve( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine, class _TCurve > +void cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >:: +GenerateData( ) +{ + const _TPolyLine* line = this->GetInput( ); + _TCurve* curve = this->GetOutput( ); + unsigned long N = this->m_NumberOfSamples; + if( N == 0 ) + N = line->GetSize( ); + curve->Clear( ); + + for( unsigned long n = 0; n < N; ++n ) + { + double u = double( n ) / double( N - 1 ); + curve->AddPoint( line->GetSmoothPoint( u ) ); + + } // rof +} + +// ------------------------------------------------------------------------- +#include +#include + +template class cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< cpExtensions::DataStructures::PolyLineParametricPath< 3 >, cpExtensions::DataStructures::Simple3DCurve< float > >; +template class cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< cpExtensions::DataStructures::PolyLineParametricPath< 3 >, cpExtensions::DataStructures::Simple3DCurve< double > >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h b/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h new file mode 100644 index 0000000..5282e88 --- /dev/null +++ b/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h @@ -0,0 +1,65 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__PolyLineParametricPathToSimple3DCurve__h__ +#define __cpExtensions__Algorithms__PolyLineParametricPathToSimple3DCurve__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TPolyLine, class _TCurve > + class cpExtensions_EXPORT PolyLineParametricPathToSimple3DCurve + : public itk::ProcessObject + { + public: + // Basic types + typedef PolyLineParametricPathToSimple3DCurve Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPathToSimple3DCurve, itk::ProcessObject ); + + itkGetConstMacro( NumberOfSamples, unsigned long ); + itkSetMacro( NumberOfSamples, unsigned long ); + + public: + _TPolyLine* GetInput( ); + const _TPolyLine* GetInput( ) const; + void SetInput( _TPolyLine* pl ); + + _TCurve* GetOutput( ); + const _TCurve* GetOutput( ) const; + + protected: + PolyLineParametricPathToSimple3DCurve( ); + virtual ~PolyLineParametricPathToSimple3DCurve( ); + + virtual void GenerateData( ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + PolyLineParametricPathToSimple3DCurve( const Self& ); + void operator=( const Self& ); + + protected: + unsigned long m_NumberOfSamples; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Algorithms__PolyLineParametricPathToSimple3DCurve__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.h b/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.h new file mode 100644 index 0000000..f699602 --- /dev/null +++ b/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.h @@ -0,0 +1,69 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__PolyLineParametricPathWriter__h__ +#define __cpExtensions__Algorithms__PolyLineParametricPathWriter__h__ + +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TPolyLine > + class PolyLineParametricPathWriter + : public itk::ProcessObject + { + public: + // Basic types + typedef PolyLineParametricPathWriter Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPathWriter, itk::ProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkGetConstMacro( NumberOfPoints, long ); + + itkSetMacro( FileName, std::string ); + itkSetMacro( NumberOfPoints, long ); + + public: + void SetInput( const _TPolyLine* input ); + const _TPolyLine* GetInput( ); + virtual void Update( ); + + protected: + PolyLineParametricPathWriter( ); + virtual ~PolyLineParametricPathWriter( ); + + virtual void GenerateData( ) override; + + private: + // Purposely not implemented + PolyLineParametricPathWriter( const Self& ); + void operator=( const Self& ); + + protected: + std::string m_FileName; + long m_NumberOfPoints; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__PolyLineParametricPathWriter__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.hxx b/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.hxx new file mode 100644 index 0000000..8e9db8e --- /dev/null +++ b/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.hxx @@ -0,0 +1,128 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__PolyLineParametricPathWriter__hxx__ +#define __cpExtensions__Algorithms__PolyLineParametricPathWriter__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +void cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >:: +SetInput( const _TPolyLine* input ) +{ + this->itk::ProcessObject::SetNthInput( + 0, const_cast< _TPolyLine* >( input ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +const _TPolyLine* +cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >:: +GetInput( ) +{ + return( + dynamic_cast< const _TPolyLine* >( + this->itk::ProcessObject::GetInput( 0 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +void cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >:: +Update( ) +{ + _TPolyLine* input = const_cast< _TPolyLine* >( this->GetInput( ) ); + if( input != NULL ) + { + input->UpdateOutputInformation( ); + input->UpdateOutputData( ); + this->GenerateData( ); + this->ReleaseInputs( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >:: +PolyLineParametricPathWriter( ) + : Superclass( ), + m_FileName( "" ), + m_NumberOfPoints( 100 ) +{ + this->SetNumberOfRequiredInputs( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >:: +~PolyLineParametricPathWriter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +void cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >:: +GenerateData( ) +{ + typedef typename _TPolyLine::TContinuousIndex _TContinuousIndex; + + // "Serialize" data + const _TPolyLine* input = this->GetInput( ); + unsigned int dim = _TPolyLine::PathDimension; + std::stringstream buffer; + long step = input->GetSize( ) / this->m_NumberOfPoints; + + for( unsigned long i = 0; i < input->GetSize( ); i += step ) + { + _TContinuousIndex idx; + idx.Fill( 0 ); + int c = 0; + for( long j = -step; j <= step; ++j ) + { + long k = i + j; + if( k >= 0 && k < input->GetSize( ) ) + { + _TContinuousIndex kdx = input->GetContinuousVertex( k ); + for( unsigned int d = 0; d < dim; ++d ) + idx[ d ] += kdx[ d ]; + c++; + + } // fi + + } // rof + if( c != 0 ) + for( unsigned int d = 0; d < dim; ++d ) + idx[ d ] /= c; + + buffer << idx[ 0 ]; + for( unsigned int d = 1; d < dim; ++d ) + buffer << " " << idx[ d ]; + buffer << std::endl; + + } // rof + + // Real write + std::ofstream file_stream( + this->m_FileName.c_str( ), std::ofstream::binary + ); + if( !file_stream ) + { + itkExceptionMacro( + << "Could not open file \"" << this->m_FileName << "\" to write a " + << "cpExtensions::DataStructures::PolyLineParametricPath< " << dim + << " > object." + ); + return; + + } // fi + file_stream.write( buffer.str( ).c_str( ), buffer.str( ).size( ) ); +} + +#endif // __cpExtensions__Algorithms__PolyLineParametricPathWriter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RGBExtractFunction.h b/lib/cpExtensions/Algorithms/RGBExtractFunction.h new file mode 100644 index 0000000..ec7126b --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBExtractFunction.h @@ -0,0 +1,54 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__ + +#include +#include +#include + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class P > + struct RGBExtractFunction + { + typedef RGBExtractFunction Self; + typedef P TOutPixel; + typedef typename P::ValueType TValue; + + template< class Tr, class Tg, class Tb > + P operator()( const Tr& r, const Tg& g, const Tb& b ) const + { + P out; + out[ 0 ] = TValue( r ); + out[ 1 ] = TValue( g ); + out[ 2 ] = TValue( b ); + return( out ); + } + + template< class C > + TOutPixel operator()( const itk::RGBPixel< C >& rgb ) const + { + return( + this->operator()( + rgb.GetRed( ), rgb.GetGreen( ), rgb.GetBlue( ) + ) + ); + } + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h new file mode 100644 index 0000000..4ce6754 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h @@ -0,0 +1,67 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I, class O, class C > + class RGBImageToOtherChannelsFilter + : public itk::ImageToImageFilter< I, O > + { + public: + typedef RGBImageToOtherChannelsFilter Self; + typedef itk::ImageToImageFilter< I, O > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef I TInputImage; + typedef O TOutputImage; + typedef C TConverter; + typedef typename I::PixelType TInputPixel; + typedef typename O::PixelType TOutputPixel; + + public: + itkNewMacro( Self ); + itkTypeMacro( RGBImageToOtherChannelsFilter, itkImageToImageFilter ); + + protected: + RGBImageToOtherChannelsFilter( ); + virtual ~RGBImageToOtherChannelsFilter( ); + + virtual void BeforeThreadedGenerateData( ); + virtual void AfterThreadedGenerateData( ); + + virtual void ThreadedGenerateData( + const typename Superclass::OutputImageRegionType& region, + itk::ThreadIdType threadId + ); + + private: + // Purposely not implemented + RGBImageToOtherChannelsFilter( const Self& other ); + void operator=( const Self& other ); + + private: + TConverter Converter; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx new file mode 100644 index 0000000..74578d4 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx @@ -0,0 +1,71 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__ + +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +template< class I, class O, class C > +cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >:: +RGBImageToOtherChannelsFilter( ) + : Superclass( ) +{ + this->SetNumberOfRequiredInputs( 1 ); + this->SetNumberOfRequiredOutputs( 1 ); + + typename O::Pointer o = O::New( ); + this->SetNthOutput( 0, o ); +} + +// ------------------------------------------------------------------------- +template< class I, class O, class C > +cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >:: +~RGBImageToOtherChannelsFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O, class C > +void cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >:: +BeforeThreadedGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O, class C > +void cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >:: +AfterThreadedGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O, class C > +void cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >:: +ThreadedGenerateData( + const typename Superclass::OutputImageRegionType& region, + itk::ThreadIdType threadId + ) +{ + // typedef typename TInputPixel::ComponentType _TComponent; + typedef itk::ImageRegionConstIterator< I > _TInIt; + typedef itk::ImageRegionIterator< O > _TOutIt; + + _TInIt inIt( this->GetInput( ), region ); + _TOutIt outIt( this->GetOutput( ), region ); + inIt.GoToBegin( ); + outIt.GoToBegin( ); + for( ; !inIt.IsAtEnd( ); ++inIt, ++outIt ) + outIt.Set( this->Converter( inIt.Get( ) ) ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RGBToHSVFunction.h b/lib/cpExtensions/Algorithms/RGBToHSVFunction.h new file mode 100644 index 0000000..b10f295 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBToHSVFunction.h @@ -0,0 +1,87 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__ + +#include +#include +#include + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class P > + struct RGBToHSVFunction + { + typedef RGBToHSVFunction Self; + typedef P TOutPixel; + typedef typename P::ValueType TValue; + + template< class Tr, class Tg, class Tb > + P operator()( const Tr& r, const Tg& g, const Tb& b ) const + { + static const double mVal = + double( std::numeric_limits< TValue >::max( ) ); + static const double _0 = double( 0 ); + static const double _1 = double( 1 ); + static const double _2 = double( 2 ); + static const double _3 = double( 3 ); + static const double _2pi = _2 * double( vnl_math::pi ); + + P hsv; + + double R = double( r ); + double G = double( g ); + double B = double( b ); + double sRGB = R + G + B; + double RG = R - G; + double RB = R - B; + double GB = G - B; + + // Hue + double A = std::sqrt( ( RG * RG ) + ( RB * GB ) ); + if( A != _0 ) + A = std::acos( ( RG + RB ) / ( _2 * A ) ); + A /= _2pi; + hsv[ 0 ] = TValue( mVal * ( ( G >= B )? A: _1 - A ) ); + + // Saturation + if( sRGB != _0 ) + { + double C = ( G < R )? G: R; + C = ( B < C )? B: C; + hsv[ 1 ] = TValue( mVal * ( _1 - ( ( _3 * C ) / sRGB ) ) ); + } + else + hsv[ 1 ] = TValue( 0 ); + + // Value + hsv[ 2 ] = TValue( sRGB / _3 ); + return( hsv ); + } + + template< class C > + TOutPixel operator()( const itk::RGBPixel< C >& rgb ) const + { + return( + this->operator()( + rgb.GetRed( ), rgb.GetGreen( ), rgb.GetBlue( ) + ) + ); + } + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h b/lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h new file mode 100644 index 0000000..83085fe --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h @@ -0,0 +1,72 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__ + +#include +#include +#include +#include + +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class P > + struct RGBToYPbPrFunction + { + typedef RGBToYPbPrFunction Self; + typedef P TOutPixel; + typedef typename P::ValueType TValue; + + template< class Tr, class Tg, class Tb > + P operator()( const Tr& r, const Tg& g, const Tb& b ) const + { + static const double M[] = + { + double( 0.2990 ), double( 0.5870 ), double( 0.1140 ), + double( -0.1687 ), double( -0.3313 ), double( 0.5000 ), + double( 0.5000 ), double( -0.4187 ), double( -0.0813 ) + }; + static const vnl_matrix< double > vM( M, 3, 3 ); + static const itk::Matrix< double, 3, 3 > iM( vM ); + + itk::Vector< double, 3 > rgb; + rgb[ 0 ] = double( r ); + rgb[ 1 ] = double( b ); + rgb[ 2 ] = double( g ); + rgb = iM * rgb; + + P out; + out[ 0 ] = TValue( rgb[ 0 ] ); + out[ 1 ] = TValue( rgb[ 1 ] ); + out[ 2 ] = TValue( rgb[ 2 ] ); + return( out ); + } + + template< class C > + TOutPixel operator()( const itk::RGBPixel< C >& rgb ) const + { + return( + this->operator()( + rgb.GetRed( ), rgb.GetGreen( ), rgb.GetBlue( ) + ) + ); + } + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RasterContourFilter.h b/lib/cpExtensions/Algorithms/RasterContourFilter.h new file mode 100644 index 0000000..4797dec --- /dev/null +++ b/lib/cpExtensions/Algorithms/RasterContourFilter.h @@ -0,0 +1,105 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__RasterContourFilter__h__ +#define __cpExtensions__Algorithms__RasterContourFilter__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TImage > + class RasterContourFilter + : public itk::ImageSource< _TImage > + { + public: + // Basic types + typedef RasterContourFilter Self; + typedef itk::ImageSource< _TImage > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TImage TImage; + typedef typename _TImage::IndexType TIndex; + typedef typename _TImage::PixelType TPixel; + typedef typename _TImage::PointType TPoint; + typedef typename _TImage::RegionType TRegion; + typedef itk::ImageBase< 2 > TImageBase; + + public: + itkNewMacro( Self ); + itkTypeMacro( RasterContourFilter, itk::ImageSource ); + + itkGetConstObjectMacro( Template, TImageBase ); + itkGetConstMacro( InsideValue, TPixel ); + itkGetConstMacro( OutsideValue, TPixel ); + + itkSetConstObjectMacro( Template, TImageBase ); + itkSetMacro( InsideValue, TPixel ); + itkSetMacro( OutsideValue, TPixel ); + + public: + void AddPoint( double x, double y ); + void AddPoint( double p[ 2 ] ); + template< class _TPoint > + inline void AddPoint( const _TPoint& p ); + void ClearPoints( ); + + protected: + RasterContourFilter( ); + virtual ~RasterContourFilter( ); + + virtual void AllocateOutputs( ) cpExtensions_OVERRIDE; + virtual void BeforeThreadedGenerateData( ) cpExtensions_OVERRIDE; + virtual void AfterThreadedGenerateData( ) cpExtensions_OVERRIDE; + virtual void ThreadedGenerateData( + const TRegion& region, itk::ThreadIdType id + ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + RasterContourFilter( const Self& ); + void operator=( const Self& ); + + protected: + std::deque< TPoint > m_Contour; + std::deque< TIndex > m_Polygon; + TRegion m_ROI; + typename TImageBase::ConstPointer m_Template; + TPixel m_InsideValue; + TPixel m_OutsideValue; + }; + + } // ecapseman + +} // ecapseman + +// ------------------------------------------------------------------------- +template< class _TImage > +template< class _TPoint > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +AddPoint( const _TPoint& p ) +{ + TPoint pnt; + pnt[ 0 ] = p[ 0 ]; + pnt[ 1 ] = p[ 2 ]; + this->m_Contour.push_back( pnt ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__RasterContourFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RasterContourFilter.hxx b/lib/cpExtensions/Algorithms/RasterContourFilter.hxx new file mode 100644 index 0000000..4e7539a --- /dev/null +++ b/lib/cpExtensions/Algorithms/RasterContourFilter.hxx @@ -0,0 +1,172 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------ + +// Inclusion test taken from: +// https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html + +#ifndef __cpExtensions__Algorithms__RasterContourFilter__hxx__ +#define __cpExtensions__Algorithms__RasterContourFilter__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +AddPoint( double x, double y ) +{ + TPoint pnt; + pnt[ 0 ] = x; + pnt[ 1 ] = y; + this->m_Contour.push_back( pnt ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +AddPoint( double p[ 2 ] ) +{ + TPoint pnt; + pnt[ 0 ] = p[ 0 ]; + pnt[ 1 ] = p[ 2 ]; + this->m_Contour.push_back( pnt ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +ClearPoints( ) +{ + this->m_Contour.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +RasterContourFilter( ) + : Superclass( ), + m_InsideValue( TPixel( 1 ) ), + m_OutsideValue( TPixel( 0 ) ) +{ + this->ClearPoints( ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +~RasterContourFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +AllocateOutputs( ) +{ + _TImage* out = this->GetOutput( 0 ); + out->SetSpacing( this->m_Template->GetSpacing( ) ); + out->SetRegions( this->m_Template->GetRequestedRegion( ) ); + out->SetOrigin( this->m_Template->GetOrigin( ) ); + out->SetDirection( this->m_Template->GetDirection( ) ); + out->Allocate( ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +BeforeThreadedGenerateData( ) +{ + // Keep just indices, not points + this->m_Polygon.clear( ); + _TImage* out = this->GetOutput( 0 ); + TIndex minIdx, maxIdx; + for( auto c = this->m_Contour.begin( ); c != this->m_Contour.end( ); ++c ) + { + TIndex idx; + out->TransformPhysicalPointToIndex( *c, idx ); + bool added = true; + if( this->m_Polygon.size( ) > 0 ) + { + if( this->m_Polygon.back( ) != idx ) + { + this->m_Polygon.push_back( idx ); + minIdx[ 0 ] = ( idx[ 0 ] < minIdx[ 0 ] )? idx[ 0 ]: minIdx[ 0 ]; + minIdx[ 1 ] = ( idx[ 1 ] < minIdx[ 1 ] )? idx[ 1 ]: minIdx[ 1 ]; + maxIdx[ 0 ] = ( idx[ 0 ] > maxIdx[ 0 ] )? idx[ 0 ]: maxIdx[ 0 ]; + maxIdx[ 1 ] = ( idx[ 1 ] > maxIdx[ 1 ] )? idx[ 1 ]: maxIdx[ 1 ]; + + } // fi + } + else + { + this->m_Polygon.push_back( idx ); + minIdx = maxIdx = idx; + + } // fi + + } // rof + + // Set ROI + typename _TImage::SizeType size; + size[ 0 ] = maxIdx[ 0 ] - minIdx[ 0 ] + 1; + size[ 1 ] = maxIdx[ 1 ] - minIdx[ 1 ] + 1; + this->m_ROI.SetIndex( minIdx ); + this->m_ROI.SetSize( size ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +AfterThreadedGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RasterContourFilter< _TImage >:: +ThreadedGenerateData( const TRegion& region, itk::ThreadIdType id ) +{ + long nVerts = this->m_Polygon.size( ); + _TImage* out = this->GetOutput( ); + itk::ImageRegionIteratorWithIndex< _TImage > iIt( out, region ); + for( iIt.GoToBegin( ); !iIt.IsAtEnd( ); ++iIt ) + { + TIndex p = iIt.GetIndex( ); + bool inside = false; + if( this->m_ROI.IsInside( p ) ) + { + long i, j; + for( i = 0, j = nVerts - 1; i < nVerts; j = i++ ) + { + TIndex pi = this->m_Polygon[ i ]; + TIndex pj = this->m_Polygon[ j ]; + double pi0 = double( pi[ 0 ] ); + double pi1 = double( pi[ 1 ] ); + double pj0 = double( pj[ 0 ] ); + double pj1 = double( pj[ 1 ] ); + double p0 = double( p[ 0 ] ); + double p1 = double( p[ 1 ] ); + double ji0 = pj0 - pi0; + double ji1 = pj1 - pi1; + double i1 = p1 - pi1; + if( + ( ( pi1 > p1 ) != ( pj1 > p1 ) ) && + ( p0 < ( ( ji0 * i1 ) / ji1 ) + pi0 ) + ) + inside = !inside; + + } // rof + + } // fi + iIt.Set( ( inside )? this->m_InsideValue: this->m_OutsideValue ); + + } // rof +} + +#endif // __cpExtensions__Algorithms__RasterContourFilter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h new file mode 100644 index 0000000..84102ad --- /dev/null +++ b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h @@ -0,0 +1,73 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__ +#define __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TImage > + class RegionOfInterestImageCalculator + : public itk::Object + { + public: + // Basic types + typedef RegionOfInterestImageCalculator Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TImage TImage; + typedef typename _TImage::IndexType TIndex; + typedef typename _TImage::PixelType TPixel; + + public: + itkNewMacro( Self ); + itkTypeMacro( RegionOfInterestImageCalculator, itkObject ); + + itkGetConstObjectMacro( Image, _TImage ); + itkGetConstMacro( BackgroundValue, TPixel ); + itkGetConstMacro( Minimum, TIndex ); + itkGetConstMacro( Maximum, TIndex ); + + itkSetConstObjectMacro( Image, _TImage ); + itkSetMacro( BackgroundValue, TPixel ); + + public: + void Compute( ); + + protected: + RegionOfInterestImageCalculator( ); + virtual ~RegionOfInterestImageCalculator( ); + + private: + // Purposely not implemented + RegionOfInterestImageCalculator( const Self& ); + void operator=( const Self& ); + + protected: + typename _TImage::ConstPointer m_Image; + TPixel m_BackgroundValue; + TIndex m_Minimum; + TIndex m_Maximum; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx new file mode 100644 index 0000000..fd7867f --- /dev/null +++ b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx @@ -0,0 +1,92 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::RegionOfInterestImageCalculator< _TImage >:: +Compute( ) +{ + typedef itk::ImageRegionConstIteratorWithIndex< _TImage > _TIterator; + typedef typename _TImage::RegionType _TRegion; + + if( this->m_Image.IsNotNull( ) ) + { + _TRegion region = this->m_Image->GetRequestedRegion( ); + TIndex minidx = region.GetIndex( ); + TIndex maxidx = minidx + region.GetSize( ); + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + maxidx[ d ] -= 1; + + bool first = true; + _TIterator i( this->m_Image, region ); + for( i.GoToBegin( ); !i.IsAtEnd( ); ++i ) + { + if( i.Get( ) != this->m_BackgroundValue ) + { + TIndex idx = i.GetIndex( ); + if( !first ) + { + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + { + minidx[ d ] = ( idx[ d ] < minidx[ d ] )? idx[ d ]: minidx[ d ]; + maxidx[ d ] = ( idx[ d ] > maxidx[ d ] )? idx[ d ]: maxidx[ d ]; + + } // rof + } + else + { + minidx = maxidx = idx; + first = false; + + } // fi + + } // fi + + } // rof + this->m_Minimum = minidx; + this->m_Maximum = maxidx; + } + else + { + this->m_Minimum.Fill( 0 ); + this->m_Maximum.Fill( 0 ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::RegionOfInterestImageCalculator< _TImage >:: +RegionOfInterestImageCalculator( ) + : Superclass( ), + m_BackgroundValue( TPixel( 0 ) ) +{ + this->m_Minimum.Fill( 0 ); + this->m_Maximum.Fill( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::RegionOfInterestImageCalculator< _TImage >:: +~RegionOfInterestImageCalculator( ) +{ +} + + +/* TODO + typename _TImage::ConstPointer m_Image; + TPixel m_BackgroundValue; + TIndex m_Minimum; + TIndex m_Maximum; + }; +*/ + +#endif // __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SkeletonReader.h b/lib/cpExtensions/Algorithms/SkeletonReader.h new file mode 100644 index 0000000..e1a3064 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SkeletonReader.h @@ -0,0 +1,85 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__SkeletonReader__h__ +#define __cpExtensions__Algorithms__SkeletonReader__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TSkeleton > + class SkeletonReader + : public itk::ProcessObject + { + public: + // Basic types + typedef SkeletonReader Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TSkeleton TSkeleton; + + public: + itkNewMacro( Self ); + itkTypeMacro( SkeletonReader, itk::ImageSource ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + TSkeleton* GetOutput( ); + TSkeleton* GetOutput( unsigned int i ); + + virtual void GraftOutput( itk::DataObject* out ); + virtual void GraftOutput( + const typename Superclass::DataObjectIdentifierType& key, + itk::DataObject* out + ); + virtual void GraftNthOutput( unsigned int i, itk::DataObject* out ); + virtual itk::DataObject::Pointer MakeOutput( + itk::ProcessObject::DataObjectPointerArraySizeType i + ) cpExtensions_OVERRIDE; + + virtual void Update( ) cpExtensions_OVERRIDE + { this->GenerateData( ); } + + protected: + SkeletonReader( ); + virtual ~SkeletonReader( ); + + virtual void GenerateData( ) cpExtensions_OVERRIDE; + + // Do nothing + virtual void GenerateOutputInformation( ) cpExtensions_OVERRIDE + { } + + private: + // Purposely not implemented + SkeletonReader( const Self& ); + void operator=( const Self& ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + +} // ecapseman + +// ------------------------------------------------------------------------- +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__SkeletonReader__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SkeletonReader.hxx b/lib/cpExtensions/Algorithms/SkeletonReader.hxx new file mode 100644 index 0000000..4235539 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SkeletonReader.hxx @@ -0,0 +1,176 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__SkeletonReader__hxx__ +#define __cpExtensions__Algorithms__SkeletonReader__hxx__ + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +_TSkeleton* cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +GetOutput( ) +{ + return( + itkDynamicCastInDebugMode< TSkeleton* >( this->GetPrimaryOutput( ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +_TSkeleton* cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +GetOutput( unsigned int i ) +{ + return( + itkDynamicCastInDebugMode< TSkeleton* >( + this->itk::ProcessObject::GetOutput( i ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +GraftOutput( itk::DataObject* out ) +{ + this->GraftNthOutput( 0, out ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +GraftOutput( + const typename Superclass::DataObjectIdentifierType& key, + itk::DataObject* out + ) +{ + if( out == NULL ) + { + itkExceptionMacro( + << "Requested to graft output that is a NULL pointer" + ); + + } // fi + itk::DataObject* output = this->itk::ProcessObject::GetOutput( key ); + output->Graft( out ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +GraftNthOutput( unsigned int i, itk::DataObject* out ) +{ + if( i >= this->GetNumberOfIndexedOutputs( ) ) + { + itkExceptionMacro( + << "Requested to graft output " << i + << " but this filter only has " + << this->GetNumberOfIndexedOutputs( ) + << " indexed Outputs." + ); + + } // fi + this->GraftOutput( this->MakeNameFromOutputIndex( i ), out ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +itk::DataObject::Pointer +cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +MakeOutput( itk::ProcessObject::DataObjectPointerArraySizeType i ) +{ + return( TSkeleton::New( ).GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +SkeletonReader( ) + : Superclass( ) +{ + typename TSkeleton::Pointer out = + static_cast< TSkeleton* >( this->MakeOutput( 0 ).GetPointer( ) ); + this->itk::ProcessObject::SetNumberOfRequiredInputs( 0 ); + this->itk::ProcessObject::SetNumberOfRequiredOutputs( 1 ); + this->itk::ProcessObject::SetNthOutput( 0, out.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +~SkeletonReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >:: +GenerateData( ) +{ + typedef typename TSkeleton::TPath _TPath; + typedef typename _TPath::TSpacing _TSpacing; + typedef typename _TPath::TPoint _TPoint; + typedef typename _TPath::TDirection _TDirection; + typedef typename _TPath::TContinuousIndex _TContinuousIndex; + + std::string buffer; + /* TODO + if( !( cpExtensions::Read( buffer, this->m_FileName ) ) ) + { + itkExceptionMacro( + << "Error reading skeleton from \"" << this->m_FileName << "\"" + ); + return; + + } // fi + */ + + std::istringstream in( buffer ); + unsigned int dim; + in >> dim; + if( dim != TSkeleton::Dimension ) + { + itkExceptionMacro( + << "Mismatched skeletons dimension: " << dim + << " != " << TSkeleton::Dimension + ); + return; + + } // fi + + TSkeleton* out = this->GetOutput( ); + unsigned long size; + in >> size; + while( size > 0 ) + { + _TSpacing spa; + _TPoint ori; + _TDirection dir; + for( unsigned int d = 0; d < dim; ++d ) + in >> spa[ d ]; + for( unsigned int d = 0; d < dim; ++d ) + in >> ori[ d ]; + for( unsigned int d = 0; d < dim; ++d ) + for( unsigned int e = 0; e < dim; ++e ) + in >> dir[ d ][ e ]; + + typename _TPath::Pointer path = _TPath::New( ); + path->SetSpacing( spa ); + path->SetOrigin( ori ); + path->SetDirection( dir ); + for( unsigned long s = 0; s < size; ++s ) + { + _TContinuousIndex idx; + for( unsigned int d = 0; d < dim; ++d ) + in >> idx[ d ]; + path->AddVertex( idx ); + + } // rof + out->AddBranch( path ); + in >> size; + + } // elihw +} + +#endif // __cpExtensions__Algorithms__SkeletonReader__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SkeletonToImageFilter.h b/lib/cpExtensions/Algorithms/SkeletonToImageFilter.h new file mode 100644 index 0000000..8c9d8fe --- /dev/null +++ b/lib/cpExtensions/Algorithms/SkeletonToImageFilter.h @@ -0,0 +1,81 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__SkeletonToImageFilter__h__ +#define __cpExtensions__Algorithms__SkeletonToImageFilter__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TSkeleton, class _TImage > + class SkeletonToImageFilter + : public itk::ImageSource< _TImage > + { + public: + // Basic types + typedef SkeletonToImageFilter Self; + typedef itk::ImageSource< _TImage > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TSkeleton TSkeleton; + typedef _TImage TImage; + typedef typename _TImage::IndexType TIndex; + typedef typename _TImage::PixelType TPixel; + typedef typename _TImage::PointType TPoint; + typedef typename _TImage::RegionType TRegion; + typedef itk::ImageBase< _TImage::ImageDimension > TImageBase; + + public: + itkNewMacro( Self ); + itkTypeMacro( SkeletonToImageFilter, itk::ImageSource ); + + itkGetConstMacro( InsideValue, TPixel ); + itkGetConstMacro( OutsideValue, TPixel ); + + itkSetMacro( InsideValue, TPixel ); + itkSetMacro( OutsideValue, TPixel ); + + public: + const TImageBase* GetTemplateImage( ) const; + void SetTemplateImage( const TImageBase* image ); + + const TSkeleton* GetSkeleton( ) const; + void SetSkeleton( const TSkeleton* skeleton ); + + protected: + SkeletonToImageFilter( ); + virtual ~SkeletonToImageFilter( ); + + virtual void GenerateData( ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + SkeletonToImageFilter( const Self& ); + void operator=( const Self& ); + + protected: + TPixel m_InsideValue; + TPixel m_OutsideValue; + }; + + } // ecapseman + +} // ecapseman + +// ------------------------------------------------------------------------- +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__SkeletonToImageFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SkeletonToImageFilter.hxx b/lib/cpExtensions/Algorithms/SkeletonToImageFilter.hxx new file mode 100644 index 0000000..1f428c9 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SkeletonToImageFilter.hxx @@ -0,0 +1,119 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__SkeletonToImageFilter__hxx__ +#define __cpExtensions__Algorithms__SkeletonToImageFilter__hxx__ + +// ------------------------------------------------------------------------- +template< class _TSkeleton, class _TImage > +const typename +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +TImageBase* +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +GetTemplateImage( ) const +{ + return( + dynamic_cast< const TImageBase* >( + this->itk::ProcessObject::GetInput( 0 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton, class _TImage > +void +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +SetTemplateImage( const TImageBase* image ) +{ + this->itk::ProcessObject::SetNthInput( + 0, const_cast< TImageBase* >( image ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton, class _TImage > +const typename +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +TSkeleton* +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +GetSkeleton( ) const +{ + return( + dynamic_cast< const TSkeleton* >( + this->itk::ProcessObject::GetInput( 1 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton, class _TImage > +void +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +SetSkeleton( const TSkeleton* skeleton ) +{ + this->itk::ProcessObject::SetNthInput( + 1, const_cast< TSkeleton* >( skeleton ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton, class _TImage > +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +SkeletonToImageFilter( ) + : Superclass( ), + m_InsideValue( TPixel( 1 ) ), + m_OutsideValue( TPixel( 0 ) ) +{ + this->SetNumberOfRequiredInputs( 2 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton, class _TImage > +cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +~SkeletonToImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton, class _TImage > +void cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >:: +GenerateData( ) +{ + const TSkeleton* sk = this->GetSkeleton( ); + const TImageBase* im = this->GetTemplateImage( ); + TImage* out = this->GetOutput( 0 ); + + out->SetLargestPossibleRegion( im->GetLargestPossibleRegion( ) ); + out->SetRequestedRegion( im->GetRequestedRegion( ) ); + out->SetBufferedRegion( im->GetBufferedRegion( ) ); + out->SetSpacing( im->GetSpacing( ) ); + out->SetOrigin( im->GetOrigin( ) ); + out->SetDirection( im->GetDirection( ) ); + out->Allocate( ); + out->FillBuffer( this->m_OutsideValue ); + + // Fill skeleton + auto mIt = sk->BeginEdgesRows( ); + for( ; mIt != sk->EndEdgesRows( ); ++mIt ) + { + auto rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + auto eIt = rIt->second.begin( ); + for( ; eIt != rIt->second.end( ); ++eIt ) + { + auto path = *eIt; + for( unsigned int i = 0; i < path->GetSize( ); ++i ) + out->SetPixel( path->GetVertex( i ), this->m_InsideValue ); + + } // rof + + } // rof + + } // rof +} + +#endif // __cpExtensions__Algorithms__SkeletonToImageFilter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SkeletonWriter.h b/lib/cpExtensions/Algorithms/SkeletonWriter.h new file mode 100644 index 0000000..3112693 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SkeletonWriter.h @@ -0,0 +1,69 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__SkeletonWriter__h__ +#define __cpExtensions__Algorithms__SkeletonWriter__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TSkeleton > + class SkeletonWriter + : public itk::ProcessObject + { + public: + // Basic types + typedef SkeletonWriter Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TSkeleton TSkeleton; + + public: + itkNewMacro( Self ); + itkTypeMacro( SkeletonWriter, itk::ImageSource ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + const TSkeleton* GetInput( ) const; + void SetInput( const TSkeleton* skeleton ); + virtual void Update( ) cpExtensions_OVERRIDE; + + protected: + SkeletonWriter( ); + virtual ~SkeletonWriter( ); + + virtual void GenerateData( ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + SkeletonWriter( const Self& ); + void operator=( const Self& ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + +} // ecapseman + +// ------------------------------------------------------------------------- +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__SkeletonWriter__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SkeletonWriter.hxx b/lib/cpExtensions/Algorithms/SkeletonWriter.hxx new file mode 100644 index 0000000..76e05c1 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SkeletonWriter.hxx @@ -0,0 +1,127 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__SkeletonWriter__hxx__ +#define __cpExtensions__Algorithms__SkeletonWriter__hxx__ + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +const _TSkeleton* cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >:: +GetInput( ) const +{ + return( + dynamic_cast< const TSkeleton* >( + this->itk::ProcessObject::GetInput( 0 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >:: +SetInput( const _TSkeleton* skeleton ) +{ + this->itk::ProcessObject::SetNthInput( + 0, const_cast< TSkeleton* >( skeleton ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >:: +Update( ) +{ + TSkeleton* input = const_cast< TSkeleton* >( this->GetInput( ) ); + if( input != NULL ) + { + input->UpdateOutputInformation( ); + input->UpdateOutputData( ); + this->GenerateData( ); + this->ReleaseInputs( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >:: +SkeletonWriter( ) + : Superclass( ), + m_FileName( "" ) +{ + this->SetNumberOfRequiredInputs( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >:: +~SkeletonWriter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >:: +GenerateData( ) +{ + const TSkeleton* sk = this->GetInput( ); + std::stringstream out; + out << TSkeleton::Dimension << std::endl; + + // Write + auto mIt = sk->BeginEdgesRows( ); + for( ; mIt != sk->EndEdgesRows( ); ++mIt ) + { + auto rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + auto eIt = rIt->second.begin( ); + for( ; eIt != rIt->second.end( ); ++eIt ) + { + auto path = *eIt; + unsigned int size = path->GetSize( ); + auto spa = path->GetSpacing( ); + auto ori = path->GetOrigin( ); + auto dir = path->GetDirection( ); + out << size << std::endl; + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out << spa[ d ] << " "; + out << std::endl; + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out << ori[ d ] << " "; + out << std::endl; + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + for( unsigned int e = 0; e < TSkeleton::Dimension; ++e ) + out << dir[ d ][ e ] << " "; + out << std::endl; + + for( unsigned int i = 0; i < path->GetSize( ); ++i ) + { + auto v = path->GetVertex( i ); + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out << v[ d ] << " "; + + } // rof + out << std::endl; + + } // rof + + } // rof + + } // rof + out << "0" << std::endl; + + /* TODO + if( !( cpExtensions::Write( out.str( ), this->m_FileName ) ) ) + itkExceptionMacro( + << "Unable to write skeleton to \"" + << this->m_FileName + << "\"" + ); + */ +} + +#endif // __cpExtensions__Algorithms__SkeletonWriter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h new file mode 100644 index 0000000..2b81fb7 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h @@ -0,0 +1,87 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I, class O = I > + class SpatialObjectMaskImageFilter + : public itk::ImageToImageFilter< I, O > + { + public: + typedef SpatialObjectMaskImageFilter Self; + typedef itk::ImageToImageFilter< I, O > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef I TInputImage; + typedef O TOutputImage; + + itkStaticConstMacro( InputDimension, unsigned int, I::ImageDimension ); + itkStaticConstMacro( OutputDimension, unsigned int, O::ImageDimension ); + +#ifdef ITK_USE_CONCEPT_CHECKING + itkConceptMacro( + SameDimensionCheck1, + ( itk::Concept::SameDimension< InputDimension, OutputDimension > ) + ); +#endif + + typedef typename I::RegionType TRegion; + typedef typename O::PixelType TOutPixel; + typedef itk::SpatialObject< InputDimension > TSpatialObject; + + public: + itkNewMacro( Self ); + itkTypeMacro( SpatialObjectMaskImageFilter, itk::ImageToImageFilter ); + + itkGetObjectMacro( SpatialObject, TSpatialObject ); + itkGetConstObjectMacro( SpatialObject, TSpatialObject ); + itkGetConstMacro( OutsideValue, TOutPixel ); + + itkSetObjectMacro( SpatialObject, TSpatialObject ); + itkSetMacro( OutsideValue, TOutPixel ); + + public: + O* GetPositiveOutput( ); + const O* GetPositiveOutput( ) const; + O* GetNegativeOutput( ); + const O* GetNegativeOutput( ) const; + + protected: + SpatialObjectMaskImageFilter( ); + virtual ~SpatialObjectMaskImageFilter( ); + + virtual void GenerateOutputInformation( ); + virtual void ThreadedGenerateData( + const TRegion& region, itk::ThreadIdType threadId + ); + + private: + // Purposely not implemented. + SpatialObjectMaskImageFilter( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TSpatialObject::Pointer m_SpatialObject; + TOutPixel m_OutsideValue; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx new file mode 100644 index 0000000..2c3cac7 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx @@ -0,0 +1,136 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class I, class O > +O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +GetPositiveOutput( ) +{ + return( this->GetOutput( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +const O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +GetPositiveOutput( ) const +{ + return( this->GetOutput( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +GetNegativeOutput( ) +{ + return( this->GetOutput( 1 ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +const O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +GetNegativeOutput( ) const +{ + return( this->GetOutput( 1 ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +SpatialObjectMaskImageFilter( ) + : Superclass( ) +{ + this->SetNumberOfRequiredInputs( 1 ); + this->SetNumberOfRequiredOutputs( 2 ); + this->SetNthOutput( 0, O::New( ) ); + this->SetNthOutput( 1, O::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +~SpatialObjectMaskImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +GenerateOutputInformation( ) +{ + const I* in = + dynamic_cast< const I* >( this->itk::ProcessObject::GetInput( 0 ) ); + for( unsigned int idx = 0; idx < this->GetNumberOfOutputs( ); ++idx ) + { + itk::DataObject* out = this->GetOutput( idx ); + if( out ) + out->CopyInformation( in ); + + } // rof +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >:: +ThreadedGenerateData( const TRegion& region, itk::ThreadIdType threadId ) +{ + if( this->m_SpatialObject.IsNull( ) ) + { + itkGenericExceptionMacro( << "No itk::SpatialObject given." ); + return; + + } // fi + + // Get inputs + const I* in = + dynamic_cast< const I* >( this->itk::ProcessObject::GetInput( 0 ) ); + O* pos_out = this->GetPositiveOutput( ); + O* neg_out = this->GetNegativeOutput( ); + const auto size0 = region.GetSize( 0 ); + if( size0 == 0 ) + return; + const auto nLines = region.GetNumberOfPixels( ) / size0; + + // Create iterators + itk::ImageScanlineConstIterator< I > iIt( in, region ); + itk::ImageScanlineIterator< O > pos_oIt( pos_out, region ); + itk::ImageScanlineIterator< O > neg_oIt( neg_out, region ); + itk::ProgressReporter progress( this, threadId, nLines ); + + // Main loop + typename TSpatialObject::PointType pnt; + while( !iIt.IsAtEnd( ) ) + { + while( !iIt.IsAtEndOfLine( ) ) + { + auto idx = iIt.GetIndex( ); + in->TransformIndexToPhysicalPoint( idx, pnt ); + if( this->m_SpatialObject->IsInside( pnt ) ) + { + pos_oIt.Set( TOutPixel( iIt.Get( ) ) ); + neg_oIt.Set( this->m_OutsideValue ); + } + else + { + neg_oIt.Set( TOutPixel( iIt.Get( ) ) ); + pos_oIt.Set( this->m_OutsideValue ); + + } // fi + ++iIt; + ++pos_oIt; + ++neg_oIt; + + } // elihw + iIt.NextLine( ); + pos_oIt.NextLine( ); + neg_oIt.NextLine( ); + progress.CompletedPixel( ); + + } // elihw +} + +#endif // __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h new file mode 100644 index 0000000..7de8b66 --- /dev/null +++ b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h @@ -0,0 +1,102 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + namespace Functor + { + /** + */ + template< typename _TInput > + class UnaryThreshold + { + public: + UnaryThreshold( ); + virtual ~UnaryThreshold( ); + + const _TInput& GetThreshold( ) const; + const _TInput& GetInsideValue( ) const; + const _TInput& GetOutsideValue( ) const; + const bool& GetStrict( ) const; + + void StrictOn( ); + void StrictOff( ); + void SetStrict( bool s ); + void SetThreshold( const _TInput& thresh ); + void SetInsideValue( const _TInput& value ); + void SetOutsideValue( const _TInput& value ); + bool operator!=( const UnaryThreshold& other ) const; + bool operator==( const UnaryThreshold& other ) const; + _TInput operator()( const _TInput& A ) const; + + private: + _TInput m_Threshold; + _TInput m_InsideValue; + _TInput m_OutsideValue; + bool m_Strict; + }; + } + + /** + */ + template< class _TImage > + class UnaryThresholdImageFilter + : public itk::UnaryFunctorImageFilter< _TImage, _TImage, cpExtensions::Algorithms::Functor::UnaryThreshold< typename _TImage::PixelType > > + { + public: + // Basic types + typedef typename _TImage::PixelType TPixel; + typedef cpExtensions::Algorithms::Functor::UnaryThreshold< TPixel > TFunctor; + typedef itk::UnaryFunctorImageFilter< _TImage, _TImage, TFunctor > Superclass; + typedef UnaryThresholdImageFilter Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TImage TImage; + + public: + itkNewMacro( Self ); + itkTypeMacro( UnaryThresholdImageFilter, itkUnaryFunctorImageFilter ); + + public: + const TPixel& GetThreshold( ) const; + const TPixel& GetInsideValue( ) const; + const TPixel& GetOutsideValue( ) const; + const bool& GetStrict( ) const; + + void StrictOn( ); + void StrictOff( ); + void SetStrict( bool s ); + void SetThreshold( const TPixel& thresh ); + void SetInsideValue( const TPixel& value ); + void SetOutsideValue( const TPixel& value ); + + protected: + UnaryThresholdImageFilter( ); + virtual ~UnaryThresholdImageFilter( ); + + private: + // Purposely not implemented + UnaryThresholdImageFilter( const Self& ); + void operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx new file mode 100644 index 0000000..ff85edd --- /dev/null +++ b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx @@ -0,0 +1,245 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__HXX__ + +// ------------------------------------------------------------------------- +template< typename _TInput > +cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +UnaryThreshold( ) + : m_Strict( false ) +{ + this->m_Threshold = itk::NumericTraits< _TInput >::NonpositiveMin( ); + this->m_OutsideValue = itk::NumericTraits< _TInput >::ZeroValue( ); + this->m_InsideValue = itk::NumericTraits< _TInput >::max( ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +~UnaryThreshold( ) +{ +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +const _TInput& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +GetThreshold( ) const +{ + return( this->m_Threshold ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +const _TInput& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +GetInsideValue( ) const +{ + return( this->m_InsideValue ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +const _TInput& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +GetOutsideValue( ) const +{ + return( this->m_OutsideValue ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +const bool& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +GetStrict( ) const +{ + return( this->m_Strict ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +StrictOn( ) +{ + this->SetStrict( true ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +StrictOff( ) +{ + this->SetStrict( false ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +SetStrict( bool s ) +{ + this->m_Strict = s; +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +SetThreshold( const _TInput& thresh ) +{ + this->m_Threshold = thresh; +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +SetInsideValue( const _TInput& value ) +{ + this->m_InsideValue = value; +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +SetOutsideValue( const _TInput& value ) +{ + this->m_OutsideValue = value; +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +bool cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +operator!=( const UnaryThreshold& other ) const +{ + return( + this->m_Threshold != other.m_Threshold || + itk::Math::NotExactlyEquals( this->m_InsideValue, other.m_InsideValue ) || + itk::Math::NotExactlyEquals( this->m_OutsideValue, other.m_OutsideValue ) + ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +bool cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +operator==( const UnaryThreshold& other ) const +{ + return( !( *this != other ) ); +} + +// ------------------------------------------------------------------------- +template< typename _TInput > +_TInput cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >:: +operator()( const _TInput& A ) const +{ + if( this->m_Strict ) + { + if( this->m_Threshold < A ) + return( this->m_InsideValue ); + return( this->m_OutsideValue ); + } + else + { + if( this->m_Threshold <= A ) + return( this->m_InsideValue ); + return( this->m_OutsideValue ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TImage > +const typename cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +TPixel& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +GetThreshold( ) const +{ + return( this->GetFunctor( ).GetThreshold( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +const typename cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +TPixel& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +GetInsideValue( ) const +{ + return( this->GetFunctor( ).GetInsideValue( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +const typename cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +TPixel& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +GetOutsideValue( ) const +{ + return( this->GetFunctor( ).GetOutsideValue( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +const bool& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +GetStrict( ) const +{ + return( this->GetFunctor( ).GetStrict( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +StrictOn( ) +{ + this->GetFunctor( ).SetStrict( true ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +StrictOff( ) +{ + this->GetFunctor( ).SetStrict( false ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +SetStrict( bool s ) +{ + this->GetFunctor( ).SetStrict( s ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +SetThreshold( const TPixel& thresh ) +{ + this->GetFunctor( ).SetThreshold( thresh ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +SetInsideValue( const TPixel& value ) +{ + this->GetFunctor( ).SetInsideValue( value ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +SetOutsideValue( const TPixel& value ) +{ + this->GetFunctor( ).SetOutsideValue( value ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +UnaryThresholdImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > +cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >:: +~UnaryThresholdImageFilter( ) +{ +} + +#endif // __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Config.h.in b/lib/cpExtensions/Config.h.in new file mode 100644 index 0000000..4585244 --- /dev/null +++ b/lib/cpExtensions/Config.h.in @@ -0,0 +1,70 @@ +#ifndef __cpExtensions__Config__h__ +#define __cpExtensions__Config__h__ + +#include + +/* + * ========================================================================= + * Identify OS + * ========================================================================= + */ +#define cpExtensions_OS_@CMAKE_SYSTEM_NAME@ + +/* + * ========================================================================= + * Some global values + * ========================================================================= + */ +#define cpExtensions_QT4_@QT4_FOUND@ +#ifdef cpExtensions_QT4_TRUE +# ifndef cpExtensions_QT4 +# define cpExtensions_QT4 +# endif // cpExtensions_QT4 +# define cpExtensions_QVTKWidget @cpPlugins_Qt4_VTKWidget@ +# include <@cpPlugins_Qt4_VTKWidget@.h> +#else // cpExtensions_QT4_TRUE +# undef cpExtensions_QT4 +#endif // cpExtensions_QT4_TRUE + +/* + * ========================================================================= + * Version numbers and strings + * ========================================================================= + */ + +#define cpExtensions_MAJOR_VERSION @prj_MAJOR_VERSION@ +#define cpExtensions_MINOR_VERSION @prj_MINOR_VERSION@ +#define cpExtensions_RELEASE_VERSION @prj_RELEASE_VERSION@ +#define cpExtensions_VERSION "@prj_VERSION@" +#define cpExtensions_SHORT_VERSION "@prj_SHORT_VERSION@" + +/* + * ========================================================================= + * Language related macros + * ========================================================================= + */ + +#if __cplusplus >= 201103L +# define cpExtensions_OVERRIDE override +# define cpExtensions_DELETE_FUNCTION =delete +# define cpExtensions_NULLPTR nullptr +# define cpExtensions_NOEXCEPT noexcept +# define cpExtensions_HAS_CXX11_STATIC_ASSERT +# define cpExtensions_HAS_CXX11_RVREF +#else +# define cpExtensions_OVERRIDE +# define cpExtensions_DELETE_FUNCTION +# define cpExtensions_NULLPTR NULL +# define cpExtensions_NOEXCEPT throw() +#endif + +// ------------------------------------------------------------------------- +#ifdef cpExtensions_OS_Windows +# define cpExtensions_SPRINTF( B, S, O ) sprintf_s( B, S, "%s", O ); +#else // cpExtensions_OS_Windows +# define cpExtensions_SPRINTF( B, S, O ) std::sprintf( B, "%s", O ); +#endif // cpExtensions_OS_Windows + +#endif // __cpExtensions__Config__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Graph.h b/lib/cpExtensions/DataStructures/Graph.h new file mode 100644 index 0000000..d9e913d --- /dev/null +++ b/lib/cpExtensions/DataStructures/Graph.h @@ -0,0 +1,166 @@ +#ifndef __cpExtensions__DataStructures__Graph__h__ +#define __cpExtensions__DataStructures__Graph__h__ + +#include +#include +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** \brief A generic graph with templated index types. + * + * @param _TVertex Vertex type. + * @param _TCost Cost type. + * @param _TIndex Index type (it should be a strict weak ordering type). + */ + template< class _TVertex, class _TCost, class _TIndex = unsigned long, class _TIndexCompare = std::less< _TIndex > > + class Graph + : public itk::DataObject + { + public: + typedef Graph Self; + typedef itk::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef _TCost TCost; + typedef _TIndex TIndex; + typedef _TIndexCompare TIndexCompare; + + // Base types + typedef std::map< TIndex, TVertex, TIndexCompare > TVertices; + typedef std::vector< TCost > TEdges; + typedef std::map< TIndex, TEdges, TIndexCompare > TMatrixRow; + typedef std::map< TIndex, TMatrixRow, TIndexCompare > TMatrix; + + public: + itkNewMacro( Self ); + itkTypeMacro( Graph, itk::DataObject ); + + public: + /*! \brief Iterators over vertices. + * These allow you to iterate over all of graph's vertices. + * + * Typical iteration should be done as: + * + * TGraph g; + * ... + * TGraph::TVertices::[const_]iterator vIt = g.BeginVertices( ); + * for( ; vIt != g.EndVertices( ); ++vIt ) + * { + * vIt->first; --> this is the vertex's index <-- + * vIt->second; --> this is the vertex's value <-- + * } + */ + inline typename TVertices::iterator BeginVertices( ) + { return( this->m_Vertices.begin( ) ); } + inline typename TVertices::iterator EndVertices( ) + { return( this->m_Vertices.end( ) ); } + inline typename TVertices::const_iterator BeginVertices( ) const + { return( this->m_Vertices.begin( ) ); } + inline typename TVertices::const_iterator EndVertices( ) const + { return( this->m_Vertices.end( ) ); } + + /*! \brief Iterators over edges. + * These allow you to iterate over all of graph's edges. + * + * Typical iteration should be done as: + * + * TGraph g; + * ... + * TGraph::TMatrix::[const_]iterator mIt = g.BeginEdgesRows( ); + * for( ; mIt != g.EndEdgesRows( ); ++mIt ) + * { + * mIt->first; --> this is the row index. <-- + * TGraph::TMatrixRow::[const_]iterator rIt = mIt->second.begin( ); + * for( ; rIt != mIt->second.end( ); ++rIt ) + * { + * rIt->first; --> this is the column index. + * TGraph::TEdges::[const_]iterator eIt = rIt->second.begin( ); + * for( ; eIt != rIt->second.end( ); ++eIt ) + * *eIt; --> this is the cost between mIt->first and rIt->first + * } + * } + */ + inline typename TMatrix::iterator BeginEdgesRows( ) + { return( this->m_Matrix.begin( ) ); } + inline typename TMatrix::iterator EndEdgetsRows( ) + { return( this->m_Matrix.end( ) ); } + inline typename TMatrix::const_iterator BeginEdgesRows( ) const + { return( this->m_Matrix.begin( ) ); } + inline typename TMatrix::const_iterator EndEdgesRows( ) const + { return( this->m_Matrix.end( ) ); } + + /*! \brief Clear all vertices and edges. + */ + void Clear( ); + + /*! \brief Clear all edges. + */ + inline void ClearEdges( ) + { this->m_Matrix.clear( ); } + + /*! \brief Vertex manipulation methods. + * Names are self-explanatory. + */ + inline bool HasVertexIndex( const TIndex& i ) const + { return( this->m_Vertices.find( i ) != this->m_Vertices.end( ) ); } + inline void SetVertex( const TIndex& index, TVertex& vertex ) + { this->m_Vertices[ index ] = vertex; } + inline TVertex& GetVertex( const TIndex& index ) + { return( this->m_Vertices[ index ] ); } + inline const TVertex& GetVertex( const TIndex& index ) const + { return( this->m_Vertices[ index ] ); } + bool RenameVertex( const TIndex& old_index, const TIndex& new_index ); + void RemoveVertex( const TIndex& index ); + + /*! \brief Edge manipulation methods. + * Names are self-explanatory. + */ + inline void AddEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ) + { this->m_Matrix[ orig ][ dest ].push_back( cost ); } + TEdges& GetEdges( const TIndex& orig, const TIndex& dest ); + const TEdges& GetEdges( const TIndex& orig, const TIndex& dest ) const; + bool HasEdge( const TIndex& orig, const TIndex& dest ) const; + void RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ); + void RemoveEdges( const TIndex& orig, const TIndex& dest ); + + /*! \brief Returns graph's sinks. + * + * A sink is a special vertex which does not have any "exiting" edges. + * + * @return Sinks ordered by their index. + */ + std::set< TIndex, TIndexCompare > GetSinks( ) const; + + protected: + Graph( ); + virtual ~Graph( ); + + private: + // Purposely not implemented + Graph( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TVertices m_Vertices; + TMatrix m_Matrix; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__DataStructures__Graph__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Graph.hxx b/lib/cpExtensions/DataStructures/Graph.hxx new file mode 100644 index 0000000..62c6b75 --- /dev/null +++ b/lib/cpExtensions/DataStructures/Graph.hxx @@ -0,0 +1,267 @@ +#ifndef __cpExtensions__DataStructures__Graph__hxx__ +#define __cpExtensions__DataStructures__Graph__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +Clear( ) +{ + this->m_Vertices.clear( ); + this->m_Matrix.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +bool cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RenameVertex( const TIndex& old_index, const TIndex& new_index ) +{ + auto old_v = this->m_Vertices.find( old_index ); + auto new_v = this->m_Vertices.find( new_index ); + if( old_v != this->m_Vertices.end( ) && new_v == this->m_Vertices.end( ) ) + { + // Replace vertex + this->m_Vertices[ new_index ] = old_v->second; + this->m_Vertices.erase( old_index ); + + // Duplicate edges + auto mIt = this->m_Matrix.begin( ); + auto found_row = this->m_Matrix.end( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + if( mIt->first == old_index ) + found_row = mIt; + + auto rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + if( mIt->first == old_index ) + this->m_Matrix[ new_index ][ rIt->first ] = rIt->second; + else if( rIt->first == old_index ) + this->m_Matrix[ mIt->first ][ new_index ] = rIt->second; + + } // rof + + } // rof + + // Delete old edges + if( found_row != this->m_Matrix.end( ) ) + this->m_Matrix.erase( found_row ); + + mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + auto rIt = mIt->second.begin( ); + while( rIt != mIt->second.end( ) ) + { + if( rIt->first == old_index ) + { + mIt->second.erase( rIt ); + rIt = mIt->second.begin( ); + } + else + ++rIt; + + } // elihw + + } // rof + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveVertex( const TIndex& index ) +{ + auto i = this->m_Vertices.find( index ); + if( i != this->m_Vertices.end( ) ) + { + // Delete vertex + this->m_Vertices.erase( i ); + + // Delete edges starting from given vertex + auto mIt = this->m_Matrix.find( index ); + if( mIt != this->m_Matrix.end( ) ) + this->m_Matrix.erase( mIt ); + + // Delete edges arriving to given vertex + mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + auto rIt = mIt->second.begin( ); + while( rIt != mIt->second.end( ) ) + { + if( rIt->first == index ) + { + mIt->second.erase( rIt ); + rIt = mIt->second.begin( ); + } + else + ++rIt; + + } // elihw + + } // rof + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +typename +cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +TEdges& +cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetEdges( const TIndex& orig, const TIndex& dest ) +{ + static TEdges null_edges; + auto o = this->m_Matrix.find( orig ); + if( o != this->m_Matrix.find( orig ) ) + { + auto d = o->second.find( dest ); + if( d == o->second.end( ) ) + { + null_edges.clear( ); + return( null_edges ); + } + else + return( d->second ); + } + else + { + null_edges.clear( ); + return( null_edges ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +const typename +cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +TEdges& +cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetEdges( const TIndex& orig, const TIndex& dest ) const +{ + static const TEdges null_edges; + auto o = this->m_Matrix.find( orig ); + if( o != this->m_Matrix.find( orig ) ) + { + auto d = o->second.find( dest ); + if( d == o->second.end( ) ) + return( null_edges ); + else + return( d->second ); + } + else + return( null_edges ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +bool cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +HasEdge( const TIndex& orig, const TIndex& dest ) const +{ + auto mIt = this->m_Matrix.find( orig ); + if( mIt != this->m_Matrix.end( ) ) + return( mIt->second.find( dest ) != mIt->second.end( ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ) +{ + auto m = this->m_Matrix.find( orig ); + if( m != this->m_Matrix.end( ) ) + { + auto r = m->second.find( dest ); + if( r != m->second.end( ) ) + { + auto e = r->second.end( ); + for( + auto i = r->second.begin( ); + i != r->second.end( ) && e == r->second.end( ); + ++i + ) + if( *i == cost ) + e = i; + if( e != r->second.end( ) ) + { + r->second.erase( e ); + if( r->second.size( ) == 0 ) + { + m->second.erase( r ); + if( m->second.size( ) == 0 ) + this->m_Matrix.erase( m ); + + } // fi + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveEdges( const TIndex& orig, const TIndex& dest ) +{ + auto m = this->m_Matrix.find( orig ); + if( m != this->m_Matrix.end( ) ) + { + auto r = m->second.find( dest ); + if( r != m->second.end( ) ) + { + m->second.erase( r ); + if( m->second.size( ) == 0 ) + this->m_Matrix.erase( m ); + + } // fi + + } // fi + +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +std::set< _TIndex, _TIndexCompare > +cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetSinks( ) const +{ + std::set< _TIndex, _TIndexCompare > sinks; + + auto vIt = this->m_Vertices.begin( ); + for( ; vIt != this->m_Vertices.end( ); ++vIt ) + sinks.insert( vIt->first ); + auto mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + sinks.erase( mIt->first ); + + return( sinks ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +Graph( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +~Graph( ) +{ +} + +#endif // __cpExtensions__DataStructures__Graph__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/PolyLineParametricPath.h b/lib/cpExtensions/DataStructures/PolyLineParametricPath.h new file mode 100644 index 0000000..7f12200 --- /dev/null +++ b/lib/cpExtensions/DataStructures/PolyLineParametricPath.h @@ -0,0 +1,100 @@ +#ifndef __cpExtensions__DataStructures__PolyLineParametricPath__h__ +#define __cpExtensions__DataStructures__PolyLineParametricPath__h__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< unsigned int _VDim > + class PolyLineParametricPath + : public itk::PolyLineParametricPath< _VDim > + { + public: + typedef PolyLineParametricPath Self; + typedef itk::PolyLineParametricPath< _VDim > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef itk::ImageBase< _VDim > TImageBase; + typedef typename TImageBase::SpacingType TSpacing; + typedef typename TImageBase::PointType TPoint; + typedef typename TImageBase::DirectionType TDirection; + typedef typename Superclass::ContinuousIndexType TContinuousIndex; + typedef typename TContinuousIndex::IndexType TIndex; + + typedef typename TPoint::VectorType TVector; + typedef cpExtensions::Algorithms::BezierCurveFunction< TVector > TBezier; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPath, itk::PolyLineParametricPath ); + + itkGetConstReferenceMacro( Spacing, TSpacing ); + itkGetConstReferenceMacro( Origin, TPoint ); + itkGetConstReferenceMacro( Direction, TDirection ); + itkGetConstReferenceMacro( InverseDirection, TDirection ); + + itkSetMacro( Origin, TPoint ); + + public: + void AddVertex( const TContinuousIndex& vertex ); + unsigned long GetSize( ) const; + TContinuousIndex GetContinuousVertex( unsigned long i ) const; + TIndex GetVertex( unsigned long i ) const; + TPoint GetPoint( unsigned long i ) const; + TPoint GetSmoothPoint( double u ) const; + + virtual void SetSpacing( const TSpacing& spac ); + virtual void SetSpacing( const double spac[ _VDim ] ); + virtual void SetSpacing( const float spac[ _VDim ] ); + virtual void SetOrigin( const double ori[ _VDim ] ); + virtual void SetOrigin( const float ori[ _VDim ] ); + virtual void SetDirection( const TDirection& dir ); + + template< class _TRefImage > + inline void SetReferenceImage( const _TRefImage* image ) + { + this->SetSpacing( image->GetSpacing( ) ); + this->SetOrigin( image->GetOrigin( ) ); + this->SetDirection( image->GetDirection( ) ); + } + + protected: + PolyLineParametricPath( ); + virtual ~PolyLineParametricPath( ); + + virtual void _ComputeIndexToPhysicalPointMatrices( ); + + private: + // Purposely not implemented + PolyLineParametricPath( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TBezier::Pointer m_Bezier; + + TSpacing m_Spacing; + TPoint m_Origin; + TDirection m_Direction; + TDirection m_InverseDirection; + TDirection m_IndexToPhysicalPoint; + TDirection m_PhysicalPointToIndex; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__DataStructures__PolyLineParametricPath__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/PolyLineParametricPath.hxx b/lib/cpExtensions/DataStructures/PolyLineParametricPath.hxx new file mode 100644 index 0000000..635c8b7 --- /dev/null +++ b/lib/cpExtensions/DataStructures/PolyLineParametricPath.hxx @@ -0,0 +1,215 @@ +#ifndef __cpExtensions__DataStructures__PolyLineParametricPath__hxx__ +#define __cpExtensions__DataStructures__PolyLineParametricPath__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +AddVertex( const TContinuousIndex& vertex ) +{ + this->Superclass::AddVertex( vertex ); + this->m_Bezier->AddPoint( + this->GetPoint( this->GetSize( ) - 1 ).GetVectorFromOrigin( ) + ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +unsigned long cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +GetSize( ) const +{ + return( this->GetVertexList( )->Size( ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +TContinuousIndex +cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +GetContinuousVertex( unsigned long i ) const +{ + return( this->GetVertexList( )->GetElement( i ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +TIndex cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +GetVertex( unsigned long i ) const +{ + TContinuousIndex cidx = this->GetContinuousVertex( i ); + TIndex idx; + for( unsigned int d = 0; d < _VDim; ++d ) + idx[ d ] = cidx[ d ]; + return( idx ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +TPoint cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +GetPoint( unsigned long i ) const +{ + typedef typename TPoint::CoordRepType _TCoordRep; + TPoint pnt; + TContinuousIndex idx = this->GetVertex( i ); + for( unsigned int r = 0; r < _VDim; ++r ) + { + _TCoordRep sum = itk::NumericTraits< _TCoordRep >::ZeroValue( ); + for( unsigned int c = 0; c < _VDim; ++c ) + sum += this->m_IndexToPhysicalPoint( r, c ) * idx[ c ]; + pnt[ r ] = sum + this->m_Origin[ r ]; + + } // rof + return( pnt ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +TPoint cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +GetSmoothPoint( double u ) const +{ + TPoint p; + p.Fill( 0 ); + p += this->m_Bezier->Evaluate( u ); + return( p ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +SetSpacing( const TSpacing& spac ) +{ + if( this->m_Spacing != spac ) + { + this->m_Spacing = spac; + this->_ComputeIndexToPhysicalPointMatrices( ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +SetSpacing( const double spac[ _VDim ] ) +{ + this->SetSpacing( TSpacing( spac ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +SetSpacing( const float spac[ _VDim ] ) +{ + TSpacing s; + for( unsigned int d = 0; d < _VDim; ++d ) + s[ d ] = spac[ d ]; + this->SetSpacing( s ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +SetOrigin( const double ori[ _VDim ] ) +{ + this->SetOrigin( TPoint( ori ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +SetOrigin( const float ori[ _VDim ] ) +{ + this->SetOrigin( TPoint( ori ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +SetDirection( const TDirection& dir ) +{ + bool modified = false; + for( unsigned int r = 0; r < _VDim; r++ ) + { + for( unsigned int c = 0; c < _VDim; c++ ) + { + if( + itk::Math::NotExactlyEquals( + this->m_Direction[ r ][ c ], dir[ r ][ c ] + ) + ) + { + this->m_Direction[ r ][ c ] = dir[ r ][ c ]; + modified = true; + } // fi + + } // rof + + } // rof + if( modified ) + { + this->_ComputeIndexToPhysicalPointMatrices( ); + this->m_InverseDirection = this->m_Direction.GetInverse( ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +PolyLineParametricPath( ) + : Superclass( ) +{ + this->m_Bezier = TBezier::New( ); + + this->m_Spacing.Fill( 1.0 ); + this->m_Origin.Fill( 0.0 ); + this->m_Direction.SetIdentity( ); + this->m_InverseDirection.SetIdentity( ); + this->m_IndexToPhysicalPoint.SetIdentity( ); + this->m_PhysicalPointToIndex.SetIdentity( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +~PolyLineParametricPath( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >:: +_ComputeIndexToPhysicalPointMatrices( ) +{ + TDirection scale; + scale.Fill( 0.0 ); + for( unsigned int i = 0; i < _VDim; i++ ) + { + if( this->m_Spacing[ i ] == 0.0 ) + itkExceptionMacro( + "A spacing of 0 is not allowed: Spacing is " << this->m_Spacing + ); + scale[ i ][ i ] = this->m_Spacing[ i ]; + + } // rof + + if( vnl_determinant( this->m_Direction.GetVnlMatrix( ) ) == 0.0 ) + itkExceptionMacro( + << "Bad direction, determinant is 0. Direction is " + << this->m_Direction + ); + this->m_IndexToPhysicalPoint = this->m_Direction * scale; + this->m_PhysicalPointToIndex = this->m_IndexToPhysicalPoint.GetInverse( ); + this->Modified( ); +} + +#endif // __cpExtensions__DataStructures__PolyLineParametricPath__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Simple3DCurve.cxx b/lib/cpExtensions/DataStructures/Simple3DCurve.cxx new file mode 100644 index 0000000..1d1a92e --- /dev/null +++ b/lib/cpExtensions/DataStructures/Simple3DCurve.cxx @@ -0,0 +1,137 @@ +#include + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +Modified( ) const +{ + this->Superclass::Modified( ); + this->m_FramesUpdated = false; +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +Clear( ) +{ + this->m_Points.clear( ); + this->m_Frames.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +unsigned long cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +GetNumberOfPoints( ) const +{ + return( this->m_Points.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +const typename cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +TMatrix& cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +GetFrame( unsigned int id ) const +{ + if( !( this->m_FramesUpdated ) ) + { + unsigned long N = this->m_Points.size( ); + + std::vector< TVector > tg( N ); + tg[ 0 ] = this->m_Points[ 1 ] - this->m_Points[ 0 ]; + tg[ N - 1 ] = this->m_Points[ N - 1 ] - this->m_Points[ N - 2 ]; + for( unsigned int i = 1; i < N - 1; ++i ) + tg[ i ] = this->m_Points[ i + 1 ] - this->m_Points[ i - 1 ]; + + std::vector< TVector > no( N ); + std::vector< TVector > bn( N ); + TVector prev_tg( _TScalar( 0 ) ), prev_no( _TScalar( 0 ) ); + prev_tg[ 0 ] = _TScalar( 1 ); + prev_no[ 1 ] = _TScalar( 1 ); + for( unsigned int i = 0; i < N; ++i ) + { + auto ntg = tg[ i ].GetNorm( ); + if( double( ntg ) > double( 0 ) ) + tg[ i ] /= ntg; + + _TScalar ct = prev_tg * tg[ i ]; + TVector a = itk::CrossProduct( prev_tg, tg[ i ] ); + _TScalar st = a.GetNorm( ); + if( st > _TScalar( 0 ) ) + a /= st; + + no[ i ] = + ( prev_no * ct ) + + ( itk::CrossProduct( a, prev_no ) * st ) + + ( a * ( ( a * prev_no ) * ( _TScalar( 1 ) - ct ) ) ); + auto nno = no[ i ].GetNorm( ); + if( double( nno ) > double( 0 ) ) + no[ i ] /= nno; + + bn[ i ] = itk::CrossProduct( tg[ i ], no[ i ] ); + + prev_tg = tg[ i ]; + prev_no = no[ i ]; + + } // rof + + this->m_Frames.clear( ); + for( unsigned int i = 0; i < N; ++i ) + { + TMatrix m; + for( unsigned int d = 0; d < 3; ++d ) + { + m[ d ][ 0 ] = tg[ i ][ d ]; + m[ d ][ 1 ] = no[ i ][ d ]; + m[ d ][ 2 ] = bn[ i ][ d ]; + + } // rof + this->m_Frames.push_back( m ); + + } // rof + + this->m_FramesUpdated = true; + + } // fi + return( this->m_Frames[ id ] ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +const typename cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +TPoint& cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +GetPoint( unsigned int id ) const +{ + return( this->m_Points[ id ] ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +typename cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +TVector cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +GetVector( unsigned int id ) const +{ + return( this->m_Points[ id ].GetVectorFromOrigin( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +Simple3DCurve( ) + : Superclass( ), + m_FramesUpdated( false ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +cpExtensions::DataStructures::Simple3DCurve< _TScalar >:: +~Simple3DCurve( ) +{ +} + +// ------------------------------------------------------------------------- +template class cpExtensions::DataStructures::Simple3DCurve< float >; +template class cpExtensions::DataStructures::Simple3DCurve< double >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Simple3DCurve.h b/lib/cpExtensions/DataStructures/Simple3DCurve.h new file mode 100644 index 0000000..0641d43 --- /dev/null +++ b/lib/cpExtensions/DataStructures/Simple3DCurve.h @@ -0,0 +1,75 @@ +#ifndef __cpExtensions__DataStructures__Simple3DCurve__h__ +#define __cpExtensions__DataStructures__Simple3DCurve__h__ + +#include +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< class _TScalar > + class cpExtensions_EXPORT Simple3DCurve + : public itk::DataObject + { + public: + typedef Simple3DCurve Self; + typedef itk::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TScalar TScalar; + typedef itk::Matrix< TScalar, 3, 3 > TMatrix; + typedef itk::Point< TScalar, 3 > TPoint; + typedef typename TPoint::VectorType TVector; + + public: + itkNewMacro( Self ); + itkTypeMacro( Simple3DCurve, itk::DataObject ); + + public: + template< class _TVector > + inline void AddPoint( const _TVector& v ) + { + TPoint p; + p[ 0 ] = v[ 0 ]; + p[ 1 ] = v[ 1 ]; + p[ 2 ] = v[ 2 ]; + this->m_Points.push_back( p ); + this->Modified( ); + } + + virtual void Modified( ) const cpExtensions_OVERRIDE; + void Clear( ); + unsigned long GetNumberOfPoints( ) const; + const TMatrix& GetFrame( unsigned int id ) const; + const TPoint& GetPoint( unsigned int id ) const; + TVector GetVector( unsigned int id ) const; + + protected: + Simple3DCurve( ); + virtual ~Simple3DCurve( ); + + private: + // Purposely not implemented + Simple3DCurve( const Self& other ); + Self& operator=( const Self& other ); + + protected: + std::vector< TPoint > m_Points; + mutable std::vector< TMatrix > m_Frames; + mutable bool m_FramesUpdated; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__DataStructures__Simple3DCurve__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Skeleton.h b/lib/cpExtensions/DataStructures/Skeleton.h new file mode 100644 index 0000000..9d0bd9b --- /dev/null +++ b/lib/cpExtensions/DataStructures/Skeleton.h @@ -0,0 +1,58 @@ +#ifndef __cpExtensions__DataStructures__Skeleton__h__ +#define __cpExtensions__DataStructures__Skeleton__h__ + +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< unsigned int _VDim > + class Skeleton + : public Graph< typename PolyLineParametricPath< _VDim >::TIndex, typename PolyLineParametricPath< _VDim >::Pointer, typename PolyLineParametricPath< _VDim >::TIndex, typename PolyLineParametricPath< _VDim >::TIndex::LexicographicCompare > + { + public: + typedef PolyLineParametricPath< _VDim > TPath; + typedef typename TPath::TIndex TIndex; + typedef typename TIndex::LexicographicCompare TIndexCompare; + typedef typename TPath::Pointer TPathPointer; + + itkStaticConstMacro( Dimension, unsigned int, _VDim ); + + typedef Graph< TIndex, TPathPointer, TIndex, TIndexCompare > Superclass; + typedef Skeleton Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Skeleton, Graph ); + + public: + void AddBranch( TPath* path ); + const TPath* GetBranch( const TIndex& a, const TIndex& b ) const; + + protected: + Skeleton( ); + virtual ~Skeleton( ); + + private: + // Purposely not implemented + Skeleton( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__DataStructures__Skeleton__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Skeleton.hxx b/lib/cpExtensions/DataStructures/Skeleton.hxx new file mode 100644 index 0000000..e6635ae --- /dev/null +++ b/lib/cpExtensions/DataStructures/Skeleton.hxx @@ -0,0 +1,58 @@ +#ifndef __cpExtensions__DataStructures__Skeleton__hxx__ +#define __cpExtensions__DataStructures__Skeleton__hxx__ + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void cpExtensions::DataStructures::Skeleton< _VDim >:: +AddBranch( TPath* path ) +{ + // Check inputs + if( path == NULL ) + return; + unsigned long size = path->GetSize( ); + if( size == 0 ) + return; + TIndex a = path->GetVertex( 0 ); + TIndex b = path->GetVertex( size - 1 ); + if( this->HasEdge( a, b ) ) + return; + + // Add path + this->SetVertex( a, a ); + this->SetVertex( b, b ); + this->AddEdge( a, b, path ); + this->AddEdge( b, a, path ); + // TODO: this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +const typename cpExtensions::DataStructures::Skeleton< _VDim >:: +TPath* cpExtensions::DataStructures::Skeleton< _VDim >:: +GetBranch( const TIndex& a, const TIndex& b ) const +{ + static const TPath* null_path = NULL; + if( this->HasEdge( a, b ) ) + return( this->GetEdges( a, b ).front( ) ); + else + return( null_path ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +cpExtensions::DataStructures::Skeleton< _VDim >:: +Skeleton( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +cpExtensions::DataStructures::Skeleton< _VDim >:: +~Skeleton( ) +{ +} + +#endif // __cpExtensions__DataStructures__Skeleton__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/BaseStyle.cxx b/lib/cpExtensions/Interaction/BaseStyle.cxx new file mode 100644 index 0000000..39bd24b --- /dev/null +++ b/lib/cpExtensions/Interaction/BaseStyle.cxx @@ -0,0 +1,437 @@ +#include + +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +long cpExtensions::Interaction::BaseStyle::_TMouseButtonEvent:: +MaxDoubleClick = 350; // ms + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +SetSetDoubleClickDelay( long delay ) +{ + Self::_TMouseButtonEvent::MaxDoubleClick = delay; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +DelegateTDxEvent( unsigned long event, void* calldata ) +{ + // TODO + std::cerr << "No TDx support at this time!" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +OnMouseMove( ) +{ + if( this->Interactor == NULL ) + return; + + // Get modifiers + bool alt = ( this->Interactor->GetAltKey( ) == 1 ); + bool ctr = ( this->Interactor->GetControlKey( ) == 1 ); + bool sft = ( this->Interactor->GetShiftKey( ) == 1 ); + ButtonID button = this->GetButtonID( ); + + // Invoke possible generic events + auto x = this->Interactor->GetEventPosition( )[ 0 ]; + auto y = this->Interactor->GetEventPosition( )[ 1 ]; + if( button == Self::ButtonID_Right ) + { + if( !alt && !ctr && !sft ) + { + this->FindPokedRenderer( x, y ); + this->Dolly( ); + + } // fi + } + else if( button == Self::ButtonID_Middle ) + { + if( !alt && !ctr && !sft ) + { + this->FindPokedRenderer( x, y ); + this->Pan( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +OnLeftButtonDown( ) +{ + this->m_ActiveButton = Self::ButtonID_Left; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +OnLeftButtonUp( ) +{ + this->m_ActiveButton = Self::ButtonID_None; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +OnMiddleButtonDown( ) +{ + this->m_ActiveButton = Self::ButtonID_Middle; + + // Get current position on the associated actors + if( this->Interactor == NULL ) + return; + + // Get modifiers + bool alt = ( this->Interactor->GetAltKey( ) == 1 ); + bool ctr = ( this->Interactor->GetControlKey( ) == 1 ); + bool sft = ( this->Interactor->GetShiftKey( ) == 1 ); + if( !alt && !ctr && !sft ) + this->StartPan( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +OnMiddleButtonUp( ) +{ + this->m_ActiveButton = Self::ButtonID_None; + + // Get current position on the associated actors + if( this->Interactor == NULL ) + return; + + switch( this->State ) + { + case VTKIS_PAN: + this->EndPan( ); + break; + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +OnRightButtonDown( ) +{ + this->m_ActiveButton = Self::ButtonID_Right; + + // Get current position on the associated actors + if( this->Interactor == NULL ) + return; + + // Get modifiers + bool alt = ( this->Interactor->GetAltKey( ) == 1 ); + bool ctr = ( this->Interactor->GetControlKey( ) == 1 ); + bool sft = ( this->Interactor->GetShiftKey( ) == 1 ); + if( !alt && !ctr && !sft ) + this->StartDolly( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +OnRightButtonUp( ) +{ + this->m_ActiveButton = Self::ButtonID_None; + + // Get current position on the associated actors + if( this->Interactor == NULL ) + return; + + switch( this->State ) + { + case VTKIS_DOLLY: + this->EndDolly( ); + break; + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +#define cpExtensions_BaseStyle_Click( S, T ) \ + void cpExtensions::Interaction::BaseStyle:: \ + On##S##T( ) \ + { \ + if( this->Interactor == NULL ) \ + return; \ + static int idx[ 2 ]; \ + static double pos[ 3 ]; \ + if( !( this->_PickPosition( idx, pos ) ) ) \ + return; \ + auto i = this->m_Mouse##T##Commands.begin( ); \ + for( ; i != this->m_Mouse##T##Commands.end( ); ++i ) \ + i->first( \ + i->second, \ + Self::ButtonID_##S, \ + idx, pos, \ + this->Interactor->GetAltKey( ) == 1, \ + this->Interactor->GetControlKey( ) == 1, \ + this->Interactor->GetShiftKey( ) == 1 \ + ); \ + } + +cpExtensions_BaseStyle_Click( Left, Click ); +cpExtensions_BaseStyle_Click( Middle, Click ); +cpExtensions_BaseStyle_Click( Right, Click ); +cpExtensions_BaseStyle_Click( Left, DoubleClick ); +cpExtensions_BaseStyle_Click( Middle, DoubleClick ); +cpExtensions_BaseStyle_Click( Right, DoubleClick ); + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +Dolly( ) +{ + if( this->CurrentRenderer == NULL ) + return; + + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + double *center = this->CurrentRenderer->GetCenter( ); + int dy = rwi->GetEventPosition( )[ 1 ] - rwi->GetLastEventPosition( )[ 1 ]; + double dyf = this->m_MotionFactor * dy / center[ 1 ]; + this->_Dolly( std::pow( 1.1, dyf ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +Pan( ) +{ + if( this->CurrentRenderer == NULL ) + return; + + vtkRenderWindowInteractor* rwi = this->Interactor; + double viewFocus[ 4 ], focalDepth, viewPoint[ 3 ]; + double newPickPoint[ 4 ], oldPickPoint[ 4 ], motionVector[ 3 ]; + + // Calculate the focal depth since we'll be using it a lot + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera( ); + camera->GetFocalPoint( viewFocus ); + this->ComputeWorldToDisplay( + viewFocus[ 0 ], viewFocus[ 1 ], viewFocus[ 2 ], viewFocus + ); + focalDepth = viewFocus[ 2 ]; + this->ComputeDisplayToWorld( + rwi->GetEventPosition( )[ 0 ], + rwi->GetEventPosition( )[ 1 ], + focalDepth, + newPickPoint + ); + + // Has to recalc old mouse point since the viewport has moved, + // so can't move it outside the loop + this->ComputeDisplayToWorld( + rwi->GetLastEventPosition( )[ 0 ], + rwi->GetLastEventPosition( )[ 1 ], + focalDepth, + oldPickPoint + ); + + // Camera motion is reversed + motionVector[ 0 ] = oldPickPoint[ 0 ] - newPickPoint[ 0 ]; + motionVector[ 1 ] = oldPickPoint[ 1 ] - newPickPoint[ 1 ]; + motionVector[ 2 ] = oldPickPoint[ 2 ] - newPickPoint[ 2 ]; + + camera->GetFocalPoint( viewFocus ); + camera->GetPosition( viewPoint ); + camera->SetFocalPoint( + motionVector[ 0 ] + viewFocus[ 0 ], + motionVector[ 1 ] + viewFocus[ 1 ], + motionVector[ 2 ] + viewFocus[ 2 ] + ); + camera->SetPosition( + motionVector[ 0 ] + viewPoint[ 0 ], + motionVector[ 1 ] + viewPoint[ 1 ], + motionVector[ 2 ] + viewPoint[ 2 ] + ); + if( rwi->GetLightFollowCamera( ) ) + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera( ); + rwi->Render( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::BaseStyle:: +BaseStyle( ) + : Superclass( ), + m_MotionFactor( double( 10 ) ) +{ + this->m_LeftButtonEvent.Reset( ); + this->m_MiddleButtonEvent.Reset( ); + this->m_RightButtonEvent.Reset( ); + this->m_ActiveButton = Self::ButtonID_None; + + this->EventCallbackCommand->SetCallback( Self::_ProcessEvents ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::BaseStyle:: +~BaseStyle( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +_Dolly( double factor ) +{ + if( this->CurrentRenderer == NULL ) + return; + + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera( ); + if( camera->GetParallelProjection( ) == 0 ) + { + camera->Dolly( factor ); + if( this->AutoAdjustCameraClippingRange ) + this->CurrentRenderer->ResetCameraClippingRange( ); + } + else + camera->SetParallelScale( camera->GetParallelScale( ) / factor ); + if( this->Interactor->GetLightFollowCamera( ) ) + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera( ); + this->Interactor->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseStyle:: +_ProcessEvents( + vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata + ) +{ + // Get active style and interactor + Self* s = reinterpret_cast< Self* >( clientdata ); + if( s == NULL ) + return; + + // Process events + switch( event ) + { + case vtkCommand::MouseMoveEvent: + { + s->OnMouseMove( ); + } + break; + case vtkCommand::LeftButtonPressEvent: + { + unsigned char nc = s->m_LeftButtonEvent.Clicks( ); + if( nc == 2 ) + s->OnLeftDoubleClick( ); + else if( nc == 1 ) + s->OnLeftClick( ); + s->OnLeftButtonDown( ); + } + break; + case vtkCommand::LeftButtonReleaseEvent: + { + s->m_LeftButtonEvent.Release( ); + s->OnLeftButtonUp( ); + } + break; + case vtkCommand::MiddleButtonPressEvent: + { + unsigned char nc = s->m_MiddleButtonEvent.Clicks( ); + if( nc == 2 ) + s->OnMiddleDoubleClick( ); + else if( nc == 1 ) + s->OnMiddleClick( ); + s->OnMiddleButtonDown( ); + } + break; + case vtkCommand::MiddleButtonReleaseEvent: + { + s->m_MiddleButtonEvent.Release( ); + s->OnMiddleButtonUp( ); + } + break; + case vtkCommand::RightButtonPressEvent: + { + unsigned char nc = s->m_RightButtonEvent.Clicks( ); + if( nc == 2 ) + s->OnRightDoubleClick( ); + else if( nc == 1 ) + s->OnRightClick( ); + s->OnRightButtonDown( ); + } + break; + case vtkCommand::RightButtonReleaseEvent: + { + s->m_RightButtonEvent.Release( ); + s->OnRightButtonUp( ); + } + break; + case vtkCommand::MouseWheelForwardEvent: + { + s->OnMouseWheelForward( ); + } + break; + case vtkCommand::MouseWheelBackwardEvent: + { + s->OnMouseWheelBackward( ); + } + break; + case vtkCommand::KeyPressEvent: + { + s->OnKeyDown( ); + s->OnKeyPress( ); + } + break; + case vtkCommand::KeyReleaseEvent: + { + s->OnKeyUp( ); + s->OnKeyRelease( ); + } + break; + case vtkCommand::CharEvent: + { + s->OnChar( ); + } + break; + case vtkCommand::ExposeEvent: + { + s->OnExpose( ); + } + break; + case vtkCommand::ConfigureEvent: + { + s->OnConfigure( ); + } + break; + case vtkCommand::EnterEvent: + { + s->OnEnter( ); + } + break; + case vtkCommand::LeaveEvent: + { + s->OnLeave( ); + } + break; + case vtkCommand::TimerEvent: + { + // Do nothing + } + break; + case vtkCommand::DeleteEvent: + { + s->SetInteractor( 0 ); + } + break; + case vtkCommand::TDxMotionEvent: + case vtkCommand::TDxButtonPressEvent: + case vtkCommand::TDxButtonReleaseEvent: + { + s->DelegateTDxEvent( event, calldata ); + } + break; + default: + break; + } // hctiws +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/BaseStyle.h b/lib/cpExtensions/Interaction/BaseStyle.h new file mode 100644 index 0000000..cee7078 --- /dev/null +++ b/lib/cpExtensions/Interaction/BaseStyle.h @@ -0,0 +1,193 @@ +#ifndef __cpExtensions__Interaction__BaseStyle__h__ +#define __cpExtensions__Interaction__BaseStyle__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpExtensions_BaseStyle_Commands( C ) \ + protected: \ + std::map< T##C##Command, void* > m_##C##Commands; \ + public: \ + inline void Add##C##Command( T##C##Command c, void* d ) \ + { \ + if( c != NULL ) \ + { \ + this->m_##C##Commands[ c ] = d; \ + this->Modified( ); \ + } \ + } \ + inline void Remove##C##Command( T##C##Command c ) \ + { \ + std::map< T##C##Command, void* >::iterator i = \ + this->m_##C##Commands.find( c ); \ + if( i != this->m_##C##Commands.end( ) ) \ + { \ + this->m_##C##Commands.erase( i ); \ + this->Modified( ); \ + } \ + } + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT BaseStyle + : public vtkInteractorStyle + { + public: + typedef BaseStyle Self; + vtkTypeMacro( BaseStyle, vtkInteractorStyle ); + + enum ButtonID + { + ButtonID_None = 0, + ButtonID_Left, + ButtonID_Middle, + ButtonID_Right + }; + + // Callbacks types + typedef void ( *TMouseCommand )( + void*, const ButtonID&, int*, double*, bool, bool, bool + ); + typedef TMouseCommand TMouseClickCommand; + typedef TMouseCommand TMouseDoubleClickCommand; + + // Associate callbacks for each event + cpExtensions_BaseStyle_Commands( MouseClick ); + cpExtensions_BaseStyle_Commands( MouseDoubleClick ); + + public: + static void SetSetDoubleClickDelay( long delay ); + void DelegateTDxEvent( unsigned long event, void* calldata ); + + // Possible mouse motion events + virtual void OnMouseMove( ) cpExtensions_OVERRIDE; + virtual void OnMouseWheelForward( ) cpExtensions_OVERRIDE { } + virtual void OnMouseWheelBackward( ) cpExtensions_OVERRIDE { } + + // Possible mouse click-related events + inline ButtonID GetButtonID( ) const { return( this->m_ActiveButton ); } + + virtual void OnLeftButtonDown( ) cpExtensions_OVERRIDE; + virtual void OnLeftButtonUp( ) cpExtensions_OVERRIDE; + virtual void OnMiddleButtonDown( ) cpExtensions_OVERRIDE; + virtual void OnMiddleButtonUp( ) cpExtensions_OVERRIDE; + virtual void OnRightButtonDown( ) cpExtensions_OVERRIDE; + virtual void OnRightButtonUp( ) cpExtensions_OVERRIDE; + + virtual void OnLeftClick( ); + virtual void OnLeftDoubleClick( ); + virtual void OnMiddleClick( ); + virtual void OnMiddleDoubleClick( ); + virtual void OnRightClick( ); + virtual void OnRightDoubleClick( ); + + // Keyboard-related events + virtual void OnChar( ) cpExtensions_OVERRIDE { } + virtual void OnKeyDown( ) cpExtensions_OVERRIDE { } + virtual void OnKeyUp( ) cpExtensions_OVERRIDE { } + virtual void OnKeyPress( ) cpExtensions_OVERRIDE { } + virtual void OnKeyRelease( ) cpExtensions_OVERRIDE { } + + // Other events + virtual void OnExpose( ) cpExtensions_OVERRIDE { } + virtual void OnConfigure( ) cpExtensions_OVERRIDE { } + virtual void OnEnter( ) cpExtensions_OVERRIDE { } + virtual void OnLeave( ) cpExtensions_OVERRIDE { } + + virtual void Dolly( ) cpExtensions_OVERRIDE; + virtual void Pan( ) cpExtensions_OVERRIDE; + + protected: + BaseStyle( ); + virtual ~BaseStyle( ); + + virtual void _Dolly( double factor ); + + // Extension interface + virtual bool _PickPosition( int idx[ 2 ], double pos[ 3 ] ) = 0; + + // Main event callback + static void _ProcessEvents( + vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata + ); + + private: + // Purposely not implemented + BaseStyle( const Self& ); + Self& operator=( const Self& ); + + protected: + double m_MotionFactor; + + /** + * Button events + */ + struct _TMouseButtonEvent + { + static long MaxDoubleClick; + long m_LastButtonUp; + long m_LastButtonHeld; + long m_LastButtonDown; + + inline _TMouseButtonEvent( ) + { this->Reset( ); } + inline void Reset( ) + { + this->m_LastButtonUp = 0; + this->m_LastButtonHeld = 0; + this->m_LastButtonDown = -1; + } + inline void Release( ) + { + /* TODO + long c = cpExtensions_CHRONO; + this->m_LastButtonUp = c; + this->m_LastButtonHeld = c - this->m_LastButtonDown; + this->m_LastButtonDown = -1; + */ + } + inline unsigned char Clicks( ) + { + /* TODO + unsigned char n = 0; + long c = cpExtensions_CHRONO; + if( + this->m_LastButtonHeld < MaxDoubleClick && + ( c - this->m_LastButtonUp ) < MaxDoubleClick + ) + { + this->Reset( ); + n = 2; + } + else + n = 1; + if( this->m_LastButtonDown < 0 ) + this->m_LastButtonDown = c; + return( n ); + */ + return( 1 ); + } + }; + _TMouseButtonEvent m_LeftButtonEvent; + _TMouseButtonEvent m_MiddleButtonEvent; + _TMouseButtonEvent m_RightButtonEvent; + ButtonID m_ActiveButton; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Interaction__BaseStyle__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/ImageSlicePointPlacer.cxx b/lib/cpExtensions/Interaction/ImageSlicePointPlacer.cxx new file mode 100644 index 0000000..45c020b --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageSlicePointPlacer.cxx @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +vtkCxxSetObjectMacro( + cpExtensions::Interaction::ImageSlicePointPlacer, ImageSlice, vtkImageSlice + ); + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageSlicePointPlacer:: +Self* cpExtensions::Interaction::ImageSlicePointPlacer:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSlicePointPlacer:: +ComputeWorldPosition( + vtkRenderer* ren, + double displayPos[ 2 ], + double worldPos[ 3 ], + double worldOrient[ 9 ] + ) +{ + if( !this->UpdateInternalState( ) ) + return( 0 ); + return( + this->Placer->ComputeWorldPosition( + ren, displayPos, worldPos, worldOrient + ) + ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSlicePointPlacer:: +ComputeWorldPosition( + vtkRenderer* ren, + double displayPos[ 2 ], + double refWorldPos[ 2 ], + double worldPos[ 3 ], + double worldOrient[ 9 ] + ) +{ + if( !this->UpdateInternalState( ) ) + return( 0 ); + return( + this->Placer->ComputeWorldPosition( + ren, displayPos, refWorldPos, worldPos, worldOrient + ) + ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSlicePointPlacer:: +ValidateWorldPosition( double worldPos[ 3 ] ) +{ + if( !this->UpdateInternalState( ) ) + return( 0 ); + return( this->Placer->ValidateWorldPosition( worldPos ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSlicePointPlacer:: +ValidateWorldPosition( double worldPos[ 3 ], double worldOrient[ 9 ] ) +{ + if( !this->UpdateInternalState( ) ) + return( 0 ); + return( this->Placer->ValidateWorldPosition( worldPos, worldOrient ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSlicePointPlacer:: +UpdateWorldPosition( + vtkRenderer* ren, double worldPos[ 3 ], double worldOrient[ 9 ] + ) +{ + if( !this->UpdateInternalState( ) ) + return( 0 ); + return( this->Placer->UpdateWorldPosition( ren, worldPos, worldOrient ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSlicePointPlacer:: +UpdateInternalState( ) +{ + if( !this->ImageSlice ) + return( 0 ); + + vtkImageData* input = this->ImageSlice->GetMapper( )->GetInput( ); + if( !input ) + return( 0 ); + + double spacing[ 3 ]; + input->GetSpacing( spacing ); + + double origin[ 3 ]; + input->GetOrigin( origin ); + + double b[ 6 ]; + this->ImageSlice->GetBounds( b ); + if( this->Bounds[ 0 ] != VTK_DOUBLE_MAX) + { + b[ 0 ] = ( b[ 0 ] < this->Bounds[ 0 ] )? this->Bounds[ 0 ] : b[ 0 ]; + b[ 1 ] = ( b[ 1 ] > this->Bounds[ 1 ] )? this->Bounds[ 1 ] : b[ 1 ]; + b[ 2 ] = ( b[ 2 ] < this->Bounds[ 2 ] )? this->Bounds[ 2 ] : b[ 2 ]; + b[ 3 ] = ( b[ 3 ] > this->Bounds[ 3 ] )? this->Bounds[ 3 ] : b[ 3 ]; + b[ 4 ] = ( b[ 4 ] < this->Bounds[ 4 ] )? this->Bounds[ 4 ] : b[ 4 ]; + b[ 5 ] = ( b[ 5 ] > this->Bounds[ 5 ] )? this->Bounds[ 5 ] : b[ 5 ]; + + } // fi + + int displayExtent[ 6 ] = { 0, 1, 0, 1, 0, 1 }; + input->GetExtent( displayExtent ); + auto mapper = + dynamic_cast< cpExtensions::Visualization::ImageSliceMapper* >( + this->ImageSlice->GetMapper( ) + ); + if( mapper != NULL ) + { + auto ori = mapper->GetOrientation( ); + displayExtent[ ( ori << 1 ) + 1 ] = + displayExtent[ ori << 1 ] = + mapper->GetSliceNumber( ); + + } // fi + + int axis; + double position; + if( displayExtent[ 0 ] == displayExtent[ 1 ] ) + { + axis = vtkBoundedPlanePointPlacer::XAxis; + position = origin[ 0 ] + displayExtent[ 0 ] * spacing[ 0 ]; + } + else if( displayExtent[ 2 ] == displayExtent[ 3 ] ) + { + axis = vtkBoundedPlanePointPlacer::YAxis; + position = origin[ 1 ] + displayExtent[ 2 ] * spacing[ 1 ]; + } + else if( displayExtent[ 4 ] == displayExtent[ 5 ] ) + { + axis = vtkBoundedPlanePointPlacer::ZAxis; + position = origin[ 2 ] + displayExtent[ 4 ] * spacing[ 2 ]; + } + else + { + vtkErrorMacro( "Incorrect display extent in Image Slice" ); + return( 0 ); + + } // fi + + if( + axis != this->Placer->GetProjectionNormal( ) || + position != this->Placer->GetProjectionPosition( ) || + b[ 0 ] != this->SavedBounds[ 0 ] || + b[ 1 ] != this->SavedBounds[ 1 ] || + b[ 2 ] != this->SavedBounds[ 2 ] || + b[ 3 ] != this->SavedBounds[ 3 ] || + b[ 4 ] != this->SavedBounds[ 4 ] || + b[ 5 ] != this->SavedBounds[ 5 ] + ) + { + this->SavedBounds[ 0 ] = b[ 0 ]; + this->SavedBounds[ 1 ] = b[ 1 ]; + this->SavedBounds[ 2 ] = b[ 2 ]; + this->SavedBounds[ 3 ] = b[ 3 ]; + this->SavedBounds[ 4 ] = b[ 4 ]; + this->SavedBounds[ 5 ] = b[ 5 ]; + + this->Placer->SetProjectionNormal( axis ); + this->Placer->SetProjectionPosition( position ); + + this->Placer->RemoveAllBoundingPlanes( ); + + vtkPlane* plane; + if( axis != vtkBoundedPlanePointPlacer::XAxis ) + { + plane = vtkPlane::New( ); + plane->SetOrigin( b[ 0 ], b[ 2 ], b[ 4 ] ); + plane->SetNormal( 1.0, 0.0, 0.0 ); + this->Placer->AddBoundingPlane( plane ); + plane->Delete( ); + + plane = vtkPlane::New(); + plane->SetOrigin( b[ 1 ], b[ 3 ], b[ 5 ] ); + plane->SetNormal( -1.0, 0.0, 0.0 ); + this->Placer->AddBoundingPlane( plane ); + plane->Delete( ); + + } // fi + + if( axis != vtkBoundedPlanePointPlacer::YAxis ) + { + plane = vtkPlane::New( ); + plane->SetOrigin( b[ 0 ], b[ 2 ], b[ 4 ] ); + plane->SetNormal( 0.0, 1.0, 0.0 ); + this->Placer->AddBoundingPlane( plane ); + plane->Delete( ); + + plane = vtkPlane::New( ); + plane->SetOrigin( b[ 1 ], b[ 3 ], b[ 5 ] ); + plane->SetNormal( 0.0, -1.0, 0.0 ); + this->Placer->AddBoundingPlane( plane ); + plane->Delete( ); + + } // fi + + if( axis != vtkBoundedPlanePointPlacer::ZAxis ) + { + plane = vtkPlane::New( ); + plane->SetOrigin( b[ 0 ], b[ 2 ], b[ 4 ] ); + plane->SetNormal( 0.0, 0.0, 1.0 ); + this->Placer->AddBoundingPlane( plane ); + plane->Delete( ); + + plane = vtkPlane::New( ); + plane->SetOrigin( b[ 1 ], b[ 3 ], b[ 5 ] ); + plane->SetNormal( 0.0, 0.0, -1.0 ); + this->Placer->AddBoundingPlane( plane ); + plane->Delete( ); + + } // fi + + this->Modified( ); + + } // fi + return( 1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSlicePointPlacer:: +SetWorldTolerance( double tol ) +{ + double t = + ( tol < 0.0 )? 0.0: ( ( tol > VTK_DOUBLE_MAX )? VTK_DOUBLE_MAX: tol ); + if( this->WorldTolerance != t ) + { + this->WorldTolerance = t; + this->Placer->SetWorldTolerance( tol ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageSlicePointPlacer:: +ImageSlicePointPlacer( ) + : Superclass( ) +{ + this->Placer = vtkBoundedPlanePointPlacer::New( ); + this->ImageSlice = NULL; + this->SavedBounds[ 0 ] = 0.0; + this->SavedBounds[ 1 ] = 0.0; + this->SavedBounds[ 2 ] = 0.0; + this->SavedBounds[ 3 ] = 0.0; + this->SavedBounds[ 4 ] = 0.0; + this->SavedBounds[ 5 ] = 0.0; + this->Bounds[ 0 ] = this->Bounds[ 2 ] = this->Bounds[ 4 ] = VTK_DOUBLE_MAX; + this->Bounds[ 1 ] = this->Bounds[ 3 ] = this->Bounds[ 5 ] = VTK_DOUBLE_MIN; +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageSlicePointPlacer:: +~ImageSlicePointPlacer( ) +{ + this->Placer->Delete( ); + this->SetImageSlice( NULL ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/ImageSlicePointPlacer.h b/lib/cpExtensions/Interaction/ImageSlicePointPlacer.h new file mode 100644 index 0000000..e0465d9 --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageSlicePointPlacer.h @@ -0,0 +1,78 @@ +#ifndef __cpExtensions__Interaction__ImageSlicePointPlacer__h__ +#define __cpExtensions__Interaction__ImageSlicePointPlacer__h__ + +#include +#include + +class vtkBoundedPlanePointPlacer; +class vtkImageSlice; +class vtkRenderer; + +namespace cpExtensions +{ + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT ImageSlicePointPlacer + : public vtkPointPlacer + { + public: + typedef ImageSlicePointPlacer Self; + vtkTypeMacro( ImageSlicePointPlacer, vtkPointPlacer ); + + vtkGetObjectMacro( ImageSlice, vtkImageSlice ); + vtkSetVector6Macro( Bounds, double ); + vtkGetVector6Macro( Bounds, double ); + + public: + static Self* New( ); + + int ComputeWorldPosition( + vtkRenderer* ren, + double displayPos[ 2 ], + double worldPos[ 3 ], + double worldOrient[ 9 ] + ); + int ComputeWorldPosition( + vtkRenderer* ren, + double displayPos[ 2 ], + double refWorldPos[ 2 ], + double worldPos[ 3 ], + double worldOrient[ 9 ] + ); + int ValidateWorldPosition( double worldPos[ 3 ] ); + int ValidateWorldPosition( + double worldPos[ 3 ], double worldOrient[ 9 ] + ); + int UpdateWorldPosition( + vtkRenderer* ren, double worldPos[ 3 ], double worldOrient[ 9 ] + ); + int UpdateInternalState( ); + + void SetImageSlice( vtkImageSlice* slice ); + virtual void SetWorldTolerance( double tol ); + + protected: + ImageSlicePointPlacer( ); + virtual ~ImageSlicePointPlacer( ); + + private: + // Purposely not implemented + ImageSlicePointPlacer( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkImageSlice* ImageSlice; + vtkBoundedPlanePointPlacer* Placer; + double SavedBounds[ 6 ]; + double Bounds[ 6 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Interaction__ImageSlicePointPlacer__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/ImageSliceStyle.cxx b/lib/cpExtensions/Interaction/ImageSliceStyle.cxx new file mode 100644 index 0000000..7b9df5a --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageSliceStyle.cxx @@ -0,0 +1,414 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageSliceStyle:: +Self* cpExtensions::Interaction::ImageSliceStyle:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSliceStyle:: +GetSliceNumber( ) const +{ + if( this->m_WLActor.GetPointer( ) != NULL ) + return( this->m_WLActor->GetSliceNumber( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Interaction::ImageSliceStyle:: +GetOrientation( ) const +{ + if( this->m_WLActor.GetPointer( ) != NULL ) + return( this->m_WLActor->GetOrientation( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnMouseMove( ) +{ + static bool cursor_visible = false; + + int idx[ 2 ]; + double pnt[ 3 ]; + if( this->_PickPointOnImageActor( idx, pnt ) ) + { + this->m_Cursor->SetCursor( pnt, false ); + this->_ShowText( pnt ); + if( !cursor_visible ) + { + this->m_Cursor->VisibilityOn( ); + this->m_Text->VisibilityOn( ); + cursor_visible = true; + + } // fi + this->Interactor->Render( ); + } + else + { + if( cursor_visible ) + { + this->m_Cursor->VisibilityOff( ); + this->m_Text->VisibilityOff( ); + cursor_visible = false; + this->Interactor->Render( ); + + } // fi + + } // fi + + this->Overclass::OnMouseMove( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnMouseWheelForward( ) +{ + static int s = 0; + if( this->m_WLActor.GetPointer( ) == NULL ) + return; + s = this->m_WLActor->GetSliceNumber( ); + s += ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1; + this->m_WLActor->SetSliceNumber( s ); + s = this->m_WLActor->GetSliceNumber( ); + if( this->m_LUTActor.GetPointer( ) != NULL ) + this->m_LUTActor->SetSliceNumber( s ); + this->InvokeEvent( vtkCommand::UserEvent + 2, &s ); + this->Interactor->Render( ); + this->OnMouseMove( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnMouseWheelBackward( ) +{ + static int s = 0; + if( this->m_WLActor.GetPointer( ) == NULL ) + return; + s = this->m_WLActor->GetSliceNumber( ); + s -= ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1; + this->m_WLActor->SetSliceNumber( s ); + s = this->m_WLActor->GetSliceNumber( ); + if( this->m_LUTActor.GetPointer( ) != NULL ) + this->m_LUTActor->SetSliceNumber( s ); + this->InvokeEvent( vtkCommand::UserEvent + 2, &s ); + this->Interactor->Render( ); + this->OnMouseMove( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnChar( ) +{ + switch( this->Interactor->GetKeyCode( ) ) + { + case 'r': case 'R': + { + this->FindPokedRenderer( + this->Interactor->GetEventPosition( )[ 0 ], + this->Interactor->GetEventPosition( )[ 1 ] + ); + this->CurrentRenderer->ResetCamera( ); + this->Interactor->Render( ); + } + break; + default: + break; + + } // hctiws +} + +/* TODO +cpExtensions::Visualization::ImageViewerActors* +cpExtensions::Interaction::ImageSliceStyle:: +GetActors( ) +{ + return( this->m_Actors ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization::ImageViewerActors* +cpExtensions::Interaction::ImageSliceStyle:: +GetActors( ) const +{ + return( this->m_Actors ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +SetActors( cpExtensions::Visualization::ImageViewerActors* actors ) +{ + this->m_Actors = actors; + if( actors != NULL ) + { + this->m_PropPicker = vtkSmartPointer< vtkPropPicker >::New( ); + this->m_PropPicker->PickFromListOn( ); + this->m_PropPicker->GetPickList( )->RemoveAllItems( ); + this->m_PropPicker-> + AddPickList( this->m_Actors->GetWindowLevelImageActor( ) ); + } + else + this->m_PropPicker = NULL; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnMouseMove( ) +{ + this->Superclass::OnMouseMove( ); + if( this->m_Actors.GetPointer( ) == NULL ) + return; + + // Slice synch + static int idx[ 2 ]; + static double pos[ 3 ]; + if( this->_PickPosition( idx, pos ) ) + { + if( + this->Interactor->GetControlKey( ) == 1 && + this->GetButtonID( ) == Self::ButtonID_Left + ) + { + this->m_Actors->SetSuperCursor( pos, this->m_Actors->GetOrientation( ) == 2 ); + this->InvokeEvent( vtkCommand::UserEvent + 1, pos ); + } + else + this->m_Actors->SetCursor( pos, this->m_Actors->GetOrientation( ) == 2 ); + } + else + this->m_Actors->HideViewerActors( ); + this->Interactor->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnMouseWheelForward( ) +{ + static int s = 0; + if( this->m_Actors.GetPointer( ) == NULL ) + return; + s = this->m_Actors->GetSliceNumber( ); + s += ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1; + this->m_Actors->SetSliceNumber( s ); + s = this->m_Actors->GetSliceNumber( ); + this->InvokeEvent( vtkCommand::UserEvent + 2, &s ); + this->Interactor->Render( ); + this->OnMouseMove( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnMouseWheelBackward( ) +{ + static int s = 0; + if( this->m_Actors.GetPointer( ) == NULL ) + return; + s = this->m_Actors->GetSliceNumber( ); + s -= ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1; + this->m_Actors->SetSliceNumber( s ); + s = this->m_Actors->GetSliceNumber( ); + this->InvokeEvent( vtkCommand::UserEvent + 2, &s ); + this->Interactor->Render( ); + this->OnMouseMove( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +OnChar( ) +{ +} +*/ + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageSliceStyle:: +ImageSliceStyle( ) + : Superclass( ) +{ + this->SetInteractionModeToImage2D( ); + this->m_PropPicker = vtkSmartPointer< vtkPropPicker >::New( ); + this->m_PropPicker->PickFromListOn( ); + + this->m_Cursor = vtkSmartPointer< TCursor >::New( ); + this->m_Cursor->VisibilityOff( ); + this->m_Cursor->GetProperty( 0 )->SetColor( 1, 1, 0 ); + this->m_Cursor->GetProperty( 1 )->SetColor( 1, 1, 0 ); + + // Prepare text + this->m_TextBuffer[ 0 ] = '\0'; + this->m_Text = vtkSmartPointer< vtkTextActor >::New( ); + this->m_Text->SetTextScaleModeToNone( ); + auto textprop = this->m_Text->GetTextProperty( ); + textprop->SetColor( 1, 1, 0 ); + textprop->SetFontFamilyToCourier( ); + textprop->SetFontSize( 12 ); + textprop->BoldOff( ); + textprop->ItalicOff( ); + textprop->ShadowOff( ); + textprop->SetJustificationToLeft( ); + textprop->SetVerticalJustificationToBottom( ); + auto coord = this->m_Text->GetPositionCoordinate( ); + coord->SetCoordinateSystemToNormalizedViewport( ); + coord->SetValue( 0.01, 0.02 ); + this->m_Text->VisibilityOff( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageSliceStyle:: +~ImageSliceStyle( ) +{ +} + +// ------------------------------------------------------------------------- +bool cpExtensions::Interaction::ImageSliceStyle:: +_PickPointOnImageActor( int idx[ 2 ], double pnt[ 3 ] ) +{ + // Check if data is valid + if( + this->Interactor == NULL || + this->CurrentRenderer == NULL || + this->m_PropPicker.GetPointer( ) == NULL + ) + return( false ); + + // Find the renderer where the event has been raised + idx[ 0 ] = this->Interactor->GetEventPosition( )[ 0 ]; + idx[ 1 ] = this->Interactor->GetEventPosition( )[ 1 ]; + this->FindPokedRenderer( double( idx[ 0 ] ), double( idx[ 1 ] ) ); + + // Check if the image has changed + this->Interactor->GetPicker( )-> + Pick( idx[ 0 ], idx[ 1 ], 0.0, this->CurrentRenderer ); + auto picker = + vtkAbstractPropPicker::SafeDownCast( this->Interactor->GetPicker( ) ); + if( picker == NULL ) + return( false ); + TWLActor* curr_actor = dynamic_cast< TWLActor* >( picker->GetProp3D( ) ); + if( curr_actor != this->m_WLActor.GetPointer( ) && curr_actor != NULL ) + { + this->m_WLActor = curr_actor; + this->m_PropPicker->GetPickList( )->RemoveAllItems( ); + this->m_PropPicker->AddPickList( curr_actor ); + + auto props = this->CurrentRenderer->GetViewProps( ); + this->m_LUTActor = NULL; + props->InitTraversal( ); + vtkProp* prop; + while( ( ( prop = props->GetNextProp( ) ) != NULL ) && ( this->m_LUTActor.GetPointer( ) == NULL ) ) + this->m_LUTActor = dynamic_cast< TLUTActor* >( prop ); + + this->m_Cursor->SetImageBounds( curr_actor->GetImage( )->GetBounds( ) ); + this->m_Cursor->SetImageOrientation( curr_actor->GetOrientation( ) ); + this->m_Cursor->InitTraversal( ); + while( vtkProp* prop = this->m_Cursor->GetNextProp( ) ) + this->CurrentRenderer->AddViewProp( prop ); + this->CurrentRenderer->AddViewProp( this->m_Text ); + + } // fi + if( this->m_WLActor.GetPointer( ) == NULL ) + { + this->m_PropPicker->GetPickList( )->RemoveAllItems( ); + return( false ); + + } // fi + + // Pick a 3D position + int r = this->m_PropPicker->Pick( + double( idx[ 0 ] ), double( idx[ 1 ] ), double( 0 ), + this->CurrentRenderer + ); + if( r == 0 ) + return( false ); + this->m_PropPicker->GetPickPosition( pnt ); + return( true ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +_CorrectPosition( double pos[ 3 ], int ijk[ 3 ] ) +{ + if( this->m_WLActor.GetPointer( ) == NULL ) + return; + auto image = this->m_WLActor->GetImage( ); + if( image == NULL ) + return; + + // Approximate image index + double pcoords[ 3 ]; + image->ComputeStructuredCoordinates( pos, ijk, pcoords ); + + // Manually correct index + int ext[ 6 ]; + image->GetExtent( ext ); + for( int i = 0; i < 3; ++i ) + { + if( ijk[ i ] < ext[ i << 1 ] ) + ijk[ i ] = ext[ i << 1 ]; + if( ext[ ( i << 1 ) + 1 ] < ijk[ i ] ) + ijk[ i ] = ext[ ( i << 1 ) + 1 ]; + + } // rof + + // Get real coordinates + int o = this->m_WLActor->GetOrientation( ); + ijk[ o ] = this->m_WLActor->GetSliceNumber( ); + image->GetPoint( image->ComputePointId( ijk ), pos ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageSliceStyle:: +_ShowText( double pos[ 3 ] ) +{ + if( this->m_WLActor.GetPointer( ) == NULL ) + return; + auto image = this->m_WLActor->GetImage( ); + if( image == NULL ) + return; + + int ijk[ 3 ]; + this->_CorrectPosition( pos, ijk ); + int o = this->m_WLActor->GetOrientation( ); + + std::stringstream buffer; + buffer << "Axis: " << char( 'X' + char( o ) ) << std::endl; + int nScl = image->GetNumberOfScalarComponents( ); + buffer + << "Pixel: [" << ijk[ 0 ] + << "," << ijk[ 1 ] + << "," << ijk[ 2 ] << "] = < " + << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 ); + for( int n = 1; n < nScl; ++n ) + buffer + << " : " + << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n ); + buffer << " >" << std::endl; + buffer + << "Point: (" + << pos[ 0 ] << ", " << pos[ 1 ] << ", " << pos[ 2 ] + << ")"; + cpExtensions_SPRINTF( this->m_TextBuffer, 1024, buffer.str( ).c_str( ) ); + this->m_Text->SetInput( this->m_TextBuffer ); + this->m_Text->VisibilityOn( ); + this->m_Text->Modified( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/ImageSliceStyle.h b/lib/cpExtensions/Interaction/ImageSliceStyle.h new file mode 100644 index 0000000..6d2b114 --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageSliceStyle.h @@ -0,0 +1,88 @@ +#ifndef __cpExtensions__Interaction__ImageSliceStyle__h__ +#define __cpExtensions__Interaction__ImageSliceStyle__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkPropPicker; +class vtkTextActor; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class CursorActors; + class LUTImageActor; + class WindowLevelImageActor; + } + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT ImageSliceStyle + : public vtkInteractorStyleImage + { + public: + typedef ImageSliceStyle Self; + typedef cpExtensions::Visualization::CursorActors TCursor; + typedef cpExtensions::Visualization::LUTImageActor TLUTActor; + typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor; + + public: + vtkTypeMacro( ImageSliceStyle, vtkInteractorStyleImage ); + typedef vtkInteractorStyleImage::Superclass Overclass; + + public: + static Self* New( ); + + int GetSliceNumber( ) const; + int GetOrientation( ) const; + + virtual void OnMouseMove( ) cpExtensions_OVERRIDE; + virtual void OnMouseWheelForward( ) cpExtensions_OVERRIDE; + virtual void OnMouseWheelBackward( ) cpExtensions_OVERRIDE; + virtual void OnChar( ) cpExtensions_OVERRIDE; + + + /* TODO + cpExtensions::Visualization::ImageViewerActors* GetActors( ); + const cpExtensions::Visualization::ImageViewerActors* GetActors( ) const; + void SetActors( cpExtensions::Visualization::ImageViewerActors* actors ); + + // Events + virtual void OnMouseMove( ) cpExtensions_OVERRIDE; + virtual void OnChar( ) cpExtensions_OVERRIDE; + */ + + protected: + ImageSliceStyle( ); + virtual ~ImageSliceStyle( ); + + bool _PickPointOnImageActor( int idx[ 2 ], double pnt[ 3 ] ); + void _CorrectPosition( double pos[ 3 ], int ijk[ 3 ] ); + void _ShowText( double pos[ 3 ] ); + + private: + // Purposely not implemented + ImageSliceStyle( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkPropPicker > m_PropPicker; + vtkSmartPointer< TLUTActor > m_LUTActor; + vtkSmartPointer< TWLActor > m_WLActor; + vtkSmartPointer< TCursor > m_Cursor; + vtkSmartPointer< vtkTextActor > m_Text; + char m_TextBuffer[ 1024 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Interaction__ImageSliceStyle__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/SeedWidget.cxx b/lib/cpExtensions/Interaction/SeedWidget.cxx new file mode 100644 index 0000000..509d7c2 --- /dev/null +++ b/lib/cpExtensions/Interaction/SeedWidget.cxx @@ -0,0 +1,165 @@ +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SeedWidget:: +Self* cpExtensions::Interaction::SeedWidget:: +New( ) +{ + return( new Self ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SeedWidget:: +SetInteractor( vtkRenderWindowInteractor* rwi ) +{ + this->Superclass::SetInteractor( rwi ); + /* TODO + if( rwi != NULL ) + { + TBaseStyle* s = + dynamic_cast< TBaseStyle* >( rwi->GetInteractorStyle( ) ); + if( s != NULL ) + { + s->AddMouseClickCommand( Self::_Click, this ); + s->AddMouseDoubleClickCommand( Self::_DoubleClick, this ); + + } // fi + + } // fi + */ +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SeedWidget:: +SeedWidget( ) + : Superclass( ) +{ + // These are the event callbacks supported by this widget + this->CallbackMapper->SetCallbackMethod( + vtkCommand::LeftButtonPressEvent, + vtkWidgetEvent::AddPoint, + this, Self::_AddPointAction + ); + this->CallbackMapper->SetCallbackMethod( + vtkCommand::RightButtonPressEvent, + vtkWidgetEvent::Completed, + this, Self::_CompletedAction + ); + this->CallbackMapper->SetCallbackMethod( + vtkCommand::MouseMoveEvent, + vtkWidgetEvent::Move, + this, Self::_MoveAction + ); + this->CallbackMapper->SetCallbackMethod( + vtkCommand::LeftButtonReleaseEvent, + vtkWidgetEvent::EndSelect, + this, Self::_EndSelectAction + ); + this->CallbackMapper->SetCallbackMethod( + vtkCommand::KeyPressEvent, + vtkEvent::NoModifier, 127, 1, "Delete", + vtkWidgetEvent::Delete, + this, Self::_DeleteAction + ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SeedWidget:: +~SeedWidget( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SeedWidget:: +_AddPointAction( vtkAbstractWidget* wdg ) +{ + Self* self = dynamic_cast< Self* >( wdg ); + if( self == NULL ) + return; + auto iren = self->GetInteractor( ); + if( iren == NULL ) + return; + int shift = iren->GetShiftKey( ); + if( shift == 1 ) + Self::AddPointAction( wdg ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SeedWidget:: +_CompletedAction( vtkAbstractWidget* wdg ) +{ + // Do nothing + Self::CompletedAction( wdg ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SeedWidget:: +_MoveAction( vtkAbstractWidget* wdg ) +{ + // Do nothing + Self::MoveAction( wdg ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SeedWidget:: +_EndSelectAction( vtkAbstractWidget* wdg ) +{ + // Do nothing + Self::EndSelectAction( wdg ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SeedWidget:: +_DeleteAction( vtkAbstractWidget* wdg ) +{ + // Do nothing + Self::DeleteAction( wdg ); +} + +// ------------------------------------------------------------------------- +/* TODO + void cpExtensions::Interaction::SeedWidget:: + _Click( + void* data, const TBaseStyle::ButtonID& button, + int* idx, double* pos, bool alt, bool ctr, bool sft + ) + { + SeedWidget* self = reinterpret_cast< SeedWidget* >( data ); + if( self == NULL ) + return; + if( self->WidgetState == vtkSeedWidget::MovingSeed ) + return; + + int st = self->WidgetRep->ComputeInteractionState( idx[ 0 ], idx[ 1 ] ); + if( st == vtkSeedRepresentation::NearSeed ) + { + self->WidgetState = vtkSeedWidget::MovingSeed; + + // Invoke an event on ourself for the handles + self->InvokeEvent( vtkCommand::LeftButtonPressEvent, NULL ); + self->Superclass::StartInteraction( ); + self->InvokeEvent( vtkCommand::StartInteractionEvent, NULL ); + self->EventCallbackCommand->SetAbortFlag( 1 ); + self->Render( ); + + } // fi + } + + // ------------------------------------------------------------------------- + void cpExtensions::Interaction::SeedWidget:: + _DoubleClick( + void* data, const TBaseStyle::ButtonID& button, + int* idx, double* pos, bool alt, bool ctr, bool sft + ) + { + Self::AddPointAction( reinterpret_cast< vtkAbstractWidget* >( data ) ); + } +*/ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/SeedWidget.h b/lib/cpExtensions/Interaction/SeedWidget.h new file mode 100644 index 0000000..858218b --- /dev/null +++ b/lib/cpExtensions/Interaction/SeedWidget.h @@ -0,0 +1,63 @@ +#ifndef __cpExtensions__Interaction__SeedWidget__h__ +#define __cpExtensions__Interaction__SeedWidget__h__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT SeedWidget + : public vtkSeedWidget + { + public: + typedef SeedWidget Self; + vtkTypeMacro( SeedWidget, vtkSeedWidget ); + + typedef cpExtensions::Interaction::BaseStyle TBaseStyle; + + public: + static Self* New( ); + + virtual void SetInteractor( + vtkRenderWindowInteractor* rwi + ) cpExtensions_OVERRIDE; + + protected: + SeedWidget( ); + virtual ~SeedWidget( ); + + static void _AddPointAction( vtkAbstractWidget* wdg ); + static void _CompletedAction( vtkAbstractWidget* wdg ); + static void _MoveAction( vtkAbstractWidget* wdg ); + static void _EndSelectAction( vtkAbstractWidget* wdg ); + static void _DeleteAction( vtkAbstractWidget* wdg ); + + /* TODO + static void _Click( + void* data, const TBaseStyle::ButtonID& button, + int* idx, double* pos, bool alt, bool ctr, bool sft + ); + static void _DoubleClick( + void* data, const TBaseStyle::ButtonID& button, + int* idx, double* pos, bool alt, bool ctr, bool sft + ); + */ + + private: + // Purposely not implemented + SeedWidget( const Self& ); + Self& operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Interaction__SeedWidget__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/ActorsWidgetInterface.h b/lib/cpExtensions/QT/ActorsWidgetInterface.h new file mode 100644 index 0000000..6af66ea --- /dev/null +++ b/lib/cpExtensions/QT/ActorsWidgetInterface.h @@ -0,0 +1,68 @@ +#ifndef __cpExtensions__QT__ActorsWidgetInterface__h__ +#define __cpExtensions__QT__ActorsWidgetInterface__h__ + +#include + +#include +#include + +class vtkRenderWindowInteractor; + +namespace cpExtensions +{ + namespace QT + { + /** + */ + class cpExtensions_EXPORT ActorsWidgetInterface + { + public: + typedef ActorsWidgetInterface Self; + + public: + ActorsWidgetInterface( ) { } + virtual ~ActorsWidgetInterface( ) { } + + virtual std::set< vtkRenderWindowInteractor* > GetInteractors( ) const = 0; + + virtual std::set< std::string > GetActorsNames( ) const = 0; + virtual bool IsWindowLevelImageActor( const std::string& name ) const = 0; + virtual bool IsLUTImageActor( const std::string& name ) const = 0; + virtual bool Is3DActor( const std::string& name ) const = 0; + + virtual void GetScalarRange( const std::string& name, double r[ 2 ] ) const = 0; + virtual void GetWindowLevel( const std::string& name, double wl[ 2 ] ) const = 0; + virtual double GetWindow( const std::string& name ) const = 0; + virtual double GetLevel( const std::string& name ) const = 0; + virtual char GetImageInterpolation( const std::string& name ) const = 0; + + virtual void GetColor( const std::string& name, double& r, double& g, double& b ) const = 0; + virtual double GetOpacity( const std::string& name ) const = 0; + virtual double GetPointSize( const std::string& name ) const = 0; + virtual double GetLineWidth( const std::string& name ) const = 0; + virtual int GetRepresentation( const std::string& name ) const = 0; + + virtual void SetScalarRange( const std::string& name, double r[ 2 ] ) = 0; + virtual void SetScalarRange( const std::string& name, double min, double max ) = 0; + virtual void SetWindowLevel( const std::string& name, double wl[ 2 ] ) = 0; + virtual void SetWindowLevel( const std::string& name, double w, double l ) = 0; + virtual void SetWindow( const std::string& name, double w ) = 0; + virtual void SetLevel( const std::string& name, double l ) = 0; + virtual void SetImageInterpolation( const std::string& name, char i ) = 0; + + virtual void SetColor( const std::string& name, double r, double g, double b ) = 0; + virtual void SetOpacity( const std::string& name, double o ) = 0; + virtual void SetPointSize( const std::string& name, double s ) = 0; + virtual void SetLineWidth( const std::string& name, double w ) = 0; + virtual void SetRepresentationToPoints( const std::string& name ) = 0; + virtual void SetRepresentationToSurface( const std::string& name ) = 0; + virtual void SetRepresentationToWireframe( const std::string& name ) = 0; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__ActorsWidgetInterface__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/ConfigurationChooser.cxx b/lib/cpExtensions/QT/ConfigurationChooser.cxx new file mode 100644 index 0000000..00c121b --- /dev/null +++ b/lib/cpExtensions/QT/ConfigurationChooser.cxx @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::ConfigurationChooser:: +ConfigurationChooser( QWidget* parent, Qt::WindowFlags f ) + : Superclass( parent, f ), + m_UI( new Ui::ConfigurationChooser ), + m_Data( NULL ) +{ + this->m_UI->setupUi( this ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::ConfigurationChooser:: +~ConfigurationChooser( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::ConfigurationChooser:: +setData( ActorsWidgetInterface* data ) +{ + this->m_Data = data; + if( this->m_Data != NULL ) + { + auto actors = this->m_Data->GetActorsNames( ); + for( auto n = actors.begin( ); n != actors.end( ); ++n ) + { + if( this->m_Data->IsWindowLevelImageActor( *n ) ) + { + auto wl_wdg = new WindowLevelImageConfiguration( this ); + wl_wdg->setData( data, *n ); + this->m_UI->Configurations->addTab( wl_wdg, n->c_str( ) ); + } + else if( this->m_Data->IsLUTImageActor( *n ) ) + { + } + else if( this->m_Data->Is3DActor( *n ) ) + { + } // fi + + } // rof + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/ConfigurationChooser.h b/lib/cpExtensions/QT/ConfigurationChooser.h new file mode 100644 index 0000000..dc908ff --- /dev/null +++ b/lib/cpExtensions/QT/ConfigurationChooser.h @@ -0,0 +1,45 @@ +#ifndef __cpExtensions__QT__ConfigurationChooser__h__ +#define __cpExtensions__QT__ConfigurationChooser__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace Ui { class ConfigurationChooser; } + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace QT + { + class ActorsWidgetInterface; + + /** + */ + class cpExtensions_EXPORT ConfigurationChooser + : public QDialog + { + Q_OBJECT; + + public: + typedef ConfigurationChooser Self; + typedef QDialog Superclass; + + public: + explicit ConfigurationChooser( QWidget* parent = NULL, Qt::WindowFlags f = 0 ); + virtual ~ConfigurationChooser( ); + + void setData( ActorsWidgetInterface* data ); + + protected: + Ui::ConfigurationChooser* m_UI; + ActorsWidgetInterface* m_Data; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__ConfigurationChooser__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/ConfigurationChooser.ui b/lib/cpExtensions/QT/ConfigurationChooser.ui new file mode 100644 index 0000000..4c33dfa --- /dev/null +++ b/lib/cpExtensions/QT/ConfigurationChooser.ui @@ -0,0 +1,51 @@ + + + ConfigurationChooser + + + + 0 + 0 + 475 + 317 + + + + Dialog + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + Buttons + accepted() + ConfigurationChooser + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/lib/cpExtensions/QT/ImageWidget.cxx b/lib/cpExtensions/QT/ImageWidget.cxx new file mode 100644 index 0000000..bac5f17 --- /dev/null +++ b/lib/cpExtensions/QT/ImageWidget.cxx @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::ImageWidget:: +ImageWidget( QWidget* parent, Qt::WindowFlags f ) + : Superclass( parent, f ), + m_ImageName( "" ), + m_OutlineActor( NULL ) +{ + this->m_Style = vtkSmartPointer< TStyle >::New( ); + this->m_Style->SetCurrentRenderer( this->m_Renderer ); + this->SetStyle( this->m_Style ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::ImageWidget:: +~ImageWidget( ) +{ + this->Clear( ); + if( this->m_OutlineActor != NULL ) + delete this->m_OutlineActor; + for( auto a = this->m_Actors.begin( ); a != this->m_Actors.end( ); ++a ) + delete *a; + this->m_Actors.clear( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::ImageWidget:: +Clear( ) +{ + this->RemoveViewProps( ); + this->m_ImageName = ""; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::ImageWidget:: +SetImage( vtkImageData* image, const std::string& name, int orientation ) +{ + if( name == "" ) + return; + if( this->m_ImageName != "" ) + this->Clear( ); + this->m_ImageName = name; + + this->m_WLActor = vtkSmartPointer< TWLActor >::New( ); + this->m_WLActor->SetImage( image ); + this->m_WLActor->SetOrientation( orientation ); + + this->m_LUTActor = vtkSmartPointer< TLUTActor >::New( ); + this->m_LUTActor->SetOrientation( orientation ); + + this->m_Outline = vtkSmartPointer< TOutline >::New( ); + this->m_Outline->SetBounds( image->GetBounds( ) ); + this->m_Outline->Update( ); + + if( this->m_OutlineActor != NULL ) + delete this->m_OutlineActor; + this->m_OutlineActor = new TActor( ); + this->m_OutlineActor->SetMesh( this->m_Outline->GetOutput( ) ); + + double cr = double( 0 ); + double cg = double( 0 ); + double cb = double( 0 ); + switch( this->m_WLActor->GetOrientation( ) ) + { + case 0: cr = double( 1 ); break; + case 1: cg = double( 1 ); break; + case 2: cb = double( 1 ); break; + default: cr = double( 1 ); break; + } // hctiws + this->m_OutlineActor->GetActor( )->GetProperty( )->SetColor( cr, cg, cb ); + + this->AddViewProp( this->m_WLActor, this->m_ImageName ); + this->AddAuxViewProp( this->m_OutlineActor->GetActor( ), this->m_ImageName ); + this->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::ImageWidget:: +Add( vtkDataSet* data, const std::string& name ) +{ + auto image = dynamic_cast< vtkImageData* >( data ); + auto pdata = dynamic_cast< vtkPolyData* >( data ); + if( image != NULL ) + { + this->m_LUTActor->AddImage( image ); + this->m_LUTActor->GetProperty( )->SetOpacity( 0.5 ); + this->AddViewProp( this->m_LUTActor, "__LUT_IMAGE__" ); + this->Render( ); + } + else if( pdata != NULL ) + { + TActor* actor = new TActor( ); + actor->SetMesh( pdata ); + this->m_Actors.push_back( actor ); + this->AddViewProp( actor->GetActor( ), name ); + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::ImageWidget:: +ResetCamera( ) +{ + if( this->m_WLActor.GetPointer( ) != NULL ) + { + auto image = this->m_WLActor->GetImage( ); + if( image != NULL ) + { + double bounds[ 6 ]; + image->GetBounds( bounds ); + + // Compute camera properties + double center[ 3 ]; + center[ 0 ] = ( bounds[ 1 ] + bounds[ 0 ] ) / double( 2 ); + center[ 1 ] = ( bounds[ 3 ] + bounds[ 2 ] ) / double( 2 ); + center[ 2 ] = ( bounds[ 5 ] + bounds[ 4 ] ) / double( 2 ); + + int ori = this->m_WLActor->GetOrientation( ); + double pos[ 3 ] = { double( 0 ) }; + pos[ ori ] = double( 1 ); + pos[ 0 ] += center[ 0 ]; + pos[ 1 ] += center[ 1 ]; + pos[ 2 ] += center[ 2 ]; + + double up[ 3 ] = { double( 0 ) }; + if( ori == 0 ) + { + if ( this->m_Quadrant == 0 ) up[ 2 ] = double( 1 ); + else if( this->m_Quadrant == 1 ) up[ 2 ] = double( 1 ); + else if( this->m_Quadrant == 2 ) up[ 2 ] = double( 1 ); + else if( this->m_Quadrant == 3 ) up[ 2 ] = double( 1 ); + } + else if( ori == 1 ) + { + if ( this->m_Quadrant == 0 ) up[ 2 ] = double( 1 ); + else if( this->m_Quadrant == 1 ) up[ 2 ] = double( 1 ); + else if( this->m_Quadrant == 2 ) up[ 2 ] = double( 1 ); + else if( this->m_Quadrant == 3 ) up[ 2 ] = double( 1 ); + } + else if( ori == 2 ) + { + if ( this->m_Quadrant == 0 ) up[ 1 ] = double( -1 ); + else if( this->m_Quadrant == 1 ) up[ 1 ] = double( -1 ); + else if( this->m_Quadrant == 2 ) up[ 1 ] = double( -1 ); + else if( this->m_Quadrant == 3 ) up[ 1 ] = double( -1 ); + pos[ 2 ] *= double( -1 ); + + } // fi + + // Reconfigure camera and return + auto camera = this->m_Renderer->GetActiveCamera( ); + camera->ParallelProjectionOn( ); + camera->SetFocalPoint( center ); + camera->SetPosition( pos ); + camera->SetViewUp( up ); + this->m_Renderer->ResetCamera( bounds ); + } + else + this->Superclass::ResetCamera( ); + } + else + this->Superclass::ResetCamera( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::ImageWidget:: +TWLActor* cpExtensions::QT::ImageWidget:: +GetImageActor( ) +{ + return( this->m_WLActor ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::QT::ImageWidget:: +TWLActor* cpExtensions::QT::ImageWidget:: +GetImageActor( ) const +{ + return( this->m_WLActor ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::ImageWidget:: +SetColor( const std::string& name, double r, double g, double b ) +{ + auto props = this->GetViewProps( name ); + for( auto p = props.begin( ); p != props.end( ); ++p ) + { + auto actor = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( actor != NULL ) + actor->GetProperty( )->SetColor( r, g, b ); + + } // rof + this->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::ImageWidget:: +SetLineWidth( const std::string& name, double w ) +{ + auto props = this->GetViewProps( name ); + for( auto p = props.begin( ); p != props.end( ); ++p ) + { + auto actor = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( actor != NULL ) + actor->GetProperty( )->SetLineWidth( w ); + + } // rof + this->Render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/ImageWidget.h b/lib/cpExtensions/QT/ImageWidget.h new file mode 100644 index 0000000..9932bda --- /dev/null +++ b/lib/cpExtensions/QT/ImageWidget.h @@ -0,0 +1,75 @@ +#ifndef __cpExtensions__QT__ImageWidget__h__ +#define __cpExtensions__QT__ImageWidget__h__ + +#include + +// ------------------------------------------------------------------------- +class vtkDataSet; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class OutlineSource; + class LUTImageActor; + class WindowLevelImageActor; + class MeshActor; + } + namespace Interaction { class ImageSliceStyle; } + + namespace QT + { + /** + */ + class cpExtensions_EXPORT ImageWidget + : public RendererWidget + { + Q_OBJECT; + + public: + typedef ImageWidget Self; + typedef RendererWidget Superclass; + + typedef cpExtensions::Visualization::OutlineSource TOutline; + typedef cpExtensions::Visualization::MeshActor TActor; + typedef cpExtensions::Visualization::LUTImageActor TLUTActor; + typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor; + typedef cpExtensions::Interaction::ImageSliceStyle TStyle; + + public: + explicit ImageWidget( QWidget* parent = NULL, Qt::WindowFlags f = 0 ); + virtual ~ImageWidget( ); + + void Clear( ); + void SetImage( + vtkImageData* image, const std::string& name, int orientation = 2 + ); + void Add( vtkDataSet* data, const std::string& name ); + virtual void ResetCamera( ) cpExtensions_OVERRIDE; + + TWLActor* GetImageActor( ); + const TWLActor* GetImageActor( ) const; + + void SetColor( const std::string& name, double r, double g, double b ); + void SetLineWidth( const std::string& name, double w ); + + protected: + std::string m_ImageName; + + vtkSmartPointer< TWLActor > m_WLActor; + vtkSmartPointer< TLUTActor > m_LUTActor; + vtkSmartPointer< TOutline > m_Outline; + TActor* m_OutlineActor; + std::vector< TActor* > m_Actors; + + vtkSmartPointer< TStyle > m_Style; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__ImageWidget__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/MPR3DWidget.cxx b/lib/cpExtensions/QT/MPR3DWidget.cxx new file mode 100644 index 0000000..f86992d --- /dev/null +++ b/lib/cpExtensions/QT/MPR3DWidget.cxx @@ -0,0 +1,140 @@ +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::MPR3DWidget:: +MPR3DWidget( QWidget* parent, Qt::WindowFlags f ) + : Superclass( parent, f ), + m_ImageName( "" ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::MPR3DWidget:: +~MPR3DWidget( ) +{ + for( auto a = this->m_Actors.begin( ); a != this->m_Actors.end( ); ++a ) + delete *a; + this->m_Actors.clear( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::MPR3DWidget:: +Clear( ) +{ + this->RemoveViewProps( ); + this->m_ImageName = ""; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::MPR3DWidget:: +SetImage( vtkImageData* image, const std::string& name ) +{ + if( name == "" ) + return; + if( this->m_ImageName != "" ) + this->Clear( ); + this->m_ImageName = name; + + for( unsigned int o = 0; o < 3; ++o ) + { + this->m_WLActors[ o ] = vtkSmartPointer< TWLActor >::New( ); + this->m_WLActors[ o ]->SetImage( image ); + this->m_WLActors[ o ]->SetOrientation( o ); + + this->m_OLActors[ o ] = vtkSmartPointer< TOLActor >::New( ); + this->m_OLActors[ o ]->SetBounds( + o, image->GetBounds( )[ o << 1 ], image->GetBounds( ) + ); + + this->AddViewProp( this->m_WLActors[ o ], this->m_ImageName ); + this->AddAuxViewProp( this->m_OLActors[ o ], this->m_ImageName ); + this->ResetCamera( ); + + } // rof +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::MPR3DWidget:: +Add( vtkDataSet* data, const std::string& name ) +{ + auto image = dynamic_cast< vtkImageData* >( data ); + auto pdata = dynamic_cast< vtkPolyData* >( data ); + if( image != NULL ) + { + /* TODO + if( this->m_ImageName != "" ) + { + } + else + this->SetImage( image, name ); + */ + } + else if( pdata != NULL ) + { + TActor* actor = new TActor( ); + actor->SetMesh( pdata ); + this->m_Actors.push_back( actor ); + this->AddViewProp( actor->GetActor( ), name ); + this->Render( ); + if( this->m_ImageName == "" ) + this->ResetCamera( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::MPR3DWidget:: +TWLActor* cpExtensions::QT::MPR3DWidget:: +GetImageActor( int o ) +{ + return( this->m_WLActors[ o % 3 ] ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::QT::MPR3DWidget:: +TWLActor* cpExtensions::QT::MPR3DWidget:: +GetImageActor( int o ) const +{ + return( this->m_WLActors[ o % 3 ] ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::MPR3DWidget:: +SetSliceNumber( int orientation, int slice ) +{ + int o = orientation % 3; + this->m_WLActors[ o ]->SetSliceNumber( slice ); + this->m_OLActors[ o ]->SetBounds( + o, + this->m_WLActors[ o ]->GetSlicePlane( )->GetOrigin( )[ o ], + this->m_WLActors[ o ]->GetImage( )->GetBounds( ) + ); + this->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::MPR3DWidget:: +SetSlicesNumbers( int x, int y, int z ) +{ + int s[] = { x, y, z }; + for( int o = 0; o < 3; ++o ) + { + this->m_WLActors[ o ]->SetSliceNumber( s[ o ] ); + this->m_OLActors[ o ]->SetBounds( + o, + this->m_WLActors[ o ]->GetSlicePlane( )->GetOrigin( )[ o ], + this->m_WLActors[ o ]->GetImage( )->GetBounds( ) + ); + + } // rof + this->Render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/MPR3DWidget.h b/lib/cpExtensions/QT/MPR3DWidget.h new file mode 100644 index 0000000..6a0ef6e --- /dev/null +++ b/lib/cpExtensions/QT/MPR3DWidget.h @@ -0,0 +1,64 @@ +#ifndef __cpExtensions__QT__MPR3DWidget__h__ +#define __cpExtensions__QT__MPR3DWidget__h__ + +#include + +// ------------------------------------------------------------------------- +class vtkDataSet; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class ImageOutlineActor; + class MeshActor; + class WindowLevelImageActor; + } + + namespace QT + { + /** + */ + class cpExtensions_EXPORT MPR3DWidget + : public cpExtensions::QT::RendererWidget + { + Q_OBJECT; + + public: + typedef MPR3DWidget Self; + typedef cpExtensions::QT::RendererWidget Superclass; + + typedef cpExtensions::Visualization::MeshActor TActor; + typedef cpExtensions::Visualization::ImageOutlineActor TOLActor; + typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor; + + public: + explicit MPR3DWidget( QWidget* parent = NULL, Qt::WindowFlags f = 0 ); + virtual ~MPR3DWidget( ); + + void Clear( ); + void SetImage( vtkImageData* image, const std::string& name ); + void Add( vtkDataSet* data, const std::string& name ); + + TWLActor* GetImageActor( int o ); + const TWLActor* GetImageActor( int o ) const; + + void SetSliceNumber( int orientation, int slice ); + void SetSlicesNumbers( int x, int y, int z ); + + protected: + std::string m_ImageName; + + vtkSmartPointer< TWLActor > m_WLActors[ 3 ]; + vtkSmartPointer< TOLActor > m_OLActors[ 3 ]; + std::vector< TActor* > m_Actors; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__MPR3DWidget__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/MPRInteractionCommand.cxx b/lib/cpExtensions/QT/MPRInteractionCommand.cxx new file mode 100644 index 0000000..39dc19d --- /dev/null +++ b/lib/cpExtensions/QT/MPRInteractionCommand.cxx @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::MPRInteractionCommand:: +Self* cpExtensions::QT::MPRInteractionCommand:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::MPRInteractionCommand:: +AddWidget( QWidget* w ) +{ + typedef cpExtensions::QT::ImageWidget _TImageWidget; + typedef cpExtensions::QT::MPR3DWidget _TMPR3DWidget; + + auto img = dynamic_cast< _TImageWidget* >( w ); + auto ren = dynamic_cast< _TMPR3DWidget* >( w ); + if( img != NULL ) + this->m_ImageWidgets.insert( img ); + else if( ren != NULL ) + this->m_MPR3DWidgets.insert( ren ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::MPRInteractionCommand:: +Execute( vtkObject* caller, unsigned long evId, void* data ) +{ + typedef cpExtensions::Interaction::ImageSliceStyle _TStyle; + + static const unsigned long _SuperCursor = vtkCommand::UserEvent + 1; + static const unsigned long _Slice = vtkCommand::UserEvent + 2; + + // Prepare interaction data + auto* src = dynamic_cast< _TStyle* >( caller ); + if( src == NULL || ( evId != _SuperCursor && evId != _Slice ) ) + return; + if( evId == _SuperCursor ) + { + /* TODO + auto ori = src->GetActors( )->GetOrientation( ); + auto img = src->GetActors( )->GetImage( ); + auto pos = reinterpret_cast< double* >( data ); + int ijk[ 3 ]; + double pcoords[ 3 ]; + img->ComputeStructuredCoordinates( pos, ijk, pcoords ); + + for( + auto i = this->m_ImageWidgets.begin( ); + i != this->m_ImageWidgets.end( ); + ++i + ) + if( ( *i )->GetInteractorStyle( ) != src ) + ( *i )->SetSliceNumber( ijk[ ( *i )->GetOrientation( ) ] ); + + for( + auto r = this->m_MPR3DWidgets.begin( ); + r != this->m_MPR3DWidgets.end( ); + ++r + ) + ( *r )->SetSlicesNumbers( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ] ); + */ + } + else if( evId == _Slice ) + { + int slc = src->GetSliceNumber( ); + int ori = src->GetOrientation( ); + for( + auto r = this->m_MPR3DWidgets.begin( ); + r != this->m_MPR3DWidgets.end( ); + ++r + ) + ( *r )->SetSliceNumber( ori, slc ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::MPRInteractionCommand:: +MPRInteractionCommand( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::MPRInteractionCommand:: +~MPRInteractionCommand( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/MPRInteractionCommand.h b/lib/cpExtensions/QT/MPRInteractionCommand.h new file mode 100644 index 0000000..29aa5de --- /dev/null +++ b/lib/cpExtensions/QT/MPRInteractionCommand.h @@ -0,0 +1,58 @@ +#ifndef __cpExtensions__QT__MPRInteractionCommand__h__ +#define __cpExtensions__QT__MPRInteractionCommand__h__ + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace QT + { + class ImageWidget; + class MPR3DWidget; + + /** + */ + class cpExtensions_EXPORT MPRInteractionCommand + : public vtkCommand + { + public: + typedef MPRInteractionCommand Self; + + public: + vtkTypeMacro( MPRInteractionCommand, vtkCommand ); + + public: + static Self* New( ); + + void AddWidget( QWidget* w ); + + virtual void Execute( + vtkObject* caller, unsigned long evId, void* data + ) cpExtensions_OVERRIDE; + + protected: + MPRInteractionCommand( ); + virtual ~MPRInteractionCommand( ); + + private: + // Purposely not implemented + MPRInteractionCommand( const Self& ); + Self& operator=( const Self& ); + + protected: + std::set< cpExtensions::QT::ImageWidget* > m_ImageWidgets; + std::set< cpExtensions::QT::MPR3DWidget* > m_MPR3DWidgets; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__MPRInteractionCommand__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/RendererWidget.cxx b/lib/cpExtensions/QT/RendererWidget.cxx new file mode 100644 index 0000000..0189ef6 --- /dev/null +++ b/lib/cpExtensions/QT/RendererWidget.cxx @@ -0,0 +1,990 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::RendererWidget:: +RendererWidget( QWidget* parent, Qt::WindowFlags f ) + : Superclass( parent, f ), + Superclass2( ) +{ + this->m_Renderer = vtkSmartPointer< vtkRenderer >::New( ); + this->GetRenderWindow( )->AddRenderer( this->m_Renderer ); + + vtkAxesActor* axes = vtkAxesActor::New( ); + axes->AxisLabelsOff( ); + this->m_Marker = vtkSmartPointer< vtkOrientationMarkerWidget >::New( ); + this->m_Marker->SetOutlineColor( 1, 1, 1 ); + this->m_Marker->SetOrientationMarker( axes ); + this->m_Marker->SetInteractor( this->GetRenderWindow( )->GetInteractor( ) ); + this->m_Marker->EnabledOn( ); + this->m_Marker->InteractiveOff( ); + axes->Delete( ); + this->SetQuadrant( 0 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::RendererWidget:: +~RendererWidget( ) +{ +} + +// ------------------------------------------------------------------------- +int cpExtensions::QT::RendererWidget:: +GetQuadrant( ) const +{ + return( this->m_Quadrant ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetQuadrant( int q ) +{ + this->m_Quadrant = ( q - 1 ) % 4; + if( this->m_Quadrant == 0 ) + this->m_Marker->SetViewport( 0.85, 0.00, 1.00, 0.15 ); + else if( this->m_Quadrant == 1 ) + this->m_Marker->SetViewport( 0.00, 0.00, 0.15, 0.15 ); + else if( this->m_Quadrant == 2 ) + this->m_Marker->SetViewport( 0.00, 0.85, 0.15, 1.00 ); + else if( this->m_Quadrant == 3 ) + this->m_Marker->SetViewport( 0.85, 0.85, 1.00, 1.00 ); +} + +// ------------------------------------------------------------------------- +vtkRenderer* cpExtensions::QT::RendererWidget:: +GetRenderer( ) +{ + return( this->m_Renderer ); +} + +// ------------------------------------------------------------------------- +const vtkRenderer* cpExtensions::QT::RendererWidget:: +GetRenderer( ) const +{ + return( this->m_Renderer ); +} + +// ------------------------------------------------------------------------- +vtkInteractorStyle* cpExtensions::QT::RendererWidget:: +GetStyle( ) +{ + auto iren = this->GetInteractor( ); + if( iren != NULL ) + return( + dynamic_cast< vtkInteractorStyle* >( iren->GetInteractorStyle( ) ) + ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const vtkInteractorStyle* cpExtensions::QT::RendererWidget:: +GetStyle( ) const +{ + // Ugly, but necessary :-( + Self* self = const_cast< Self* >( this ); + if( self != NULL ) + { + auto iren = self->GetInteractor( ); + if( iren != NULL ) + return( + dynamic_cast< const vtkInteractorStyle* >( + iren->GetInteractorStyle( ) + ) + ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetStyle( vtkInteractorStyle* style ) +{ + this->GetInteractor( )->SetInteractorStyle( style ); +} + +// ------------------------------------------------------------------------- +vtkCamera* cpExtensions::QT::RendererWidget:: +GetActiveCamera( ) +{ + return( this->m_Renderer->GetActiveCamera( ) ); +} + +// ------------------------------------------------------------------------- +const vtkCamera* cpExtensions::QT::RendererWidget:: +GetActiveCamera( ) const +{ + return( this->m_Renderer->GetActiveCamera( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +AddViewProp( vtkProp* prop, const std::string& name ) +{ + if( prop != NULL ) + { + auto i = this->m_ViewProps.find( name ); + if( i == this->m_ViewProps.end( ) ) + i = + this->m_ViewProps.insert( + TPropCollection::value_type( name, TProps( ) ) + ).first; + i->second.insert( prop ); + this->m_Renderer->AddViewProp( prop ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +AddViewProps( vtkPropCollection* props, const std::string& name ) +{ + if( props != NULL ) + { + auto i = this->m_ViewProps.find( name ); + if( i == this->m_ViewProps.end( ) ) + i = + this->m_ViewProps.insert( + TPropCollection::value_type( name, TProps( ) ) + ).first; + props->InitTraversal( ); + while( vtkProp* prop = props->GetNextProp( ) ) + { + i->second.insert( prop ); + this->m_Renderer->AddViewProp( prop ); + + } // elihw + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +AddAuxViewProp( vtkProp* prop, const std::string& name ) +{ + if( prop != NULL ) + { + auto i = this->m_AuxViewProps.find( name ); + if( i == this->m_AuxViewProps.end( ) ) + i = + this->m_AuxViewProps.insert( + TPropCollection::value_type( name, TProps( ) ) + ).first; + i->second.insert( prop ); + this->m_Renderer->AddViewProp( prop ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +AddAuxViewProps( vtkPropCollection* props, const std::string& name ) +{ + if( props != NULL ) + { + auto i = this->m_AuxViewProps.find( name ); + if( i == this->m_AuxViewProps.end( ) ) + i = + this->m_AuxViewProps.insert( + TPropCollection::value_type( name, TProps( ) ) + ).first; + props->InitTraversal( ); + while( vtkProp* prop = props->GetNextProp( ) ) + { + i->second.insert( prop ); + this->m_Renderer->AddViewProp( prop ); + + } // elhiw + + } // fi +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::RendererWidget:: +TProps& cpExtensions::QT::RendererWidget:: +GetViewProps( const std::string& name ) +{ + static TProps zero; + auto i = this->m_ViewProps.find( name ); + if( i == this->m_ViewProps.end( ) ) + { + zero.clear( ); + return( zero ); + } + else + return( i->second ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::QT::RendererWidget:: +TProps& cpExtensions::QT::RendererWidget:: +GetViewProps( const std::string& name ) const +{ + static const TProps zero; + auto i = this->m_ViewProps.find( name ); + if( i == this->m_ViewProps.end( ) ) + return( zero ); + else + return( i->second ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::RendererWidget:: +TProps& cpExtensions::QT::RendererWidget:: +GetAuxViewProps( const std::string& name ) +{ + static TProps zero; + auto i = this->m_AuxViewProps.find( name ); + if( i == this->m_AuxViewProps.end( ) ) + { + zero.clear( ); + return( zero ); + } + else + return( i->second ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::QT::RendererWidget:: +TProps& cpExtensions::QT::RendererWidget:: +GetAuxViewProps( const std::string& name ) const +{ + static const TProps zero; + auto i = this->m_AuxViewProps.find( name ); + if( i == this->m_AuxViewProps.end( ) ) + return( zero ); + else + return( i->second ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +RemoveViewProps( const std::string& name ) +{ + auto i = this->m_ViewProps.find( name ); + if( i != this->m_ViewProps.end( ) ) + { + for( auto p = i->second.begin( ); p != i->second.end( ); ++p ) + this->m_Renderer->RemoveViewProp( *p ); + this->m_ViewProps.erase( i ); + + } // fi + + i = this->m_AuxViewProps.find( name ); + if( i != this->m_AuxViewProps.end( ) ) + { + for( auto p = i->second.begin( ); p != i->second.end( ); ++p ) + this->m_Renderer->RemoveViewProp( *p ); + this->m_AuxViewProps.erase( i ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +RemoveViewProps( ) +{ + this->m_Renderer->RemoveAllViewProps( ); + this->m_ViewProps.clear( ); + this->m_AuxViewProps.clear( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +HideViewProps( const std::string& name ) +{ + auto i = this->m_ViewProps.find( name ); + if( i != this->m_ViewProps.end( ) ) + for( auto p = i->second.begin( ); p != i->second.end( ); ++p ) + ( *p )->VisibilityOff( ); + i = this->m_AuxViewProps.find( name ); + if( i != this->m_AuxViewProps.end( ) ) + for( auto p = i->second.begin( ); p != i->second.end( ); ++p ) + ( *p )->VisibilityOff( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +ShowViewProps( const std::string& name ) +{ + auto i = this->m_ViewProps.find( name ); + if( i != this->m_ViewProps.end( ) ) + for( auto p = i->second.begin( ); p != i->second.end( ); ++p ) + ( *p )->VisibilityOn( ); + i = this->m_AuxViewProps.find( name ); + if( i != this->m_AuxViewProps.end( ) ) + for( auto p = i->second.begin( ); p != i->second.end( ); ++p ) + ( *p )->VisibilityOn( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +ResetCamera( ) +{ + this->m_Renderer->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +Render( ) +{ + this->GetRenderWindow( )->Render( ); +} + +// ------------------------------------------------------------------------- +std::set< vtkRenderWindowInteractor* > cpExtensions::QT::RendererWidget:: +GetInteractors( ) const +{ + Self* self = const_cast< Self* >( this ); + std::set< vtkRenderWindowInteractor* > ret; + ret.insert( self->GetRenderWindow( )->GetInteractor( ) ); + return( ret ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpExtensions::QT::RendererWidget:: +GetActorsNames( ) const +{ + std::set< std::string > names; + for( + auto p = this->m_ViewProps.begin( ); + p != this->m_ViewProps.end( ); + ++p + ) + names.insert( p->first ); + return( names ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::RendererWidget:: +IsWindowLevelImageActor( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto a = it->second.begin( ); + if( a != it->second.end( ) ) + return( dynamic_cast< TWLActor* >( a->GetPointer( ) ) != NULL ); + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::RendererWidget:: +IsLUTImageActor( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto a = it->second.begin( ); + if( a != it->second.end( ) ) + return( dynamic_cast< TLUTActor* >( a->GetPointer( ) ) != NULL ); + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::RendererWidget:: +Is3DActor( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto a = it->second.begin( ); + if( a != it->second.end( ) ) + return( dynamic_cast< vtkActor* >( a->GetPointer( ) ) != NULL ); + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +GetScalarRange( const std::string& name, double r[ 2 ] ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + TWLActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + a->GetRange( r ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +GetWindowLevel( const std::string& name, double wl[ 2 ] ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + TWLActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + a->GetWindowLevel( wl ); + + } // fi +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::RendererWidget:: +GetWindow( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + TWLActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + return( a->GetWindow( ) ); + else + return( 0 ); + } + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::RendererWidget:: +GetLevel( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + TWLActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + return( a->GetLevel( ) ); + else + return( 0 ); + } + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +char cpExtensions::QT::RendererWidget:: +GetImageInterpolation( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + TWLActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + { + int int_type = a->GetProperty( )->GetInterpolationType( ); + char ret = 0; + switch( int_type ) + { + case VTK_NEAREST_INTERPOLATION: ret = 'N'; break; + case VTK_LINEAR_INTERPOLATION: ret = 'L'; break; + case VTK_CUBIC_INTERPOLATION: ret = 'C'; break; + default: ret = 0; break; + } // hctiws + return( ret ); + } + else + return( 0 ); + } + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +GetColor( const std::string& name, double& r, double& g, double& b ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + vtkActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + return( a->GetProperty( )->GetColor( r, g, b ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::RendererWidget:: +GetOpacity( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + vtkActor* a = NULL; + vtkImageSlice* s = NULL; + while( a == NULL && s == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + s = dynamic_cast< vtkImageSlice* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + return( a->GetProperty( )->GetOpacity( ) ); + else if( s != NULL ) + return( s->GetProperty( )->GetOpacity( ) ); + else + return( 0 ); + } + return( 0 ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::RendererWidget:: +GetPointSize( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + vtkActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + return( a->GetProperty( )->GetPointSize( ) ); + else + return( 0 ); + } + return( 0 ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::RendererWidget:: +GetLineWidth( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + vtkActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + return( a->GetProperty( )->GetLineWidth( ) ); + else + return( 0 ); + } + return( 0 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::QT::RendererWidget:: +GetRepresentation( const std::string& name ) const +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + auto p = it->second.begin( ); + vtkActor* a = NULL; + while( a == NULL && p != it->second.end( ) ) + { + a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + p++; + + } // elihw + if( a != NULL ) + return( a->GetProperty( )->GetRepresentation( ) ); + else + return( -1 ); + } + return( -1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetScalarRange( const std::string& name, double r[ 2 ] ) +{ + this->SetScalarRange( name, r[ 0 ], r[ 1 ] ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetScalarRange( const std::string& name, double min, double max ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->SetRange( min, max ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetWindowLevel( const std::string& name, double wl[ 2 ] ) +{ + this->SetWindowLevel( name, wl[ 0 ], wl[ 1 ] ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetWindowLevel( const std::string& name, double w, double l ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->SetWindowLevel( w, l ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetWindow( const std::string& name, double w ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->SetWindow( w ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetLevel( const std::string& name, double l ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->SetLevel( l ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetImageInterpolation( const std::string& name, char i ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + int int_type = VTK_NEAREST_INTERPOLATION; + switch( i ) + { + case 'L': int_type = VTK_LINEAR_INTERPOLATION; break; + case 'C': int_type = VTK_CUBIC_INTERPOLATION; break; + default: int_type = VTK_NEAREST_INTERPOLATION; break; + } // hctiws + a->GetProperty( )->SetInterpolationType( int_type ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetColor( const std::string& name, double r, double g, double b ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->GetProperty( )->SetColor( r, g, b ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetOpacity( const std::string& name, double o ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + vtkImageSlice* s = dynamic_cast< vtkImageSlice* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->GetProperty( )->SetOpacity( o ); + } + else if( s != NULL ) + { + render = true; + s->GetProperty( )->SetOpacity( o ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetPointSize( const std::string& name, double s ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->GetProperty( )->SetPointSize( s ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetLineWidth( const std::string& name, double w ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->GetProperty( )->SetLineWidth( w ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetRepresentationToPoints( const std::string& name ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->GetProperty( )->SetRepresentationToPoints( ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetRepresentationToSurface( const std::string& name ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->GetProperty( )->SetRepresentationToSurface( ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::RendererWidget:: +SetRepresentationToWireframe( const std::string& name ) +{ + auto it = this->m_ViewProps.find( name ); + if( it != this->m_ViewProps.end( ) ) + { + bool render = false; + for( auto p = it->second.begin( ); p != it->second.end( ); ++p ) + { + vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) ); + if( a != NULL ) + { + render = true; + a->GetProperty( )->SetRepresentationToWireframe( ); + + } // fi + + } // rof + if( render ) + this->Render( ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/RendererWidget.h b/lib/cpExtensions/QT/RendererWidget.h new file mode 100644 index 0000000..2a5b145 --- /dev/null +++ b/lib/cpExtensions/QT/RendererWidget.h @@ -0,0 +1,138 @@ +#ifndef __cpExtensions__QT__RendererWidget__h__ +#define __cpExtensions__QT__RendererWidget__h__ + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkCamera; +class vtkInteractorStyle; +class vtkOrientationMarkerWidget; +class vtkProp; +class vtkPropCollection; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class LUTImageActor; + class WindowLevelImageActor; + } + + namespace QT + { + /** + */ + class cpExtensions_EXPORT RendererWidget + : public cpExtensions_QVTKWidget, + public ActorsWidgetInterface + { + Q_OBJECT; + public: + typedef RendererWidget Self; + typedef cpExtensions_QVTKWidget Superclass; + typedef ActorsWidgetInterface Superclass2; + + typedef std::set< vtkSmartPointer< vtkProp > > TProps; + typedef std::map< std::string, TProps > TPropCollection; + + typedef cpExtensions::Visualization::LUTImageActor TLUTActor; + typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor; + + public: + explicit RendererWidget( + QWidget* parent = NULL, Qt::WindowFlags f = 0 + ); + virtual ~RendererWidget( ); + + int GetQuadrant( ) const; + void SetQuadrant( int q ); + + vtkRenderer* GetRenderer( ); + const vtkRenderer* GetRenderer( ) const; + + vtkInteractorStyle* GetStyle( ); + const vtkInteractorStyle* GetStyle( ) const; + void SetStyle( vtkInteractorStyle* style ); + + vtkCamera* GetActiveCamera( ); + const vtkCamera* GetActiveCamera( ) const; + + void AddViewProp( vtkProp* prop, const std::string& name = "" ); + void AddViewProps( + vtkPropCollection* props, const std::string& name = "" + ); + void AddAuxViewProp( vtkProp* prop, const std::string& name = "" ); + void AddAuxViewProps( + vtkPropCollection* props, const std::string& name = "" + ); + + TProps& GetViewProps( const std::string& name ); + const TProps& GetViewProps( const std::string& name ) const; + TProps& GetAuxViewProps( const std::string& name ); + const TProps& GetAuxViewProps( const std::string& name ) const; + + void RemoveViewProps( const std::string& name ); + void RemoveViewProps( ); + + virtual void HideViewProps( const std::string& name ); + virtual void ShowViewProps( const std::string& name ); + + virtual void ResetCamera( ); + virtual void Render( ); + + virtual std::set< vtkRenderWindowInteractor* > GetInteractors( ) const cpExtensions_OVERRIDE; + virtual std::set< std::string > GetActorsNames( ) const cpExtensions_OVERRIDE; + virtual bool IsWindowLevelImageActor( const std::string& name ) const cpExtensions_OVERRIDE; + virtual bool IsLUTImageActor( const std::string& name ) const cpExtensions_OVERRIDE; + virtual bool Is3DActor( const std::string& name ) const cpExtensions_OVERRIDE; + + virtual void GetScalarRange( const std::string& name, double r[ 2 ] ) const cpExtensions_OVERRIDE; + virtual void GetWindowLevel( const std::string& name, double wl[ 2 ] ) const cpExtensions_OVERRIDE; + virtual double GetWindow( const std::string& name ) const cpExtensions_OVERRIDE; + virtual double GetLevel( const std::string& name ) const cpExtensions_OVERRIDE; + virtual char GetImageInterpolation( const std::string& name ) const cpExtensions_OVERRIDE; + + virtual void GetColor( const std::string& name, double& r, double& g, double& b ) const cpExtensions_OVERRIDE; + virtual double GetOpacity( const std::string& name ) const cpExtensions_OVERRIDE; + virtual double GetPointSize( const std::string& name ) const cpExtensions_OVERRIDE; + virtual double GetLineWidth( const std::string& name ) const cpExtensions_OVERRIDE; + virtual int GetRepresentation( const std::string& name ) const cpExtensions_OVERRIDE; + + virtual void SetScalarRange( const std::string& name, double r[ 2 ] ) cpExtensions_OVERRIDE; + virtual void SetScalarRange( const std::string& name, double min, double max ) cpExtensions_OVERRIDE; + virtual void SetWindowLevel( const std::string& name, double wl[ 2 ] ) cpExtensions_OVERRIDE; + virtual void SetWindowLevel( const std::string& name, double w, double l ) cpExtensions_OVERRIDE; + virtual void SetWindow( const std::string& name, double w ) cpExtensions_OVERRIDE; + virtual void SetLevel( const std::string& name, double l ) cpExtensions_OVERRIDE; + virtual void SetImageInterpolation( const std::string& name, char i ) cpExtensions_OVERRIDE; + + virtual void SetColor( const std::string& name, double r, double g, double b ) cpExtensions_OVERRIDE; + virtual void SetOpacity( const std::string& name, double o ) cpExtensions_OVERRIDE; + virtual void SetPointSize( const std::string& name, double s ) cpExtensions_OVERRIDE; + virtual void SetLineWidth( const std::string& name, double w ) cpExtensions_OVERRIDE; + virtual void SetRepresentationToPoints( const std::string& name ) cpExtensions_OVERRIDE; + virtual void SetRepresentationToSurface( const std::string& name ) cpExtensions_OVERRIDE; + virtual void SetRepresentationToWireframe( const std::string& name ) cpExtensions_OVERRIDE; + + protected: + vtkSmartPointer< vtkRenderer > m_Renderer; + vtkSmartPointer< vtkOrientationMarkerWidget > m_Marker; + int m_Quadrant; + + TPropCollection m_ViewProps; + TPropCollection m_AuxViewProps; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__RendererWidget__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.cxx b/lib/cpExtensions/QT/SimpleMPRWidget.cxx new file mode 100644 index 0000000..9b47dfd --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.cxx @@ -0,0 +1,635 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +SimpleMPRWidget( QWidget* parent, Qt::WindowFlags f ) + : Superclass( parent, f ), + Superclass2( ), + m_UI( new Ui::SimpleMPRWidget ), + m_MainImageName( "" ) +{ + this->m_UI->setupUi( this ); + + // Prepare default configuration + this->m_UI->Q1->hide( ); + this->m_UI->Q2->hide( ); + this->m_UI->Q3->hide( ); + this->m_UI->Q4->hide( ); + this->m_UI->Q1->close( ); + this->m_UI->Q2->close( ); + this->m_UI->Q3->close( ); + this->m_UI->Q4->close( ); + delete this->m_UI->Q1; + delete this->m_UI->Q2; + delete this->m_UI->Q3; + delete this->m_UI->Q4; + this->m_XImage = new ImageWidget( this ); + this->m_YImage = new ImageWidget( this ); + this->m_ZImage = new ImageWidget( this ); + this->m_3DView = new MPR3DWidget( this ); + this->m_UI->Q1 = this->m_XImage; + this->m_UI->Q2 = this->m_YImage; + this->m_UI->Q3 = this->m_ZImage; + this->m_UI->Q4 = this->m_3DView; + this->Configure( 'y', 'x', 'w', 'z' ); + + // Interaction synchronizer + unsigned long ev1 = vtkCommand::UserEvent + 1; + unsigned long ev2 = vtkCommand::UserEvent + 2; + vtkSmartPointer< cpExtensions::QT::MPRInteractionCommand > cmd = + vtkSmartPointer< cpExtensions::QT::MPRInteractionCommand >::New( ); + cmd->AddWidget( this->m_XImage ); + cmd->AddWidget( this->m_YImage ); + cmd->AddWidget( this->m_ZImage ); + cmd->AddWidget( this->m_3DView ); + this->m_XImage->GetStyle( )->AddObserver( ev1, cmd ); + this->m_YImage->GetStyle( )->AddObserver( ev1, cmd ); + this->m_ZImage->GetStyle( )->AddObserver( ev1, cmd ); + this->m_XImage->GetStyle( )->AddObserver( ev2, cmd ); + this->m_YImage->GetStyle( )->AddObserver( ev2, cmd ); + this->m_ZImage->GetStyle( )->AddObserver( ev2, cmd ); + + // Connect slots + this->connect( + this->m_UI->Top, SIGNAL( splitterMoved( int, int ) ), + this, SLOT( _SyncBottom( int, int ) ) + ); + this->connect( + this->m_UI->Bottom, SIGNAL( splitterMoved( int, int ) ), + this, SLOT( _SyncTop( int, int ) ) + ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +~SimpleMPRWidget( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +Configure( char q1, char q2, char q3, char q4 ) +{ + // Hide all widgets + this->m_UI->Q1->hide( ); + this->m_UI->Q2->hide( ); + this->m_UI->Q3->hide( ); + this->m_UI->Q4->hide( ); + this->m_UI->Q1->close( ); + this->m_UI->Q2->close( ); + this->m_UI->Q3->close( ); + this->m_UI->Q4->close( ); + + // Reorder them + if ( q1 == 'x' ) this->m_UI->Top->addWidget( this->m_XImage ); + else if( q1 == 'y' ) this->m_UI->Top->addWidget( this->m_YImage ); + else if( q1 == 'z' ) this->m_UI->Top->addWidget( this->m_ZImage ); + else if( q1 == 'w' ) this->m_UI->Top->addWidget( this->m_3DView ); + if ( q2 == 'x' ) this->m_UI->Top->addWidget( this->m_XImage ); + else if( q2 == 'y' ) this->m_UI->Top->addWidget( this->m_YImage ); + else if( q2 == 'z' ) this->m_UI->Top->addWidget( this->m_ZImage ); + else if( q2 == 'w' ) this->m_UI->Top->addWidget( this->m_3DView ); + this->m_UI->Top->update( ); + if ( q4 == 'x' ) this->m_UI->Bottom->addWidget( this->m_XImage ); + else if( q4 == 'y' ) this->m_UI->Bottom->addWidget( this->m_YImage ); + else if( q4 == 'z' ) this->m_UI->Bottom->addWidget( this->m_ZImage ); + else if( q4 == 'w' ) this->m_UI->Bottom->addWidget( this->m_3DView ); + if ( q3 == 'x' ) this->m_UI->Bottom->addWidget( this->m_XImage ); + else if( q3 == 'y' ) this->m_UI->Bottom->addWidget( this->m_YImage ); + else if( q3 == 'z' ) this->m_UI->Bottom->addWidget( this->m_ZImage ); + else if( q3 == 'w' ) this->m_UI->Bottom->addWidget( this->m_3DView ); + this->m_UI->Bottom->update( ); + + // Keep track + if ( q1 == 'x' ) this->m_UI->Q1 = this->m_XImage; + else if( q1 == 'y' ) this->m_UI->Q1 = this->m_YImage; + else if( q1 == 'z' ) this->m_UI->Q1 = this->m_ZImage; + else if( q1 == 'w' ) this->m_UI->Q1 = this->m_3DView; + if ( q2 == 'x' ) this->m_UI->Q2 = this->m_XImage; + else if( q2 == 'y' ) this->m_UI->Q2 = this->m_YImage; + else if( q2 == 'z' ) this->m_UI->Q2 = this->m_ZImage; + else if( q2 == 'w' ) this->m_UI->Q2 = this->m_3DView; + if ( q3 == 'x' ) this->m_UI->Q3 = this->m_XImage; + else if( q3 == 'y' ) this->m_UI->Q3 = this->m_YImage; + else if( q3 == 'z' ) this->m_UI->Q3 = this->m_ZImage; + else if( q3 == 'w' ) this->m_UI->Q3 = this->m_3DView; + if ( q4 == 'x' ) this->m_UI->Q4 = this->m_XImage; + else if( q4 == 'y' ) this->m_UI->Q4 = this->m_YImage; + else if( q4 == 'z' ) this->m_UI->Q4 = this->m_ZImage; + else if( q4 == 'w' ) this->m_UI->Q4 = this->m_3DView; + + // Draw all + this->m_UI->Q1->show( ); + this->m_UI->Q2->show( ); + this->m_UI->Q3->show( ); + this->m_UI->Q4->show( ); + dynamic_cast< RendererWidget* >( this->m_UI->Q1 )->SetQuadrant( 1 ); + dynamic_cast< RendererWidget* >( this->m_UI->Q2 )->SetQuadrant( 2 ); + dynamic_cast< RendererWidget* >( this->m_UI->Q3 )->SetQuadrant( 3 ); + dynamic_cast< RendererWidget* >( this->m_UI->Q4 )->SetQuadrant( 4 ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +HasImage( ) const +{ + return( this->m_MainImage.GetPointer( ) != NULL ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetImage( vtkImageData* image, const std::string& name ) +{ + if( this->m_MainImageName != "" || image == NULL ) + { + // TODO: Clear visualization + + } // fi + this->m_MainImageName = name; + this->m_MainImage = image; + + if( this->m_MainImage != NULL && this->m_MainImageName != "" ) + { + this->m_XImage->SetImage( this->m_MainImage, name, 0 ); + this->m_YImage->SetImage( this->m_MainImage, name, 1 ); + this->m_ZImage->SetImage( this->m_MainImage, name, 2 ); + this->m_3DView->SetImage( this->m_MainImage, name ); + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +Add( vtkDataSet* data, const std::string& name ) +{ + bool success = true; + auto image = dynamic_cast< vtkImageData* >( data ); + auto pdata = dynamic_cast< vtkPolyData* >( data ); + + if( image != NULL ) + { + if( this->m_MainImageName != "" ) + { + this->m_XImage->Add( image, name ); + this->m_YImage->Add( image, name ); + this->m_ZImage->Add( image, name ); + // TODO: this->m_3DView->Add( image, name ); + } + else + this->SetImage( image, name ); + } + else if( pdata != NULL ) + this->m_3DView->Add( pdata, name ); + else + success = false; + return( success ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +TProps cpExtensions::QT::SimpleMPRWidget:: +GetViewProps( const std::string& name ) const +{ +/* + auto x = this->m_XImage->GetViewProps( name ); + auto y = this->m_YImage->GetViewProps( name ); + auto z = this->m_ZImage->GetViewProps( name ); + auto w = this->m_3DView->GetViewProps( name ); + + TProps props; + if( x != NULL ) props.insert( x ); + if( y != NULL ) props.insert( y ); + if( z != NULL ) props.insert( z ); + if( w != NULL ) props.insert( w ); + return( props ); +*/ + TProps props; + return( props ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +TProps cpExtensions::QT::SimpleMPRWidget:: +GetImageProps( ) const +{ + return( this->GetViewProps( this->m_MainImageName ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetXInteractor( ) +{ + return( this->m_XImage->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetXInteractor( ) const +{ + return( this->m_XImage->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetYInteractor( ) +{ + return( this->m_YImage->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetYInteractor( ) const +{ + return( this->m_YImage->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetZInteractor( ) +{ + return( this->m_ZImage->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetZInteractor( ) const +{ + return( this->m_ZImage->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetWInteractor( ) +{ + return( this->m_3DView->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetWInteractor( ) const +{ + return( this->m_3DView->GetInteractor( ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetXRenderWindow( ) +{ + return( this->m_XImage->GetRenderWindow( ) ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetXRenderWindow( ) const +{ + return( this->m_XImage->GetRenderWindow( ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetYRenderWindow( ) +{ + return( this->m_YImage->GetRenderWindow( ) ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetYRenderWindow( ) const +{ + return( this->m_YImage->GetRenderWindow( ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetZRenderWindow( ) +{ + return( this->m_ZImage->GetRenderWindow( ) ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetZRenderWindow( ) const +{ + return( this->m_ZImage->GetRenderWindow( ) ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetWRenderWindow( ) +{ + return( this->m_3DView->GetRenderWindow( ) ); +} + + +// ------------------------------------------------------------------------- +const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetWRenderWindow( ) const +{ + return( this->m_3DView->GetRenderWindow( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +ResetCameras( ) +{ + this->m_XImage->ResetCamera( ); + this->m_YImage->ResetCamera( ); + this->m_ZImage->ResetCamera( ); + this->m_3DView->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +Render( ) +{ + this->m_XImage->Render( ); + this->m_YImage->Render( ); + this->m_ZImage->Render( ); + this->m_3DView->Render( ); +} + +// ------------------------------------------------------------------------- +std::set< vtkRenderWindowInteractor* > cpExtensions::QT::SimpleMPRWidget:: +GetInteractors( ) const +{ + std::set< vtkRenderWindowInteractor* > ret; + ret.insert( this->m_XImage->GetInteractor( ) ); + ret.insert( this->m_YImage->GetInteractor( ) ); + ret.insert( this->m_ZImage->GetInteractor( ) ); + ret.insert( this->m_3DView->GetInteractor( ) ); + return( ret ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpExtensions::QT::SimpleMPRWidget:: +GetActorsNames( ) const +{ + std::set< std::string > names = this->m_XImage->GetActorsNames( ); + std::set< std::string > y = this->m_YImage->GetActorsNames( ); + std::set< std::string > z = this->m_ZImage->GetActorsNames( ); + std::set< std::string > w = this->m_3DView->GetActorsNames( ); + names.insert( y.begin( ), y.end( ) ); + names.insert( z.begin( ), z.end( ) ); + names.insert( w.begin( ), w.end( ) ); + return( names ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +IsWindowLevelImageActor( const std::string& name ) const +{ + return( this->m_XImage->IsWindowLevelImageActor( name ) ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +IsLUTImageActor( const std::string& name ) const +{ + return( this->m_XImage->IsLUTImageActor( name ) ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +Is3DActor( const std::string& name ) const +{ + return( + this->m_XImage->Is3DActor( name ) || this->m_3DView->Is3DActor( name ) + ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +GetScalarRange( const std::string& name, double r[ 2 ] ) const +{ + this->m_XImage->GetScalarRange( name, r ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +GetWindowLevel( const std::string& name, double wl[ 2 ] ) const +{ + this->m_XImage->GetWindowLevel( name, wl ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::SimpleMPRWidget:: +GetWindow( const std::string& name ) const +{ + return( this->m_XImage->GetWindow( name ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::SimpleMPRWidget:: +GetLevel( const std::string& name ) const +{ + return( this->m_XImage->GetLevel( name ) ); +} + +// ------------------------------------------------------------------------- +char cpExtensions::QT::SimpleMPRWidget:: +GetImageInterpolation( const std::string& name ) const +{ + return( this->m_XImage->GetImageInterpolation( name ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +GetColor( const std::string& name, double& r, double& g, double& b ) const +{ + this->m_XImage->GetColor( name, r, g, b ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::SimpleMPRWidget:: +GetOpacity( const std::string& name ) const +{ + return( this->m_XImage->GetOpacity( name ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::SimpleMPRWidget:: +GetPointSize( const std::string& name ) const +{ + return( this->m_XImage->GetPointSize( name ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::QT::SimpleMPRWidget:: +GetLineWidth( const std::string& name ) const +{ + return( this->m_XImage->GetLineWidth( name ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::QT::SimpleMPRWidget:: +GetRepresentation( const std::string& name ) const +{ + return( this->m_XImage->GetRepresentation( name ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetScalarRange( const std::string& name, double r[ 2 ] ) +{ + this->m_XImage->SetScalarRange( name, r ); + this->m_YImage->SetScalarRange( name, r ); + this->m_ZImage->SetScalarRange( name, r ); + this->m_3DView->SetScalarRange( name, r ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetScalarRange( const std::string& name, double min, double max ) +{ + this->m_XImage->SetScalarRange( name, min, max ); + this->m_YImage->SetScalarRange( name, min, max ); + this->m_ZImage->SetScalarRange( name, min, max ); + this->m_3DView->SetScalarRange( name, min, max ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetWindowLevel( const std::string& name, double wl[ 2 ] ) +{ + this->m_XImage->SetWindowLevel( name, wl ); + this->m_YImage->SetWindowLevel( name, wl ); + this->m_ZImage->SetWindowLevel( name, wl ); + this->m_3DView->SetWindowLevel( name, wl ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetWindowLevel( const std::string& name, double w, double l ) +{ + this->m_XImage->SetWindowLevel( name, w, l ); + this->m_YImage->SetWindowLevel( name, w, l ); + this->m_ZImage->SetWindowLevel( name, w, l ); + this->m_3DView->SetWindowLevel( name, w, l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetWindow( const std::string& name, double w ) +{ + this->m_XImage->SetWindow( name, w ); + this->m_YImage->SetWindow( name, w ); + this->m_ZImage->SetWindow( name, w ); + this->m_3DView->SetWindow( name, w ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetLevel( const std::string& name, double l ) +{ + this->m_XImage->SetLevel( name, l ); + this->m_YImage->SetLevel( name, l ); + this->m_ZImage->SetLevel( name, l ); + this->m_3DView->SetLevel( name, l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetImageInterpolation( const std::string& name, char i ) +{ + this->m_XImage->SetImageInterpolation( name, i ); + this->m_YImage->SetImageInterpolation( name, i ); + this->m_ZImage->SetImageInterpolation( name, i ); + this->m_3DView->SetImageInterpolation( name, i ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetColor( const std::string& name, double r, double g, double b ) +{ + this->m_XImage->SetColor( name, r, g, b ); + this->m_YImage->SetColor( name, r, g, b ); + this->m_ZImage->SetColor( name, r, g, b ); + this->m_3DView->SetColor( name, r, g, b ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetOpacity( const std::string& name, double o ) +{ + this->m_XImage->SetOpacity( name, o ); + this->m_YImage->SetOpacity( name, o ); + this->m_ZImage->SetOpacity( name, o ); + this->m_3DView->SetOpacity( name, o ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetPointSize( const std::string& name, double s ) +{ + this->m_XImage->SetPointSize( name, s ); + this->m_YImage->SetPointSize( name, s ); + this->m_ZImage->SetPointSize( name, s ); + this->m_3DView->SetPointSize( name, s ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetLineWidth( const std::string& name, double w ) +{ + this->m_XImage->SetLineWidth( name, w ); + this->m_YImage->SetLineWidth( name, w ); + this->m_ZImage->SetLineWidth( name, w ); + this->m_3DView->SetLineWidth( name, w ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetRepresentationToPoints( const std::string& name ) +{ + this->m_XImage->SetRepresentationToPoints( name ); + this->m_YImage->SetRepresentationToPoints( name ); + this->m_ZImage->SetRepresentationToPoints( name ); + this->m_3DView->SetRepresentationToPoints( name ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetRepresentationToSurface( const std::string& name ) +{ + this->m_XImage->SetRepresentationToSurface( name ); + this->m_YImage->SetRepresentationToSurface( name ); + this->m_ZImage->SetRepresentationToSurface( name ); + this->m_3DView->SetRepresentationToSurface( name ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetRepresentationToWireframe( const std::string& name ) +{ + this->m_XImage->SetRepresentationToWireframe( name ); + this->m_YImage->SetRepresentationToWireframe( name ); + this->m_ZImage->SetRepresentationToWireframe( name ); + this->m_3DView->SetRepresentationToWireframe( name ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +_SyncBottom( int a, int b ) +{ + this->m_UI->Bottom->setSizes( this->m_UI->Top->sizes( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +_SyncTop( int a, int b ) +{ + this->m_UI->Top->setSizes( this->m_UI->Bottom->sizes( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.h b/lib/cpExtensions/QT/SimpleMPRWidget.h new file mode 100644 index 0000000..bc07ed3 --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.h @@ -0,0 +1,135 @@ +#ifndef __cpExtensions__QT__SimpleMPRWidget__h__ +#define __cpExtensions__QT__SimpleMPRWidget__h__ + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkDataSet; +class vtkProp; +class vtkPropCollection; + +namespace Ui { class SimpleMPRWidget; } + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace QT + { + class MPR3DWidget; + class ImageWidget; + + /** + */ + class cpExtensions_EXPORT SimpleMPRWidget + : public QWidget, + public ActorsWidgetInterface + { + Q_OBJECT; + + public: + typedef SimpleMPRWidget Self; + typedef QWidget Superclass; + typedef ActorsWidgetInterface Superclass2; + + typedef vtkSmartPointer< vtkPropCollection > TProp; + typedef std::set< TProp > TProps; + + // typedef cpExtensions::Visualization::MeshActor TMeshActor; + + public: + explicit SimpleMPRWidget( QWidget* parent = NULL, Qt::WindowFlags f = 0 ); + virtual ~SimpleMPRWidget( ); + + void Configure( char q1, char q2, char q3, char q4 ); + + bool HasImage( ) const; + void SetImage( vtkImageData* image, const std::string& name ); + + bool Add( vtkDataSet* data, const std::string& name ); + + TProps GetViewProps( const std::string& name ) const; + TProps GetImageProps( ) const; + + vtkRenderWindowInteractor* GetXInteractor( ); + const vtkRenderWindowInteractor* GetXInteractor( ) const; + vtkRenderWindowInteractor* GetYInteractor( ); + const vtkRenderWindowInteractor* GetYInteractor( ) const; + vtkRenderWindowInteractor* GetZInteractor( ); + const vtkRenderWindowInteractor* GetZInteractor( ) const; + vtkRenderWindowInteractor* GetWInteractor( ); + const vtkRenderWindowInteractor* GetWInteractor( ) const; + + vtkRenderWindow* GetXRenderWindow( ); + const vtkRenderWindow* GetXRenderWindow( ) const; + vtkRenderWindow* GetYRenderWindow( ); + const vtkRenderWindow* GetYRenderWindow( ) const; + vtkRenderWindow* GetZRenderWindow( ); + const vtkRenderWindow* GetZRenderWindow( ) const; + vtkRenderWindow* GetWRenderWindow( ); + const vtkRenderWindow* GetWRenderWindow( ) const; + + void ResetCameras( ); + void Render( ); + + virtual std::set< vtkRenderWindowInteractor* > GetInteractors( ) const cpExtensions_OVERRIDE; + virtual std::set< std::string > GetActorsNames( ) const cpExtensions_OVERRIDE; + virtual bool IsWindowLevelImageActor( const std::string& name ) const cpExtensions_OVERRIDE; + virtual bool IsLUTImageActor( const std::string& name ) const cpExtensions_OVERRIDE; + virtual bool Is3DActor( const std::string& name ) const cpExtensions_OVERRIDE; + + virtual void GetScalarRange( const std::string& name, double r[ 2 ] ) const cpExtensions_OVERRIDE; + virtual void GetWindowLevel( const std::string& name, double wl[ 2 ] ) const cpExtensions_OVERRIDE; + virtual double GetWindow( const std::string& name ) const cpExtensions_OVERRIDE; + virtual double GetLevel( const std::string& name ) const cpExtensions_OVERRIDE; + virtual char GetImageInterpolation( const std::string& name ) const cpExtensions_OVERRIDE; + + virtual void GetColor( const std::string& name, double& r, double& g, double& b ) const cpExtensions_OVERRIDE; + virtual double GetOpacity( const std::string& name ) const cpExtensions_OVERRIDE; + virtual double GetPointSize( const std::string& name ) const cpExtensions_OVERRIDE; + virtual double GetLineWidth( const std::string& name ) const cpExtensions_OVERRIDE; + virtual int GetRepresentation( const std::string& name ) const cpExtensions_OVERRIDE; + + virtual void SetScalarRange( const std::string& name, double r[ 2 ] ) cpExtensions_OVERRIDE; + virtual void SetScalarRange( const std::string& name, double min, double max ) cpExtensions_OVERRIDE; + virtual void SetWindowLevel( const std::string& name, double wl[ 2 ] ) cpExtensions_OVERRIDE; + virtual void SetWindowLevel( const std::string& name, double w, double l ) cpExtensions_OVERRIDE; + virtual void SetWindow( const std::string& name, double w ) cpExtensions_OVERRIDE; + virtual void SetLevel( const std::string& name, double l ) cpExtensions_OVERRIDE; + virtual void SetImageInterpolation( const std::string& name, char i ) cpExtensions_OVERRIDE; + + virtual void SetColor( const std::string& name, double r, double g, double b ) cpExtensions_OVERRIDE; + virtual void SetOpacity( const std::string& name, double o ) cpExtensions_OVERRIDE; + virtual void SetPointSize( const std::string& name, double s ) cpExtensions_OVERRIDE; + virtual void SetLineWidth( const std::string& name, double w ) cpExtensions_OVERRIDE; + virtual void SetRepresentationToPoints( const std::string& name ) cpExtensions_OVERRIDE; + virtual void SetRepresentationToSurface( const std::string& name ) cpExtensions_OVERRIDE; + virtual void SetRepresentationToWireframe( const std::string& name ) cpExtensions_OVERRIDE; + + private slots: + void _SyncBottom( int a, int b ); + void _SyncTop( int a, int b ); + + protected: + Ui::SimpleMPRWidget* m_UI; + + ImageWidget* m_XImage; + ImageWidget* m_YImage; + ImageWidget* m_ZImage; + MPR3DWidget* m_3DView; + + std::string m_MainImageName; + vtkSmartPointer< vtkImageData > m_MainImage; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__SimpleMPRWidget__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.ui b/lib/cpExtensions/QT/SimpleMPRWidget.ui new file mode 100644 index 0000000..3f0750e --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.ui @@ -0,0 +1,48 @@ + + + SimpleMPRWidget + + + + 0 + 0 + 495 + 394 + + + + Form + + + + 0 + + + 0 + + + + + Qt::Vertical + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + + + + diff --git a/lib/cpExtensions/QT/WindowLevelImageConfiguration.cxx b/lib/cpExtensions/QT/WindowLevelImageConfiguration.cxx new file mode 100644 index 0000000..b2baa94 --- /dev/null +++ b/lib/cpExtensions/QT/WindowLevelImageConfiguration.cxx @@ -0,0 +1,231 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::WindowLevelImageConfiguration:: +WindowLevelImageConfiguration( QWidget* parent, Qt::WindowFlags f ) + : Superclass( parent, f ), + m_UI( new Ui::WindowLevelImageConfiguration ), + m_Data( NULL ), + m_Name( "" ) +{ + this->m_UI->setupUi( this ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::WindowLevelImageConfiguration:: +~WindowLevelImageConfiguration( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::WindowLevelImageConfiguration:: +setData( ActorsWidgetInterface* data, const std::string& name ) +{ + if( this->m_Data != data ) + { + this->m_Data = data; + this->m_Name = name; + + // Get data + double range[ 2 ], win_lev[ 2 ]; + this->m_Data->GetScalarRange( this->m_Name, range ); + this->m_Data->GetWindowLevel( this->m_Name, win_lev ); + + // Intensity range + this->m_UI->MinimumBox->setMinimum( -1000000 ); + this->m_UI->MinimumBox->setMaximum( 1000000 ); + this->m_UI->MaximumBox->setMinimum( -1000000 ); + this->m_UI->MaximumBox->setMaximum( 1000000 ); + this->m_UI->MinimumBox->setValue( range[ 0 ] ); + this->m_UI->MaximumBox->setValue( range[ 1 ] ); + + // Window/level + double off = range[ 1 ] - range[ 0 ]; + this->m_UI->WindowBox->setMinimum( 0 ); + this->m_UI->WindowBox->setMaximum( off ); + this->m_UI->LevelBox->setMinimum( range[ 0 ] ); + this->m_UI->LevelBox->setMaximum( range[ 1 ] ); + this->m_UI->WindowBox->setValue( win_lev[ 0 ] ); + this->m_UI->LevelBox->setValue( win_lev[ 1 ] ); + + double w = win_lev[ 0 ] / off; + w *= + double( this->m_UI->WindowSlider->maximum( ) ) - + double( this->m_UI->WindowSlider->minimum( ) ); + w += double( this->m_UI->WindowSlider->minimum( ) ); + this->m_UI->WindowSlider->setValue( w ); + + double l = ( win_lev[ 1 ] - range[ 0 ] ) / off; + l *= + double( this->m_UI->LevelSlider->maximum( ) ) - + double( this->m_UI->LevelSlider->minimum( ) ); + l += double( this->m_UI->LevelSlider->minimum( ) ); + this->m_UI->LevelSlider->setValue( l ); + + // Opacity + double o = this->m_Data->GetOpacity( this->m_Name ); + o *= + double( this->m_UI->OpacitySlider->maximum( ) ) - + double( this->m_UI->OpacitySlider->minimum( ) ); + o += double( this->m_UI->OpacitySlider->minimum( ) ); + this->m_UI->OpacitySlider->setValue( o ); + + // Interpolation mode + switch( this->m_Data->GetImageInterpolation( this->m_Name ) ) + { + case 'L': this->m_UI->InterpolatorBox->setCurrentIndex( 1 ); break; + case 'C': this->m_UI->InterpolatorBox->setCurrentIndex( 2 ); break; + default : this->m_UI->InterpolatorBox->setCurrentIndex( 0 ); break; + } // hctiws + + // Slots <-> signals + this->connect( + this->m_UI->MaximumBox, SIGNAL( valueChanged( int ) ), + this, SLOT( _maximumValue( int ) ) + ); + this->connect( + this->m_UI->MinimumBox, SIGNAL( valueChanged( int ) ), + this, SLOT( _minimumValue( int ) ) + ); + this->connect( + this->m_UI->LevelBox, SIGNAL( valueChanged( int ) ), + this, SLOT( _levelValue( int ) ) + ); + this->connect( + this->m_UI->LevelSlider, SIGNAL( valueChanged( int ) ), + this, SLOT( _levelValue( int ) ) + ); + this->connect( + this->m_UI->WindowBox, SIGNAL( valueChanged( int ) ), + this, SLOT( _windowValue( int ) ) + ); + this->connect( + this->m_UI->WindowSlider, SIGNAL( valueChanged( int ) ), + this, SLOT( _windowValue( int ) ) + ); + this->connect( + this->m_UI->OpacitySlider, SIGNAL( valueChanged( int ) ), + this, SLOT( _opacityValue( int ) ) + ); + this->connect( + this->m_UI->InterpolatorBox, SIGNAL( currentIndexChanged( int ) ), + this, SLOT( _interpolatorValue( int ) ) + ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::WindowLevelImageConfiguration:: +_maximumValue( int v ) +{ + double range[ 2 ]; + range[ 0 ] = double( this->m_UI->MinimumBox->value( ) ); + range[ 1 ] = double( v ); + this->m_Data->SetScalarRange( this->m_Name, range ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::WindowLevelImageConfiguration:: +_minimumValue( int v ) +{ + double range[ 2 ]; + range[ 0 ] = double( v ); + range[ 1 ] = double( this->m_UI->MaximumBox->value( ) ); + this->m_Data->SetScalarRange( this->m_Name, range ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::WindowLevelImageConfiguration:: +_levelValue( int v ) +{ + double r[ 2 ]; + double l, s; + + this->m_Data->GetScalarRange( this->m_Name, r ); + if( this->sender( ) == this->m_UI->LevelSlider ) + { + s = double( v ) / double( this->m_UI->LevelSlider->maximum( ) ); + l = ( ( r[ 1 ] - r[ 0 ] ) * s ) + r[ 0 ]; + } + else + { + l = double( v ); + s = ( l - r[ 0 ] ) / ( r[ 1 ] - r[ 0 ] ); + + } // fi + s *= this->m_UI->LevelSlider->maximum( ); + + bool b = this->m_UI->LevelSlider->blockSignals( true ); + this->m_UI->LevelSlider->setValue( s ); + this->m_UI->LevelSlider->blockSignals( b ); + b = this->m_UI->LevelBox->blockSignals( true ); + this->m_UI->LevelBox->setValue( l ); + this->m_UI->LevelBox->blockSignals( b ); + + this->m_Data->SetLevel( this->m_Name, l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::WindowLevelImageConfiguration:: +_windowValue( int v ) +{ + double r[ 2 ]; + double w, s; + + this->m_Data->GetScalarRange( this->m_Name, r ); + if( this->sender( ) == this->m_UI->WindowSlider ) + { + s = double( v ) / double( this->m_UI->WindowSlider->maximum( ) ); + w = ( ( r[ 1 ] - r[ 0 ] ) * s ) + r[ 0 ]; + } + else + { + w = double( v ); + s = ( w - r[ 0 ] ) / ( r[ 1 ] - r[ 0 ] ); + + } // fi + s *= this->m_UI->WindowSlider->maximum( ); + + bool b = this->m_UI->WindowSlider->blockSignals( true ); + this->m_UI->WindowSlider->setValue( s ); + this->m_UI->WindowSlider->blockSignals( b ); + b = this->m_UI->WindowBox->blockSignals( true ); + this->m_UI->WindowBox->setValue( w ); + this->m_UI->WindowBox->blockSignals( b ); + + this->m_Data->SetWindow( this->m_Name, w ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::WindowLevelImageConfiguration:: +_opacityValue( int v ) +{ + if( this->m_Data != NULL ) + { + double o = double( v ); + o -= double( this->m_UI->OpacitySlider->minimum( ) ); + o /= + double( this->m_UI->OpacitySlider->maximum( ) ) - + double( this->m_UI->OpacitySlider->minimum( ) ); + this->m_Data->SetOpacity( this->m_Name, o ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::WindowLevelImageConfiguration:: +_interpolatorValue( int v ) +{ + switch( v ) + { + case 1 : this->m_Data->SetImageInterpolation( this->m_Name, 'L' ); break; + case 2 : this->m_Data->SetImageInterpolation( this->m_Name, 'C' ); break; + default : this->m_Data->SetImageInterpolation( this->m_Name, 'N' ); break; + } // hctiws +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/WindowLevelImageConfiguration.h b/lib/cpExtensions/QT/WindowLevelImageConfiguration.h new file mode 100644 index 0000000..1725253 --- /dev/null +++ b/lib/cpExtensions/QT/WindowLevelImageConfiguration.h @@ -0,0 +1,56 @@ +#ifndef __cpExtensions__QT__WindowLevelImageConfiguration__h__ +#define __cpExtensions__QT__WindowLevelImageConfiguration__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace Ui { class WindowLevelImageConfiguration; } + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace QT + { + class ActorsWidgetInterface; + + /** + */ + class cpExtensions_EXPORT WindowLevelImageConfiguration + : public QWidget + { + Q_OBJECT; + + public: + typedef WindowLevelImageConfiguration Self; + typedef QWidget Superclass; + + public: + explicit WindowLevelImageConfiguration( + QWidget* parent = NULL, Qt::WindowFlags f = 0 + ); + virtual ~WindowLevelImageConfiguration( ); + + void setData( ActorsWidgetInterface* data, const std::string& name ); + + protected slots: + void _maximumValue( int v ); + void _minimumValue( int v ); + void _levelValue( int v ); + void _windowValue( int v ); + void _opacityValue( int v ); + void _interpolatorValue( int v ); + + protected: + Ui::WindowLevelImageConfiguration* m_UI; + ActorsWidgetInterface* m_Data; + std::string m_Name; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__QT__WindowLevelImageConfiguration__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/WindowLevelImageConfiguration.ui b/lib/cpExtensions/QT/WindowLevelImageConfiguration.ui new file mode 100644 index 0000000..65d066e --- /dev/null +++ b/lib/cpExtensions/QT/WindowLevelImageConfiguration.ui @@ -0,0 +1,216 @@ + + + WindowLevelImageConfiguration + + + + 0 + 0 + 313 + 322 + + + + + 313 + 322 + + + + Form + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + Window: + + + + + + + + + + + + 1000 + + + 100 + + + Qt::Horizontal + + + + + + + + + + + + + Level: + + + + + + + + + + + + 1000 + + + 100 + + + Qt::Horizontal + + + + + + + + + + + Minimum: + + + + + + + + + + Maximum: + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 0 + + + + + + + + 16777215 + 16777215 + + + + Interpolation: + + + + + + + + Nearest + + + + + Linear + + + + + Cubic + + + + + + + + + + + + Opacity: + + + + + + + 100 + + + Qt::Horizontal + + + + + + + + + + + + label + label_2 + label_3 + label_4 + label_5 + label_6 + InterpolatorBox + WindowSlider + LevelSlider + OpacitySlider + MinimumBox + MaximumBox + WindowSlider + frame + frame_2 + + + + diff --git a/lib/cpExtensions/Visualization/CursorActors.cxx b/lib/cpExtensions/Visualization/CursorActors.cxx new file mode 100644 index 0000000..29dedc3 --- /dev/null +++ b/lib/cpExtensions/Visualization/CursorActors.cxx @@ -0,0 +1,176 @@ +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::CursorActors:: +Self* cpExtensions::Visualization::CursorActors:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::CursorActors:: +Modified( ) +{ + for( unsigned int i = 0; i < 2; ++i ) + { + if( this->m_Lines[ i ].GetPointer( ) != NULL ) + { + this->m_Lines[ i ]->Modified( ); + this->m_Mappers[ i ]->Modified( ); + this->m_Actors[ i ]->Modified( ); + + } // fi + + } // rof + this->Superclass::Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::CursorActors:: +SetImageBounds( double* bounds ) +{ + this->m_Bounds[ 0 ] = bounds[ 0 ]; + this->m_Bounds[ 1 ] = bounds[ 1 ]; + this->m_Bounds[ 2 ] = bounds[ 2 ]; + this->m_Bounds[ 3 ] = bounds[ 3 ]; + this->m_Bounds[ 4 ] = bounds[ 4 ]; + this->m_Bounds[ 5 ] = bounds[ 5 ]; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::CursorActors:: +SetImageOrientation( int orientation ) +{ + this->m_Orientation = orientation % 3; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::CursorActors:: +SetCursor( double* pos, bool neg ) +{ + static const double _eps = 1e-3; + double pnts[ 4 ][ 3 ]; + if( this->m_Orientation == 0 ) + { + pnts[ 0 ][ 1 ] = this->m_Bounds[ 2 ]; + pnts[ 1 ][ 1 ] = this->m_Bounds[ 3 ]; + pnts[ 0 ][ 2 ] = pnts[ 1 ][ 2 ] = pos[ 2 ]; + + pnts[ 2 ][ 1 ] = pnts[ 3 ][ 1 ] = pos[ 1 ]; + pnts[ 2 ][ 2 ] = this->m_Bounds[ 4 ]; + pnts[ 3 ][ 2 ] = this->m_Bounds[ 5 ]; + + pnts[ 0 ][ 0 ] = pnts[ 1 ][ 0 ] = + pnts[ 2 ][ 0 ] = pnts[ 3 ][ 0 ] = + pos[ 0 ] + ( double( neg? -1: 1 ) * _eps ); + } + else if( this->m_Orientation == 1 ) + { + pnts[ 0 ][ 0 ] = pnts[ 1 ][ 0 ] = pos[ 0 ]; + pnts[ 0 ][ 2 ] = this->m_Bounds[ 4 ]; + pnts[ 1 ][ 2 ] = this->m_Bounds[ 5 ]; + + pnts[ 2 ][ 0 ] = this->m_Bounds[ 0 ]; + pnts[ 3 ][ 0 ] = this->m_Bounds[ 1 ]; + pnts[ 2 ][ 2 ] = pnts[ 3 ][ 2 ] = pos[ 2 ]; + + pnts[ 0 ][ 1 ] = pnts[ 1 ][ 1 ] = + pnts[ 2 ][ 1 ] = pnts[ 3 ][ 1 ] = + pos[ 1 ] + ( double( neg? -1: 1 ) * _eps ); + } + else if( this->m_Orientation == 2 ) + { + pnts[ 0 ][ 0 ] = this->m_Bounds[ 0 ]; + pnts[ 1 ][ 0 ] = this->m_Bounds[ 1 ]; + pnts[ 0 ][ 1 ] = pnts[ 1 ][ 1 ] = pos[ 1 ]; + + pnts[ 2 ][ 0 ] = pnts[ 3 ][ 0 ] = pos[ 0 ]; + pnts[ 2 ][ 1 ] = this->m_Bounds[ 2 ]; + pnts[ 3 ][ 1 ] = this->m_Bounds[ 3 ]; + + pnts[ 0 ][ 2 ] = pnts[ 1 ][ 2 ] = + pnts[ 2 ][ 2 ] = pnts[ 3 ][ 2 ] = + pos[ 2 ] + ( double( neg? -1: 1 ) * _eps ); + + } // fi + + this->m_Lines[ 0 ]->SetPoint1( pnts[ 0 ] ); + this->m_Lines[ 0 ]->SetPoint2( pnts[ 1 ] ); + this->m_Lines[ 1 ]->SetPoint1( pnts[ 2 ] ); + this->m_Lines[ 1 ]->SetPoint2( pnts[ 3 ] ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +vtkProperty* cpExtensions::Visualization::CursorActors:: +GetProperty( unsigned int i ) +{ + return( this->m_Actors[ i % 2 ]->GetProperty( ) ); +} + +// ------------------------------------------------------------------------- +const vtkProperty* cpExtensions::Visualization::CursorActors:: +GetProperty( unsigned int i ) const +{ + return( this->m_Actors[ i % 2 ]->GetProperty( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::CursorActors:: +SetVisibility( int v ) +{ + this->m_Actors[ 0 ]->SetVisibility( v ); + this->m_Actors[ 1 ]->SetVisibility( v ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::CursorActors:: +VisibilityOn( ) +{ + this->m_Actors[ 0 ]->VisibilityOn( ); + this->m_Actors[ 1 ]->VisibilityOn( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::CursorActors:: +VisibilityOff( ) +{ + this->m_Actors[ 0 ]->VisibilityOff( ); + this->m_Actors[ 1 ]->VisibilityOff( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::CursorActors:: +CursorActors( ) + : Superclass( ) +{ + this->m_Bounds[ 0 ] = this->m_Bounds[ 1 ] = this->m_Bounds[ 2 ] = + this->m_Bounds[ 3 ] = this->m_Bounds[ 4 ] = this->m_Bounds[ 5 ] = + double( 0 ); + + for( unsigned int i = 0; i < 2; ++i ) + { + this->m_Lines[ i ] = vtkSmartPointer< LineSource >::New( ); + this->m_Mappers[ i ] = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_Actors[ i ] = vtkSmartPointer< vtkActor >::New( ); + this->m_Mappers[ i ]->SetInputConnection( + this->m_Lines[ i ]->GetOutputPort( ) + ); + this->m_Actors[ i ]->SetMapper( this->m_Mappers[ i ] ); + this->AddItem( this->m_Actors[ i ] ); + + } // rof +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::CursorActors:: +~CursorActors( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/CursorActors.h b/lib/cpExtensions/Visualization/CursorActors.h new file mode 100644 index 0000000..77a6d8e --- /dev/null +++ b/lib/cpExtensions/Visualization/CursorActors.h @@ -0,0 +1,70 @@ +#ifndef __cpExtensions__Visualization__CursorActors__h__ +#define __cpExtensions__Visualization__CursorActors__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkActor; +class vtkPolyDataMapper; +class vtkProperty; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class LineSource; + + /** + */ + class cpExtensions_EXPORT CursorActors + : public vtkPropCollection + { + public: + typedef CursorActors Self; + + public: + vtkTypeMacro( CursorActors, vtkPropCollection ); + + public: + static Self* New( ); + + virtual void Modified( ) cpExtensions_OVERRIDE; + + void SetImageBounds( double* bounds ); + void SetImageOrientation( int orientation ); + void SetCursor( double* pos, bool neg ); + + vtkProperty* GetProperty( unsigned int i ); + const vtkProperty* GetProperty( unsigned int i ) const; + + void SetVisibility( int v ); + void VisibilityOn( ); + void VisibilityOff( ); + + protected: + CursorActors( ); + virtual ~CursorActors( ); + + private: + // Purposely not implemented + CursorActors( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< LineSource > m_Lines[ 2 ]; + vtkSmartPointer< vtkPolyDataMapper > m_Mappers[ 2 ]; + vtkSmartPointer< vtkActor > m_Actors[ 2 ]; + double m_Bounds[ 6 ]; + int m_Orientation; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__CursorActors__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageActor.cxx b/lib/cpExtensions/Visualization/ImageActor.cxx new file mode 100644 index 0000000..d1f72ac --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageActor.cxx @@ -0,0 +1,94 @@ +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageActor:: +Modified( ) +{ + if( this->m_Mapper->GetNumberOfInputConnections( 0 ) > 0 ) + { + this->m_Mapper->Modified( ); + this->m_Mapper->Update( ); + this->Superclass::Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageActor:: +GetOrientation( ) const +{ + return( this->m_Mapper->GetOrientation( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageActor:: +SetOrientation( int orientation ) +{ + this->m_Mapper->SetOrientation( ( orientation < 3 )? orientation: 2 ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageActor:: +GetSliceNumber( ) const +{ + return( this->m_Mapper->GetSliceNumber( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageActor:: +SetSliceNumber( int slice ) +{ + static int s = 0; + auto image = this->m_Mapper->GetInput( ); + if( image != NULL ) + { + // Update slice + s = slice; + if( s < this->m_Mapper->GetSliceNumberMinValue( ) ) + s = this->m_Mapper->GetSliceNumberMinValue( ); + if( s > this->m_Mapper->GetSliceNumberMaxValue( ) ) + s = this->m_Mapper->GetSliceNumberMaxValue( ); + this->m_Mapper->SetSliceNumber( s ); + this->InvokeEvent( vtkCommand::InteractionEvent, &s ); + + // Propagate modifications + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +vtkPlane* cpExtensions::Visualization::ImageActor:: +GetSlicePlane( ) +{ + return( this->m_Mapper->GetSlicePlane( ) ); +} + +// ------------------------------------------------------------------------- +const vtkPlane* cpExtensions::Visualization::ImageActor:: +GetSlicePlane( ) const +{ + return( this->m_Mapper->GetSlicePlane( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageActor:: +ImageActor( ) + : Superclass( ) +{ + this->m_Mapper = vtkSmartPointer< ImageSliceMapper >::New( ); + this->SetMapper( this->m_Mapper ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageActor:: +~ImageActor( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageActor.h b/lib/cpExtensions/Visualization/ImageActor.h new file mode 100644 index 0000000..c62c132 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageActor.h @@ -0,0 +1,62 @@ +#ifndef __cpExtensions__Visualization__ImageActor__h__ +#define __cpExtensions__Visualization__ImageActor__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkImageAlgorithm; +class vtkImageData; +class vtkPlane; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class ImageSliceMapper; + + /** + */ + class cpExtensions_EXPORT ImageActor + : public vtkImageSlice + { + public: + typedef ImageActor Self; + + public: + vtkTypeMacro( ImageActor, vtkImageSlice ); + + public: + virtual void Modified( ) cpExtensions_OVERRIDE; + + int GetOrientation( ) const; + void SetOrientation( int orientation ); + + int GetSliceNumber( ) const; + void SetSliceNumber( int slice ); + + vtkPlane* GetSlicePlane( ); + const vtkPlane* GetSlicePlane( ) const; + + protected: + ImageActor( ); + virtual ~ImageActor( ); + + private: + // Purposely not implemented + ImageActor( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< ImageSliceMapper > m_Mapper; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__ImageActor__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h new file mode 100644 index 0000000..5129512 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h @@ -0,0 +1,71 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + template< class _TIndexes > + class ImageIndexesContainerToPolyData + : public vtkPolyDataAlgorithm + { + public: + typedef ImageIndexesContainerToPolyData Self; + + typedef _TIndexes TIndexes; + typedef typename TIndexes::ComponentType TContainer; + typedef typename TContainer::value_type TIndex; + typedef itk::ImageBase< TIndex::Dimension > TImage; + + public: + vtkTypeMacro( ImageIndexesContainerToPolyData, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + const TIndexes* GetInput( ) const; + const TImage* GetReferenceImage( ) const; + void SetInput( const TIndexes* c ); + void SetReferenceImage( const TImage* i ); + + protected: + ImageIndexesContainerToPolyData( ); + virtual ~ImageIndexesContainerToPolyData( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + private: + // Purposely not implemented + ImageIndexesContainerToPolyData( const Self& ); + void operator=( const Self& ); + + protected: + const TIndexes* m_Indexes; + const TImage* m_ReferenceImage; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx new file mode 100644 index 0000000..a1403ce --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx @@ -0,0 +1,188 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TIndexes > +typename cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +Self* cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +const typename cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +TIndexes* cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +GetInput( ) const +{ + return( this->m_Indexes ); +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +const typename cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +TImage* cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +GetReferenceImage( ) const +{ + return( this->m_ReferenceImage ); +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +void cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +SetInput( const TIndexes* c ) +{ + if( this->m_Indexes != c ) + { + this->m_Indexes = c; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +void cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +SetReferenceImage( const TImage* i ) +{ + if( this->m_ReferenceImage != i ) + { + this->m_ReferenceImage = i; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +ImageIndexesContainerToPolyData( ) + : vtkPolyDataAlgorithm( ), + m_Indexes( NULL ), + m_ReferenceImage( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +~ImageIndexesContainerToPolyData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +int cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + static const unsigned int dim = TIndex::Dimension; + + if( this->m_Indexes == NULL ) + return( 0 ); + + // Get output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Get input data + auto& lst = this->m_Indexes->Get( ); + + // Prepare points + vtkPoints* points = out->GetPoints( ); + if( points == NULL ) + { + points = vtkPoints::New( ); + out->SetPoints( points ); + points->Delete( ); + + } // fi + points->SetNumberOfPoints( lst.size( ) ); + + // Prepare cells + vtkSmartPointer< vtkCellArray > verts = + vtkSmartPointer< vtkCellArray >::New( ); + + for( unsigned int i = 0; i < lst.size( ); ++i ) + { + auto idx = lst[ i ]; + if( this->m_ReferenceImage != NULL ) + { + typename TImage::PointType pnt; + this->m_ReferenceImage->TransformIndexToPhysicalPoint( idx, pnt ); + if( dim == 1 ) + points->SetPoint( i, pnt[ 0 ], 0, 0 ); + else if( dim == 2 ) + points->SetPoint( i, pnt[ 0 ], pnt[ 1 ], 0 ); + else + points->SetPoint( i, pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + } + else + { + if( dim == 1 ) + points->SetPoint( i, idx[ 0 ], 0, 0 ); + else if( dim == 2 ) + points->SetPoint( i, idx[ 0 ], idx[ 1 ], 0 ); + else + points->SetPoint( i, idx[ 0 ], idx[ 1 ], idx[ 2 ] ); + + } // fi + verts->InsertNextCell( 1 ); + verts->InsertCellPoint( i ); + + } // rof + out->SetPoints( points ); + out->SetVerts( verts ); + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TIndexes > +int +cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + vtkInformation* info = output->GetInformationObject( 0 ); + /* TODO + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES( ), -1 + ); + */ + + if( this->m_Indexes != NULL && this->m_ReferenceImage != NULL ) + { + /* TODO + typename C::TScalar len = this->m_RGC->GetTotalLength( ); + typename C::TScalar s0 = this->m_RGC->Gets0( ); + typename C::TPoint p0 = this->m_RGC->Axis( s0 ); + typename C::TPoint p1 = this->m_RGC->Axis( s0 + len ); + + info->Set( + vtkStreamingDemandDrivenPipeline::WHOLE_BOUNDING_BOX( ), + double( p0[ 0 ] ), double( p1[ 0 ] ), + double( p0[ 1 ] ), double( p1[ 1 ] ), + double( p0[ 2 ] ), double( p1[ 2 ] ) + ); + */ + + } // fi + return( 1 ); +} + +#endif // __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageOutlineActor.cxx b/lib/cpExtensions/Visualization/ImageOutlineActor.cxx new file mode 100644 index 0000000..9cef8d1 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageOutlineActor.cxx @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageOutlineActor::Colors[ 3 ][ 3 ] = +{ + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } +}; + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageOutlineActor:: +Self* cpExtensions::Visualization::ImageOutlineActor:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageOutlineActor:: +Modified( ) +{ + this->m_Outline->Modified( ); + this->m_Mapper->Modified( ); + this->Superclass::Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageOutlineActor:: +SetBounds( int orientation, double step, double* bounds ) +{ + // Update geometry + this->m_Outline->SetBounds( orientation, step, bounds ); + + // Update visualization properties + int o = orientation % 3; + this->GetProperty( )->SetLineWidth( 1.5 ); + this->GetProperty( )->SetColor( + Self::Colors[ o ][ 0 ], + Self::Colors[ o ][ 1 ], + Self::Colors[ o ][ 2 ] + ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageOutlineActor:: +ImageOutlineActor( ) + : Superclass( ) +{ + this->m_Outline = vtkSmartPointer< ImageOutlineSource >::New( ); + this->m_Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_Mapper->SetInputConnection( this->m_Outline->GetOutputPort( ) ); + this->SetMapper( this->m_Mapper ); + + this->UseBoundsOff( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageOutlineActor:: +~ImageOutlineActor( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageOutlineActor.h b/lib/cpExtensions/Visualization/ImageOutlineActor.h new file mode 100644 index 0000000..5ba8c73 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageOutlineActor.h @@ -0,0 +1,59 @@ +#ifndef __cpExtensions__Visualization__ImageOutlineActor__h__ +#define __cpExtensions__Visualization__ImageOutlineActor__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkPolyDataMapper; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class ImageOutlineSource; + + /** + */ + class cpExtensions_EXPORT ImageOutlineActor + : public vtkOpenGLActor + { + public: + typedef ImageOutlineActor Self; + + public: + vtkTypeMacro( ImageOutlineActor, vtkOpenGLActor ); + + public: + static Self* New( ); + + virtual void Modified( ) cpExtensions_OVERRIDE; + + void SetBounds( int orientation, double step, double* bounds ); + + protected: + ImageOutlineActor( ); + virtual ~ImageOutlineActor( ); + + private: + // Purposely not implemented + ImageOutlineActor( const Self& ); + Self& operator=( const Self& ); + + public: + static double Colors[ 3 ][ 3 ]; + + protected: + vtkSmartPointer< ImageOutlineSource > m_Outline; + vtkSmartPointer< vtkPolyDataMapper > m_Mapper; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__ImageOutlineActor__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageOutlineSource.cxx b/lib/cpExtensions/Visualization/ImageOutlineSource.cxx new file mode 100644 index 0000000..8fa8131 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageOutlineSource.cxx @@ -0,0 +1,156 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageOutlineSource:: +Self* cpExtensions::Visualization::ImageOutlineSource:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageOutlineSource:: +SetBounds( int orientation, double step, double* bounds ) +{ + // Update geometry + int o = orientation % 3; + if( o == 0 ) + { + this->m_Bounds[ 0 ][ 0 ] = step; + this->m_Bounds[ 0 ][ 1 ] = bounds[ 2 ]; + this->m_Bounds[ 0 ][ 2 ] = bounds[ 4 ]; + + this->m_Bounds[ 1 ][ 0 ] = step; + this->m_Bounds[ 1 ][ 1 ] = bounds[ 2 ]; + this->m_Bounds[ 1 ][ 2 ] = bounds[ 5 ]; + + this->m_Bounds[ 2 ][ 0 ] = step; + this->m_Bounds[ 2 ][ 1 ] = bounds[ 3 ]; + this->m_Bounds[ 2 ][ 2 ] = bounds[ 5 ]; + + this->m_Bounds[ 3 ][ 0 ] = step; + this->m_Bounds[ 3 ][ 1 ] = bounds[ 3 ]; + this->m_Bounds[ 3 ][ 2 ] = bounds[ 4 ]; + } + else if( o == 1 ) + { + this->m_Bounds[ 0 ][ 0 ] = bounds[ 0 ]; + this->m_Bounds[ 0 ][ 1 ] = step; + this->m_Bounds[ 0 ][ 2 ] = bounds[ 4 ]; + + this->m_Bounds[ 1 ][ 0 ] = bounds[ 1 ]; + this->m_Bounds[ 1 ][ 1 ] = step; + this->m_Bounds[ 1 ][ 2 ] = bounds[ 4 ]; + + this->m_Bounds[ 2 ][ 0 ] = bounds[ 1 ]; + this->m_Bounds[ 2 ][ 1 ] = step; + this->m_Bounds[ 2 ][ 2 ] = bounds[ 5 ]; + + this->m_Bounds[ 3 ][ 0 ] = bounds[ 0 ]; + this->m_Bounds[ 3 ][ 1 ] = step; + this->m_Bounds[ 3 ][ 2 ] = bounds[ 5 ]; + } + else if( o == 2 ) + { + this->m_Bounds[ 0 ][ 0 ] = bounds[ 0 ]; + this->m_Bounds[ 0 ][ 1 ] = bounds[ 2 ]; + this->m_Bounds[ 0 ][ 2 ] = step; + + this->m_Bounds[ 1 ][ 0 ] = bounds[ 1 ]; + this->m_Bounds[ 1 ][ 1 ] = bounds[ 2 ]; + this->m_Bounds[ 1 ][ 2 ] = step; + + this->m_Bounds[ 2 ][ 0 ] = bounds[ 1 ]; + this->m_Bounds[ 2 ][ 1 ] = bounds[ 3 ]; + this->m_Bounds[ 2 ][ 2 ] = step; + + this->m_Bounds[ 3 ][ 0 ] = bounds[ 0 ]; + this->m_Bounds[ 3 ][ 1 ] = bounds[ 3 ]; + this->m_Bounds[ 3 ][ 2 ] = step; + + } // fi + this->Modified( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageOutlineSource:: +ImageOutlineSource( ) + : Superclass( ) +{ + this->SetNumberOfInputPorts( 0 ); + for( unsigned int j = 0; j < 4; ++j ) + for( unsigned int i = 0; i < 3; ++i ) + this->m_Bounds[ j ][ i ] = double( 0 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageOutlineSource:: +~ImageOutlineSource( ) +{ +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageOutlineSource:: +RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) +{ + // Get output object + vtkInformation* outInfo = outputVector->GetInformationObject( 0 ); + vtkPolyData* output = + vtkPolyData::SafeDownCast( + outInfo->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Create points + vtkPoints* points = vtkPoints::New( ); + points->SetDataType( VTK_FLOAT ); + points->Allocate( 4 ); + + // Create lines + vtkCellArray* verts = vtkCellArray::New( ); + vtkCellArray* lines = vtkCellArray::New( ); + vtkCellArray* faces = vtkCellArray::New( ); + vtkCellArray* strips = vtkCellArray::New( ); + lines->Allocate( lines->EstimateSize( 4, 2 ) ); + + // Assign points + points->InsertPoint( 0, this->m_Bounds[ 0 ] ); + points->InsertPoint( 1, this->m_Bounds[ 1 ] ); + points->InsertPoint( 2, this->m_Bounds[ 2 ] ); + points->InsertPoint( 3, this->m_Bounds[ 3 ] ); + + // Assign cells + vtkIdType cell_pts[ 4 ][ 2 ] = + { + { 0, 1 }, + { 1, 2 }, + { 2, 3 }, + { 3, 0 } + }; + lines->InsertNextCell( 2, cell_pts[ 0 ] ); + lines->InsertNextCell( 2, cell_pts[ 1 ] ); + lines->InsertNextCell( 2, cell_pts[ 2 ] ); + lines->InsertNextCell( 2, cell_pts[ 3 ] ); + + // Assign to output + output->SetPoints( points ); + output->SetVerts( verts ); + output->SetLines( lines ); + output->SetPolys( faces ); + output->SetStrips( strips ); + + // Finish and return + points->Delete( ); + verts->Delete( ); + lines->Delete( ); + faces->Delete( ); + strips->Delete( ); + return( 1 ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageOutlineSource.h b/lib/cpExtensions/Visualization/ImageOutlineSource.h new file mode 100644 index 0000000..5f3f7d8 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageOutlineSource.h @@ -0,0 +1,53 @@ +#ifndef __cpExtensions__Visualization__ImageOutlineSource__h__ +#define __cpExtensions__Visualization__ImageOutlineSource__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT ImageOutlineSource + : public vtkPolyDataAlgorithm + { + public: + typedef ImageOutlineSource Self; + + public: + vtkTypeMacro( ImageOutlineSource, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + void SetBounds( int orientation, double step, double* bounds ); + + protected: + ImageOutlineSource( ); + virtual ~ImageOutlineSource( ); + + virtual int RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + ImageOutlineSource( const Self& ); + Self& operator=( const Self& ); + + protected: + double m_Bounds[ 4 ][ 3 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__ImageOutlineSource__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.cxx b/lib/cpExtensions/Visualization/ImageSliceActors.cxx new file mode 100644 index 0000000..6d67a66 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceActors.cxx @@ -0,0 +1,174 @@ +#include +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +Self* cpExtensions::Visualization::ImageSliceActors:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::ImageSliceActors:: +GetImage( ) +{ + if( this->m_WindowLevelImageActor.GetPointer( ) != NULL ) + return( this->m_WindowLevelImageActor->GetImage( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const vtkImageData* cpExtensions::Visualization::ImageSliceActors:: +GetImage( ) const +{ + if( this->m_WindowLevelImageActor.GetPointer( ) != NULL ) + return( this->m_WindowLevelImageActor->GetImage( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +WindowLevelImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetWindowLevelImageActor( ) +{ + return( this->m_WindowLevelImageActor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization:: +WindowLevelImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetWindowLevelImageActor( ) const +{ + return( this->m_WindowLevelImageActor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +LUTImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetLUTImageActor( ) +{ + return( this->m_LUTImageActor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization:: +LUTImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetLUTImageActor( ) const +{ + return( this->m_LUTImageActor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +ImageOutlineActor* cpExtensions::Visualization::ImageSliceActors:: +GetImageOutlineActor( ) +{ + return( this->m_ImageOutlineActor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization:: +ImageOutlineActor* cpExtensions::Visualization::ImageSliceActors:: +GetImageOutlineActor( ) const +{ + return( this->m_ImageOutlineActor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +GetOrientation( ) const +{ + if( this->m_WindowLevelImageActor.GetPointer( ) != NULL ) + return( this->m_WindowLevelImageActor->GetOrientation( ) ); + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetImage( vtkImageData* image, int orientation ) +{ + this->m_WindowLevelImageActor = + vtkSmartPointer< WindowLevelImageActor >::New( ); + this->m_WindowLevelImageActor->SetImage( image ); + this->m_WindowLevelImageActor->SetOrientation( orientation ); + this->m_ImageOutlineActor = vtkSmartPointer< ImageOutlineActor >::New( ); + this->m_LUTImageActor = NULL; + + // Put an initial slice + int ext[ 6 ]; + image->GetExtent( ext ); + this->SetSliceNumber( + ext[ this->m_WindowLevelImageActor->GetOrientation( ) << 1 ] + ); + + // Update collection + this->RemoveAllItems( ); + this->AddItem( this->m_ImageOutlineActor ); + this->AddItem( this->m_WindowLevelImageActor ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::ImageSliceActors:: +AddLUTImage( vtkImageData* image ) +{ + if( this->GetImage( ) != NULL ) + { + if( this->m_LUTImageActor.GetPointer( ) == NULL ) + { + this->m_LUTImageActor = vtkSmartPointer< LUTImageActor >::New( ); + this->m_LUTImageActor->SetOrientation( this->GetOrientation( ) ); + this->AddItem( this->m_LUTImageActor ); + + } // fi + this->m_LUTImageActor->AddImage( image ); + return( this->m_LUTImageActor->GetNumberOfImages( ) ); + } + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +GetSliceNumber( ) const +{ + return( this->m_WindowLevelImageActor->GetSliceNumber( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetSliceNumber( int slice ) +{ + this->m_WindowLevelImageActor->SetSliceNumber( slice ); + if( this->m_LUTImageActor.GetPointer( ) != NULL ) + this->m_LUTImageActor->SetSliceNumber( slice ); + + double bounds[ 6 ]; + this->m_WindowLevelImageActor->GetImage( )->GetBounds( bounds ); + int o = this->m_WindowLevelImageActor->GetOrientation( ); + double p = this->m_WindowLevelImageActor->GetSlicePlane( )->GetOrigin( )[ o ]; + this->m_ImageOutlineActor->SetBounds( o, p, bounds ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +ImageSliceActors( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +~ImageSliceActors( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.h b/lib/cpExtensions/Visualization/ImageSliceActors.h new file mode 100644 index 0000000..25f81f6 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceActors.h @@ -0,0 +1,74 @@ +#ifndef __cpExtensions__Visualization__ImageSliceActors__h__ +#define __cpExtensions__Visualization__ImageSliceActors__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkImageData; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class ImageOutlineActor; + class LUTImageActor; + class WindowLevelImageActor; + + /** + */ + class cpExtensions_EXPORT ImageSliceActors + : public vtkPropCollection + { + public: + typedef ImageSliceActors Self; + + public: + vtkTypeMacro( ImageSliceActors, vtkPropCollection ); + + public: + static Self* New( ); + + vtkImageData* GetImage( ); + const vtkImageData* GetImage( ) const; + + WindowLevelImageActor* GetWindowLevelImageActor( ); + const WindowLevelImageActor* GetWindowLevelImageActor( ) const; + + LUTImageActor* GetLUTImageActor( ); + const LUTImageActor* GetLUTImageActor( ) const; + + ImageOutlineActor* GetImageOutlineActor( ); + const ImageOutlineActor* GetImageOutlineActor( ) const; + + int GetOrientation( ) const; + + int GetSliceNumber( ) const; + virtual void SetImage( vtkImageData* image, int orientation ); + virtual unsigned int AddLUTImage( vtkImageData* image ); + virtual void SetSliceNumber( int slice ); + + protected: + ImageSliceActors( ); + virtual ~ImageSliceActors( ); + + private: + // Purposely not implemented + ImageSliceActors( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< ImageOutlineActor > m_ImageOutlineActor; + vtkSmartPointer< LUTImageActor > m_LUTImageActor; + vtkSmartPointer< WindowLevelImageActor > m_WindowLevelImageActor; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__ImageSliceActors__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageSliceMapper.cxx b/lib/cpExtensions/Visualization/ImageSliceMapper.cxx new file mode 100644 index 0000000..5bf36fc --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceMapper.cxx @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceMapper:: +Self* cpExtensions::Visualization::ImageSliceMapper:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceMapper:: +ImageSliceMapper( ) + : Superclass( ) +{ +#ifdef cpPlugins_OpenGL_BackEnd_OpenGL2 + // Complete polydatas to avoid bizarre rendering errors (multi-thread) + vtkActor* a[ 3 ]; + a[ 0 ] = this->PolyDataActor; + a[ 1 ] = this->BackingPolyDataActor; + a[ 2 ] = this->BackgroundPolyDataActor; + for( unsigned int i = 0; i < 3; ++i ) + { + if( a[ i ] != NULL ) + { + auto m = + dynamic_cast< vtkOpenGLPolyDataMapper* >( a[ i ]->GetMapper( ) ); + if( m != NULL ) + { + auto p = m->GetInput( ); + if( p != NULL ) + { + vtkNew< vtkCellArray > verts; + vtkNew< vtkCellArray > lines; + vtkNew< vtkCellArray > strips; + p->SetVerts( verts.Get( ) ); + p->SetLines( lines.Get( ) ); + p->SetStrips( strips.Get( ) ); + p->Modified( ); + m->Modified( ); + a[ i ]->Modified( ); + + } // fi + + } // fi + + } // fi + + } // rof +#endif // cpPlugins_OpenGL_BackEnd_OpenGL2 +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceMapper:: +~ImageSliceMapper( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageSliceMapper.h b/lib/cpExtensions/Visualization/ImageSliceMapper.h new file mode 100644 index 0000000..10e8404 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceMapper.h @@ -0,0 +1,43 @@ +#ifndef __cpExtensions__Visualization__ImageSliceMapper__h__ +#define __cpExtensions__Visualization__ImageSliceMapper__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT ImageSliceMapper + : public vtkOpenGLImageSliceMapper + { + public: + typedef ImageSliceMapper Self; + + public: + vtkTypeMacro( ImageSliceMapper, vtkOpenGLImageSliceMapper ); + + public: + static Self* New( ); + + protected: + ImageSliceMapper( ); + virtual ~ImageSliceMapper( ); + + private: + // Purposely not implemented + ImageSliceMapper( const Self& ); + Self& operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__ImageSliceMapper__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageViewerActors.cxx b/lib/cpExtensions/Visualization/ImageViewerActors.cxx new file mode 100644 index 0000000..65114c8 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageViewerActors.cxx @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageViewerActors:: +Self* cpExtensions::Visualization::ImageViewerActors:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageViewerActors:: +SetImage( vtkImageData* image, int orientation ) +{ + this->Superclass::SetImage( image, orientation ); + + this->m_Cursor = vtkSmartPointer< CursorActors >::New( ); + this->m_Cursor->SetImageBounds( image->GetBounds( ) ); + this->m_Cursor->SetImageOrientation( orientation ); + this->m_Cursor->GetProperty( 0 )->SetColor( 1, 1, 0 ); + this->m_Cursor->GetProperty( 1 )->SetColor( 1, 1, 0 ); + this->m_Cursor->GetProperty( 0 )->SetLineWidth( 1.5 ); + this->m_Cursor->GetProperty( 1 )->SetLineWidth( 1.5 ); + this->m_Cursor->VisibilityOff( ); + + this->m_SuperCursor = vtkSmartPointer< CursorActors >::New( ); + this->m_SuperCursor->SetImageBounds( image->GetBounds( ) ); + this->m_SuperCursor->SetImageOrientation( orientation ); + this->m_SuperCursor->GetProperty( 0 )->SetColor( 0, 1, 1 ); + this->m_SuperCursor->GetProperty( 1 )->SetColor( 0, 1, 1 ); + this->m_SuperCursor->GetProperty( 0 )->SetLineWidth( 1.5 ); + this->m_SuperCursor->GetProperty( 1 )->SetLineWidth( 1.5 ); + this->m_SuperCursor->VisibilityOff( ); + + // Prepare text + this->m_TextBuffer[ 0 ] = '\0'; + this->m_Text = vtkSmartPointer< vtkTextActor >::New( ); + this->m_Text->SetTextScaleModeToNone( ); + auto textprop = this->m_Text->GetTextProperty( ); + textprop->SetColor( 1, 1, 0 ); + textprop->SetFontFamilyToCourier( ); + textprop->SetFontSize( 18 ); + textprop->BoldOff( ); + textprop->ItalicOff( ); + textprop->ShadowOff( ); + textprop->SetJustificationToLeft( ); + textprop->SetVerticalJustificationToBottom( ); + auto coord = this->m_Text->GetPositionCoordinate( ); + coord->SetCoordinateSystemToNormalizedViewport( ); + coord->SetValue( 0.01, 0.05 ); + this->m_Text->VisibilityOff( ); + + // Update actor list + this->m_Cursor->InitTraversal( ); + while( vtkProp* prop = this->m_Cursor->GetNextProp( ) ) + this->AddItem( prop ); + this->m_SuperCursor->InitTraversal( ); + while( vtkProp* prop = this->m_SuperCursor->GetNextProp( ) ) + this->AddItem( prop ); + this->AddItem( this->m_Text ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageViewerActors:: +SetCursor( double* pos, bool neg ) +{ + this->m_Cursor->SetCursor( pos, neg ); + this->_ShowText( pos ); + this->m_Cursor->VisibilityOn( ); + this->m_Text->VisibilityOn( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageViewerActors:: +SetSuperCursor( double* pos, bool neg ) +{ + this->SetCursor( pos, neg ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageViewerActors:: +HideViewerActors( ) +{ + this->m_Cursor->VisibilityOff( ); + this->m_Text->VisibilityOff( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageViewerActors:: +ImageViewerActors( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageViewerActors:: +~ImageViewerActors( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageViewerActors:: +_CorrectPosition( double* pos, int* ijk ) +{ + auto image = this->GetImage( ); + if( image == NULL ) + return; + + // Approximate image index + double pcoords[ 3 ]; + image->ComputeStructuredCoordinates( pos, ijk, pcoords ); + + // Manually correct index + int ext[ 6 ]; + image->GetExtent( ext ); + for( int i = 0; i < 3; ++i ) + { + if( ijk[ i ] < ext[ i << 1 ] ) + ijk[ i ] = ext[ i << 1 ]; + if( ext[ ( i << 1 ) + 1 ] < ijk[ i ] ) + ijk[ i ] = ext[ ( i << 1 ) + 1 ]; + + } // rof + + // Get real coordinates + int o = this->GetOrientation( ); + ijk[ o ] = this->GetSliceNumber( ); + image->GetPoint( image->ComputePointId( ijk ), pos ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageViewerActors:: +_ShowText( double* pos ) +{ + auto image = this->GetImage( ); + if( image == NULL ) + return; + + int ijk[ 3 ]; + this->_CorrectPosition( pos, ijk ); + int o = this->GetOrientation( ); + + std::stringstream buffer; + buffer << "Axis: " << char( 'X' + char( o ) ) << std::endl; + int nScl = image->GetNumberOfScalarComponents( ); + buffer + << "Pixel: [" << ijk[ 0 ] + << "," << ijk[ 1 ] + << "," << ijk[ 2 ] << "]=(" + << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 ); + for( int n = 1; n < nScl; ++n ) + buffer + << " : " + << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n ); + buffer << ")"; + cpExtensions_SPRINTF( this->m_TextBuffer, 1024, buffer.str( ).c_str( ) ); + this->m_Text->SetInput( this->m_TextBuffer ); + this->m_Text->VisibilityOn( ); + this->m_Text->Modified( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageViewerActors.h b/lib/cpExtensions/Visualization/ImageViewerActors.h new file mode 100644 index 0000000..b12e9c8 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageViewerActors.h @@ -0,0 +1,64 @@ +#ifndef __cpExtensions__Visualization__ImageViewerActors__h__ +#define __cpExtensions__Visualization__ImageViewerActors__h__ + +#include +#include + +// ------------------------------------------------------------------------- +class vtkTextActor; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class CursorActors; + + /** + */ + class cpExtensions_EXPORT ImageViewerActors + : public ImageSliceActors + { + public: + typedef ImageViewerActors Self; + + public: + vtkTypeMacro( ImageViewerActors, ImageSliceActors ); + + public: + static Self* New( ); + + virtual void SetImage( + vtkImageData* image, int orientation + ) cpExtensions_OVERRIDE; + + void SetCursor( double* pos, bool neg ); + void SetSuperCursor( double* pos, bool neg ); + void HideViewerActors( ); + + protected: + ImageViewerActors( ); + virtual ~ImageViewerActors( ); + + void _CorrectPosition( double* pos, int* ijk ); + void _ShowText( double* pos ); + + private: + // Purposely not implemented + ImageViewerActors( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< CursorActors > m_Cursor; + vtkSmartPointer< CursorActors > m_SuperCursor; + vtkSmartPointer< vtkTextActor > m_Text; + char m_TextBuffer[ 1024 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__ImageViewerActors__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/LUTImageActor.cxx b/lib/cpExtensions/Visualization/LUTImageActor.cxx new file mode 100644 index 0000000..d377215 --- /dev/null +++ b/lib/cpExtensions/Visualization/LUTImageActor.cxx @@ -0,0 +1,160 @@ +#include +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::LUTImageActor:: +Self* cpExtensions::Visualization::LUTImageActor:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::LUTImageActor:: +GetNumberOfImages( ) const +{ + return( this->m_Images.size( ) ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::LUTImageActor:: +GetImage( unsigned int id ) +{ + if( id < this->m_Images.size( ) ) + return( this->m_Images[ id ] ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const vtkImageData* cpExtensions::Visualization::LUTImageActor:: +GetImage( unsigned int id ) const +{ + if( id < this->m_Images.size( ) ) + return( this->m_Images[ id ] ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::LUTImageActor:: +GetImageId( vtkImageData* image ) const +{ + unsigned int i = 0; + bool f = false; + while( i < this->m_Images.size( ) && !f ) + { + if( this->m_Images[ i ].GetPointer( ) == image ) + f = true; + else + i++; + + } // elihw + return( i ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::LUTImageActor:: +GetLUTColor( + unsigned int id, double& r, double& g, double& b, double& a + ) const +{ + double rgba[ 4 ]; + this->m_LUT->GetTableValue( id, rgba ); + r = rgba[ 0 ]; + g = rgba[ 1 ]; + b = rgba[ 2 ]; + a = rgba[ 3 ]; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::LUTImageActor:: +GetLUTColor( + vtkImageData* image, double& r, double& g, double& b, double& a + ) const +{ + this->GetLUTColor( this->GetImageId( image ), r, g, b, a ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::LUTImageActor:: +SetLUTColor( unsigned int id, double r, double g, double b, double a ) +{ + if( id >= ( unsigned int )( this->m_LUT->GetNumberOfTableValues( ) ) ) + this->m_LUT->SetNumberOfTableValues( id + 1 ); + this->m_LUT->SetTableValue( id, r, g, b, a ); + this->m_LUT->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::LUTImageActor:: +SetLUTColor( vtkImageData* image, double r, double g, double b, double a ) +{ + this->SetLUTColor( this->GetImageId( image ), r, g, b, a ); +} + +// TODO: !!!!! +#include + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::LUTImageActor:: +AddImage( vtkImageData* image, double r, double g, double b, double a ) +{ + static vtkSmartPointer< vtkImageCast > cast; + cast = vtkSmartPointer< vtkImageCast >::New( ); + + if( image != NULL ) + { + cast->SetOutputScalarTypeToUnsignedChar( ); + cast->SetInputData( image ); + cast->Update( ); + + this->m_Images.push_back( image ); + this->SetLUTColor( this->m_Images.size( ), r, g, b, a ); + this->m_Blender->AddInputData( cast->GetOutput( ) ); + this->m_Blender->Update( ); + + if( this->m_Images.size( ) == 1 ) + { + this->m_ImageMap-> + SetInputConnection( this->m_Blender->GetOutputPort( ) ); + this->m_Mapper-> + SetInputConnection( this->m_ImageMap->GetOutputPort( ) ); + + } // fi + this->Modified( ); + + this->GetProperty( )->SetInterpolationTypeToNearest( ); + + } // fi + return( this->m_Images.size( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::LUTImageActor:: +LUTImageActor( ) + : Superclass( ) +{ + this->m_LUT = vtkSmartPointer< vtkLookupTable >::New( ); + this->m_LUT->SetNumberOfTableValues( 1 ); + this->m_LUT->SetNanColor( 0, 0, 0, 0 ); + this->m_LUT->SetTableValue( 0, 0, 0, 0, 0 ); + + this->m_Blender = vtkSmartPointer< _TImageBlender >::New( ); + this->m_ImageMap = vtkSmartPointer< vtkImageMapToColors >::New( ); + this->m_ImageMap->SetLookupTable( this->m_LUT ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::LUTImageActor:: +~LUTImageActor( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/LUTImageActor.h b/lib/cpExtensions/Visualization/LUTImageActor.h new file mode 100644 index 0000000..851afa5 --- /dev/null +++ b/lib/cpExtensions/Visualization/LUTImageActor.h @@ -0,0 +1,78 @@ +#ifndef __cpExtensions__Visualization__LUTImageActor__h__ +#define __cpExtensions__Visualization__LUTImageActor__h__ + +#include +#include + +// ------------------------------------------------------------------------- +class vtkImageMapToColors; +class vtkLookupTable; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Algorithms { class ImageBlender; } + + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT LUTImageActor + : public ImageActor + { + public: + typedef LUTImageActor Self; + + protected: + typedef cpExtensions::Algorithms::ImageBlender _TImageBlender; + + public: + vtkTypeMacro( LUTImageActor, ImageActor ); + + public: + static Self* New( ); + + unsigned int GetNumberOfImages( ) const; + vtkImageData* GetImage( unsigned int id ); + const vtkImageData* GetImage( unsigned int id ) const; + unsigned int GetImageId( vtkImageData* image ) const; + void GetLUTColor( + unsigned int id, double& r, double& g, double& b, double& a + ) const; + void GetLUTColor( + vtkImageData* image, double& r, double& g, double& b, double& a + ) const; + void SetLUTColor( + unsigned int id, double r, double g, double b, double a + ); + void SetLUTColor( + vtkImageData* image, double r, double g, double b, double a + ); + unsigned int AddImage( + vtkImageData* image, + double r = 1, double g = 0, double b = 0, double a = 1 + ); + + protected: + LUTImageActor( ); + virtual ~LUTImageActor( ); + + private: + // Purposely not implemented + LUTImageActor( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkLookupTable > m_LUT; + vtkSmartPointer< _TImageBlender > m_Blender; + vtkSmartPointer< vtkImageMapToColors > m_ImageMap; + std::vector< vtkSmartPointer< vtkImageData > > m_Images; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__LUTImageActor__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/LineSource.cxx b/lib/cpExtensions/Visualization/LineSource.cxx new file mode 100644 index 0000000..6280cba --- /dev/null +++ b/lib/cpExtensions/Visualization/LineSource.cxx @@ -0,0 +1,119 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::LineSource:: +Self* cpExtensions::Visualization::LineSource:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::LineSource:: +SetPoint1( float pnt[ 3 ] ) +{ + double p[ 3 ]; + p[ 0 ] = pnt[ 0 ]; + p[ 1 ] = pnt[ 1 ]; + p[ 2 ] = pnt[ 2 ]; + this->SetPoint1( p ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::LineSource:: +SetPoint2( float pnt[ 3 ] ) +{ + double p[ 3 ]; + p[ 0 ] = pnt[ 0 ]; + p[ 1 ] = pnt[ 1 ]; + p[ 2 ] = pnt[ 2 ]; + this->SetPoint2( p ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::LineSource:: +LineSource( ) + : Superclass( ) +{ + this->SetNumberOfInputPorts( 0 ); + this->Point1[ 0 ] = -double( 0.5 ); + this->Point1[ 1 ] = double( 0.0 ); + this->Point1[ 2 ] = double( 0.0 ); + this->Point2[ 0 ] = double( 0.5 ); + this->Point2[ 1 ] = double( 0.0 ); + this->Point2[ 2 ] = double( 0.0 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::LineSource:: +~LineSource( ) +{ +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::LineSource:: +RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) +{ + // Get output object + vtkInformation* outInfo = outputVector->GetInformationObject( 0 ); + vtkPolyData* output = + vtkPolyData::SafeDownCast( + outInfo->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Create points + vtkPoints* points = vtkPoints::New( ); + points->SetDataType( VTK_FLOAT ); + points->Allocate( 2 ); + + // Create cells + vtkCellArray* verts = vtkCellArray::New( ); + vtkCellArray* lines = vtkCellArray::New( ); + vtkCellArray* faces = vtkCellArray::New( ); + vtkCellArray* strips = vtkCellArray::New( ); + lines->Allocate( lines->EstimateSize( 2, 2 ) ); + + // Assign points + points->InsertPoint( 0, this->Point1 ); + points->InsertPoint( 1, this->Point2 ); + + // Assign cells + vtkIdType cell_pts[ 2 ] = { 0, 1 }; + lines->InsertNextCell( 2, cell_pts ); + + // Assign to output + output->SetPoints( points ); + output->SetVerts( verts ); + output->SetLines( lines ); + output->SetPolys( faces ); + output->SetStrips( strips ); + + // Finish and return + points->Delete( ); + verts->Delete( ); + lines->Delete( ); + faces->Delete( ); + strips->Delete( ); + return( 1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::LineSource:: +RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) +{ + vtkInformation* outInfo = outputVector->GetInformationObject( 0 ); + outInfo->Set( CAN_HANDLE_PIECE_REQUEST(), 1 ); + return( 1 ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/LineSource.h b/lib/cpExtensions/Visualization/LineSource.h new file mode 100644 index 0000000..c675257 --- /dev/null +++ b/lib/cpExtensions/Visualization/LineSource.h @@ -0,0 +1,66 @@ +#ifndef __cpExtensions__Visualization__LineSource__h__ +#define __cpExtensions__Visualization__LineSource__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT LineSource + : public vtkPolyDataAlgorithm + { + public: + typedef LineSource Self; + + public: + vtkTypeMacro( LineSource, vtkPolyDataAlgorithm ); + + vtkSetVector3Macro( Point1, double ); + vtkSetVector3Macro( Point2, double ); + vtkGetVectorMacro( Point1, double, 3 ); + vtkGetVectorMacro( Point2, double, 3 ); + + public: + static Self* New( ); + + void SetPoint1( float pnt[ 3 ] ); + void SetPoint2( float pnt[ 3 ] ); + + protected: + LineSource( ); + virtual ~LineSource( ); + + virtual int RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) cpExtensions_OVERRIDE; + + virtual int RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + LineSource( const Self& ); + Self& operator=( const Self& ); + + protected: + double Point1[ 3 ]; + double Point2[ 3 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__LineSource__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MPR3DActors.cxx b/lib/cpExtensions/Visualization/MPR3DActors.cxx new file mode 100644 index 0000000..b3f4700 --- /dev/null +++ b/lib/cpExtensions/Visualization/MPR3DActors.cxx @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPR3DActors:: +Self* cpExtensions::Visualization::MPR3DActors:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::MPR3DActors:: +GetImage( ) +{ + return( this->m_Slices[ 0 ]->GetImage( ) ); +} + +// ------------------------------------------------------------------------- +const vtkImageData* cpExtensions::Visualization::MPR3DActors:: +GetImage( ) const +{ + return( this->m_Slices[ 0 ]->GetImage( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +WindowLevelImageActor* cpExtensions::Visualization::MPR3DActors:: +GetWindowLevelImageActor( int o ) +{ + return( this->m_Slices[ o % 3 ]->GetWindowLevelImageActor( ) ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization:: +WindowLevelImageActor* cpExtensions::Visualization::MPR3DActors:: +GetWindowLevelImageActor( int o ) const +{ + return( this->m_Slices[ o % 3 ]->GetWindowLevelImageActor( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +LUTImageActor* cpExtensions::Visualization::MPR3DActors:: +GetLUTImageActor( int o ) +{ + return( this->m_Slices[ o % 3 ]->GetLUTImageActor( ) ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization:: +LUTImageActor* cpExtensions::Visualization::MPR3DActors:: +GetLUTImageActor( int o ) const +{ + return( this->m_Slices[ o % 3 ]->GetLUTImageActor( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +ImageOutlineActor* cpExtensions::Visualization::MPR3DActors:: +GetImageOutlineActor( int o ) +{ + return( this->m_Slices[ o % 3 ]->GetImageOutlineActor( ) ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization:: +ImageOutlineActor* cpExtensions::Visualization::MPR3DActors:: +GetImageOutlineActor( int o ) const +{ + return( this->m_Slices[ o % 3 ]->GetImageOutlineActor( ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPR3DActors:: +GetSliceNumber( int o ) const +{ + return( this->m_Slices[ o % 3 ]->GetSliceNumber( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPR3DActors:: +SetImage( vtkImageData* image ) +{ + this->RemoveAllItems( ); + for( int i = 0; i < 3; ++i ) + { + this->m_Slices[ i ]->SetImage( image, i ); + this->m_Slices[ i ]->InitTraversal( ); + while( vtkProp* p = this->m_Slices[ i ]->GetNextProp( ) ) + this->AddItem( p ); + + } // rof +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::MPR3DActors:: +AddLUTImage( vtkImageData* image ) +{ + unsigned int res = 0; + for( int i = 0; i < 3; ++i ) + { + res = this->m_Slices[ i ]->AddLUTImage( image ); + this->AddItem( this->m_Slices[ i ]->GetLUTImageActor( ) ); + + } // rof + return( res ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPR3DActors:: +SetSliceNumber( int o, int s ) +{ + this->m_Slices[ o % 3 ]->SetSliceNumber( s ); +} + +// ------------------------------------------------------------------------- +vtkActor* cpExtensions::Visualization::MPR3DActors:: +AddMesh( vtkPolyData* mesh ) +{ + TMeshActor actor; + actor.SetMesh( mesh ); + this->m_Meshes[ mesh ] = actor; + this->AddItem( actor.GetActor( ) ); + return( actor.GetActor( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPR3DActors:: +SetScalarRange( double r[ 2 ] ) +{ + this->m_Slices[ 0 ]->GetWindowLevelImageActor( )->SetRange( r ); + this->m_Slices[ 1 ]->GetWindowLevelImageActor( )->SetRange( r ); + this->m_Slices[ 2 ]->GetWindowLevelImageActor( )->SetRange( r ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPR3DActors:: +SetWindowLevel( double wl[ 2 ] ) +{ + this->m_Slices[ 0 ]->GetWindowLevelImageActor( )->SetWindowLevel( wl ); + this->m_Slices[ 1 ]->GetWindowLevelImageActor( )->SetWindowLevel( wl ); + this->m_Slices[ 2 ]->GetWindowLevelImageActor( )->SetWindowLevel( wl ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPR3DActors:: +SetImageOpacity( double o ) +{ + this->m_Slices[ 0 ]->GetWindowLevelImageActor( )-> + GetProperty( )->SetOpacity( o ); + this->m_Slices[ 1 ]->GetWindowLevelImageActor( )-> + GetProperty( )->SetOpacity( o ); + this->m_Slices[ 2 ]->GetWindowLevelImageActor( )-> + GetProperty( )->SetOpacity( o ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPR3DActors:: +SetImageInterpolation( unsigned char i ) +{ + // TODO +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPR3DActors:: +MPR3DActors( ) + : Superclass( ) +{ + this->m_Slices[ 0 ] = vtkSmartPointer< ImageSliceActors >::New( ); + this->m_Slices[ 1 ] = vtkSmartPointer< ImageSliceActors >::New( ); + this->m_Slices[ 2 ] = vtkSmartPointer< ImageSliceActors >::New( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPR3DActors:: +~MPR3DActors( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MPR3DActors.h b/lib/cpExtensions/Visualization/MPR3DActors.h new file mode 100644 index 0000000..07c41ba --- /dev/null +++ b/lib/cpExtensions/Visualization/MPR3DActors.h @@ -0,0 +1,85 @@ +#ifndef __cpExtensions__Visualization__MPR3DActors__h__ +#define __cpExtensions__Visualization__MPR3DActors__h__ + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkActor; +class vtkImageData; +class vtkPolyData; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + class ImageOutlineActor; + class ImageSliceActors; + class LUTImageActor; + class WindowLevelImageActor; + + /** + */ + class cpExtensions_EXPORT MPR3DActors + : public vtkPropCollection + { + public: + typedef MPR3DActors Self; + + typedef cpExtensions::Visualization::MeshActor TMeshActor; + + public: + vtkTypeMacro( MPR3DActors, vtkPropCollection ); + + public: + static Self* New( ); + + vtkImageData* GetImage( ); + const vtkImageData* GetImage( ) const; + + WindowLevelImageActor* GetWindowLevelImageActor( int o ); + const WindowLevelImageActor* GetWindowLevelImageActor( int o ) const; + + LUTImageActor* GetLUTImageActor( int o ); + const LUTImageActor* GetLUTImageActor( int o ) const; + + ImageOutlineActor* GetImageOutlineActor( int o ); + const ImageOutlineActor* GetImageOutlineActor( int o ) const; + + int GetSliceNumber( int o ) const; + virtual void SetImage( vtkImageData* image ); + virtual unsigned int AddLUTImage( vtkImageData* image ); + virtual void SetSliceNumber( int o, int s ); + + virtual vtkActor* AddMesh( vtkPolyData* mesh ); + + void SetScalarRange( double r[ 2 ] ); + void SetWindowLevel( double wl[ 2 ] ); + void SetImageOpacity( double o ); + void SetImageInterpolation( unsigned char i ); + + protected: + MPR3DActors( ); + virtual ~MPR3DActors( ); + + private: + // Purposely not implemented + MPR3DActors( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< ImageSliceActors > m_Slices[ 3 ]; + std::map< vtkSmartPointer< vtkPolyData >, TMeshActor > m_Meshes; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__MPR3DActors__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MeshActor.cxx b/lib/cpExtensions/Visualization/MeshActor.cxx new file mode 100644 index 0000000..ca6f1f9 --- /dev/null +++ b/lib/cpExtensions/Visualization/MeshActor.cxx @@ -0,0 +1,56 @@ +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MeshActor:: +MeshActor( ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MeshActor:: +~MeshActor( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MeshActor:: +SetMesh( vtkPolyData* mesh ) +{ + static unsigned long MAX = std::numeric_limits< unsigned short >::max( ); + + this->m_Mesh = mesh; + this->m_Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + unsigned long c = mesh->GetNumberOfPolys( ) + mesh->GetNumberOfStrips( ); + if( c >= MAX ) + { + vtkSmartPointer< vtkQuadricLODActor > q = + vtkSmartPointer< vtkQuadricLODActor >::New( ); + q->DeferLODConstructionOff( ); + this->m_Actor = q.GetPointer( ); + } + else + this->m_Actor = vtkSmartPointer< vtkActor >::New( ); + this->m_Mapper->SetInputData( this->m_Mesh ); + this->m_Actor->SetMapper( this->m_Mapper ); +} + +// ------------------------------------------------------------------------- +vtkActor* cpExtensions::Visualization::MeshActor:: +GetActor( ) +{ + return( this->m_Actor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const vtkActor* cpExtensions::Visualization::MeshActor:: +GetActor( ) const +{ + return( this->m_Actor.GetPointer( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MeshActor.h b/lib/cpExtensions/Visualization/MeshActor.h new file mode 100644 index 0000000..c26b8d7 --- /dev/null +++ b/lib/cpExtensions/Visualization/MeshActor.h @@ -0,0 +1,45 @@ +#ifndef __cpExtensions__Visualization__MeshActor__h__ +#define __cpExtensions__Visualization__MeshActor__h__ + +#include +#include + +// ------------------------------------------------------------------------- +class vtkActor; +class vtkPolyData; +class vtkPolyDataMapper; + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT MeshActor + { + public: + typedef MeshActor Self; + + public: + MeshActor( ); + virtual ~MeshActor( ); + + void SetMesh( vtkPolyData* mesh ); + + vtkActor* GetActor( ); + const vtkActor* GetActor( ) const; + + protected: + vtkSmartPointer< vtkPolyData > m_Mesh; + vtkSmartPointer< vtkPolyDataMapper > m_Mapper; + vtkSmartPointer< vtkActor > m_Actor; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__MeshActor__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/OutlineSource.cxx b/lib/cpExtensions/Visualization/OutlineSource.cxx new file mode 100644 index 0000000..a00a221 --- /dev/null +++ b/lib/cpExtensions/Visualization/OutlineSource.cxx @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::OutlineSource:: +Self* cpExtensions::Visualization::OutlineSource:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::OutlineSource:: +OutlineSource( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::OutlineSource:: +~OutlineSource( ) +{ +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::OutlineSource:: +RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) +{ + int r = this->Superclass::RequestData( request, inputVector, outputVector ); + + // Complete polydatas to avoid bizarre rendering errors (multi-thread) + vtkInformation *outInfo = outputVector->GetInformationObject( 0 ); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + output->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + output->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + if( this->GenerateFaces != 1 ) + output->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + return( r ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/OutlineSource.h b/lib/cpExtensions/Visualization/OutlineSource.h new file mode 100644 index 0000000..295a5b5 --- /dev/null +++ b/lib/cpExtensions/Visualization/OutlineSource.h @@ -0,0 +1,48 @@ +#ifndef __cpExtensions__Visualization__OutlineSource__h__ +#define __cpExtensions__Visualization__OutlineSource__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT OutlineSource + : public vtkOutlineSource + { + public: + typedef OutlineSource Self; + + public: + vtkTypeMacro( OutlineSource, vtkOutlineSource ); + + public: + static Self* New( ); + + protected: + OutlineSource( ); + virtual ~OutlineSource( ); + + virtual int RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector + ) cpExtensions_OVERRIDE; + + private: + // Purposely not implemented + OutlineSource( const Self& ); + Self& operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__OutlineSource__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.cxx b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.cxx new file mode 100644 index 0000000..c97fac7 --- /dev/null +++ b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.cxx @@ -0,0 +1,131 @@ +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +typename +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +Self* +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +const typename +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +TPolyLine* +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +GetInput( ) const +{ + return( this->m_PolyLine ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +void +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +SetInput( const TPolyLine* pl ) +{ + if( this->m_PolyLine != pl ) + { + this->m_PolyLine = pl; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +PolyLineParametricPathToPolyData( ) + : vtkPolyDataAlgorithm( ), + m_PolyLine( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +~PolyLineParametricPathToPolyData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +int +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + static const unsigned int dim = _TPolyLine::PathDimension; + + if( this->m_PolyLine == NULL ) + return( 0 ); + + // Get output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Prepare data + out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + vtkPoints* points = out->GetPoints( ); + vtkCellArray* lines = out->GetLines( ); + + // Get data + for( unsigned long i = 0; i < this->m_PolyLine->GetSize( ); ++i ) + { + typename _TPolyLine::TPoint pnt = this->m_PolyLine->GetPoint( i ); + if( dim == 1 ) points->InsertNextPoint( pnt[ 0 ], 0, 0 ); + else if( dim == 2 ) points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], 0 ); + else points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + if( i > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( i - 1 ); + lines->InsertCellPoint( i ); + + } // fi + + } // rof + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +int +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + return( 1 ); +} + +// ------------------------------------------------------------------------- +#include + +template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 1 > >; +template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 2 > >; +template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 3 > >; +template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 4 > >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h new file mode 100644 index 0000000..8e73108 --- /dev/null +++ b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h @@ -0,0 +1,60 @@ +#ifndef __cpExtensions__Visualization__PolyLineParametricPathToPolyData__h__ +#define __cpExtensions__Visualization__PolyLineParametricPathToPolyData__h__ + +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + template< class _TPolyLine > + class cpExtensions_EXPORT PolyLineParametricPathToPolyData + : public vtkPolyDataAlgorithm + { + public: + typedef PolyLineParametricPathToPolyData Self; + typedef _TPolyLine TPolyLine; + + public: + vtkTypeMacro( PolyLineParametricPathToPolyData, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + const TPolyLine* GetInput( ) const; + void SetInput( const TPolyLine* pl ); + + protected: + PolyLineParametricPathToPolyData( ); + virtual ~PolyLineParametricPathToPolyData( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + private: + // Purposely not implemented + PolyLineParametricPathToPolyData( const Self& ); + void operator=( const Self& ); + + protected: + const TPolyLine* m_PolyLine; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__PolyLineParametricPathToPolyData__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.cxx b/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.cxx new file mode 100644 index 0000000..697807f --- /dev/null +++ b/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.cxx @@ -0,0 +1,119 @@ +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TCurve > +typename cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +Self* cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TCurve > +const typename cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +TCurve* cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +GetInput( ) const +{ + return( this->m_Curve ); +} + +// ------------------------------------------------------------------------- +template< class _TCurve > +void +cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +SetInput( const TCurve* c ) +{ + if( this->m_Curve != c ) + { + this->m_Curve = c; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TCurve > +cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +Simple3DCurveToPolyData( ) + : vtkPolyDataAlgorithm( ), + m_Curve( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TCurve > +cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +~Simple3DCurveToPolyData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TCurve > +int cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + if( this->m_Curve == NULL ) + return( 0 ); + + // Get output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Prepare data + out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + vtkPoints* points = out->GetPoints( ); + vtkCellArray* lines = out->GetLines( ); + + // Get data + for( unsigned long i = 0; i < this->m_Curve->GetNumberOfPoints( ); ++i ) + { + typename _TCurve::TPoint pnt = this->m_Curve->GetPoint( i ); + points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + if( i > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( i - 1 ); + lines->InsertCellPoint( i ); + + } // fi + + } // rof + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TCurve > +int cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + return( 1 ); +} + +// ------------------------------------------------------------------------- +#include + +template class cpExtensions::Visualization::Simple3DCurveToPolyData< cpExtensions::DataStructures::Simple3DCurve< float > >; +template class cpExtensions::Visualization::Simple3DCurveToPolyData< cpExtensions::DataStructures::Simple3DCurve< double > >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.h b/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.h new file mode 100644 index 0000000..7407cea --- /dev/null +++ b/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.h @@ -0,0 +1,60 @@ +#ifndef __cpExtensions__Visualization__Simple3DCurveToPolyData__h__ +#define __cpExtensions__Visualization__Simple3DCurveToPolyData__h__ + +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + template< class _TCurve > + class cpExtensions_EXPORT Simple3DCurveToPolyData + : public vtkPolyDataAlgorithm + { + public: + typedef Simple3DCurveToPolyData Self; + typedef _TCurve TCurve; + + public: + vtkTypeMacro( Simple3DCurveToPolyData, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + const TCurve* GetInput( ) const; + void SetInput( const TCurve* c ); + + protected: + Simple3DCurveToPolyData( ); + virtual ~Simple3DCurveToPolyData( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + private: + // Purposely not implemented + Simple3DCurveToPolyData( const Self& ); + void operator=( const Self& ); + + protected: + const TCurve* m_Curve; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__Simple3DCurveToPolyData__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/SkeletonToPolyData.cxx b/lib/cpExtensions/Visualization/SkeletonToPolyData.cxx new file mode 100644 index 0000000..5aa7d20 --- /dev/null +++ b/lib/cpExtensions/Visualization/SkeletonToPolyData.cxx @@ -0,0 +1,147 @@ +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +typename cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +Self* cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +const typename +cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +TSkeleton* cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +GetInput( ) const +{ + return( this->m_Skeleton ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +SetInput( const TSkeleton* sk ) +{ + if( this->m_Skeleton != sk ) + { + this->m_Skeleton = sk; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +SkeletonToPolyData( ) + : vtkPolyDataAlgorithm( ), + m_Skeleton( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +~SkeletonToPolyData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +int cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + typedef typename _TSkeleton::TPath _TPath; + static const unsigned int dim = _TPath::PathDimension; + + if( this->m_Skeleton == NULL ) + return( 0 ); + + // Get output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Prepare data + out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + vtkPoints* points = out->GetPoints( ); + vtkCellArray* lines = out->GetLines( ); + + // Assign all data + auto mIt = this->m_Skeleton->BeginEdgesRows( ); + for( ; mIt != this->m_Skeleton->EndEdgesRows( ); ++mIt ) + { + // TODO: mIt->first; --> this is the row index. <-- + auto rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + // TODO: rIt->first; --> this is the column index. + auto eIt = rIt->second.begin( ); + for( ; eIt != rIt->second.end( ); ++eIt ) + { + _TPath* path = *eIt; + for( unsigned long i = 0; i < path->GetSize( ); ++i ) + { + auto pnt = path->GetPoint( i ); + if( dim == 1 ) + points->InsertNextPoint( pnt[ 0 ], 0, 0 ); + else if( dim == 2 ) + points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], 0 ); + else + points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + if( i > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 1 ); + + } // fi + + } // rof + + } // rof + + } // rof + + } // rof + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +int cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + return( 1 ); +} + +// ------------------------------------------------------------------------- +#include + +template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 1 > >; +template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 2 > >; +template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 3 > >; +template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 4 > >; + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/SkeletonToPolyData.h b/lib/cpExtensions/Visualization/SkeletonToPolyData.h new file mode 100644 index 0000000..1cef407 --- /dev/null +++ b/lib/cpExtensions/Visualization/SkeletonToPolyData.h @@ -0,0 +1,60 @@ +#ifndef __cpExtensions__Visualization__SkeletonToPolyData__h__ +#define __cpExtensions__Visualization__SkeletonToPolyData__h__ + +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + template< class _TSkeleton > + class cpExtensions_EXPORT SkeletonToPolyData + : public vtkPolyDataAlgorithm + { + public: + typedef SkeletonToPolyData Self; + typedef _TSkeleton TSkeleton; + + public: + vtkTypeMacro( SkeletonToPolyData, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + const TSkeleton* GetInput( ) const; + void SetInput( const TSkeleton* sk ); + + protected: + SkeletonToPolyData( ); + virtual ~SkeletonToPolyData( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + private: + // Purposely not implemented + SkeletonToPolyData( const Self& ); + void operator=( const Self& ); + + protected: + const TSkeleton* m_Skeleton; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__SkeletonToPolyData__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/WindowLevelImageActor.cxx b/lib/cpExtensions/Visualization/WindowLevelImageActor.cxx new file mode 100644 index 0000000..c7cbbd4 --- /dev/null +++ b/lib/cpExtensions/Visualization/WindowLevelImageActor.cxx @@ -0,0 +1,200 @@ +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::WindowLevelImageActor:: +Self* cpExtensions::Visualization::WindowLevelImageActor:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::WindowLevelImageActor:: +GetImage( ) +{ + return( this->m_Mapper->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +const vtkImageData* cpExtensions::Visualization::WindowLevelImageActor:: +GetImage( ) const +{ + return( this->m_Mapper->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetImage( vtkImageData* image ) +{ + this->m_Mapper->SetInputData( image ); + this->ResetRange( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::WindowLevelImageActor:: +GetLevel( ) const +{ + Self* self = const_cast< Self* >( this ); + return( self->GetProperty( )->GetColorLevel( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::WindowLevelImageActor:: +GetWindow( ) const +{ + Self* self = const_cast< Self* >( this ); + return( self->GetProperty( )->GetColorWindow( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +GetWindowLevel( double wl[ 2 ] ) const +{ + Self* self = const_cast< Self* >( this ); + wl[ 0 ] = self->GetProperty( )->GetColorWindow( ); + wl[ 1 ] = self->GetProperty( )->GetColorLevel( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +ResetWindowLevel( ) +{ + this->SetWindowLevel( + ( this->m_Range[ 1 ] - this->m_Range[ 0 ] ), + ( this->m_Range[ 1 ] + this->m_Range[ 0 ] ) / double( 2 ) + ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetLevel( double l ) +{ + double ol = this->GetProperty( )->GetColorLevel( ); + if( l != ol && this->m_Range[ 0 ] <= l && l <= this->m_Range[ 1 ] ) + { + this->GetProperty( )->SetColorLevel( l ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetWindow( double w ) +{ + double mw = this->m_Range[ 1 ] - this->m_Range[ 0 ]; + double ow = this->GetProperty( )->GetColorWindow( ); + if( w != ow && double( 0 ) <= w && w <= mw ) + { + this->GetProperty( )->SetColorWindow( w ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetWindowLevel( double w, double l ) +{ + this->SetWindow( w ); + this->SetLevel( l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetWindowLevel( double wl[ 2 ] ) +{ + this->SetWindow( wl[ 0 ] ); + this->SetLevel( wl[ 1 ] ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::WindowLevelImageActor:: +GetMinimum( ) const +{ + return( this->m_Range[ 0 ] ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::WindowLevelImageActor:: +GetMaximum( ) const +{ + return( this->m_Range[ 0 ] ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +GetRange( double r[ 2 ] ) const +{ + r[ 0 ] = this->m_Range[ 0 ]; + r[ 1 ] = this->m_Range[ 1 ]; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +ResetRange( ) +{ + this->GetImage( )->GetScalarRange( this->m_Range ); + this->ResetWindowLevel( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetMinimum( double a ) +{ + if( this->m_Range[ 0 ] != a ) + { + this->m_Range[ 0 ] = a; + this->ResetWindowLevel( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetMaximum( double b ) +{ + if( this->m_Range[ 1 ] != b ) + { + this->m_Range[ 1 ] = b; + this->ResetWindowLevel( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetRange( double a, double b ) +{ + this->SetMinimum( a ); + this->SetMaximum( b ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::WindowLevelImageActor:: +SetRange( double r[ 2 ] ) +{ + this->SetMinimum( r[ 0 ] ); + this->SetMaximum( r[ 1 ] ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::WindowLevelImageActor:: +WindowLevelImageActor( ) + : Superclass( ) +{ + this->m_Range[ 0 ] = this->m_Range[ 1 ] = double( 0 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::WindowLevelImageActor:: +~WindowLevelImageActor( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/WindowLevelImageActor.h b/lib/cpExtensions/Visualization/WindowLevelImageActor.h new file mode 100644 index 0000000..8af3943 --- /dev/null +++ b/lib/cpExtensions/Visualization/WindowLevelImageActor.h @@ -0,0 +1,66 @@ +#ifndef __cpExtensions__Visualization__WindowLevelImageActor__h__ +#define __cpExtensions__Visualization__WindowLevelImageActor__h__ + +#include + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT WindowLevelImageActor + : public ImageActor + { + public: + typedef WindowLevelImageActor Self; + + public: + vtkTypeMacro( WindowLevelImageActor, ImageActor ); + + public: + static Self* New( ); + + vtkImageData* GetImage( ); + const vtkImageData* GetImage( ) const; + void SetImage( vtkImageData* image ); + + double GetLevel( ) const; + double GetWindow( ) const; + void GetWindowLevel( double wl[ 2 ] ) const; + void ResetWindowLevel( ); + void SetLevel( double l ); + void SetWindow( double w ); + void SetWindowLevel( double w, double l ); + void SetWindowLevel( double wl[ 2 ] ); + + double GetMinimum( ) const; + double GetMaximum( ) const; + void GetRange( double r[ 2 ] ) const; + void ResetRange( ); + void SetMinimum( double a ); + void SetMaximum( double b ); + void SetRange( double a, double b ); + void SetRange( double r[ 2 ] ); + + protected: + WindowLevelImageActor( ); + virtual ~WindowLevelImageActor( ); + + private: + // Purposely not implemented + WindowLevelImageActor( const Self& ); + Self& operator=( const Self& ); + + protected: + double m_Range[ 2 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpExtensions__Visualization__WindowLevelImageActor__h__ + +// eof - $RCSfile$ diff --git a/lib/cpInstances/BaseObjects/ITKBaseObjects.i b/lib/cpInstances/BaseObjects/ITKBaseObjects.i new file mode 100644 index 0000000..c74dfa2 --- /dev/null +++ b/lib/cpInstances/BaseObjects/ITKBaseObjects.i @@ -0,0 +1,41 @@ +header #define ITK_MANUAL_INSTANTIATION + +define fadims=1;2;3;4;6 +tinclude itkFixedArray:h|hxx +instances itk::FixedArray< #scalar_types#, #fadims# > + +define arrays=Array2D;Array;RGBPixel;RGBAPixel +tinclude itk#arrays#:h|hxx +instances itk::#arrays#< #scalar_types# > + +define vectors=CovariantVector;Point;Vector;SymmetricSecondRankTensor +tinclude itk#vectors#:h|hxx +tinclude itkVectorContainer:h|hxx +instances itk::#vectors#< #real_types#, #pdims# > +instances itk::VectorContainer< unsigned long, itk::#vectors#< #real_types#, #pdims# > > +instances itk::VectorContainer< unsigned long, #scalar_types# > + +tinclude itkDiffusionTensor3D:h|hxx +instances itk::DiffusionTensor3D< #real_types# > + +cinclude set +instances itk::VectorContainer< unsigned long, std::set< #scalar_types# > > + +define cout_vectors=FixedArray;Point;Vector +minstances #_export_# std::ostream& itk::operator<< < #real_types#, #pdims# >( std::ostream& a, itk::#cout_vectors#< #real_types#, #pdims# > const& b ) + +define matrices=Matrix +tinclude itk#matrices#:h|hxx +instances itk::#matrices#< #real_types#, #pdims#, #pdims# > + +define decorated=std::string;#scalar_types# +tinclude itkSimpleDataObjectDecorator:h|hxx +instances itk::SimpleDataObjectDecorator< #decorated# > + +tinclude itkVariableLengthVector:h|hxx +instances itk::VariableLengthVector< #scalar_types# > + +tinclude itkSymmetricEigenAnalysis:h|hxx +instances itk::SymmetricEigenAnalysis< itk::Matrix< #real_types#, #pdims#, #pdims# >, itk::FixedArray< #real_types#, #pdims# >, itk::Matrix< #real_types#, #pdims#, #pdims# > > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/BaseObjects/ITKBoundingBoxes.i b/lib/cpInstances/BaseObjects/ITKBoundingBoxes.i new file mode 100644 index 0000000..9bf736e --- /dev/null +++ b/lib/cpInstances/BaseObjects/ITKBoundingBoxes.i @@ -0,0 +1,6 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude itkBoundingBox:h|hxx +instances itk::BoundingBox< unsigned long, #pdims#, #real_types#, itk::VectorContainer< unsigned long, itk::Point< #real_types#, #pdims# > > > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/BaseObjects/ITKTransforms.i b/lib/cpInstances/BaseObjects/ITKTransforms.i new file mode 100644 index 0000000..bc6b05d --- /dev/null +++ b/lib/cpInstances/BaseObjects/ITKTransforms.i @@ -0,0 +1,18 @@ +header #define ITK_MANUAL_INSTANTIATION + +define tr=AffineTransform + +tinclude itkOptimizerParameters:h|hxx +tinclude itkTransform:h|hxx +tinclude itkMatrixOffsetTransformBase:h|hxx +tinclude itk#tr#:h|hxx +tinclude itkDataObjectDecorator:h|hxx + +instances itk::OptimizerParameters< #real_types# > +instances itk::MatrixOffsetTransformBase< #real_types#, #pdims#, #pdims# > +instances itk::Transform< #real_types#, #pdims#, #pdims# > +instances itk::#tr#< #real_types#, #pdims# > +instances itk::DataObjectDecorator< itk::Transform< #real_types#, #pdims#, #pdims# > > +instances itk::DataObjectDecorator< itk::#tr#< #real_types#, #pdims# > > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/CMakeLists.txt b/lib/cpInstances/CMakeLists.txt new file mode 100644 index 0000000..2c86239 --- /dev/null +++ b/lib/cpInstances/CMakeLists.txt @@ -0,0 +1,50 @@ +## =========================================== +## == Directories containing instantiations == +## =========================================== + +SET( + _directories + BaseObjects + Images + Geometries + Extensions + ) + +## ========================= +## == Real instantiations == +## ========================= + +SET(_pfx cpInstances_) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/BaseObjects + ${CMAKE_CURRENT_BINARY_DIR}/BaseObjects + ${CMAKE_CURRENT_SOURCE_DIR}/Images + ${CMAKE_CURRENT_BINARY_DIR}/Images + ) +FOREACH(_dir ${_directories}) + cpPlugins_BuildLibrary(${_pfx}${_dir} SHARED ${_dir}) +ENDFOREACH(_dir) + +## =========== +## == Links == +## =========== + +TARGET_LINK_LIBRARIES(${_pfx}BaseObjects ${ITK_LIBRARIES}) +TARGET_LINK_LIBRARIES(${_pfx}Images ${_pfx}BaseObjects ${VTK_LIBRARIES}) +TARGET_LINK_LIBRARIES(${_pfx}Geometries ${_pfx}BaseObjects) +TARGET_LINK_LIBRARIES(${_pfx}Extensions cpExtensions ${_pfx}Geometries) + +## ========================== +## == Generic data objects == +## ========================== + +cpPlugins_BuildLibrary(cpPluginsDataObjects SHARED DataObjects) +TARGET_LINK_LIBRARIES( + cpPluginsDataObjects + cpExtensions + cpPlugins + ${_pfx}Images ${_pfx}Geometries ${_pfx}Extensions + ) + +## eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/BoundingBox.cxx b/lib/cpInstances/DataObjects/BoundingBox.cxx new file mode 100644 index 0000000..ea05810 --- /dev/null +++ b/lib/cpInstances/DataObjects/BoundingBox.cxx @@ -0,0 +1,93 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::BoundingBox:: +SetDataObject( DataObject* o ) +{ + auto i = o->GetITK< itk::LightObject >( ); + auto v = o->GetVTK< vtkObjectBase >( ); + if( v != NULL ) this->SetVTK( v ); + else if( i != NULL ) this->SetITK( i ); + this->_UpdateVTK( ); +} + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::BoundingBox:: +Copy( Self* other ) +{ + this->m_Points[ 0 ] = other->m_Points[ 0 ]; + this->m_Points[ 1 ] = other->m_Points[ 1 ]; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::BoundingBox:: +Blend( Self* other ) +{ + if( this->m_Points[ 0 ].size( ) < other->m_Points[ 0 ].size( ) ) + this->m_Points[ 0 ].resize( + other->m_Points[ 0 ].size( ), + std::numeric_limits< double >::max( ) + ); + if( this->m_Points[ 1 ].size( ) < other->m_Points[ 1 ].size( ) ) + this->m_Points[ 1 ].resize( + other->m_Points[ 1 ].size( ), + -std::numeric_limits< double >::max( ) + ); + for( unsigned int d = 0; d < this->m_Points[ 0 ].size( ); ++d ) + if( other->m_Points[ 0 ][ d ] < this->m_Points[ 0 ][ d ] ) + this->m_Points[ 0 ][ d ] = other->m_Points[ 0 ][ d ]; + for( unsigned int d = 0; d < this->m_Points[ 1 ].size( ); ++d ) + if( other->m_Points[ 1 ][ d ] > this->m_Points[ 1 ][ d ] ) + this->m_Points[ 1 ][ d ] = other->m_Points[ 1 ][ d ]; + this->Modified( ); + this->_UpdateVTK( ); +} + +// ------------------------------------------------------------------------- +cpInstances::DataObjects::BoundingBox:: +BoundingBox( ) + : Superclass( ) +{ + this->m_Points[ 0 ].push_back( double( 0 ) ); + this->m_Points[ 1 ].push_back( double( 0 ) ); + this->m_Outline = vtkSmartPointer< vtkOutlineSource >::New( ); + this->_UpdateVTK( ); +} + +// ------------------------------------------------------------------------- +cpInstances::DataObjects::BoundingBox:: +~BoundingBox( ) +{ +} + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::BoundingBox:: +_UpdateVTK( ) +{ + auto dobj = this->GetVTK< vtkDataSet >( ); + if( dobj == NULL ) + return; + + // Get bounds + double bounds[ 6 ]; + dobj->GetBounds( bounds ); + + this->m_Points[ 0 ].clear( ); + this->m_Points[ 1 ].clear( ); + this->m_Points[ 0 ].push_back( bounds[ 0 ] ); + this->m_Points[ 0 ].push_back( bounds[ 2 ] ); + this->m_Points[ 0 ].push_back( bounds[ 4 ] ); + this->m_Points[ 1 ].push_back( bounds[ 1 ] ); + this->m_Points[ 1 ].push_back( bounds[ 3 ] ); + this->m_Points[ 1 ].push_back( bounds[ 5 ] ); + + // Update vtk objects + this->m_Outline->SetBounds( bounds ); + this->m_Outline->Update( ); + this->m_VTK = this->m_Outline->GetOutput( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/BoundingBox.h b/lib/cpInstances/DataObjects/BoundingBox.h new file mode 100644 index 0000000..dfe1300 --- /dev/null +++ b/lib/cpInstances/DataObjects/BoundingBox.h @@ -0,0 +1,107 @@ +#ifndef __cpInstances__BoundingBox__h__ +#define __cpInstances__BoundingBox__h__ + +#define ITK_MANUAL_INSTANTIATION +#include +#include +#include +#include +#include + +namespace cpInstances +{ + namespace DataObjects + { + /** + */ + class cpPluginsDataObjects_EXPORT BoundingBox + : public cpPlugins::Pipeline::DataObject + { + public: + typedef BoundingBox Self; + typedef cpPlugins::Pipeline::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( BoundingBox, DataObject ); + cpPlugins_Id_Macro( BoundingBox, Object ); + cpPlugins_Compatibility_Macro; + + public: + void SetDataObject( DataObject* o ); + + void Copy( Self* other ); + void Blend( Self* other ); + + template< class _TPoint > + inline void SetMinimum( const _TPoint& p ) + { + this->_SetPoint( 0, p ); + } + + template< class _TPoint > + inline void SetMaximum( const _TPoint& p ) + { + this->_SetPoint( 1, p ); + } + + template< class _TPoint > + inline _TPoint GetMinimum( ) const + { + return( this->_GetPoint< _TPoint >( 0 ) ); + } + + template< class _TPoint > + inline _TPoint GetMaximum( ) const + { + return( this->_GetPoint< _TPoint >( 1 ) ); + } + + protected: + BoundingBox( ); + virtual ~BoundingBox( ); + + void _UpdateVTK( ); + + template< class _TPoint > + inline void _SetPoint( unsigned int m, const _TPoint& p ) + { + this->m_Points[ m ].clear( ); + for( unsigned int d = 0; d < _TPoint::PointDimension; ++d ) + this->m_Points[ m ].push_back( double( p[ d ] ) ); + this->_UpdateVTK( ); + this->Modified( ); + } + + template< class _TPoint > + inline _TPoint _GetPoint( unsigned int m ) const + { + unsigned int dim = this->m_Points[ m ].size( ); + dim = + ( _TPoint::PointDimension < dim )? _TPoint::PointDimension: dim; + _TPoint p; + p.Fill( 0 ); + for( unsigned int d = 0; d < dim; ++d ) + p[ d ] = this->m_Points[ m ][ d ]; + return( p ); + } + + private: + // Purposely not implemented + BoundingBox( const Self& ); + Self& operator=( const Self& ); + + protected: + std::vector< double > m_Points[ 2 ]; + vtkSmartPointer< vtkOutlineSource > m_Outline; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpInstances__BoundingBox__h__ + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Image.cxx b/lib/cpInstances/DataObjects/Image.cxx new file mode 100644 index 0000000..09cf834 --- /dev/null +++ b/lib/cpInstances/DataObjects/Image.cxx @@ -0,0 +1,196 @@ +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::Image:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + this->m_VTK = NULL; + this->m_ITKvVTK = NULL; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::Image:: +SetVTK( vtkObjectBase* o ) +{ + this->Superclass::SetVTK( o ); + this->m_ITK = NULL; + this->m_ITKvVTK = NULL; + this->Modified( ); + + /* TODO + vtkImageData* img = dynamic_cast< vtkImageData* >( o ); + this->Superclass::SetVTK( img ); + if( img == NULL ) + { + this->m_ITK = NULL; + this->m_ITKvVTK = NULL; + this->Modified( ); + return; + + } // fi + + bool success = false; + auto stype = img->GetScalarType( ); + #ifdef cpPlugins_CONFIG_INTEGER_TYPES_char + if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< char >( img ); + if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned char >( img ); + #endif // cpPlugins_CONFIG_INTEGER_TYPES_char + #ifdef cpPlugins_CONFIG_INTEGER_TYPES_short + if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< short >( img ); + if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned short >( img ); + #endif // cpPlugins_CONFIG_INTEGER_TYPES_short + #ifdef cpPlugins_CONFIG_INTEGER_TYPES_int + if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< int >( img ); + if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned int >( img ); + #endif // cpPlugins_CONFIG_INTEGER_TYPES_int + #ifdef cpPlugins_CONFIG_INTEGER_TYPES_long + if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< long >( img ); + if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned long >( img ); + #endif // cpPlugins_CONFIG_INTEGER_TYPES_long + #ifdef cpPlugins_CONFIG_REAL_TYPES_float + if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< float >( img ); + #endif // cpPlugins_CONFIG_REAL_TYPES_float + #ifdef cpPlugins_CONFIG_REAL_TYPES_double + if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< double >( img ); + #endif // cpPlugins_CONFIG_REAL_TYPES_double + */ + /* TODO + #define cpPlugins_CONFIG_COLOR_PIXELS_RGBPixel + #define cpPlugins_CONFIG_COLOR_PIXELS_RGBAPixel + #define cpPlugins_CONFIG_VECTORS_CovariantVector + #define cpPlugins_CONFIG_VECTORS_Point + #define cpPlugins_CONFIG_VECTORS_SymmetricSecondRankTensor + #define cpPlugins_CONFIG_VECTORS_Vector + #define cpPlugins_CONFIG_DIFFUSIONTENSORS_DiffusionTensor3D + #define cpPlugins_CONFIG_MATRICES_Matrix + */ + /* TODO + if( !success ) + { + this->m_ITK = NULL; + this->m_ITKvVTK = NULL; + + } // fi + this->Modified( ); + */ +} + +// ------------------------------------------------------------------------- +cpInstances::DataObjects::Image:: +Image( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpInstances::DataObjects::Image:: +~Image( ) +{ +} + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::Image:: +_UpdateITK( ) const +{ + // TODO: std::cout << "Create ITK representation." << std::endl; +} + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::Image:: +_UpdateVTK( ) const +{ + auto i = const_cast< itk::LightObject* >( this->m_ITK.GetPointer( ) ); + auto v = const_cast< vtkObjectBase* >( this->m_VTK.GetPointer( ) ); + if( i != NULL && v == NULL ) + { + cpPlugins_Demangle_Image_VisualDims_1( i, _ITK_2_VTK_0 ) + cpPlugins_Demangle_Image_DiffTensors3D_1( i, _ITK_2_VTK_1 ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpInstances::DataObjects::Image:: +_ITK_2_VTK_0( _TImage* image ) const +{ + static const unsigned int d = _TImage::ImageDimension; + cpPlugins_Demangle_Image_ScalarPixels_1( image, _ITK_2_VTK_1, d ) + cpPlugins_Demangle_Image_ColorPixels_1( image, _ITK_2_VTK_1, d ) + cpPlugins_Demangle_Image_VectorPixels_1( image, _ITK_2_VTK_1, d ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpInstances::DataObjects::Image:: +_ITK_2_VTK_1( _TImage* image ) const +{ + typedef itk::ImageToVTKImageFilter< _TImage > _TFilter; + + Self* self = const_cast< Self* >( this ); + _TFilter* f = dynamic_cast< _TFilter* >( self->m_ITKvVTK.GetPointer( ) ); + if( f == NULL ) + { + typename _TFilter::Pointer nf = _TFilter::New( ); + self->m_ITKvVTK = nf; + f = nf.GetPointer( ); + + } // fi + f->SetInput( image ); + f->Update( ); + + // Keep object track + self->m_ITK = image; + self->m_VTK = f->GetOutput( ); +} + +// ------------------------------------------------------------------------- +template< class _TPixel > +bool cpInstances::DataObjects::Image:: +_VTK_2_ITK_0( vtkImageData* image ) +{ + bool success = false; + unsigned int dim = image->GetDataDimension( ); +#ifdef cpPlugins_CONFIG_VISUAL_DIMENSIONS_2 + if( dim == 2 ) success = this->_VTK_2_ITK_1< _TPixel, 2 >( image ); +#endif // cpPlugins_CONFIG_VISUAL_DIMENSIONS_2 +#ifdef cpPlugins_CONFIG_VISUAL_DIMENSIONS_3 + if( dim == 3 ) success = this->_VTK_2_ITK_1< _TPixel, 3 >( image ); +#endif // cpPlugins_CONFIG_VISUAL_DIMENSIONS_2 + return( success ); +} + +// ------------------------------------------------------------------------- +template< class _TPixel, unsigned int _VDim > +bool cpInstances::DataObjects::Image:: +_VTK_2_ITK_1( vtkImageData* image ) +{ + typedef itk::Image< _TPixel, _VDim > _TImage; + typedef itk::VTKImageToImageFilter< _TImage > _TFilter; + _TFilter* f = dynamic_cast< _TFilter* >( this->m_ITKvVTK.GetPointer( ) ); + if( f == NULL ) + { + typename _TFilter::Pointer nf = _TFilter::New( ); + this->m_ITKvVTK = nf; + f = nf.GetPointer( ); + + } // fi + f->SetInput( image ); + f->Update( ); + + // Keep object track + this->m_VTK = image; + this->m_ITK = f->GetOutput( ); + return( true ); +} + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Image.d b/lib/cpInstances/DataObjects/Image.d new file mode 100644 index 0000000..b9a2444 --- /dev/null +++ b/lib/cpInstances/DataObjects/Image.d @@ -0,0 +1,27 @@ +define all_ints=#int_types#;unsigned #int_types# +define color_pixels=RGBPixel;RGBAPixel + +ProcessDims itk::ImageBase< #pdims# > +VisualDims itk::ImageBase< #vdims# > + +IntPixels|d itk::Image< #all_ints#, d > +RealPixels|d itk::Image< #real_types#, d > +ScalarPixels|d itk::Image< #scalar_types#, d > +ComplexPixels|d itk::Image< std::complex< #real_types# >, d > +ColorPixels|d itk::Image< itk::#color_pixels#< #scalar_types# >, d > +VectorPixels|d itk::Image< itk::#vectors#< #real_types#, d >, d > +DiffTensors3D itk::Image< itk::#diff_tensors#< #real_types# >, 3 > + +IntPixels_AllDims itk::Image< #all_ints#, #pdims# > +IntPixels_VisualDims itk::Image< #all_ints#, #pdims# > +RealPixels_AllDims itk::Image< #real_types#, #pdims# > +RealPixels_VisualDims itk::Image< #real_types#, #pdims# > +ScalarPixels_AllDims itk::Image< #scalar_types#, #pdims# > +ScalarPixels_VisualDims itk::Image< #scalar_types#, #vdims# > +ColorPixels_AllDims itk::Image< itk::#color_pixels#< #scalar_types# >, #pdims# > +ColorPixels_VisualDims itk::Image< itk::#color_pixels#< #scalar_types# >, #vdims# > +VectorPixels_AllDims itk::Image< itk::#vectors#< #real_types#, #pdims# >, #pdims# > +VectorPixels_VisualDims itk::Image< itk::#vectors#< #real_types#, #vdims# >, #vdims# > +CovariantVectorPixels_AllDims itk::Image< itk::CovariantVector< #real_types#, #pdims# >, #pdims# > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Image.h b/lib/cpInstances/DataObjects/Image.h new file mode 100644 index 0000000..a3ee5ef --- /dev/null +++ b/lib/cpInstances/DataObjects/Image.h @@ -0,0 +1,71 @@ +#ifndef __cpInstances__Image__h__ +#define __cpInstances__Image__h__ + +#define ITK_MANUAL_INSTANTIATION +#include +#include +#include +#include + +class vtkImageData; + +namespace cpInstances +{ + namespace DataObjects + { + /** + */ + class cpPluginsDataObjects_EXPORT Image + : public cpPlugins::Pipeline::DataObject + { + public: + typedef Image Self; + typedef cpPlugins::Pipeline::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Image, cpPlugins::Pipeline::DataObject ); + cpPlugins_Id_Macro( Image, Object ); + cpPlugins_Compatibility_Macro; + + public: + virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE; + + protected: + Image( ); + virtual ~Image( ); + + virtual void _UpdateITK( ) const cpPlugins_OVERRIDE; + virtual void _UpdateVTK( ) const cpPlugins_OVERRIDE; + + template< class _TImage > + inline void _ITK_2_VTK_0( _TImage* image ) const; + + template< class _TImage > + inline void _ITK_2_VTK_1( _TImage* image ) const; + + template< class _TPixel > + inline bool _VTK_2_ITK_0( vtkImageData* image ); + + template< class _TPixel, unsigned int _VDim > + inline bool _VTK_2_ITK_1( vtkImageData* image ); + + private: + // Purposely not implemented + Image( const Self& ); + Self& operator=( const Self& ); + + protected: + itk::ProcessObject::Pointer m_ITKvVTK; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpInstances__Image__h__ + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Mesh.cxx b/lib/cpInstances/DataObjects/Mesh.cxx new file mode 100644 index 0000000..2118301 --- /dev/null +++ b/lib/cpInstances/DataObjects/Mesh.cxx @@ -0,0 +1,180 @@ +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::Mesh:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + cpPlugins_Demangle_Mesh_AllMeshes_1( o, _ITK_2_VTK ) + { + this->m_VTK = NULL; + } + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpInstances::DataObjects::Mesh:: +SetVTK( vtkObjectBase* o ) +{ + vtkPolyData* mesh = dynamic_cast< vtkPolyData* >( o ); + if( mesh == NULL ) + { + this->m_ITK = NULL; + this->Modified( ); + return; + + } // fi + + if( this->m_VTK.GetPointer( ) != mesh ) + { + this->m_VTK = mesh; +#ifdef cpPlugins_PROCESS_DIMS_3 + typedef itk::Mesh< double, 3 > _TMesh; + typedef _TMesh::CellType _TCell; + typedef _TCell::CellAutoPointer _TCellAutoPointer; + typedef itk::LineCell< _TCell > _TLine; + typedef itk::TriangleCell< _TCell > _TTriangle; + typedef itk::PolygonCell< _TCell > _TPolygon; + + // Copy points + _TMesh::Pointer imesh = _TMesh::New( ); + double point[ 3 ]; + for( long i = 0; i < mesh->GetNumberOfPoints( ); ++i ) + { + mesh->GetPoint( i, point ); + _TMesh::PointType ipoint; + ipoint[ 0 ] = point[ 0 ]; + ipoint[ 1 ] = point[ 1 ]; + ipoint[ 2 ] = point[ 2 ]; + imesh->SetPoint( i, ipoint ); + + } // rof + + // Copy cells + vtkCellArray* arrays[ 4 ]; + arrays[ 0 ] = mesh->GetLines( ); + arrays[ 1 ] = mesh->GetPolys( ); + arrays[ 2 ] = NULL; // TODO: mesh->GetStrips( ); + arrays[ 3 ] = mesh->GetVerts( ); + + for( unsigned int c = 0; c < 4; c++ ) + { + if( arrays[ c ] != NULL ) + { + vtkSmartPointer< vtkIdList > ids = + vtkSmartPointer< vtkIdList >::New( ); + arrays[ c ]->InitTraversal( ); + while( arrays[ c ]->GetNextCell( ids ) == 1 ) + { + long nPoints = ids->GetNumberOfIds( ); + _TCellAutoPointer icell; + if( nPoints == 2 ) + { + icell.TakeOwnership( new _TLine ); + icell->SetPointId( 0, ids->GetId( 0 ) ); + icell->SetPointId( 1, ids->GetId( 1 ) ); + } + else if( nPoints == 3 ) + { + icell.TakeOwnership( new _TTriangle ); + icell->SetPointId( 0, ids->GetId( 0 ) ); + icell->SetPointId( 1, ids->GetId( 1 ) ); + icell->SetPointId( 2, ids->GetId( 2 ) ); + } + else if( nPoints > 3 ) + { + _TPolygon* polygon = new _TPolygon( ); + for( long j = 0; j < nPoints; ++j ) + polygon->AddPointId( ids->GetId( j ) ); + icell.TakeOwnership( polygon ); + + } // fi + imesh->SetCell( imesh->GetNumberOfCells( ), icell ); + + } // elihw + + } // fi + + } // rof + this->m_ITK = imesh; +#endif // cpPlugins_PROCESS_DIMS_3 + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpInstances::DataObjects::Mesh:: +Mesh( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpInstances::DataObjects::Mesh:: +~Mesh( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TMesh > +void cpInstances::DataObjects::Mesh:: +_ITK_2_VTK( _TMesh* mesh ) +{ + long numPoints = mesh->GetNumberOfPoints( ); + if( numPoints == 0 ) + return; + + vtkSmartPointer< vtkPoints > vpoints = + vtkSmartPointer< vtkPoints >::New( ); + vpoints->SetNumberOfPoints( numPoints ); + auto points = mesh->GetPoints( ); + + // Copy points + vtkIdType VTKId = 0; + std::map< vtkIdType, long > IndexMap; + for( auto i = points->Begin( ); i != points->End( ); ++i, VTKId++ ) + { + IndexMap[ VTKId ] = i->Index( ); + if( _TMesh::PointDimension == 2 ) + vpoints->SetPoint( + VTKId, + i->Value( )[ 0 ], i->Value( )[ 1 ], 0 + ); + else if( _TMesh::PointDimension == 3 ) + vpoints->SetPoint( + VTKId, + i->Value( )[ 0 ], i->Value( )[ 1 ], i->Value( )[ 2 ] + ); + + } // rof + + // Copy cells + vtkSmartPointer< vtkCellArray > vcells = + vtkSmartPointer< vtkCellArray >::New( ); + auto cells = mesh->GetCells( ); + for( auto j = cells->Begin( ); j != cells->End( ); ++j ) + { + auto cell = j->Value( ); + vcells->InsertNextCell( cell->GetNumberOfPoints( ) ); + for( auto k = cell->PointIdsBegin( ); k != cell->PointIdsEnd( ); ++k ) + vcells->InsertCellPoint( IndexMap[ *k ] ); + + } // rof + + // Final assignations + vtkSmartPointer< vtkPolyData > vmesh = + vtkSmartPointer< vtkPolyData >::New( ); + vmesh->SetPoints( vpoints ); + vmesh->SetPolys( vcells ); + this->m_VTK = vmesh; + this->Modified( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Mesh.d b/lib/cpInstances/DataObjects/Mesh.d new file mode 100644 index 0000000..8f98aca --- /dev/null +++ b/lib/cpInstances/DataObjects/Mesh.d @@ -0,0 +1,4 @@ +AllMeshes itk::Mesh< #real_types#, #vdims# > +Meshes|d itk::Mesh< #real_types#, d > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Mesh.h b/lib/cpInstances/DataObjects/Mesh.h new file mode 100644 index 0000000..fa658ed --- /dev/null +++ b/lib/cpInstances/DataObjects/Mesh.h @@ -0,0 +1,53 @@ +#ifndef __cpInstances__Mesh__h__ +#define __cpInstances__Mesh__h__ + +#define ITK_MANUAL_INSTANTIATION +#include +#include +#include + +namespace cpInstances +{ + namespace DataObjects + { + /** + */ + class cpPluginsDataObjects_EXPORT Mesh + : public cpPlugins::Pipeline::DataObject + { + public: + typedef Mesh Self; + typedef cpPlugins::Pipeline::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Mesh, DataObject ); + cpPlugins_Id_Macro( Mesh, Object ); + cpPlugins_Compatibility_Macro; + + public: + virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE; + + protected: + Mesh( ); + virtual ~Mesh( ); + + template< class _TMesh > + inline void _ITK_2_VTK( _TMesh* mesh ); + + private: + // Purposely not implemented + Mesh( const Self& ); + Self& operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpInstances__Mesh__h__ + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/PolyLineParametricPath.cxx b/lib/cpInstances/DataObjects/PolyLineParametricPath.cxx new file mode 100644 index 0000000..488be38 --- /dev/null +++ b/lib/cpInstances/DataObjects/PolyLineParametricPath.cxx @@ -0,0 +1,39 @@ +#include + +// ------------------------------------------------------------------------- +void cpInstances::PolyLineParametricPath:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + /* TODO + cpPlugins_Demangle_PolyLineParametricPath_VisualDims_1( o, _ITK_2_VTK_0 ) + cpPlugins_Demangle_PolyLineParametricPath_DiffTensors3D_1( o, _ITK_2_VTK_1 ) + { + this->m_VTK = NULL; + this->m_ITKvVTK = NULL; + + } // fi + */ + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpInstances::PolyLineParametricPath:: +SetVTK( vtkObjectBase* o ) +{ +} + +// ------------------------------------------------------------------------- +cpInstances::PolyLineParametricPath:: +PolyLineParametricPath( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpInstances::PolyLineParametricPath:: +~PolyLineParametricPath( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/PolyLineParametricPath.d b/lib/cpInstances/DataObjects/PolyLineParametricPath.d new file mode 100644 index 0000000..e13c77f --- /dev/null +++ b/lib/cpInstances/DataObjects/PolyLineParametricPath.d @@ -0,0 +1,4 @@ +All cpExtensions::DataStructures::PolyLineParametricPath< #pdims# > +Dim|d cpExtensions::DataStructures::PolyLineParametricPath< d > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/PolyLineParametricPath.h b/lib/cpInstances/DataObjects/PolyLineParametricPath.h new file mode 100644 index 0000000..b563d41 --- /dev/null +++ b/lib/cpInstances/DataObjects/PolyLineParametricPath.h @@ -0,0 +1,48 @@ +#ifndef __cpInstances__PolyLineParametricPath__h__ +#define __cpInstances__PolyLineParametricPath__h__ + +#include +#include +#include +#include + +class vtkPolyLineParametricPathData; + +namespace cpInstances +{ + /** + */ + class cpPluginsDataObjects_EXPORT PolyLineParametricPath + : public cpPlugins::Pipeline::DataObject + { + public: + typedef PolyLineParametricPath Self; + typedef cpPlugins::Pipeline::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPath, cpPlugins::Pipeline::DataObject ); + cpPlugins_Id_Macro( PolyLineParametricPath, Object ); + cpPlugins_Compatibility_Macro; + + public: + virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE; + + protected: + PolyLineParametricPath( ); + virtual ~PolyLineParametricPath( ); + + private: + // Purposely not implemented + PolyLineParametricPath( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __cpInstances__PolyLineParametricPath__h__ + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Simple3DCurve.cxx b/lib/cpInstances/DataObjects/Simple3DCurve.cxx new file mode 100644 index 0000000..10165f7 --- /dev/null +++ b/lib/cpInstances/DataObjects/Simple3DCurve.cxx @@ -0,0 +1,64 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpInstances::Simple3DCurve:: +SetVTK( vtkObjectBase* o ) +{ + // Do nothing +} + +// ------------------------------------------------------------------------- +cpInstances::Simple3DCurve:: +Simple3DCurve( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpInstances::Simple3DCurve:: +~Simple3DCurve( ) +{ +} + +// ------------------------------------------------------------------------- +void cpInstances::Simple3DCurve:: +_UpdateVTK( ) const +{ + auto i = const_cast< itk::LightObject* >( this->m_ITK.GetPointer( ) ); + auto v = const_cast< vtkObjectBase* >( this->m_VTK.GetPointer( ) ); + if( i != NULL && v == NULL ) + { + cpPlugins_Demangle_Simple3DCurve_All_1( i, _ITK_2_VTK ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TCurve > +void cpInstances::Simple3DCurve:: +_ITK_2_VTK( _TCurve* curve ) const +{ + typedef + cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve > + _TFilter; + + Self* self = const_cast< Self* >( this ); + _TFilter* f = dynamic_cast< _TFilter* >( self->m_ITKvVTK.GetPointer( ) ); + if( f == NULL ) + { + _TFilter* nf = _TFilter::New( ); + self->m_ITKvVTK = nf; + f = nf; + + } // fi + f->SetInput( curve ); + f->Update( ); + + // Keep object track + self->m_ITK = curve; + self->m_VTK = f->GetOutput( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Simple3DCurve.d b/lib/cpInstances/DataObjects/Simple3DCurve.d new file mode 100644 index 0000000..2ba68a1 --- /dev/null +++ b/lib/cpInstances/DataObjects/Simple3DCurve.d @@ -0,0 +1 @@ +All cpExtensions::DataStructures::Simple3DCurve< #real_types# > diff --git a/lib/cpInstances/DataObjects/Simple3DCurve.h b/lib/cpInstances/DataObjects/Simple3DCurve.h new file mode 100644 index 0000000..e53df26 --- /dev/null +++ b/lib/cpInstances/DataObjects/Simple3DCurve.h @@ -0,0 +1,58 @@ +#ifndef __cpInstances__Simple3DCurve__h__ +#define __cpInstances__Simple3DCurve__h__ + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkPolyDataAlgorithm; + +// ------------------------------------------------------------------------- +namespace cpInstances +{ + /** + */ + class cpPluginsDataObjects_EXPORT Simple3DCurve + : public cpPlugins::Pipeline::DataObject + { + public: + typedef Simple3DCurve Self; + typedef cpPlugins::Pipeline::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Simple3DCurve, cpPlugins::Pipeline::DataObject ); + cpPlugins_Id_Macro( Simple3DCurve, Object ); + cpPlugins_Compatibility_Macro; + + public: + virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE; + + protected: + Simple3DCurve( ); + virtual ~Simple3DCurve( ); + + virtual void _UpdateVTK( ) const cpPlugins_OVERRIDE; + + template< class _TCurve > + inline void _ITK_2_VTK( _TCurve* curve ) const; + + private: + // Purposely not implemented + Simple3DCurve( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkPolyDataAlgorithm > m_ITKvVTK; + }; + +} // ecapseman + +#endif // __cpInstances__Simple3DCurve__h__ + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Skeleton.cxx b/lib/cpInstances/DataObjects/Skeleton.cxx new file mode 100644 index 0000000..fc4492b --- /dev/null +++ b/lib/cpInstances/DataObjects/Skeleton.cxx @@ -0,0 +1,39 @@ +#include + +// ------------------------------------------------------------------------- +void cpInstances::Skeleton:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + /* TODO + cpPlugins_Demangle_Skeleton_VisualDims_1( o, _ITK_2_VTK_0 ) + cpPlugins_Demangle_Skeleton_DiffTensors3D_1( o, _ITK_2_VTK_1 ) + { + this->m_VTK = NULL; + this->m_ITKvVTK = NULL; + + } // fi + */ + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpInstances::Skeleton:: +SetVTK( vtkObjectBase* o ) +{ +} + +// ------------------------------------------------------------------------- +cpInstances::Skeleton:: +Skeleton( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpInstances::Skeleton:: +~Skeleton( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpInstances/DataObjects/Skeleton.d b/lib/cpInstances/DataObjects/Skeleton.d new file mode 100644 index 0000000..99e6261 --- /dev/null +++ b/lib/cpInstances/DataObjects/Skeleton.d @@ -0,0 +1 @@ +All cpExtensions::DataStructures::Skeleton< #pdims# > diff --git a/lib/cpInstances/DataObjects/Skeleton.h b/lib/cpInstances/DataObjects/Skeleton.h new file mode 100644 index 0000000..060a8e5 --- /dev/null +++ b/lib/cpInstances/DataObjects/Skeleton.h @@ -0,0 +1,46 @@ +#ifndef __cpInstances__Skeleton__h__ +#define __cpInstances__Skeleton__h__ + +#include +#include +#include +#include + +namespace cpInstances +{ + /** + */ + class cpPluginsDataObjects_EXPORT Skeleton + : public cpPlugins::Pipeline::DataObject + { + public: + typedef Skeleton Self; + typedef cpPlugins::Pipeline::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Skeleton, cpPlugins::Pipeline::DataObject ); + cpPlugins_Id_Macro( Skeleton, Object ); + cpPlugins_Compatibility_Macro; + + public: + virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE; + + protected: + Skeleton( ); + virtual ~Skeleton( ); + + private: + // Purposely not implemented + Skeleton( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __cpInstances__Skeleton__h__ + +// eof - $RCSfile$ diff --git a/lib/cpInstances/Extensions/Paths.i b/lib/cpInstances/Extensions/Paths.i new file mode 100644 index 0000000..cbf4450 --- /dev/null +++ b/lib/cpInstances/Extensions/Paths.i @@ -0,0 +1,9 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude cpExtensions/Algorithms/BezierCurveFunction:h|hxx +tinclude cpExtensions/DataStructures/PolyLineParametricPath:h|hxx + +instances cpExtensions::Algorithms::BezierCurveFunction< itk::Vector< #real_types#, #pdims# > > +instances cpExtensions::DataStructures::PolyLineParametricPath< #pdims# > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Extensions/Skeleton.i b/lib/cpInstances/Extensions/Skeleton.i new file mode 100644 index 0000000..ed1ec99 --- /dev/null +++ b/lib/cpInstances/Extensions/Skeleton.i @@ -0,0 +1,8 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude cpExtensions/DataStructures/Skeleton:h|hxx +cinclude cpExtensions/DataStructures/Graph.hxx + +instances cpExtensions::DataStructures::Skeleton< #pdims# > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Geometries/ITKMeshes.i b/lib/cpInstances/Geometries/ITKMeshes.i new file mode 100644 index 0000000..70b0c54 --- /dev/null +++ b/lib/cpInstances/Geometries/ITKMeshes.i @@ -0,0 +1,16 @@ +header #define ITK_MANUAL_INSTANTIATION + +define meshes=PointSet;Mesh +tinclude itk#meshes#:h|hxx +cinclude itkMapContainer.hxx +cinclude itkVectorContainer.hxx +instances itk::#meshes#< #real_types#, #vdims# > + +define cells=Vertex;Line;Triangle;Polygon +tinclude itk#cells#Cell:h|hxx +tinclude itkCellInterface:h|hxx +instances itk::CellInterface< #real_types#, itk::CellTraitsInfo< #vdims#, float, float, unsigned long, unsigned long, unsigned long, itk::Point< float, #vdims# >, itk::VectorContainer< unsigned long, itk::Point< float, #vdims# > >, std::set< unsigned long > > > +instances itk::VectorContainer< unsigned long, itk::CellInterface< #real_types#, itk::CellTraitsInfo< #vdims#, float, float, unsigned long, unsigned long, unsigned long, itk::Point< float, #vdims# >, itk::VectorContainer< unsigned long, itk::Point< float, #vdims# > >, std::set< unsigned long > > >* > +instances itk::#cells#Cell< itk::CellInterface< #real_types#, itk::CellTraitsInfo< #vdims#, float, float, unsigned long, unsigned long, unsigned long, itk::Point< float, #vdims# >, itk::VectorContainer< unsigned long, itk::Point< float, #vdims# > >, std::set< unsigned long > > > > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Geometries/ITKPaths.i b/lib/cpInstances/Geometries/ITKPaths.i new file mode 100644 index 0000000..d2b413f --- /dev/null +++ b/lib/cpInstances/Geometries/ITKPaths.i @@ -0,0 +1,11 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude itkPath:h|hxx +tinclude itkParametricPath:h|hxx +tinclude itkPolyLineParametricPath:h|hxx +cinclude itkVectorContainer.hxx +instances itk::Path< double, itk::ContinuousIndex< double, #pdims# >, #pdims# > +define paths=itk::ParametricPath;itk::PolyLineParametricPath +instances #paths#< #pdims# > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Images/ITK2VTKImageFilters.i b/lib/cpInstances/Images/ITK2VTKImageFilters.i new file mode 100644 index 0000000..4166981 --- /dev/null +++ b/lib/cpInstances/Images/ITK2VTKImageFilters.i @@ -0,0 +1,21 @@ +header #define ITK_MANUAL_INSTANTIATION + +define color_pixels=RGBPixel;RGBAPixel +define vector_pixels=CovariantVector;Point;Vector +define matrices=Matrix +define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# > + +cinclude itkImage.h +cinclude itk#color_pixels#.h +cinclude itkFixedArray.h +cinclude itk#vector_pixels#.h +cinclude itk#matrices#.h + +define filters=VTKImageImport;VTKImageExport;ImageToVTKImageFilter;VTKImageToImageFilter +tinclude itk#filters#:h|hxx +instances itk::#filters#< itk::Image< #pixels#, #vdims# > > +instances itk::#filters#< itk::Image< itk::FixedArray< #scalar_types#, #vdims# >, #vdims# > > +instances itk::#filters#< itk::Image< itk::#vector_pixels#< #real_types#, #vdims# >, #vdims# > > +instances itk::#filters#< itk::Image< itk::#matrices#< #real_types#, #vdims#, #vdims# >, #vdims# > > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Images/ITKImageFunctions.i b/lib/cpInstances/Images/ITKImageFunctions.i new file mode 100644 index 0000000..8b4cbdb --- /dev/null +++ b/lib/cpInstances/Images/ITKImageFunctions.i @@ -0,0 +1,13 @@ +header #define ITK_MANUAL_INSTANTIATION + +define i_reals=#real_types# +define o_reals=#real_types# +define p_reals=#real_types# + +tinclude itkImageFunction:h|hxx +cinclude itkImage.h + +instances itk::ImageFunction< itk::Image< #scalar_types#, #pdims# >, #i_reals#, #o_reals# > +instances itk::ImageFunction< itk::Image< itk::FixedArray< #i_reals#, #pdims# >, #pdims# >, itk::FixedArray< #o_reals#, #pdims# >, #p_reals# > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Images/ITKImageInterpolators.i b/lib/cpInstances/Images/ITKImageInterpolators.i new file mode 100644 index 0000000..cee831b --- /dev/null +++ b/lib/cpInstances/Images/ITKImageInterpolators.i @@ -0,0 +1,23 @@ +header #define ITK_MANUAL_INSTANTIATION + +define v=FixedArray +define i_real=#real_types# +define o_real=#real_types# +define interp=Linear + +tinclude itk#interp#InterpolateImageFunction:h|hxx +tinclude itkVectorLinearInterpolateImageFunction:h|hxx + +cinclude itk#v#.h +cinclude itkImage.h + +instances itk::#interp#InterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types# > + +instances itk::VectorLinearInterpolateImageFunction< itk::Image< itk::#v#< #i_real#, #pdims# >, #pdims# >, #o_real# > + +tinclude itkBSplineDecompositionImageFilter:h|hxx +tinclude itkBSplineInterpolateImageFunction:h|hxx +instances itk::BSplineInterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types#, #real_types# > +instances itk::BSplineDecompositionImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Images/ITKImages.i b/lib/cpInstances/Images/ITKImages.i new file mode 100644 index 0000000..33f5852 --- /dev/null +++ b/lib/cpInstances/Images/ITKImages.i @@ -0,0 +1,41 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude itkImportImageContainer:h|hxx +tinclude itkImage:h|hxx + +define base_objects=ImageRegion;ImageBase +tinclude itk#base_objects#:h|hxx +instances itk::#base_objects#< #pdims# > + +minstances #_export_# std::ostream& itk::operator<< < #pdims# >( std::ostream& a, itk::ImageRegion< #pdims# > const& b ) + +define color_pixels=RGBPixel;RGBAPixel +define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# >;#sint_types# +cinclude itk#color_pixels#.h +cinclude complex +instances itk::ImportImageContainer< unsigned long, #pixels# > +instances itk::Image< #pixels#, #pdims# > + +cinclude itkFixedArray.h +instances itk::ImportImageContainer< unsigned long, itk::FixedArray< #scalar_types#, #pdims# > > +instances itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# > + +define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor +cinclude itk#vector_pixels#.h +instances itk::ImportImageContainer< unsigned long, itk::#vector_pixels#< #real_types#, #pdims# > > +instances itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# > + +define matrices=Matrix +cinclude itk#matrices#.h +instances itk::ImportImageContainer< unsigned long, itk::#matrices#< #real_types#, #pdims#, #pdims# > > +instances itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > + +cinclude itkOffset.h +instances itk::ImportImageContainer< unsigned long, itk::Offset< #pdims# > > +instances itk::Image< itk::Offset< #pdims# >, #pdims# > + +cinclude itkDiffusionTensor3D.h +instances itk::ImportImageContainer< unsigned long, itk::DiffusionTensor3D< #real_types# > > +instances itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Images/ITKImagesBaseFilters.i b/lib/cpInstances/Images/ITKImagesBaseFilters.i new file mode 100644 index 0000000..f29b580 --- /dev/null +++ b/lib/cpInstances/Images/ITKImagesBaseFilters.i @@ -0,0 +1,58 @@ +header #define ITK_MANUAL_INSTANTIATION + +define color_pixels=RGBPixel;RGBAPixel +define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor +define matrices=Matrix +define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# > + +cinclude complex +cinclude itkImage.h +cinclude itk#color_pixels#.h +cinclude itkFixedArray.h +cinclude itk#vector_pixels#.h +cinclude itk#matrices#.h +cinclude itkDiffusionTensor3D.h + +tinclude itkImageSource:h|hxx +instances itk::ImageSource< itk::Image< #pixels#, #pdims# > > +instances itk::ImageSource< itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# > > +instances itk::ImageSource< itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# > > +instances itk::ImageSource< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > > +instances itk::ImageSource< itk::Image< itk::Offset< #pdims# >, #pdims# > > +instances itk::ImageSource< itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 > > + +define i_pixels=#pixels# +define o_pixels=#pixels# +define i_scalar_types=#scalar_types# +define o_scalar_types=#scalar_types# +define i_real_types=#real_types# +define o_real_types=#real_types# +define filters=ImageToImageFilter;InPlaceImageFilter +tinclude itk#filters#:h|hxx +instances itk::#filters#< itk::Image< #i_pixels#, #pdims# >, itk::Image< #o_pixels#, #pdims# > > +instances itk::#filters#< itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# >, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# > > +instances itk::#filters#< itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# >, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# > > +instances itk::#filters#< itk::Image< itk::#matrices#< #i_real_types#, #pdims#, #pdims# >, #pdims# >, itk::Image< itk::#matrices#< #o_real_types#, #pdims#, #pdims# >, #pdims# > > + +define i_dims=#pdims# +define o_dims=#pdims# +instances itk::#filters#< itk::Image< #pixels#, #i_dims# >, itk::Image< #pixels#, #o_dims# > > + +tinclude itkImageAlgorithm:h|hxx +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< #i_scalar_types#, #pdims# >, itk::Image< #o_scalar_types#, #pdims# > >( itk::Image< #i_scalar_types#, #pdims# > const*, itk::Image< #o_scalar_types#, #pdims# >*, itk::Image< #i_scalar_types#, #pdims# >::RegionType const&, itk::Image< #o_scalar_types#, #pdims# >::RegionType const&, std::integral_constant< bool, true > ) + +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< std::complex< #i_real_types# >, #pdims# >, itk::Image< std::complex< #o_real_types# >, #pdims# > >( itk::Image< std::complex< #i_real_types# >, #pdims# > const*, itk::Image< std::complex< #o_real_types# >, #pdims# >*, itk::Image< std::complex< #i_real_types# >, #pdims# >::RegionType const&, itk::Image< std::complex< #o_real_types# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > ) + +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::#color_pixels#< #i_scalar_types# >, #pdims# >, itk::Image< itk::#color_pixels#< #o_scalar_types# >, #pdims# > >( itk::Image< itk::#color_pixels#< #i_scalar_types# >, #pdims# > const*, itk::Image< itk::#color_pixels#< #o_scalar_types# >, #pdims# >*, itk::Image< itk::#color_pixels#< #i_scalar_types# >, #pdims# >::RegionType const&, itk::Image< itk::#color_pixels#< #o_scalar_types# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > ) + +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# >, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# > >( itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# > const*, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# >*, itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > ) + +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# >, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# > >( itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# > const*, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# >*, itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > ) + +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > >( itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > const*, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >*, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > ) + +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::Offset< #pdims# >, #pdims# >, itk::Image< itk::Offset< #pdims# >, #pdims# > >( itk::Image< itk::Offset< #pdims# >, #pdims# > const*, itk::Image< itk::Offset< #pdims# >, #pdims# >*, itk::Image< itk::Offset< #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::Offset< #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > ) + +minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::DiffusionTensor3D< #i_real_types# >, 3 >, itk::Image< itk::DiffusionTensor3D< #o_real_types# >, 3 > >( itk::Image< itk::DiffusionTensor3D< #i_real_types# >, 3 > const*, itk::Image< itk::DiffusionTensor3D< #o_real_types# >, 3 >*, itk::Image< itk::DiffusionTensor3D< #i_real_types# >, 3 >::RegionType const&, itk::Image< itk::DiffusionTensor3D< #o_real_types# >, 3 >::RegionType const&, std::integral_constant< bool, true > ) + +** eof - $RCSfile$ \ No newline at end of file diff --git a/lib/cpInstances/Images/ITKImagesNeighborhoodIterators.i b/lib/cpInstances/Images/ITKImagesNeighborhoodIterators.i new file mode 100644 index 0000000..466da61 --- /dev/null +++ b/lib/cpInstances/Images/ITKImagesNeighborhoodIterators.i @@ -0,0 +1,37 @@ +header #define ITK_MANUAL_INSTANTIATION + +define color_pixels=RGBPixel;RGBAPixel +define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor +define matrices=Matrix +define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# > + +cinclude itkImage.h +cinclude itk#color_pixels#.h +cinclude itkFixedArray.h +cinclude itk#vector_pixels#.h +cinclude itk#matrices#.h + +define it=ConstNeighborhoodIterator;NeighborhoodIterator;ConstShapedNeighborhoodIterator;ShapedNeighborhoodIterator +define co=ZeroFluxNeumannBoundaryCondition +define pi=#scalar_types#;#sint_types# +define op=Neighborhood;NeighborhoodOperator;DerivativeOperator + +tinclude itk#co#:h|hxx +tinclude itk#op#:h|hxx +tinclude itk#it#:h|hxx + +instances itk::NeighborhoodAllocator< #scalar_types#* > +instances itk::NeighborhoodAllocator< #pi# > +instances itk::Neighborhood< #scalar_types#*, #pdims#, itk::NeighborhoodAllocator< #scalar_types#* > > + +instances itk::#op#< #pi#, #pdims#, itk::NeighborhoodAllocator< #pi# > > +instances itk::#co#< itk::Image< #pi#, #pdims# >, itk::Image< #pi#, #pdims# > > +instances itk::#it#< itk::Image< #pi#, #pdims# >, itk::#co#< itk::Image< #pi#, #pdims# >, itk::Image< #pi#, #pdims# > > > + +tinclude itkNeighborhoodAlgorithm:h|hxx +instances itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< itk::Image< #pi#, #pdims# > > + +tinclude itkNeighborhoodInnerProduct:h|hxx +instances itk::NeighborhoodInnerProduct< itk::Image< #pi#, #pdims# >, #pi#, #pi# > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Images/ITKImagesSimpleIterators.i b/lib/cpInstances/Images/ITKImagesSimpleIterators.i new file mode 100644 index 0000000..e787093 --- /dev/null +++ b/lib/cpInstances/Images/ITKImagesSimpleIterators.i @@ -0,0 +1,27 @@ +header #define ITK_MANUAL_INSTANTIATION + +define color_pixels=RGBPixel;RGBAPixel +define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor +define matrices=Matrix +define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# >;#sint_types# + +cinclude itkImage.h +cinclude itk#color_pixels#.h +cinclude itkFixedArray.h +cinclude itk#vector_pixels#.h +cinclude itk#matrices#.h +cinclude itkDiffusionTensor3D.h + +define it=ImageRegionConstIterator;ImageRegionIterator;ImageScanlineConstIterator;ImageScanlineIterator;ImageConstIteratorWithIndex;ImageIteratorWithIndex;ImageRegionConstIteratorWithIndex;ImageRegionIteratorWithIndex;ImageLinearConstIteratorWithIndex;ImageLinearIteratorWithIndex + +tinclude itk#it#:h|hxx + +tinclude itk#it#:h|hxx +instances itk::#it#< itk::Image< #pixels#, #pdims# > > +instances itk::#it#< itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# > > +instances itk::#it#< itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# > > +instances itk::#it#< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > > +instances itk::#it#< itk::Image< itk::Offset< #pdims# >, #pdims# > > +instances itk::#it#< itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 > > + +** eof - $RCSfile$ diff --git a/lib/cpInstances/Images/itkImageToVTKImageFilter.h b/lib/cpInstances/Images/itkImageToVTKImageFilter.h new file mode 100644 index 0000000..9390eb8 --- /dev/null +++ b/lib/cpInstances/Images/itkImageToVTKImageFilter.h @@ -0,0 +1,111 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkImageToVTKImageFilter_h +#define itkImageToVTKImageFilter_h + +#include "itkVTKImageExport.h" +#include "vtkImageImport.h" +#include "vtkImageData.h" + +namespace itk +{ + +/** \class ImageToVTKImageFilter + * \brief Converts an ITK image into a VTK image and plugs a + * itk data pipeline to a VTK datapipeline. + * + * This class puts together an itkVTKImageExporter and a vtkImageImporter. + * It takes care of the details related to the connection of ITK and VTK + * pipelines. The User will perceive this filter as an adaptor to which + * an itk::Image can be plugged as input and a vtkImage is produced as + * output. + * + * \ingroup ITKVtkGlue + * + * \wiki + * \wikiexample{IO/ImageToVTKImageFilter,Display an ITK image} + * \wikiexample{IO/itkVtkImageConvertDICOM,Uses a custom user matrix to align the image with DICOM physical space} + * \endwiki + */ +template +class ImageToVTKImageFilter : public ProcessObject +{ +public: + /** Standard class typedefs. */ + typedef ImageToVTKImageFilter Self; + typedef ProcessObject Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ImageToVTKImageFilter, ProcessObject); + + /** Some typedefs. */ + typedef TInputImage InputImageType; + typedef typename InputImageType::ConstPointer InputImagePointer; + + typedef VTKImageExport< InputImageType> ExporterFilterType; + typedef typename ExporterFilterType::Pointer ExporterFilterPointer; + + /** Get the output in the form of a vtkImage. + This call is delegated to the internal vtkImageImporter filter */ + vtkImageData * GetOutput() const; + + /** Set the input in the form of an itk::Image */ + using Superclass::SetInput; + void SetInput( const InputImageType * ); + InputImageType * GetInput(); + + /** Return the internal VTK image importer filter. + This is intended to facilitate users the access + to methods in the importer */ + vtkImageImport * GetImporter() const; + + /** Return the internal ITK image exporter filter. + This is intended to facilitate users the access + to methods in the exporter */ + ExporterFilterType * GetExporter() const; + + /** This call delegates the update to the importer */ + virtual void Update() ITK_OVERRIDE; + + /** This call delegates the update to the importer */ + virtual void UpdateLargestPossibleRegion() ITK_OVERRIDE; + +protected: + ImageToVTKImageFilter(); + virtual ~ImageToVTKImageFilter(); + +private: + ImageToVTKImageFilter(const Self&) ITK_DELETE_FUNCTION; + void operator=(const Self&) ITK_DELETE_FUNCTION; + + ExporterFilterPointer m_Exporter; + vtkImageImport * m_Importer; +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkImageToVTKImageFilter.hxx" +#endif + +#endif diff --git a/lib/cpInstances/Images/itkImageToVTKImageFilter.hxx b/lib/cpInstances/Images/itkImageToVTKImageFilter.hxx new file mode 100644 index 0000000..e134b3f --- /dev/null +++ b/lib/cpInstances/Images/itkImageToVTKImageFilter.hxx @@ -0,0 +1,141 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkImageToVTKImageFilter_hxx +#define itkImageToVTKImageFilter_hxx + +#include "itkImageToVTKImageFilter.h" + +namespace itk +{ + +/** + * Constructor + */ +template +ImageToVTKImageFilter +::ImageToVTKImageFilter() +{ + m_Importer = vtkImageImport::New(); + m_Exporter = ExporterFilterType::New(); + + m_Importer->SetUpdateInformationCallback(m_Exporter->GetUpdateInformationCallback()); + m_Importer->SetPipelineModifiedCallback(m_Exporter->GetPipelineModifiedCallback()); + m_Importer->SetWholeExtentCallback(m_Exporter->GetWholeExtentCallback()); + m_Importer->SetSpacingCallback(m_Exporter->GetSpacingCallback()); + m_Importer->SetOriginCallback(m_Exporter->GetOriginCallback()); + m_Importer->SetScalarTypeCallback(m_Exporter->GetScalarTypeCallback()); + m_Importer->SetNumberOfComponentsCallback(m_Exporter->GetNumberOfComponentsCallback()); + m_Importer->SetPropagateUpdateExtentCallback(m_Exporter->GetPropagateUpdateExtentCallback()); + m_Importer->SetUpdateDataCallback(m_Exporter->GetUpdateDataCallback()); + m_Importer->SetDataExtentCallback(m_Exporter->GetDataExtentCallback()); + m_Importer->SetBufferPointerCallback(m_Exporter->GetBufferPointerCallback()); + m_Importer->SetCallbackUserData(m_Exporter->GetCallbackUserData()); + +} + +/** + * Destructor + */ +template +ImageToVTKImageFilter +::~ImageToVTKImageFilter() +{ + if( m_Importer ) + { + m_Importer->Delete(); + m_Importer = 0; + } +} + +/** + * Set an itk::Image as input + */ +template +void +ImageToVTKImageFilter +::SetInput( const InputImageType * inputImage ) +{ + m_Exporter->SetInput( inputImage ); +} + +template +typename ImageToVTKImageFilter::InputImageType * +ImageToVTKImageFilter +::GetInput() +{ + return m_Exporter->GetInput(); +} + +/** + * Get a vtkImage as output + */ +template +vtkImageData * +ImageToVTKImageFilter +::GetOutput() const +{ + return m_Importer->GetOutput(); +} + +/** + * Get the importer filter + */ +template +vtkImageImport * +ImageToVTKImageFilter +::GetImporter() const +{ + return m_Importer; +} + +/** + * Get the exporter filter + */ +template +typename ImageToVTKImageFilter::ExporterFilterType * +ImageToVTKImageFilter +::GetExporter() const +{ + return m_Exporter.GetPointer(); +} + +/** + * Delegate the Update to the importer + */ +template +void +ImageToVTKImageFilter +::Update() +{ + m_Importer->Update(); +} + +/** + * Delegate the UpdateLargestPossibleRegion to the importer + */ +template +void +ImageToVTKImageFilter +::UpdateLargestPossibleRegion() +{ + m_Importer->UpdateWholeExtent(); +} + +} // end namespace itk + +#endif diff --git a/lib/cpInstances/Images/itkVTKImageToImageFilter.h b/lib/cpInstances/Images/itkVTKImageToImageFilter.h new file mode 100644 index 0000000..b4427c8 --- /dev/null +++ b/lib/cpInstances/Images/itkVTKImageToImageFilter.h @@ -0,0 +1,100 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkVTKImageToImageFilter_h +#define itkVTKImageToImageFilter_h + +#include "itkVTKImageImport.h" +#include "vtkImageExport.h" +#include "vtkImageData.h" +#include "vtkSmartPointer.h" + +#ifndef vtkFloatingPointType +#define vtkFloatingPointType float +#endif + +namespace itk +{ + +/** \class VTKImageToImageFilter + * \brief Converts a VTK image into an ITK image and plugs a + * VTK data pipeline to an ITK datapipeline. + * + * This class puts together an itk::VTKImageImport and a vtk::ImageExport. + * It takes care of the details related to the connection of ITK and VTK + * pipelines. The User will perceive this filter as an adaptor to which + * a vtkImageData can be plugged as input and an itk::Image is produced as + * output. + * + * \ingroup ITKVtkGlue + */ +template +class VTKImageToImageFilter : public VTKImageImport< TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef VTKImageToImageFilter Self; + typedef VTKImageImport< TOutputImage > Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(VTKImageToImageFilter, VTKImageImport); + + /** Some typedefs. */ + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::ConstPointer OutputImagePointer; + + /** Set the input in the form of a vtkImageData */ + void SetInput( vtkImageData * ); + using Superclass::SetInput; + + /** Return the internal VTK image exporter filter. + This is intended to facilitate users the access + to methods in the exporter */ + vtkImageExport * GetExporter() const; + + /** Return the internal ITK image importer filter. + This is intended to facilitate users the access + to methods in the importer. + */ + const Superclass * GetImporter() const; + +protected: + VTKImageToImageFilter(); + virtual ~VTKImageToImageFilter(); + +private: + VTKImageToImageFilter(const Self&) ITK_DELETE_FUNCTION; + void operator=(const Self&) ITK_DELETE_FUNCTION; + + typedef vtkSmartPointer ImageExportPointer; + ImageExportPointer m_Exporter; + +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVTKImageToImageFilter.hxx" +#endif + +#endif diff --git a/lib/cpInstances/Images/itkVTKImageToImageFilter.hxx b/lib/cpInstances/Images/itkVTKImageToImageFilter.hxx new file mode 100644 index 0000000..334b02b --- /dev/null +++ b/lib/cpInstances/Images/itkVTKImageToImageFilter.hxx @@ -0,0 +1,107 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkVTKImageToImageFilter_hxx +#define itkVTKImageToImageFilter_hxx + +#include "itkVTKImageToImageFilter.h" + +#include "vtkVersion.h" + +namespace itk +{ + +/** + * Constructor + */ +template +VTKImageToImageFilter +::VTKImageToImageFilter() +{ + + m_Exporter = vtkImageExport::New(); + + this->SetUpdateInformationCallback( m_Exporter->GetUpdateInformationCallback()); + this->SetPipelineModifiedCallback( m_Exporter->GetPipelineModifiedCallback()); + this->SetWholeExtentCallback( m_Exporter->GetWholeExtentCallback()); + this->SetSpacingCallback( m_Exporter->GetSpacingCallback()); + this->SetOriginCallback( m_Exporter->GetOriginCallback()); + this->SetScalarTypeCallback( m_Exporter->GetScalarTypeCallback()); + this->SetNumberOfComponentsCallback( m_Exporter->GetNumberOfComponentsCallback()); + this->SetPropagateUpdateExtentCallback( m_Exporter->GetPropagateUpdateExtentCallback()); + this->SetUpdateDataCallback( m_Exporter->GetUpdateDataCallback()); + this->SetDataExtentCallback( m_Exporter->GetDataExtentCallback()); + this->SetBufferPointerCallback( m_Exporter->GetBufferPointerCallback()); + this->SetCallbackUserData( m_Exporter->GetCallbackUserData()); + +} + +/** + * Destructor + */ +template +VTKImageToImageFilter +::~VTKImageToImageFilter() +{ + if( m_Exporter ) + { + m_Exporter->Delete(); + m_Exporter = 0; + } +} + +/** + * Set a vtkImageData as input + */ +template +void +VTKImageToImageFilter +::SetInput( vtkImageData * inputImage ) +{ +#if VTK_MAJOR_VERSION <= 5 + m_Exporter->SetInput( inputImage ); +#else + m_Exporter->SetInputData( inputImage ); +#endif +} + +/** + * Get the exporter filter + */ +template +vtkImageExport * +VTKImageToImageFilter +::GetExporter() const +{ + return m_Exporter; +} + +/** + * Get the importer filter + */ +template +const typename VTKImageToImageFilter::Superclass * +VTKImageToImageFilter +::GetImporter() const +{ + return this; +} + +} // end namespace itk + +#endif diff --git a/lib/cpPlugins/Config.h.in b/lib/cpPlugins/Config.h.in new file mode 100644 index 0000000..c10ee8d --- /dev/null +++ b/lib/cpPlugins/Config.h.in @@ -0,0 +1,132 @@ +#ifndef __cpPlugins__Config__h__ +#define __cpPlugins__Config__h__ + +#include +#include +#include + +/* + * ========================================================================= + * Identify OS + * ========================================================================= + */ +#define cpPlugins_OS_@CMAKE_SYSTEM_NAME@ +#ifdef cpPlugins_OS_Windows +# define cpPlugins_LIB_PREFIX "" +# define cpPlugins_ENV_SEPARATOR ";" +# define cpPlugins_PATH_SEPARATOR '\\' +# define cpPlugins_LIB_EXT ".dll" +#else // cpPlugins_OS_Windows +# define cpPlugins_LIB_PREFIX "lib" +# define cpPlugins_ENV_SEPARATOR ":" +# define cpPlugins_PATH_SEPARATOR '/' +# ifdef cpPlugins_OS_Linux +# define cpPlugins_LIB_EXT ".so" +# else // cpPlugins_OS_Linux +# define cpPlugins_LIB_EXT ".dylib" +# endif // cpPlugins_OS_Linux +#endif // cpPlugins_OS_Windows + +#ifdef cpPlugins_OS_Windows +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif // WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include +# include +#endif // cpPlugins_OS_Windows + +/* + * ========================================================================= + * Some global values + * ========================================================================= + */ +#define cpPlugins_PATHS "cpPlugins_PATHS" +#define cpPlugins_CONFIG "cpPlugins_Libraries.config" + +#define cpPlugins_QT4_@QT4_FOUND@ +#ifdef cpPlugins_QT4_TRUE +# ifndef cpPlugins_QT4 +# define cpPlugins_QT4 +# endif // cpPlugins_QT4 +#else // cpPlugins_QT4_TRUE +# undef cpPlugins_QT4 +#endif // cpPlugins_QT4_TRUE + +/* + * ========================================================================= + * Version numbers and strings + * ========================================================================= + */ +#define cpPlugins_MAJOR_VERSION @prj_MAJ_VER@ +#define cpPlugins_MINOR_VERSION @prj_MIN_VER@ +#define cpPlugins_RELEASE_VERSION @prj_REL_VER@ +#define cpPlugins_VERSION "@prj_VERSION@" +#define cpPlugins_SHORT_VERSION "@prj_SHORT_VERSION@" +#define cpPlugins_OpenGL_BackEnd_@VTK_RENDERING_BACKEND@ + +/* + * ========================================================================= + * Language related macros + * ========================================================================= + */ +#if __cplusplus >= 201103L +# define cpPlugins_OVERRIDE override +# define cpPlugins_DELETE_FUNCTION =delete +# define cpPlugins_NULLPTR nullptr +# define cpPlugins_NOEXCEPT noexcept +# define cpPlugins_HAS_CXX11_STATIC_ASSERT +# define cpPlugins_HAS_CXX11_RVREF +#else // __cplusplus >= 201103L +# define cpPlugins_OVERRIDE +# define cpPlugins_DELETE_FUNCTION +# define cpPlugins_NULLPTR NULL +# define cpPlugins_NOEXCEPT throw() +#endif // __cplusplus >= 201103L + +/* + * ========================================================================= + * Some macros + * ========================================================================= + */ + +#define cpPlugins_Id_Macro( _class, _category ) \ + public: \ + virtual const char* GetClassName( ) const cpPlugins_OVERRIDE \ + { return( #_class ); } \ + virtual const char* GetClassCategory( ) const cpPlugins_OVERRIDE \ + { return( #_category ); } + +#define cpPluginsObject( _cls, _scls, _cat ) \ + public: \ + typedef _cls Self; \ + typedef _scls Superclass; \ + typedef itk::SmartPointer< Self > Pointer; \ + typedef itk::SmartPointer< const Self > ConstPointer; \ + public: \ + itkNewMacro( Self ); \ + itkTypeMacro( _cls, _scls ); \ + public: \ + virtual const char* GetClassName( ) const cpPlugins_OVERRIDE \ + { return( #_cls ); } \ + virtual const char* GetClassCategory( ) const cpPlugins_OVERRIDE \ + { return( #_cat ); } \ + protected: \ + _cls( ); \ + virtual ~_cls( ); \ + virtual void _GenerateData( ) cpPlugins_OVERRIDE; \ + private: \ + _cls( const Self& ); \ + Self& operator=( const Self& ) + +#define cpPlugins_Compatibility_Macro \ + virtual bool IsCompatible( \ + const DataObject* other \ + ) const cpPlugins_OVERRIDE \ + { \ + return( dynamic_cast< const Self* >( other ) != NULL ); \ + } + +#endif // __cpPlugins__Config__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/Loader.cxx b/lib/cpPlugins/Interface/Loader.cxx new file mode 100644 index 0000000..dfb9bfb --- /dev/null +++ b/lib/cpPlugins/Interface/Loader.cxx @@ -0,0 +1,278 @@ +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +// Static attributes initialization +// ------------------------------------------------------------------------- + +cpPlugins::Interface::Loader::TLibraries +cpPlugins::Interface::Loader::m_Libraries; + +cpPlugins::Interface::Loader::TFiltersToLibrariesReferences +cpPlugins::Interface::Loader::m_References; + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Loader:: +Loader( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Loader:: +~Loader( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Loader:: +Register( const std::string& filename ) +{ + // Canonicalize path + std::string path = cpPlugins::OS::FileSystem::CanonicalPath( filename ); + if( path == "" ) + { + throw std::runtime_error( "Unknown library file \"" + filename + "\"." ); + return; + + } // fi + + // Ignore if the library is already loaded + if( Self::m_Libraries.find( path ) != Self::m_Libraries.end( ) ) + return; + + // Try to open library + void* hnd = NULL; + try + { + hnd = cpPlugins::OS::DLLManager::Open( path ); + } + catch( std::exception& err ) + { + throw std::runtime_error( err.what( ) ); + + } // yrt + if( hnd == NULL ) + throw std::runtime_error( "Unknown file type for \"" + filename + "\"." ); + + // Get interfacing functions + TContentsFunc contents_func = NULL; + try + { + contents_func = reinterpret_cast< TContentsFunc >( + cpPlugins::OS::DLLManager::Sym( hnd, "cpPlugins_Contents" ) + ); + } + catch( std::exception& err ) + { + cpPlugins::OS::DLLManager::Close( hnd ); + throw std::runtime_error( "Library \"" + filename + "\" is not recognized as a cpPlugins library (i.e. \"cpPlugins_Contents\" function not found)." ); + + } // yrt + + TCreatorFunc creator_func = NULL; + try + { + creator_func = reinterpret_cast< TCreatorFunc >( + cpPlugins::OS::DLLManager::Sym( hnd, "cpPlugins_Creator" ) + ); + } + catch( std::exception& err ) + { + cpPlugins::OS::DLLManager::Close( hnd ); + throw std::runtime_error( "Library \"" + filename + "\" is not recognized as a cpPlugins library (i.e. \"cpPlugins_Creator\" function not found)." ); + + } // yrt + + // Keep track of handlers + Self::m_Libraries[ path ] = THandlers( hnd, contents_func, creator_func ); + + // Get library contents + std::vector< std::string > contents; + contents_func( &contents ); + + // Register contents + for( auto c : contents ) + { + std::vector< std::string > t = cpPlugins::OS::String::Tokenize( c, "@" ); + if( t.size( ) == 2 ) + Self::m_References[ t[ 1 ] ][ t[ 0 ] ] = path; + + } // rof +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Loader:: +RegisterFromDirectory( const std::string& dirname ) +{ + std::string patt = "*"; + patt += cpPlugins_LIB_EXT; + std::set< std::string > files = + cpPlugins::OS::FileSystem::LoadDirContents( + dirname, false, patt + ); + for( auto f : files ) + { + try + { + Register( f ); + } + catch( ... ) + { + // Do nothing + + } // yrt + + } // rof +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Loader:: +GuessEnvironment( const std::string& dirname ) +{ + std::stringstream fname; + fname << dirname << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS; + std::string buffer; + if( cpPlugins::OS::FileSystem::Read( buffer, fname.str( ) ) ) + { + std::istringstream input( buffer ); + for( std::string line; std::getline( input, line ); ) + Self::RegisterFromDirectory( line ); + } + else + Self::RegisterFromDirectory( dirname ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Loader:: +SaveEnvironment( const std::string& dirname ) +{ + std::set< std::string > locations; + for( auto lIt : Self::m_Libraries ) + locations.insert( + cpPlugins::OS::FileSystem::SplitPath( lIt.first ).first + ); + std::stringstream buffer; + for( auto loc : locations ) + buffer << loc << std::endl; + std::stringstream fname; + fname << dirname << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS; + cpPlugins::OS::FileSystem::Write( buffer.str( ), fname.str( ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Loader:: +UnRegister( const std::string& filename ) +{ + // Canonicalize path + std::string path = cpPlugins::OS::FileSystem::CanonicalPath( filename ); + if( path == "" ) + return; + + auto lIt = Self::m_Libraries.find( path ); + if( lIt != Self::m_Libraries.end( ) ) + { + // Unload handlers + cpPlugins::OS::DLLManager::Close( std::get< 0 >( lIt->second ) ); + Self::m_Libraries.erase( lIt ); + + // Erase references + auto cIt = Self::m_References.begin( ); + while( cIt != Self::m_References.end( ) ) + { + auto fIt = cIt->second.begin( ); + while( fIt != cIt->second.end( ) ) + { + if( fIt->second == path ) + { + cIt->second.erase( fIt ); + fIt = cIt->second.begin( ); + } + else + ++fIt; + + } // elihw + if( cIt->second.size( ) == 0 ) + { + Self::m_References.erase( cIt ); + cIt = Self::m_References.begin( ); + } + else + ++cIt; + + } // elihw + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Loader:: +UnRegisterAll( ) +{ + for( auto lIt : Self::m_Libraries ) + cpPlugins::OS::DLLManager::Close( std::get< 0 >( lIt.second ) ); + Self::m_Libraries.clear( ); + Self::m_References.clear( ); +} + +// ------------------------------------------------------------------------- +std::map< std::string, std::set< std::string > > +cpPlugins::Interface::Loader:: +GetFilters( ) const +{ + std::map< std::string, std::set< std::string > > filters; + for( auto ref : Self::m_References ) + for( auto fil : ref.second ) + filters[ ref.first ].insert( fil.first ); + return( filters ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::ProcessObject::Pointer cpPlugins::Interface::Loader:: +CreateFilter( + const std::string& category, const std::string& filter, + const std::string& name + ) +{ + cpPlugins::Pipeline::ProcessObject::Pointer ptr = NULL; + auto cIt = Self::m_References.find( category ); + if( cIt != Self::m_References.end( ) ) + { + auto fIt = cIt->second.find( filter ); + if( fIt != cIt->second.end( ) ) + { + auto lIt = Self::m_Libraries.find( fIt->second ); + if( lIt != Self::m_Libraries.end( ) ) + { + auto creator_func = std::get< 2 >( lIt->second ); + if( creator_func != NULL ) + { + itk::LightObject::Pointer l_ptr; + creator_func( l_ptr, category, filter ); + ptr = + dynamic_cast< cpPlugins::Pipeline::ProcessObject* >( + l_ptr.GetPointer( ) + ); + + } // fi + + } // fi + + } // fi + + } // fi + + if( ptr.IsNotNull( ) ) + { + if( name == "" ) + ptr->SetName( filter + "@" + category ); + else + ptr->SetName( name ); + + } // fi + return( ptr ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/Loader.h b/lib/cpPlugins/Interface/Loader.h new file mode 100644 index 0000000..115196c --- /dev/null +++ b/lib/cpPlugins/Interface/Loader.h @@ -0,0 +1,72 @@ +#ifndef __cpPlugins__Interface__Loader__h__ +#define __cpPlugins__Interface__Loader__h__ + +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + namespace Interface + { + /** + */ + class cpPlugins_EXPORT Loader + { + public: + typedef Loader Self; + + public: + typedef void ( *TContentsFunc )( std::vector< std::string >* ); + typedef void ( *TCreatorFunc )( itk::LightObject::Pointer& ptr, const std::string& c, const std::string& f ); + typedef std::tuple< void*, TContentsFunc, TCreatorFunc > THandlers; + typedef std::map< std::string, THandlers > TLibraries; + typedef std::map< std::string, std::map< std::string, std::string > > + TFiltersToLibrariesReferences; + + public: + Loader( ); + virtual ~Loader( ); + + void Register( const std::string& filename ); + void RegisterFromDirectory( const std::string& dirname ); + void GuessEnvironment( const std::string& dirname ); + void SaveEnvironment( const std::string& dirname ); + void UnRegister( const std::string& filename ); + void UnRegisterAll( ); + + std::map< std::string, std::set< std::string > > GetFilters( ) const; + + cpPlugins::Pipeline::ProcessObject::Pointer CreateFilter( + const std::string& category, const std::string& filter, + const std::string& name = "" + ); + + protected: + static TLibraries m_Libraries; + static TFiltersToLibrariesReferences m_References; + + public: + friend std::ostream& operator<<( std::ostream& o, const Loader& l ) + { + o << "cpPlugins:" << std::endl; + for( auto c : l.m_References ) + { + o << " + " << c.first << std::endl; + for( auto f : c.second ) + o << " |--> " << f.first << " (" << f.second << ")" << std::endl; + + } // rof + return( o ); + } + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Interface__Loader__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/Workspace.cxx b/lib/cpPlugins/Interface/Workspace.cxx new file mode 100644 index 0000000..3822969 --- /dev/null +++ b/lib/cpPlugins/Interface/Workspace.cxx @@ -0,0 +1,627 @@ +#include +#include + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Clear( ) +{ + this->m_Filters.clear( ); +} + +// ------------------------------------------------------------------------- +std::vector< std::string > cpPlugins::Interface::Workspace:: +GetFiltersNames( ) const +{ + std::vector< std::string > n; + for( auto i : this->m_Filters ) + n.push_back( i.first ); + return( n ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Workspace:: +TFilter* cpPlugins::Interface::Workspace:: +GetFilter( const std::string& name ) +{ + auto i = this->m_Filters.find( name ); + if( i != this->m_Filters.end( ) ) + return( i->second.GetPointer( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface::Workspace:: +TFilter* cpPlugins::Interface::Workspace:: +GetFilter( const std::string& name ) const +{ + auto i = this->m_Filters.find( name ); + if( i != this->m_Filters.end( ) ) + return( i->second.GetPointer( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Workspace:: +TWidget* cpPlugins::Interface::Workspace:: +GetWidget( const std::string& name ) +{ + TFilter* process = this->GetFilter( name ); + return( dynamic_cast< TWidget* >( process ) ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface::Workspace:: +TWidget* cpPlugins::Interface::Workspace:: +GetWidget( const std::string& name ) const +{ + const TFilter* process = this->GetFilter( name ); + return( dynamic_cast< const TWidget* >( process ) ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +HasFilter( const std::string& name ) const +{ + return( this->m_Filters.find( name ) != this->m_Filters.end( ) ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +HasWidget( const std::string& name ) const +{ + const TWidget* wdg = this->GetWidget( name ); + return( wdg != NULL ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Workspace:: +TFilter* cpPlugins::Interface::Workspace:: +CreateFilter( const std::string& category, const std::string& filter ) +{ + typedef cpPlugins::Pipeline::Widget _TWidget; + + TFilter::Pointer o = this->m_Loader.CreateFilter( category, filter ); + if( o.IsNotNull( ) ) + { + // Choose a name + std::string name = filter; + while( this->GetFilter( name ) != NULL ) + name += std::string( "_" ); + o->SetPrintExecution( this->m_PrintExecution ); + o->SetName( name ); + + // Interactors + for( + auto i = this->m_Interactors.begin( ); + i != this->m_Interactors.end( ); + ++i + ) + o->AddInteractor( *i ); + + // Finish association + this->m_Filters[ name ] = o; + + } // fi + return( o.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +RenameFilter( const std::string& old_name, const std::string& new_name ) +{ + auto o = this->m_Filters.find( old_name ); + auto n = this->m_Filters.find( new_name ); + if( o != this->m_Filters.end( ) && n == this->m_Filters.end( ) ) + { + // Rename filter + o->second->SetName( new_name ); + this->m_Filters[ new_name ] = o->second; + this->m_Filters.erase( o ); + + // Rename exposed ports + /* TODO + auto e = this->m_ExposedInputs.begin( ); + for( ; e != this->m_ExposedInputs.end( ); ++e ) + if( e->second.first == old_name ) + e->second.first = new_name; + e = this->m_ExposedOutputs.begin( ); + for( ; e != this->m_ExposedOutputs.end( ); ++e ) + if( e->second.first == old_name ) + e->second.first = new_name; + */ + + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +RemoveFilter( const std::string& name ) +{ + auto i = this->m_Filters.find( name ); + if( i != this->m_Filters.end( ) ) + { + i->second->Disconnect( ); + this->m_Filters.erase( i ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +SetPrintExecution( bool b ) +{ + this->m_PrintExecution = b; + for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i ) + i->second->SetPrintExecution( b ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +PrintExecutionOn( ) +{ + this->SetPrintExecution( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +PrintExecutionOff( ) +{ + this->SetPrintExecution( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +AddInteractor( vtkRenderWindowInteractor* iren ) +{ + if( iren != NULL ) + { + this->m_Interactors.insert( iren ); + for( auto f : this->m_Filters ) + f.second->AddInteractor( iren ); + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +Connect( + const std::string& origin_filter, + const std::string& origin_output, + const std::string& destination_filter, + const std::string& destination_input + ) +{ + // Get filters and check pertinence + TFilter* origin = this->GetFilter( origin_filter ); + TFilter* destination = this->GetFilter( destination_filter ); + if( origin == NULL || destination == NULL ) + return( false ); + if( !( destination->HasInput( destination_input ) ) ) + return( false ); + if( !( origin->HasOutput( origin_output ) ) ) + return( false ); + + // Check if there is room for a new connection + bool ok = true; + if( destination->IsInputMultiple( destination_input ) ) + { + for( + unsigned int i = 0; + i < destination->GetInputSize( destination_input ); + ++i + ) + if( + destination->GetInput( destination_input, i )->GetSource( ) == origin + ) + ok = false; + } + else + ok = ( destination->GetInput( destination_input ) == NULL ); + if( ok ) + destination->AddInput( + destination_input, + origin->GetOutput( origin_output ) + ); + return( ok ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +Connect( + TDataObject* input, + const std::string& destination_filter, + const std::string& destination_input + ) +{ + // Get filters and check pertinence + if( input == NULL ) + return( false ); + TFilter* destination = this->GetFilter( destination_filter ); + if( destination == NULL ) + return( false ); + if( !( destination->HasInput( destination_input ) ) ) + return( false ); + + // Check if there is room for a new connection + bool ok = true; + if( destination->IsInputMultiple( destination_input ) ) + { + for( + unsigned int i = 0; + i < destination->GetInputSize( destination_input ); + ++i + ) + if( + destination->GetInput( destination_input, i )->GetSource( ) == + input->GetSource( ) + ) + ok = false; + } + else + ok = ( destination->GetInput( destination_input ) == NULL ); + if( ok ) + destination->AddInput( + destination_input, + input + ); + return( ok ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +Disconnect( + const std::string& origin_filter, + const std::string& origin_output, + const std::string& destination_filter, + const std::string& destination_input + ) +{ + // Get filters and check pertinence + TFilter* origin = this->GetFilter( origin_filter ); + TFilter* destination = this->GetFilter( destination_filter ); + if( origin == NULL || destination == NULL ) + return( false ); + if( !( destination->HasInput( destination_input ) ) ) + return( false ); + if( !( origin->HasOutput( origin_output ) ) ) + return( false ); + + // Check if there is room for a new connection + bool ok = false; + unsigned int del_id = 0; + for( + unsigned int i = 0; + i < destination->GetInputSize( destination_input ); + ++i + ) + if( + destination->GetInput( destination_input, i )->GetSource( ) == origin + ) + { + ok = true; + del_id = i; + + } // fi + if( ok ) + destination->DisconnectInput( destination_input, del_id ); + return( ok ); +} + +// ------------------------------------------------------------------------- +/* +const cpPlugins::Interface::Workspace:: +TExposedPorts& cpPlugins::Interface::Workspace:: +GetExposedInputs( ) const +{ + return( this->m_ExposedInputs ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface::Workspace:: +TExposedPorts& cpPlugins::Interface::Workspace:: +GetExposedOutputs( ) const +{ + return( this->m_ExposedOutputs ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::DataObject* cpPlugins::Interface::Workspace:: +GetExposedOutput( const std::string& name ) +{ + auto i = this->m_ExposedOutputs.find( name ); + if( i != this->m_ExposedOutputs.end( ) ) + { + auto f = this->GetFilter( i->second.first ); + if( f != NULL ) + return( f->GetOutput( i->second.second ) ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Pipeline::DataObject* cpPlugins::Interface::Workspace:: +GetExposedOutput( const std::string& name ) const +{ + auto i = this->m_ExposedOutputs.find( name ); + if( i != this->m_ExposedOutputs.end( ) ) + { + auto f = this->GetFilter( i->second.first ); + if( f != NULL ) + return( f->GetOutput( i->second.second ) ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +ExposeInput( + const std::string& name, + const std::string& filter, const std::string& filter_input + ) +{ + auto i = this->m_ExposedInputs.find( name ); + if( i == this->m_ExposedInputs.end( ) ) + { + this->m_ExposedInputs[ name ] = + std::pair< std::string, std::string >( filter, filter_input ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +ExposeOutput( + const std::string& name, + const std::string& filter, const std::string& filter_output + ) +{ + auto i = this->m_ExposedOutputs.find( name ); + if( i == this->m_ExposedOutputs.end( ) ) + { + this->m_ExposedOutputs[ name ] = + std::pair< std::string, std::string >( filter, filter_output ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +HideInput( const std::string& name ) +{ + auto i = this->m_ExposedInputs.find( name ); + if( i != this->m_ExposedInputs.end( ) ) + this->m_ExposedInputs.erase( i ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +HideOutput( const std::string& name ) +{ + auto i = this->m_ExposedOutputs.find( name ); + if( i != this->m_ExposedOutputs.end( ) ) + this->m_ExposedOutputs.erase( i ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +RenameExposedInput( + const std::string& old_name, const std::string& new_name + ) +{ + auto o = this->m_ExposedInputs.find( old_name ); + auto n = this->m_ExposedInputs.find( new_name ); + if( o != this->m_ExposedInputs.end( ) && n == this->m_ExposedInputs.end( ) ) + { + this->m_ExposedInputs[ new_name ] = o->second; + this->m_ExposedInputs.erase( o ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::Workspace:: +RenameExposedOutput( + const std::string& old_name, const std::string& new_name + ) +{ + auto o = this->m_ExposedOutputs.find( old_name ); + auto n = this->m_ExposedOutputs.find( new_name ); + if( + o != this->m_ExposedOutputs.end( ) && n == this->m_ExposedOutputs.end( ) + ) + { + this->m_ExposedOutputs[ new_name ] = o->second; + this->m_ExposedOutputs.erase( o ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +std::vector< std::pair< std::string, std::string > > +cpPlugins::Interface::Workspace:: +GetConnections( + const std::string& origin, const std::string& destination + ) const +{ + std::vector< std::pair< std::string, std::string > > conns; + auto orig = this->GetFilter( origin ); + auto dest = this->GetFilter( destination ); + if( orig != NULL && dest != NULL ) + { + auto outs = orig->GetOutputsNames( ); + auto ins = dest->GetInputsNames( ); + for( auto o = outs.begin( ); o != outs.end( ); ++o ) + { + for( auto i = ins.begin( ); i != ins.end( ); ++i ) + { + unsigned int nInputs = dest->GetInputSize( *i ); + for( unsigned j = 0; j < nInputs; ++j ) + { + auto od = orig->GetOutput( *o ); + auto id = dest->GetInput( *i, j ); + if( od != NULL && od == id ) + conns.push_back( + std::pair< std::string, std::string >( *o, *i ) + ); + + } // rof + + } // rof + + } // rof + + } // fi + return( conns ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Connect( + const std::string& orig_filter, const std::string& dest_filter, + const std::string& output_name, const std::string& input_name + ) +{ + auto o = this->GetFilter( orig_filter ); + auto d = this->GetFilter( dest_filter ); + if( o != NULL && d != NULL ) + { + try + { + d->AddInput( input_name, o->GetOutput( output_name ) ); + } + catch( std::exception& err ) + { + throw std::logic_error( + std::string( "Error connecting \"" ) + + output_name + std::string( "@" ) + orig_filter + + std::string( "\" with \"" ) + + input_name + std::string( "@" ) + dest_filter + + std::string( "\": " ) + + err.what( ) + ); + + } // yrt + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Connect( + cpPlugins::Pipeline::DataObject* output, + const std::string& dest_filter, const std::string& input_name + ) +{ + auto d = this->GetFilter( dest_filter ); + if( d != NULL ) + d->AddInput( input_name, output ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Connect( + cpPlugins::Pipeline::DataObject* output, + const std::string& exposed_input_name + ) +{ + auto i = this->m_ExposedInputs.find( exposed_input_name ); + if( i != this->m_ExposedInputs.end( ) ) + this->Connect( output, i->second.first, i->second.second ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Disconnect( + const std::string& orig_filter, const std::string& dest_filter, + const std::string& output_name, const std::string& input_name + ) +{ + auto orig = this->GetFilter( orig_filter ); + auto dest = this->GetFilter( dest_filter ); + if( orig != NULL && dest != NULL ) + { + auto out = orig->GetOutput( output_name ); + auto in = dest->GetInput( input_name ); + if( out != NULL && out == in ) + dest->SetInput( + input_name, ( cpPlugins::Pipeline::DataObject* )( NULL ) + ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Disconnect( + const std::string& dest_filter, const std::string& input_name + ) +{ + throw std::logic_error( "Disconnect 1" ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Disconnect( const std::string& dest_filter ) +{ + throw std::logic_error( "Disconnect 2" ); +} +*/ + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Update( ) +{ + for( auto f = this->m_Filters.begin( ); f != this->m_Filters.end( ); ++f ) + f->second->Update( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Update( const std::string& name ) +{ + auto filter = this->GetFilter( name ); + if( filter != NULL ) + filter->Update( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Workspace:: +Workspace( ) + : Superclass( ), + m_PrintExecution( false ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Workspace:: +~Workspace( ) +{ + /* TODO + this->m_ExposedOutputs.clear( ); + this->m_ExposedInputs.clear( ); + */ + this->m_Filters.clear( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/Workspace.h b/lib/cpPlugins/Interface/Workspace.h new file mode 100644 index 0000000..745bd98 --- /dev/null +++ b/lib/cpPlugins/Interface/Workspace.h @@ -0,0 +1,152 @@ +#ifndef __cpPlugins__Interface__Workspace__h__ +#define __cpPlugins__Interface__Workspace__h__ + +#include +#include +#include +#include +#include + +class vtkRenderWindowInteractor; + +namespace cpPlugins +{ + namespace Interface + { + /** \brief A complex pipeline + */ + class cpPlugins_EXPORT Workspace + : public itk::Object + { + public: + typedef Workspace Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef cpPlugins::Pipeline::DataObject TDataObject; + typedef cpPlugins::Pipeline::ProcessObject TFilter; + typedef cpPlugins::Pipeline::Widget TWidget; + typedef cpPlugins::Interface::Loader TLoader; + + typedef std::map< std::string, TFilter::Pointer > TFilters; + + /* TODO + typedef + std::map< std::string, std::pair< std::string, std::string > > + TExposedPorts; + */ + + public: + itkNewMacro( Self ); + itkTypeMacro( Workspace, itk::Object ); + + public: + // Workspace IO + void Load( const std::string& fname ); + void Save( const std::string& fname ) const; + + // Memory management + void Clear( ); + + // Filter management + std::vector< std::string > GetFiltersNames( ) const; + TFilter* GetFilter( const std::string& name ); + const TFilter* GetFilter( const std::string& name ) const; + TWidget* GetWidget( const std::string& name ); + const TWidget* GetWidget( const std::string& name ) const; + bool HasFilter( const std::string& name ) const; + bool HasWidget( const std::string& name ) const; + TFilter* CreateFilter( + const std::string& category, const std::string& filter + ); + bool RenameFilter( + const std::string& old_name, const std::string& new_name + ); + bool RemoveFilter( const std::string& name ); + + void SetPrintExecution( bool b ); + void PrintExecutionOn( ); + void PrintExecutionOff( ); + + // Interactors + void AddInteractor( vtkRenderWindowInteractor* iren ); + + // Connection management + bool Connect( + const std::string& origin_filter, + const std::string& origin_output, + const std::string& destination_filter, + const std::string& destination_input + ); + bool Connect( + TDataObject* input, + const std::string& destination_filter, + const std::string& destination_input + ); + bool Disconnect( + const std::string& origin_filter, + const std::string& origin_output, + const std::string& destination_filter, + const std::string& destination_input + ); + + /* TODO + std::vector< std::pair< std::string, std::string > > GetConnections( + const std::string& origin, const std::string& destination + ) const; + void Connect( + const std::string& orig_filter, const std::string& dest_filter, + const std::string& output_name, const std::string& input_name + ); + void Connect( + cpPlugins::Pipeline::DataObject* output, + const std::string& dest_filter, const std::string& input_name + ); + void Connect( + cpPlugins::Pipeline::DataObject* output, + const std::string& exposed_input_name + ); + void Disconnect( + const std::string& orig_filter, const std::string& dest_filter, + const std::string& output_name, const std::string& input_name + ); + void Disconnect( + const std::string& dest_filter, const std::string& input_name + ); + void Disconnect( const std::string& dest_filter ); + */ + + // Pipeline execution + void Update( ); + void Update( const std::string& name ); + + protected: + Workspace( ); + virtual ~Workspace( ); + + private: + // Purposely not implemented + Workspace( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TLoader m_Loader; + TFilters m_Filters; + bool m_PrintExecution; + + /* TODO + TExposedPorts m_ExposedInputs; + TExposedPorts m_ExposedOutputs; + */ + + std::set< vtkRenderWindowInteractor* > m_Interactors; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Interface__Workspace__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/WorkspaceIO.cxx b/lib/cpPlugins/Interface/WorkspaceIO.cxx new file mode 100644 index 0000000..7b73c43 --- /dev/null +++ b/lib/cpPlugins/Interface/WorkspaceIO.cxx @@ -0,0 +1,315 @@ +#include +#include + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Load( const std::string& fname ) +{ + this->Clear( ); + + // Read from disk + tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( ); + doc->LoadFile( fname.c_str( ) ); + tinyxml2::XMLElement* root = doc->RootElement( ); + if( root == NULL ) + { + delete doc; + throw std::runtime_error( "cpPlugins::Workspace: No valid file" ); + + } // fi + if( std::string( root->Value( ) ) != "cpPlugins_Workspace" ) + { + delete doc; + throw std::runtime_error( "cpPlugins::Workspace: Not a valid workspace" ); + + } // fi + + // Read filters + std::stringstream err; + tinyxml2::XMLElement* filter = root->FirstChildElement( "Filter" ); + while( filter != NULL ) + { + const char* category_value = filter->Attribute( "Category" ); + const char* class_value = filter->Attribute( "Class" ); + const char* name_value = filter->Attribute( "Name" ); + float viewX = float( 0 ), viewY = float( 0 ); + filter->QueryFloatAttribute( "ViewX", &viewX ); + filter->QueryFloatAttribute( "ViewY", &viewY ); + int explicit_execution = 0; + filter->QueryIntAttribute( + "ExplicitExecution", &explicit_execution + ); + if( class_value != NULL && name_value != NULL ) + { + auto new_filter = this->CreateFilter( category_value, class_value ); + if( new_filter != NULL ) + { + this->RenameFilter( new_filter->GetName( ), name_value ); + new_filter->SetViewCoords( viewX, viewY ); + new_filter->SetExplicitExecution( explicit_execution == 1 ); + new_filter->GetParameters( )->FromXML( filter ); + } + else + err + << "No valid class \"" << class_value << "\" with name \"" + << name_value << "\"" << std::endl; + } + else + err << "Incomplete data." << std::endl; + filter = filter->NextSiblingElement( "Filter" ); + + } // elihw + + // Read connections + tinyxml2::XMLElement* connection = root->FirstChildElement( "Connection" ); + while( connection != NULL ) + { + tinyxml2::XMLElement* orig = connection->FirstChildElement( "Origin" ); + tinyxml2::XMLElement* dest = connection->FirstChildElement( "Destination" ); + if( orig != NULL && dest != NULL ) + { + const char* orig_filter = orig->Attribute( "Filter" ); + const char* dest_filter = dest->Attribute( "Filter" ); + const char* orig_name = orig->Attribute( "Name" ); + const char* dest_name = dest->Attribute( "Name" ); + if( + orig_filter != NULL && dest_filter != NULL && + orig_name != NULL && dest_name != NULL + ) + { + try + { + this->Connect( orig_filter, orig_name, dest_filter, dest_name ); + } + catch( std::exception& exc ) + { + err << exc.what( ) << std::endl; + + } // yrt + + } // fi + + } // fi + connection = connection->NextSiblingElement( "Connection" ); + + } // elihw + + // Read exposed inputs + /* TODO + tinyxml2::XMLElement* port = root->FirstChildElement( "ExposedInput" ); + while( port != NULL ) + { + this->ExposeInput( + port->Attribute( "Name" ), + port->Attribute( "Filter" ), + port->Attribute( "Input" ) + ); + port = port->NextSiblingElement( "ExposedInput" ); + + } // elihw + + // Read exposed outputs + port = root->FirstChildElement( "ExposedOutput" ); + while( port != NULL ) + { + this->ExposeOutput( + port->Attribute( "Name" ), + port->Attribute( "Filter" ), + port->Attribute( "Output" ) + ); + port = port->NextSiblingElement( "ExposedOutput" ); + + } // elihw + */ + + // Throw errors + std::string err_str = err.str( ); + if( err_str != "" ) + { + delete doc; + throw std::runtime_error( + std::string( "cpPlugins::Workspace " ) + err_str + ); + + } // fi + + // Finish + delete doc; +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::Workspace:: +Save( const std::string& fname ) const +{ + tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( ); + tinyxml2::XMLElement* root = doc->NewElement( "cpPlugins_Workspace" ); + std::set< std::string > used_plugins; + + // Save filter data + for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i ) + { + auto filter = i->second; + used_plugins.insert( filter->GetPluginName( ) ); + tinyxml2::XMLElement* e = doc->NewElement( "Filter" ); + e->SetAttribute( "Category", filter->GetClassCategory( ) ); + e->SetAttribute( "Class", filter->GetClassName( ) ); + e->SetAttribute( "Name", filter->GetName( ) ); + e->SetAttribute( "ViewX", filter->GetViewX( ) ); + e->SetAttribute( "ViewY", filter->GetViewY( ) ); + e->SetAttribute( + "ExplicitExecution", ( filter->GetExplicitExecution( ) )? 1: 0 + ); + + auto params = filter->GetParameters( ); + params->ToXML( doc, e ); + root->LinkEndChild( e ); + + } // rof + + // Save used plugins + /* TODO + tinyxml2::XMLElement* plugins = doc->NewElement( "Plugins" ); + for( auto pIt = used_plugins.begin( ); pIt != used_plugins.end( ); ++pIt ) + { + tinyxml2::XMLElement* e = doc->NewElement( "Plugin" ); + e->SetAttribute( "Name", pIt->c_str( ) ); + plugins->LinkEndChild( e ); + + } // rof + root->LinkEndChild( plugins ); + */ + + // Save connections + for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i ) + { + auto orig = i->second; + auto outputs = orig->GetOutputsNames( ); + if( outputs.size( ) == 0 ) + continue; + for( auto j = this->m_Filters.begin( ); j != this->m_Filters.end( ); ++j ) + { + if( i == j ) + continue; + auto dest = j->second; + auto inputs = dest->GetInputsNames( ); + if( inputs.size( ) == 0 ) + continue; + + for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt ) + { + auto od = orig->GetOutput( *oIt ); + for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt ) + { + unsigned int nInputs = dest->GetInputSize( *iIt ); + for( unsigned int k = 0; k < nInputs; ++k ) + { + auto id = dest->GetInput( *iIt, k ); + if( od != NULL && od == id ) + { + tinyxml2::XMLElement* e_conn = doc->NewElement( "Connection" ); + tinyxml2::XMLElement* e_orig = doc->NewElement( "Origin" ); + tinyxml2::XMLElement* e_dest = doc->NewElement( "Destination" ); + e_orig->SetAttribute( "Filter", orig->GetName( ) ); + e_orig->SetAttribute( "Name", oIt->c_str( ) ); + e_dest->SetAttribute( "Filter", dest->GetName( ) ); + e_dest->SetAttribute( "Name", iIt->c_str( ) ); + e_conn->LinkEndChild( e_orig ); + e_conn->LinkEndChild( e_dest ); + root->LinkEndChild( e_conn ); + + } // fi + + } // rof + + } // rof + + } // rof + + } // rof + + } // rof + + // Save exposed ports + /* TODO + auto eipIt = this->m_ExposedInputs.begin( ); + for( ; eipIt != this->m_ExposedInputs.end( ); ++eipIt ) + { + tinyxml2::XMLElement* port = doc->NewElement( "ExposedInput" ); + port->SetAttribute( "Name", eipIt->first.c_str( ) ); + port->SetAttribute( "Filter", eipIt->second.first.c_str( ) ); + port->SetAttribute( "Input", eipIt->second.second.c_str( ) ); + root->LinkEndChild( port ); + + } // rof + + auto eopIt = this->m_ExposedOutputs.begin( ); + for( ; eopIt != this->m_ExposedOutputs.end( ); ++eopIt ) + { + tinyxml2::XMLElement* port = doc->NewElement( "ExposedOutput" ); + port->SetAttribute( "Name", eopIt->first.c_str( ) ); + port->SetAttribute( "Filter", eopIt->second.first.c_str( ) ); + port->SetAttribute( "Output", eopIt->second.second.c_str( ) ); + root->LinkEndChild( port ); + + } // rof + */ + + // Physical write and return + doc->LinkEndChild( root ); + auto error = doc->SaveFile( fname.c_str( ) ); + delete doc; + if( error != tinyxml2::XML_SUCCESS ) + { + std::string m; + switch( error ) + { + case tinyxml2::XML_NO_ATTRIBUTE: + m = "No attribute."; break; + case tinyxml2::XML_WRONG_ATTRIBUTE_TYPE: + m = "Wrong attribute."; break; + case tinyxml2::XML_ERROR_FILE_NOT_FOUND: + m = "File not found."; break; + case tinyxml2::XML_ERROR_FILE_COULD_NOT_BE_OPENED: + m = "File not opened."; break; + case tinyxml2::XML_ERROR_FILE_READ_ERROR: + m = "File not read."; break; + case tinyxml2::XML_ERROR_ELEMENT_MISMATCH: + m = "Element mismatch."; break; + case tinyxml2::XML_ERROR_PARSING_ELEMENT: + m = "Parsing element."; break; + case tinyxml2::XML_ERROR_PARSING_ATTRIBUTE: + m = "Parsing attribute."; break; + case tinyxml2::XML_ERROR_IDENTIFYING_TAG: + m = "Tag Id."; break; + case tinyxml2::XML_ERROR_PARSING_TEXT: + m = "Parsing text."; break; + case tinyxml2::XML_ERROR_PARSING_CDATA: + m = "Parsing cdata."; break; + case tinyxml2::XML_ERROR_PARSING_COMMENT: + m = "Parsing comment."; break; + case tinyxml2::XML_ERROR_PARSING_DECLARATION: + m = "Parsing declaration."; break; + case tinyxml2::XML_ERROR_PARSING_UNKNOWN: + m = "Parsing unknown."; break; + case tinyxml2::XML_ERROR_EMPTY_DOCUMENT: + m = "Empty document."; break; + case tinyxml2::XML_ERROR_MISMATCHED_ELEMENT: + m = "Mismatched element."; break; + case tinyxml2::XML_ERROR_PARSING: + m = "Parsing."; break; + case tinyxml2::XML_CAN_NOT_CONVERT_TEXT: + m = "Cannot convert."; break; + case tinyxml2::XML_NO_TEXT_NODE: + m = "No text."; break; + default: + m = "Unknown error."; break; + } // hctiws + throw std::runtime_error( + std::string( "cpPlugins::Workspace: Error while saving \"" ) + + fname + std::string( "\": " ) + m + ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/Chrono.h b/lib/cpPlugins/OS/Chrono.h new file mode 100644 index 0000000..e012406 --- /dev/null +++ b/lib/cpPlugins/OS/Chrono.h @@ -0,0 +1,15 @@ +#ifndef __cpPlugins__OS__Chrono__h__ +#define __cpPlugins__OS__Chrono__h__ + +#include +#include + +// ------------------------------------------------------------------------- +#define cpPlugins_CHRONO \ + std::chrono::duration_cast< std::chrono::milliseconds >( \ + std::chrono::system_clock::now( ).time_since_epoch( ) \ + ).count( ) + +#endif // __cpPlugins__OS__Chrono__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/DLLManager.cxx b/lib/cpPlugins/OS/DLLManager.cxx new file mode 100644 index 0000000..ba13b36 --- /dev/null +++ b/lib/cpPlugins/OS/DLLManager.cxx @@ -0,0 +1,50 @@ +#include +#ifdef cpExtensions_OS_Windows +#else // cpExtensions_OS_Windows +# include +#endif // cpExtensions_OS_Windows + +// ------------------------------------------------------------------------- +void* cpPlugins::OS::DLLManager:: +Open( const std::string& filename ) +{ + void* hnd = NULL; +#ifdef cpExtensions_OS_Windows +#else // cpExtensions_OS_Windows + hnd = dlopen( filename.c_str( ), RTLD_NOW | RTLD_GLOBAL ); + char* error = dlerror( ); + if( error != NULL ) + throw std::runtime_error( error ); +#endif // cpExtensions_OS_Windows + return( hnd ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::OS::DLLManager:: +Close( void* hnd ) +{ +#ifdef cpExtensions_OS_Windows +#else // cpExtensions_OS_Windows + /* TODO: why this clashes with VTK? -> Unregistering of factories. + dlclose( hnd ); + dlerror( ); + */ +#endif // cpExtensions_OS_Windows +} + +// ------------------------------------------------------------------------- +void* cpPlugins::OS::DLLManager:: +Sym( void* hnd, const std::string& symbol ) +{ + void* sym = NULL; +#ifdef cpExtensions_OS_Windows +#else // cpExtensions_OS_Windows + sym = dlsym( hnd, symbol.c_str( ) ); + char* error = dlerror( ); + if( error != NULL ) + throw std::runtime_error( error ); +#endif // cpExtensions_OS_Windows + return( sym ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/DLLManager.h b/lib/cpPlugins/OS/DLLManager.h new file mode 100644 index 0000000..9e6460b --- /dev/null +++ b/lib/cpPlugins/OS/DLLManager.h @@ -0,0 +1,27 @@ +#ifndef __cpPlugins__OS__DLLManager__h__ +#define __cpPlugins__OS__DLLManager__h__ + +#include +#include + +namespace cpPlugins +{ + namespace OS + { + /** + */ + class cpPlugins_EXPORT DLLManager + { + public: + static void* Open( const std::string& filename ); + static void Close( void* hnd ); + static void* Sym( void* hnd, const std::string& symbol ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__OS__DLLManager__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/FileSystem.cxx b/lib/cpPlugins/OS/FileSystem.cxx new file mode 100644 index 0000000..334bf2a --- /dev/null +++ b/lib/cpPlugins/OS/FileSystem.cxx @@ -0,0 +1,202 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +std::string cpPlugins::OS::FileSystem:: +CanonicalPath( const std::string& path ) +{ + std::string ret = ""; +#ifdef cpExtensions_OS_Windows + TCHAR buffer[ 4096 ] = TEXT( "" ); + TCHAR** lppPart = { NULL }; + GetFullPathName( path.c_str( ), 4096, buffer, lppPart ); + ret = std::string( buffer ); +#else // cpExtensions_OS_Windows + char* canonical_path = realpath( path.c_str( ), NULL ); + if( canonical_path != NULL ) + { + ret = canonical_path; + free( canonical_path ); + + } // fi +#endif // cpExtensions_OS_Windows + return( ret ); +} + +// ------------------------------------------------------------------------- +std::pair< std::string, std::string > cpPlugins::OS::FileSystem:: +SplitPath( const std::string& path ) +{ + size_t found = path.find_last_of( "/\\" ); + return( + std::pair< std::string, std::string >( + path.substr( 0, found + 1 ), path.substr( found + 1 ) + ) + ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::OS::FileSystem:: +LoadDirContents( + const std::string& path, bool recursive, + const std::string& pattern + ) +{ + // Prepare inputs and outputs + std::stringstream path_stream; + path_stream << path << cpPlugins_PATH_SEPARATOR; + std::string path_str = path_stream.str( ); + std::set< std::string > output; + + // Process data + tinydir_dir dir; + if( tinydir_open_sorted( &dir, path.c_str( ) ) != -1 ) + { + for( auto i = 0; i < dir.n_files; i++ ) + { + tinydir_file file; + if( tinydir_readfile_n( &dir, &file , i ) != -1 ) + { + std::string fname = path_str + file.name; + if( file.is_dir ) + { + if( recursive ) + { + if( fname != "." && fname != ".." ) + { + auto tmp = Self::LoadDirContents( fname, true ); + output.insert( tmp.begin( ), tmp.end( ) ); + + } // fi + + } // fi + } + else + { + if( pattern != "" ) + { + if( Self::Glob( fname, path_str + pattern ) ) + output.insert( fname ); + } + else + output.insert( fname ); + + } // fi + + } // fi + + } // rof + + } // fi + tinydir_close( &dir ); + return( output ); +} + +// ------------------------------------------------------------------------- +int cpPlugins::OS::FileSystem:: +GlobMatch( const char* target, const char* pattern ) +{ + char* pat = const_cast< char* >( pattern ); + char* end = strchr( pat, ']' ); + char* ptr; + if( *pat == '[' && end != NULL ) + { + if( end == pat + 1 ) + { + end = strchr( pat + 2, ']' ); + if( end == NULL ) + return( 0 ); + + } // fi + + if( end - pat == 4 && pat[ 2 ] == '-' && pat[ 1 ] <= pattern[ 3 ] ) + { + if( *target >= pat[ 1 ] && *target <= pat[ 3 ] ) + return( 5 ); + else + return( 0 ); + + } // fi + + ptr = strchr( pat + 1, *target ); + if( ptr != NULL && ptr < end ) + return( end - pat + 1 ); + else + return( 0 ); + + } // fi + + if( *pat == '?' && *target != 0 ) + return( 1 ); + if( *pat == '*' ) + return( 0 ); + if( *target == 0 || *pat == 0 ) + return( 0 ); + if( *target == *pat ) + return( 1 ); + return( 0 ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::OS::FileSystem:: +Glob( const std::string& line, const std::string& pattern ) +{ + const char* target = line.c_str( ); + const char* pat = pattern.c_str( ); + int gobble; + + while( ( gobble = GlobMatch( target, pat ) ) ) + { + target++; + pat += gobble; + + } // elihw + if( *target == 0 && *pat == 0 ) + return( true ); + else if( *pat == '*' ) + { + while( pat[ 1 ] == '*' ) + pat++; + if( pat[ 1 ] == 0 ) + return( true ); + while( *target ) + if( Glob( target++, pat + 1 ) ) + return( 1 ); + + } // fi + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::OS::FileSystem:: +Read( std::string& buffer, const std::string& fname ) +{ + buffer = ""; + std::ifstream file_stream( fname.c_str( ) ); + if( !file_stream ) + return( false ); + file_stream.seekg( 0, std::ios::end ); + buffer.reserve( ( unsigned int )( file_stream.tellg( ) ) ); + file_stream.seekg( 0, std::ios::beg ); + buffer.assign( + ( std::istreambuf_iterator< char >( file_stream ) ), + std::istreambuf_iterator< char >( ) + ); + file_stream.close( ); + return( true ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::OS::FileSystem:: +Write( const std::string& buffer, const std::string& fname ) +{ + std::ofstream file_stream( fname.c_str( ), std::ofstream::binary ); + if( !file_stream ) + return( false ); + file_stream.write( buffer.c_str( ), buffer.size( ) ); + return( true ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/FileSystem.h b/lib/cpPlugins/OS/FileSystem.h new file mode 100644 index 0000000..26d5ad4 --- /dev/null +++ b/lib/cpPlugins/OS/FileSystem.h @@ -0,0 +1,59 @@ +#ifndef __cpPlugins__OS__FileSystem__h__ +#define __cpPlugins__OS__FileSystem__h__ + +#include +#include + +namespace cpPlugins +{ + namespace OS + { + /** + */ + class cpPlugins_EXPORT FileSystem + { + public: + typedef FileSystem Self; + + public: + /** + */ + static std::string CanonicalPath( const std::string& path ); + + /** + */ + static std::pair< std::string, std::string > SplitPath( + const std::string& path + ); + + /** + */ + static std::set< std::string > LoadDirContents( + const std::string& path, bool recursive = false, + const std::string& pattern = "" + ); + + /** + */ + static int GlobMatch( const char* target, const char* pattern ); + + /** + */ + static bool Glob( const std::string& line, const std::string& pattern ); + + /** + */ + static bool Read( std::string& buffer, const std::string& fname ); + + /** + */ + static bool Write( const std::string& buffer, const std::string& fname ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__OS__FileSystem__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/String.cxx b/lib/cpPlugins/OS/String.cxx new file mode 100644 index 0000000..0bb9b59 --- /dev/null +++ b/lib/cpPlugins/OS/String.cxx @@ -0,0 +1,37 @@ +#include +#include + +// ------------------------------------------------------------------------- +#ifdef cpPlugins_OS_Windows +# define cpPlugins_STRTOK( A, B, N ) strtok_s( A, B, N ) +#else // cpPlugins_OS_Windows +# define cpPlugins_STRTOK( A, B, N ) std::strtok( A, B ) +#endif // cpPlugins_OS_Windows + +// ------------------------------------------------------------------------- +std::vector< std::string > cpPlugins::OS::String:: +Tokenize( const std::string& str, const std::string& delims ) +{ + std::vector< std::string > tokens; + if( str.size( ) > 0 ) + { + auto ssize = str.size( ); + char* buffer = new char[ ssize + 1 ]; + for( unsigned long i = 0; i < ssize; ++i ) + buffer[ i ] = str[ i ]; + buffer[ ssize ] = '\0'; + char* next; + char* it = cpPlugins_STRTOK( buffer, delims.c_str( ), &next ); + while( it != NULL ) + { + tokens.push_back( std::string( it ) ); + it = cpPlugins_STRTOK( NULL, delims.c_str( ), &next ); + + } // elihw + delete [] buffer; + + } // fi + return( tokens ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/String.h b/lib/cpPlugins/OS/String.h new file mode 100644 index 0000000..d87db17 --- /dev/null +++ b/lib/cpPlugins/OS/String.h @@ -0,0 +1,28 @@ +#ifndef __cpPlugins__OS__String__h__ +#define __cpPlugins__OS__String__h__ + +#include +#include +#include + +namespace cpPlugins +{ + namespace OS + { + /** + */ + class cpPlugins_EXPORT String + { + public: + static std::vector< std::string > Tokenize( + const std::string& str, const std::string& delims + ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__OS__String__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/tinydir.h b/lib/cpPlugins/OS/tinydir.h new file mode 100644 index 0000000..432bd95 --- /dev/null +++ b/lib/cpPlugins/OS/tinydir.h @@ -0,0 +1,806 @@ +/* + Copyright (c) 2013-2016, tinydir authors: + - Cong Xu + - Lautis Sun + - Baudouin Feildel + - Andargor + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef cpPlugins__OS__TINYDIR_H +#define cpPlugins__OS__TINYDIR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if ((defined _UNICODE) && !(defined UNICODE)) +#define UNICODE +#endif + +#if ((defined UNICODE) && !(defined _UNICODE)) +#define _UNICODE +#endif + +#include +#include +#include +#ifdef _MSC_VER +# define WIN32_LEAN_AND_MEAN +# include +# include +# pragma warning(push) +# pragma warning (disable : 4996) +#else +# include +# include +# include +# include +#endif +#ifdef __MINGW32__ +# include +#endif + + +/* types */ + +/* Windows UNICODE wide character support */ +#if defined _MSC_VER || defined __MINGW32__ +#define _tinydir_char_t TCHAR +#define TINYDIR_STRING(s) _TEXT(s) +#define _tinydir_strlen _tcslen +#define _tinydir_strcpy _tcscpy +#define _tinydir_strcat _tcscat +#define _tinydir_strcmp _tcscmp +#define _tinydir_strrchr _tcsrchr +#define _tinydir_strncmp _tcsncmp +#else +#define _tinydir_char_t char +#define TINYDIR_STRING(s) s +#define _tinydir_strlen strlen +#define _tinydir_strcpy strcpy +#define _tinydir_strcat strcat +#define _tinydir_strcmp strcmp +#define _tinydir_strrchr strrchr +#define _tinydir_strncmp strncmp +#endif + +#if (defined _MSC_VER || defined __MINGW32__) +#include +#define _TINYDIR_PATH_MAX MAX_PATH +#elif defined __linux__ +#include +#define _TINYDIR_PATH_MAX PATH_MAX +#else +#define _TINYDIR_PATH_MAX 4096 +#endif + +#ifdef _MSC_VER +/* extra chars for the "\\*" mask */ +# define _TINYDIR_PATH_EXTRA 2 +#else +# define _TINYDIR_PATH_EXTRA 0 +#endif + +#define _TINYDIR_FILENAME_MAX 256 + +#if (defined _MSC_VER || defined __MINGW32__) +#define _TINYDIR_DRIVE_MAX 3 +#endif + +#ifdef _MSC_VER +# define _TINYDIR_FUNC static __inline +#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +# define _TINYDIR_FUNC static __inline__ +#else +# define _TINYDIR_FUNC static inline +#endif + +/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */ +#ifdef TINYDIR_USE_READDIR_R + +/* readdir_r is a POSIX-only function, and may not be available under various + * environments/settings, e.g. MinGW. Use readdir fallback */ +#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || \ + _POSIX_SOURCE +# define _TINYDIR_HAS_READDIR_R +#endif +#if _POSIX_C_SOURCE >= 200112L +# define _TINYDIR_HAS_FPATHCONF +# include +#endif +#if _BSD_SOURCE || _SVID_SOURCE || \ + (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) +# define _TINYDIR_HAS_DIRFD +# include +#endif +#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD && \ + defined _PC_NAME_MAX +# define _TINYDIR_USE_FPATHCONF +#endif +#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R || \ + !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX) +# define _TINYDIR_USE_READDIR +#endif + +/* Use readdir by default */ +#else +# define _TINYDIR_USE_READDIR +#endif + +/* MINGW32 has two versions of dirent, ASCII and UNICODE*/ +#ifndef _MSC_VER +#if (defined __MINGW32__) && (defined _UNICODE) +#define _TINYDIR_DIR _WDIR +#define _tinydir_dirent _wdirent +#define _tinydir_opendir _wopendir +#define _tinydir_readdir _wreaddir +#define _tinydir_closedir _wclosedir +#else +#define _TINYDIR_DIR DIR +#define _tinydir_dirent dirent +#define _tinydir_opendir opendir +#define _tinydir_readdir readdir +#define _tinydir_closedir closedir +#endif +#endif + +/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */ +#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE) +#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE) +#else +#error "Either define both alloc and free or none of them!" +#endif + +#if !defined(_TINYDIR_MALLOC) +#define _TINYDIR_MALLOC(_size) malloc(_size) +#define _TINYDIR_FREE(_ptr) free(_ptr) +#endif /* !defined(_TINYDIR_MALLOC) */ + + typedef struct tinydir_file + { + _tinydir_char_t path[_TINYDIR_PATH_MAX]; + _tinydir_char_t name[_TINYDIR_FILENAME_MAX]; + _tinydir_char_t *extension; + int is_dir; + int is_reg; + +#ifndef _MSC_VER +#ifdef __MINGW32__ + struct _stat _s; +#else + struct stat _s; +#endif +#endif + } tinydir_file; + + typedef struct tinydir_dir + { + _tinydir_char_t path[_TINYDIR_PATH_MAX]; + int has_next; + size_t n_files; + + tinydir_file *_files; +#ifdef _MSC_VER + HANDLE _h; + WIN32_FIND_DATA _f; +#else + _TINYDIR_DIR *_d; + struct _tinydir_dirent *_e; +#ifndef _TINYDIR_USE_READDIR + struct _tinydir_dirent *_ep; +#endif +#endif + } tinydir_dir; + + +/* declarations */ + + _TINYDIR_FUNC + int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path); + _TINYDIR_FUNC + int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path); + _TINYDIR_FUNC + void tinydir_close(tinydir_dir *dir); + + _TINYDIR_FUNC + int tinydir_next(tinydir_dir *dir); + _TINYDIR_FUNC + int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file); + _TINYDIR_FUNC + int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i); + _TINYDIR_FUNC + int tinydir_open_subdir_n(tinydir_dir *dir, size_t i); + + _TINYDIR_FUNC + int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path); + _TINYDIR_FUNC + void _tinydir_get_ext(tinydir_file *file); + _TINYDIR_FUNC + int _tinydir_file_cmp(const void *a, const void *b); +#ifndef _MSC_VER +#ifndef _TINYDIR_USE_READDIR + _TINYDIR_FUNC + size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp); +#endif +#endif + + +/* definitions*/ + + _TINYDIR_FUNC + int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path) + { +#ifndef _MSC_VER +#ifndef _TINYDIR_USE_READDIR + int error; + int size; /* using int size */ +#endif +#else + _tinydir_char_t path_buf[_TINYDIR_PATH_MAX]; +#endif + _tinydir_char_t *pathp; + + if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) + { + errno = EINVAL; + return -1; + } + if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) + { + errno = ENAMETOOLONG; + return -1; + } + + /* initialise dir */ + dir->_files = NULL; +#ifdef _MSC_VER + dir->_h = INVALID_HANDLE_VALUE; +#else + dir->_d = NULL; +#ifndef _TINYDIR_USE_READDIR + dir->_ep = NULL; +#endif +#endif + tinydir_close(dir); + + _tinydir_strcpy(dir->path, path); + /* Remove trailing slashes */ + pathp = &dir->path[_tinydir_strlen(dir->path) - 1]; + while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) + { + *pathp = TINYDIR_STRING('\0'); + pathp++; + } +#ifdef _MSC_VER + _tinydir_strcpy(path_buf, dir->path); + _tinydir_strcat(path_buf, TINYDIR_STRING("\\*")); + dir->_h = FindFirstFile(path_buf, &dir->_f); + if (dir->_h == INVALID_HANDLE_VALUE) + { + errno = ENOENT; +#else + dir->_d = _tinydir_opendir(path); + if (dir->_d == NULL) + { +#endif + goto bail; + } + + /* read first file */ + dir->has_next = 1; +#ifndef _MSC_VER +#ifdef _TINYDIR_USE_READDIR + dir->_e = _tinydir_readdir(dir->_d); +#else + /* allocate dirent buffer for readdir_r */ + size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */ + if (size == -1) return -1; + dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size); + if (dir->_ep == NULL) return -1; + + error = readdir_r(dir->_d, dir->_ep, &dir->_e); + if (error != 0) return -1; +#endif + if (dir->_e == NULL) + { + dir->has_next = 0; + } +#endif + + return 0; + + bail: + tinydir_close(dir); + return -1; + } + + _TINYDIR_FUNC + int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path) + { + /* Count the number of files first, to pre-allocate the files array */ + size_t n_files = 0; + if (tinydir_open(dir, path) == -1) + { + return -1; + } + while (dir->has_next) + { + n_files++; + if (tinydir_next(dir) == -1) + { + goto bail; + } + } + tinydir_close(dir); + + if (tinydir_open(dir, path) == -1) + { + return -1; + } + + dir->n_files = 0; + dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files); + if (dir->_files == NULL) + { + goto bail; + } + while (dir->has_next) + { + tinydir_file *p_file; + dir->n_files++; + + p_file = &dir->_files[dir->n_files - 1]; + if (tinydir_readfile(dir, p_file) == -1) + { + goto bail; + } + + if (tinydir_next(dir) == -1) + { + goto bail; + } + + /* Just in case the number of files has changed between the first and + second reads, terminate without writing into unallocated memory */ + if (dir->n_files == n_files) + { + break; + } + } + + qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp); + + return 0; + + bail: + tinydir_close(dir); + return -1; + } + + _TINYDIR_FUNC + void tinydir_close(tinydir_dir *dir) + { + if (dir == NULL) + { + return; + } + + memset(dir->path, 0, sizeof(dir->path)); + dir->has_next = 0; + dir->n_files = 0; + _TINYDIR_FREE(dir->_files); + dir->_files = NULL; +#ifdef _MSC_VER + if (dir->_h != INVALID_HANDLE_VALUE) + { + FindClose(dir->_h); + } + dir->_h = INVALID_HANDLE_VALUE; +#else + if (dir->_d) + { + _tinydir_closedir(dir->_d); + } + dir->_d = NULL; + dir->_e = NULL; +#ifndef _TINYDIR_USE_READDIR + _TINYDIR_FREE(dir->_ep); + dir->_ep = NULL; +#endif +#endif + } + + _TINYDIR_FUNC + int tinydir_next(tinydir_dir *dir) + { + if (dir == NULL) + { + errno = EINVAL; + return -1; + } + if (!dir->has_next) + { + errno = ENOENT; + return -1; + } + +#ifdef _MSC_VER + if (FindNextFile(dir->_h, &dir->_f) == 0) +#else +#ifdef _TINYDIR_USE_READDIR + dir->_e = _tinydir_readdir(dir->_d); +#else + if (dir->_ep == NULL) + { + return -1; + } + if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) + { + return -1; + } +#endif + if (dir->_e == NULL) +#endif + { + dir->has_next = 0; +#ifdef _MSC_VER + if (GetLastError() != ERROR_SUCCESS && + GetLastError() != ERROR_NO_MORE_FILES) + { + tinydir_close(dir); + errno = EIO; + return -1; + } +#endif + } + + return 0; + } + + _TINYDIR_FUNC + int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file) + { + if (dir == NULL || file == NULL) + { + errno = EINVAL; + return -1; + } +#ifdef _MSC_VER + if (dir->_h == INVALID_HANDLE_VALUE) +#else + if (dir->_e == NULL) +#endif + { + errno = ENOENT; + return -1; + } + if (_tinydir_strlen(dir->path) + + _tinydir_strlen( +#ifdef _MSC_VER + dir->_f.cFileName +#else + dir->_e->d_name +#endif + ) + 1 + _TINYDIR_PATH_EXTRA >= + _TINYDIR_PATH_MAX) + { + /* the path for the file will be too long */ + errno = ENAMETOOLONG; + return -1; + } + if (_tinydir_strlen( +#ifdef _MSC_VER + dir->_f.cFileName +#else + dir->_e->d_name +#endif + ) >= _TINYDIR_FILENAME_MAX) + { + errno = ENAMETOOLONG; + return -1; + } + + _tinydir_strcpy(file->path, dir->path); + _tinydir_strcat(file->path, TINYDIR_STRING("/")); + _tinydir_strcpy(file->name, +#ifdef _MSC_VER + dir->_f.cFileName +#else + dir->_e->d_name +#endif + ); + _tinydir_strcat(file->path, file->name); +#ifndef _MSC_VER +#ifdef __MINGW32__ + if (_tstat( +#else + if (stat( +#endif + file->path, &file->_s) == -1) + { + return -1; + } +#endif + _tinydir_get_ext(file); + + file->is_dir = +#ifdef _MSC_VER + !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); +#else + S_ISDIR(file->_s.st_mode); +#endif + file->is_reg = +#ifdef _MSC_VER + !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || + ( + !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) && + !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) && +#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM + !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) && +#endif +#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA + !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) && +#endif + !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) && + !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)); +#else + S_ISREG(file->_s.st_mode); +#endif + + return 0; + } + + _TINYDIR_FUNC + int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i) + { + if (dir == NULL || file == NULL) + { + errno = EINVAL; + return -1; + } + if (i >= dir->n_files) + { + errno = ENOENT; + return -1; + } + + memcpy(file, &dir->_files[i], sizeof(tinydir_file)); + _tinydir_get_ext(file); + + return 0; + } + + _TINYDIR_FUNC + int tinydir_open_subdir_n(tinydir_dir *dir, size_t i) + { + _tinydir_char_t path[_TINYDIR_PATH_MAX]; + if (dir == NULL) + { + errno = EINVAL; + return -1; + } + if (i >= dir->n_files || !dir->_files[i].is_dir) + { + errno = ENOENT; + return -1; + } + + _tinydir_strcpy(path, dir->_files[i].path); + tinydir_close(dir); + if (tinydir_open_sorted(dir, path) == -1) + { + return -1; + } + + return 0; + } + +/* Open a single file given its path */ + _TINYDIR_FUNC + int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path) + { + tinydir_dir dir; + int result = 0; + int found = 0; + _tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX]; + _tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX]; + _tinydir_char_t *dir_name; + _tinydir_char_t *base_name; +#if (defined _MSC_VER || defined __MINGW32__) + _tinydir_char_t drive_buf[_TINYDIR_DRIVE_MAX]; + _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX]; +#endif + + if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) + { + errno = EINVAL; + return -1; + } + if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) + { + errno = ENAMETOOLONG; + return -1; + } + + /* Get the parent path */ +#if (defined _MSC_VER || defined __MINGW32__) +#if ((defined _MSC_VER) && (_MSC_VER >= 1400)) + _tsplitpath_s( + path, + drive_buf, _TINYDIR_DRIVE_MAX, + dir_name_buf, _TINYDIR_FILENAME_MAX, + file_name_buf, _TINYDIR_FILENAME_MAX, + ext_buf, _TINYDIR_FILENAME_MAX); +#else + _tsplitpath( + path, + drive_buf, + dir_name_buf, + file_name_buf, + ext_buf); +#endif + +/* _splitpath_s not work fine with only filename and widechar support */ +#ifdef _UNICODE + if (drive_buf[0] == L'\xFEFE') + drive_buf[0] = '\0'; + if (dir_name_buf[0] == L'\xFEFE') + dir_name_buf[0] = '\0'; +#endif + + if (errno) + { + errno = EINVAL; + return -1; + } + /* Emulate the behavior of dirname by returning "." for dir name if it's + empty */ + if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') + { + _tinydir_strcpy(dir_name_buf, TINYDIR_STRING(".")); + } + /* Concatenate the drive letter and dir name to form full dir name */ + _tinydir_strcat(drive_buf, dir_name_buf); + dir_name = drive_buf; + /* Concatenate the file name and extension to form base name */ + _tinydir_strcat(file_name_buf, ext_buf); + base_name = file_name_buf; +#else + _tinydir_strcpy(dir_name_buf, path); + dir_name = dirname(dir_name_buf); + _tinydir_strcpy(file_name_buf, path); + base_name =basename(file_name_buf); +#endif + + /* Open the parent directory */ + if (tinydir_open(&dir, dir_name) == -1) + { + return -1; + } + + /* Read through the parent directory and look for the file */ + while (dir.has_next) + { + if (tinydir_readfile(&dir, file) == -1) + { + result = -1; + goto bail; + } + if (_tinydir_strcmp(file->name, base_name) == 0) + { + /* File found */ + found = 1; + break; + } + tinydir_next(&dir); + } + if (!found) + { + result = -1; + errno = ENOENT; + } + + bail: + tinydir_close(&dir); + return result; + } + + _TINYDIR_FUNC + void _tinydir_get_ext(tinydir_file *file) + { + _tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.')); + if (period == NULL) + { + file->extension = &(file->name[_tinydir_strlen(file->name)]); + } + else + { + file->extension = period + 1; + } + } + + _TINYDIR_FUNC + int _tinydir_file_cmp(const void *a, const void *b) + { + const tinydir_file *fa = (const tinydir_file *)a; + const tinydir_file *fb = (const tinydir_file *)b; + if (fa->is_dir != fb->is_dir) + { + return -(fa->is_dir - fb->is_dir); + } + return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX); + } + +#ifndef _MSC_VER +#ifndef _TINYDIR_USE_READDIR +/* + The following authored by Ben Hutchings + from https://womble.decadent.org.uk/readdir_r-advisory.html +*/ +/* Calculate the required buffer size (in bytes) for directory * + * entries read from the given directory handle. Return -1 if this * + * this cannot be done. * + * * + * This code does not trust values of NAME_MAX that are less than * + * 255, since some systems (including at least HP-UX) incorrectly * + * define it to be a smaller value. */ + _TINYDIR_FUNC + size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp) + { + long name_max; + size_t name_end; + /* parameter may be unused */ + (void)dirp; + +#if defined _TINYDIR_USE_FPATHCONF + name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); + if (name_max == -1) +#if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +#else + return (size_t)(-1); +#endif +#elif defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +#else +#error "buffer size for readdir_r cannot be determined" +#endif + name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1; + return (name_end > sizeof(struct _tinydir_dirent) ? + name_end : sizeof(struct _tinydir_dirent)); + } +#endif +#endif + +#ifdef __cplusplus + } +#endif + +# if defined (_MSC_VER) +# pragma warning(pop) +# endif + +#endif // cpPlugins__OS__TINYDIR_H + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OS/tinydir_COPYING.txt b/lib/cpPlugins/OS/tinydir_COPYING.txt new file mode 100644 index 0000000..0d31329 --- /dev/null +++ b/lib/cpPlugins/OS/tinydir_COPYING.txt @@ -0,0 +1,26 @@ +Copyright (c) 2013-2016, tinydir authors: +- Cong Xu +- Lautis Sun +- Baudouin Feildel +- Andargor +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/cpPlugins/OS/tinydir_README.md.txt b/lib/cpPlugins/OS/tinydir_README.md.txt new file mode 100644 index 0000000..3fab002 --- /dev/null +++ b/lib/cpPlugins/OS/tinydir_README.md.txt @@ -0,0 +1,78 @@ +TinyDir +======= +[![Build Status](https://travis-ci.org/cxong/tinydir.svg?branch=master)](https://travis-ci.org/cxong/tinydir)[![Project Stats](https://www.openhub.net/p/tinydir/widgets/project_thin_badge.gif)](https://www.openhub.net/p/tinydir) + +Lightweight, portable and easy to integrate C directory and file reader. TinyDir wraps dirent for POSIX and FindFirstFile for Windows. + +Windows unicode is supported by defining `UNICODE` and `_UNICODE` before including `tinydir.h`. + +Example +======= + +There are two methods. Error checking omitted: + +```C +tinydir_dir dir; +tinydir_open(&dir, "/path/to/dir"); + +while (dir.has_next) +{ + tinydir_file file; + tinydir_readfile(&dir, &file); + + printf("%s", file.name); + if (file.is_dir) + { + printf("/"); + } + printf("\n"); + + tinydir_next(&dir); +} + +tinydir_close(&dir); +``` + +```C +tinydir_dir dir; +int i; +tinydir_open_sorted(&dir, "/path/to/dir"); + +for (i = 0; i < dir.n_files; i++) +{ + tinydir_file file; + tinydir_readfile_n(&dir, &file, i); + + printf("%s", file.name); + if (file.is_dir) + { + printf("/"); + } + printf("\n"); +} + +tinydir_close(&dir); +``` + +See the `/samples` folder for more examples, including an interactive command-line directory navigator. + +Language +======== + +ANSI C, or C90. + +Platforms +========= + +POSIX and Windows supported. Open to the possibility of supporting other platforms. + +License +======= + +Simplified BSD; if you use tinydir you can comply by including `tinydir.h` or `COPYING` somewhere in your package. + +Known Limitations +================= + +- Limited path and filename sizes +- [Possible race condition bug if folder being read has changing content](https://github.com/cxong/tinydir/issues/13) diff --git a/lib/cpPlugins/Pipeline/DataObject.cxx b/lib/cpPlugins/Pipeline/DataObject.cxx new file mode 100644 index 0000000..7afa1c7 --- /dev/null +++ b/lib/cpPlugins/Pipeline/DataObject.cxx @@ -0,0 +1,92 @@ +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::DataObject:: +IsCompatible( const Self* other ) const +{ + return( true ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::ProcessObject* +cpPlugins::Pipeline::DataObject:: +GetSource( ) +{ + return( this->m_Source ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Pipeline::ProcessObject* +cpPlugins::Pipeline::DataObject:: +GetSource( ) const +{ + return( this->m_Source ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::DataObject:: +SetSource( cpPlugins::Pipeline::ProcessObject* src ) +{ + if( this->m_Source != src ) + { + this->m_Source = src; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::DataObject:: +DisconnectFromPipeline( ) +{ + // Disconnect input pipelines (ITK) + itk::DataObject::Pointer itk_obj = this->GetITK< itk::DataObject >( ); + if( itk_obj.IsNotNull( ) ) + itk_obj->DisconnectPipeline( ); + + // Disconnect input pipelines (VTK) + bool ok = this->_DisconnectVTK< vtkImageData >( ); + if( !ok ) ok = this->_DisconnectVTK< vtkPolyData >( ); + + // Unbind source + this->m_Source = NULL; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::DataObject:: +DataObject( ) + : Superclass( ), + m_Source( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::DataObject:: +~DataObject( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TType > +bool cpPlugins::Pipeline::DataObject:: +_DisconnectVTK( ) +{ + _TType* v = dynamic_cast< _TType* >( this->m_VTK.GetPointer( ) ); + if( v != NULL ) + { + vtkSmartPointer< _TType > d = vtkSmartPointer< _TType >::New( ); + d->ShallowCopy( v ); + this->m_VTK = d; + return( true ); + } + else + return( false ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/DataObject.h b/lib/cpPlugins/Pipeline/DataObject.h new file mode 100644 index 0000000..04623cf --- /dev/null +++ b/lib/cpPlugins/Pipeline/DataObject.h @@ -0,0 +1,62 @@ +#ifndef __cpPlugins__Pipeline__DataObject__h__ +#define __cpPlugins__Pipeline__DataObject__h__ + +#include + +namespace cpPlugins +{ + namespace Pipeline + { + // Some forward declarations + class ProcessObject; + + /** + */ + class cpPlugins_EXPORT DataObject + : public Object + { + friend class ProcessObject; + + public: + typedef DataObject Self; + typedef Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( DataObject, Object ); + cpPlugins_Id_Macro( DataObject, Object ); + + public: + virtual bool IsCompatible( const Self* other ) const; + + ProcessObject* GetSource( ); + const ProcessObject* GetSource( ) const; + void SetSource( ProcessObject* src ); + + void DisconnectFromPipeline( ); + + protected: + DataObject( ); + virtual ~DataObject( ); + + template< class _TType > + inline bool _DisconnectVTK( ); + + private: + // Purposely not implemented + DataObject( const Self& ); + Self& operator=( const Self& ); + + protected: + ProcessObject* m_Source; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Pipeline__DataObject__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Events.h b/lib/cpPlugins/Pipeline/Events.h new file mode 100644 index 0000000..a675d93 --- /dev/null +++ b/lib/cpPlugins/Pipeline/Events.h @@ -0,0 +1,51 @@ +#ifndef __cpPlugins__Pipeline__Events__h__ +#define __cpPlugins__Pipeline__Events__h__ + +#include +#include + +// ------------------------------------------------------------------------- +#define cpPluginsEventsOpenMacro( name ) \ + class name \ + : public itk::AnyEvent \ + { \ + public: \ + typedef name Self; \ + typedef itk::AnyEvent Superclass; \ + public: \ + name( ) : Superclass( ) { } \ + virtual ~name( ) { } \ + const char* GetEventName( ) const \ + { return( "cpPlugins::Pipeline::Events::#name" ); } \ + bool CheckEvent( const itk::EventObject* e ) const \ + { return( dynamic_cast< const Self* >( e ) != NULL ); } \ + itk::EventObject* MakeObject( ) const \ + { return( new Self( ) ); } + +// ------------------------------------------------------------------------- +#define cpPluginsEventsCloseMacro( name ) \ + } + +namespace cpPlugins +{ + namespace Pipeline + { + namespace Events + { + /** + */ + cpPluginsEventsOpenMacro( Modified ) + public: + itk::ModifiedTimeType Time; + long Span; + cpPluginsEventsCloseMacro( Modified ); + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Pipeline__Events__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Object.cxx b/lib/cpPlugins/Pipeline/Object.cxx new file mode 100644 index 0000000..abcac9c --- /dev/null +++ b/lib/cpPlugins/Pipeline/Object.cxx @@ -0,0 +1,98 @@ +#include + +#include +#include + +// ------------------------------------------------------------------------- +const float& cpPlugins::Pipeline::Object:: +GetViewX( ) const +{ + return( this->m_ViewX ); +} + +// ------------------------------------------------------------------------- +const float& cpPlugins::Pipeline::Object:: +GetViewY( ) const +{ + return( this->m_ViewY ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Object:: +SetViewCoords( float x, float y ) +{ + this->m_ViewX = x; + this->m_ViewY = y; + // WARNING: do not call "this->Modified( )" -> It could lead to + // re-execution of all pipeline +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Object:: +Modified( ) const +{ + const itk::Object* i = + dynamic_cast< const itk::Object* >( this->m_ITK.GetPointer( ) ); + vtkObject* v = dynamic_cast< vtkObject* >( this->m_VTK.GetPointer( ) ); + if( i != NULL ) i->Modified( ); + if( v != NULL ) v->Modified( ); + this->Superclass::Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Object:: +SetITK( itk::LightObject* o ) +{ + if( this->m_ITK.GetPointer( ) != o ) + { + this->m_ITK = o; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Object:: +SetVTK( vtkObjectBase* o ) +{ + if( this->m_VTK.GetPointer( ) != o ) + { + this->m_VTK = o; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Object:: +Object( ) + : m_ITK( NULL ), + m_VTK( NULL ), + m_ViewX( float( 0 ) ), + m_ViewY( float( 0 ) ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Object:: +~Object( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Object:: +_UpdateITK( ) const +{ + // WARNING: do nothing since this is supposed to be defined by DataObjects + // with ITK-VTK conversion strategies. +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Object:: +_UpdateVTK( ) const +{ + // WARNING: do nothing since this is supposed to be defined by DataObjects + // with ITK-VTK conversion strategies. +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Object.h b/lib/cpPlugins/Pipeline/Object.h new file mode 100644 index 0000000..c920abb --- /dev/null +++ b/lib/cpPlugins/Pipeline/Object.h @@ -0,0 +1,105 @@ +#ifndef __cpPlugins__Pipeline__Object__h__ +#define __cpPlugins__Pipeline__Object__h__ + +#include + +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + namespace Pipeline + { + /** + */ + class cpPlugins_EXPORT Object + : public itk::Object + { + public: + typedef Object Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( Object, itk::Object ); + + public: + virtual const char* GetClassName( ) const = 0; + virtual const char* GetClassCategory( ) const = 0; + + const float& GetViewX( ) const; + const float& GetViewY( ) const; + void SetViewCoords( float x, float y ); + + virtual void Modified( ) const cpPlugins_OVERRIDE; + + virtual void SetITK( itk::LightObject* o ); + virtual void SetVTK( vtkObjectBase* o ); + + template< class _TType = itk::LightObject > + inline _TType* GetITK( ) + { + if( this->m_ITK.GetPointer( ) == NULL ) + this->_UpdateITK( ); + return( dynamic_cast< _TType* >( this->m_ITK.GetPointer( ) ) ); + } + + template< class _TType = itk::LightObject > + inline const _TType* GetITK( ) const + { + if( this->m_ITK.GetPointer( ) == NULL ) + this->_UpdateITK( ); + return( + dynamic_cast< const _TType* >( this->m_ITK.GetPointer( ) ) + ); + } + + template< class _TType = vtkObjectBase > + inline _TType* GetVTK( ) + { + if( this->m_VTK.GetPointer( ) == NULL ) + this->_UpdateVTK( ); + return( dynamic_cast< _TType* >( this->m_VTK.GetPointer( ) ) ); + } + + template< class _TType = vtkObjectBase > + inline const _TType* GetVTK( ) const + { + if( this->m_VTK.GetPointer( ) == NULL ) + this->_UpdateVTK( ); + return( + dynamic_cast< const _TType* >( this->m_VTK.GetPointer( ) ) + ); + } + + protected: + Object( ); + virtual ~Object( ); + + virtual void _UpdateITK( ) const; + virtual void _UpdateVTK( ) const; + + private: + // Purposely not implemented + Object( const Self& ); + Self& operator=( const Self& ); + + protected: + itk::LightObject::Pointer m_ITK; + vtkSmartPointer< vtkObjectBase > m_VTK; + + float m_ViewX; + float m_ViewY; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Pipeline__Object__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Parameters.cxx b/lib/cpPlugins/Pipeline/Parameters.cxx new file mode 100644 index 0000000..ada5e9c --- /dev/null +++ b/lib/cpPlugins/Pipeline/Parameters.cxx @@ -0,0 +1,742 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Parameters:: +Parameters( ) + : m_ProcessObject( NULL ) +{ + this->Clear( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Parameters:: +~Parameters( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::ProcessObject* cpPlugins::Pipeline::Parameters:: +GetProcessObject( ) +{ + return( this->m_ProcessObject ); +} + +// ------------------------------------------------------------------------- +const +cpPlugins::Pipeline::ProcessObject* cpPlugins::Pipeline::Parameters:: +GetProcessObject( ) const +{ + return( this->m_ProcessObject ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +SetProcessObject( cpPlugins::Pipeline::ProcessObject* po ) +{ + this->m_ProcessObject = po; +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +Modified( ) const +{ + if( this->m_ProcessObject != NULL ) + this->m_ProcessObject->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +Clear( ) +{ + this->m_Parameters.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +GetNames( std::vector< std::string >& container ) const +{ + container.clear( ); + TParameters::const_iterator i = this->m_Parameters.begin( ); + for( ; i != this->m_Parameters.end( ); ++i ) + container.push_back( i->first ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Parameters:: +Type cpPlugins::Pipeline::Parameters:: +GetType( const std::string& name ) const +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + return( i->second.first ); + else + return( Self::NoType ); +} + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_TypeAsString( Y ) \ + if( i->second.first == Self::Y ) \ + return( #Y ) + +std::string cpPlugins::Pipeline::Parameters:: +GetTypeAsString( const std::string& name ) const +{ + auto i = this->m_Parameters.find( name ); + cpPlugins_Pipeline_Parameters_TypeAsString( String ); + else cpPlugins_Pipeline_Parameters_TypeAsString( Bool ); + else cpPlugins_Pipeline_Parameters_TypeAsString( Int ); + else cpPlugins_Pipeline_Parameters_TypeAsString( Uint ); + else cpPlugins_Pipeline_Parameters_TypeAsString( Real ); + else cpPlugins_Pipeline_Parameters_TypeAsString( OpenFileName ); + else cpPlugins_Pipeline_Parameters_TypeAsString( SaveFileName ); + else cpPlugins_Pipeline_Parameters_TypeAsString( PathName ); + else cpPlugins_Pipeline_Parameters_TypeAsString( StringList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( BoolList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( IntList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( UintList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( RealList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( OpenFileNameList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( SaveFileNameList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( PathNameList ); + else cpPlugins_Pipeline_Parameters_TypeAsString( Choices ); + else return( "NoType" ); +} + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_TypeFromString( Y, str ) \ + if( str == std::string( #Y ) ) \ + return( Self::Y ) + +cpPlugins::Pipeline::Parameters:: +Type cpPlugins::Pipeline::Parameters:: +GetTypeFromString( const std::string& t ) +{ + cpPlugins_Pipeline_Parameters_TypeFromString( String, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( Bool, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( Int, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( Uint, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( Real, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( OpenFileName, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( SaveFileName, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( PathName, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( StringList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( BoolList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( IntList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( UintList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( RealList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( OpenFileNameList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( SaveFileNameList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( PathNameList, t ); + else cpPlugins_Pipeline_Parameters_TypeFromString( Choices, t ); + else return( Self::NoType ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::Pipeline::Parameters:: +GetString( const std::string& name, bool force ) const +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == Self::String || force ) + return( i->second.second ); + else + return( "" ); + } + else + return( "" ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +SetString( const std::string& name, const std::string& v, bool force ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == Self::String || force ) + { + if( i->second.second != v ) + { + i->second.second = v; + this->Modified( ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +ConfigureAsChoices( + const std::string& name, const std::vector< std::string >& choices + ) +{ + // It is invalid not to give choices when configuring + if( choices.size( ) == 0 ) + return; + + std::stringstream str_choices; + str_choices << choices[ 0 ]; + for( unsigned int i = 1; i < choices.size( ); ++i ) + str_choices << "#" << choices[ i ]; + str_choices << "@"; + this->m_Parameters[ name ] = + TParameter( Self::Choices, str_choices.str( ) ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +ConfigureAsRealTypesChoices( const std::string& name ) +{ + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->ConfigureAsChoices( name, choices ); + this->SetSelectedChoice( name, "float" ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +ConfigureAsIntTypesChoices( const std::string& name ) +{ + std::vector< std::string > choices; + choices.push_back( "char" ); + choices.push_back( "uchar" ); + choices.push_back( "short" ); + choices.push_back( "ushort" ); + choices.push_back( "int" ); + choices.push_back( "uint" ); + choices.push_back( "long" ); + choices.push_back( "ulong" ); + this->ConfigureAsChoices( name, choices ); + this->SetSelectedChoice( name, "char" ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +ConfigureAsScalarTypesChoices( const std::string& name ) +{ + std::vector< std::string > choices; + choices.push_back( "char" ); + choices.push_back( "uchar" ); + choices.push_back( "short" ); + choices.push_back( "ushort" ); + choices.push_back( "int" ); + choices.push_back( "uint" ); + choices.push_back( "long" ); + choices.push_back( "ulong" ); + choices.push_back( "float" ); + choices.push_back( "double" ); + this->ConfigureAsChoices( name, choices ); + this->SetSelectedChoice( name, "char" ); +} + +// ------------------------------------------------------------------------- +std::vector< std::string > cpPlugins::Pipeline::Parameters:: +GetChoices( const std::string& name ) const +{ + std::vector< std::string > choices; + + TParameters::const_iterator i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == Self::Choices ) + { + std::istringstream str_choices( i->second.second ); + std::string real_choices; + std::getline( str_choices, real_choices, '@' ); + std::istringstream str( real_choices ); + std::string token; + while( std::getline( str, token, '#' ) ) + choices.push_back( token ); + + } // fi + + } // fi + return( choices ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::Pipeline::Parameters:: +GetSelectedChoice( const std::string& name ) const +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == Self::Choices ) + { + std::istringstream str_choices( i->second.second ); + std::string real_choice; + std::getline( str_choices, real_choice, '@' ); + std::getline( str_choices, real_choice, '@' ); + return( real_choice ); + } + else + return( "" ); + } + else + return( "" ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::Parameters:: +SetSelectedChoice( const std::string& name, const std::string& choice ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == Self::Choices ) + { + std::istringstream str_choices( i->second.second ); + std::string choices; + std::getline( str_choices, choices, '@' ); + if( choices.find( choice ) != std::string::npos ) + { + std::stringstream new_choices; + new_choices << choices << "@" << choice; + i->second.second = new_choices.str( ); + this->Modified( ); + return( true ); + } + else + return( false ); + } + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::Pipeline::Parameters:: +GetAcceptedFileExtensions( const std::string& name ) const +{ + auto i = this->m_AcceptedFileExtensions.find( name ); + if( i != this->m_AcceptedFileExtensions.end( ) ) + return( i->second ); + else + return( "" ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +SetAcceptedFileExtensions( + const std::string& name, const std::string& extensions + ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + bool is_valid = ( i->second.first == Self::OpenFileName ); + is_valid |= ( i->second.first == Self::SaveFileName ); + is_valid |= ( i->second.first == Self::OpenFileNameList ); + is_valid |= ( i->second.first == Self::SaveFileNameList ); + if( is_valid ) + this->m_AcceptedFileExtensions[ name ] = extensions; + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::Parameters:: +ToXML( + tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* parent_elem + ) const +{ + if( parent_elem == NULL ) + return( false ); + + auto pIt = this->m_Parameters.begin( ); + for( ; pIt != this->m_Parameters.end( ); ++pIt ) + { + tinyxml2::XMLElement* p = doc->NewElement( "Parameter" ); + p->SetAttribute( "Name", pIt->first.c_str( ) ); + p->SetAttribute( "Value", pIt->second.second.c_str( ) ); + p->SetAttribute( "Type", this->GetTypeAsString( pIt->first ).c_str( ) ); + parent_elem->InsertEndChild( p ); + + } // rof + return( true ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::Parameters:: +FromXML( const tinyxml2::XMLElement* filter_elem ) +{ + const tinyxml2::XMLElement* param = + filter_elem->FirstChildElement( "Parameter" ); + bool ret = false; + while( param != NULL ) + { + const char* param_name = param->Attribute( "Name" ); + const char* param_type = param->Attribute( "Type" ); + if( param_name != NULL && param_type != NULL ) + { + TParameter value; + value.second = param->Attribute( "Value" ); + value.first = Self::GetTypeFromString( param_type ); + this->m_Parameters[ param_name ] = value; + + } // fi + param = param->NextSiblingElement( "Parameter" ); + ret = true; + + } // elihw + this->Modified( ); + return( ret ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Parameters:: +TParameters& cpPlugins::Pipeline::Parameters:: +GetRawParameters( ) +{ + return( this->m_Parameters ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Pipeline::Parameters:: +TParameters& cpPlugins::Pipeline::Parameters:: +GetRawParameters( ) const +{ + return( this->m_Parameters ); +} + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_Configure_Code( Y ) \ + void cpPlugins::Pipeline::Parameters:: \ + ConfigureAs##Y( const std::string& name, const T##Y& init ) \ + { \ + this->_Configure< Y >( name ); \ + this->Set##Y( name, init ); \ + } \ + bool cpPlugins::Pipeline::Parameters:: \ + Has##Y( const std::string& name ) const \ + { return( this->_Has< Y >( name ) ); } + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_ConfigureList_Code( Y ) \ + void cpPlugins::Pipeline::Parameters:: \ + ConfigureAs##Y##List( const std::string& name ) \ + { this->_Configure< Y##List >( name ); } \ + bool cpPlugins::Pipeline::Parameters:: \ + Has##Y##List( const std::string& name ) const \ + { return( this->_Has< Y##List >( name ) ); } + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_GetSet_Code( Y ) \ + cpPlugins::Pipeline::Parameters::T##Y \ + cpPlugins::Pipeline::Parameters:: \ + Get##Y( const std::string& name ) const \ + { return( this->_Get< T##Y, Y >( name ) ); } \ + void cpPlugins::Pipeline::Parameters::Set##Y( \ + const std::string& name, const T##Y& v \ + ) \ + { this->_Set< T##Y, Y >( name, v ); } + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_GetSetList_Code( Y ) \ + std::vector< cpPlugins::Pipeline::Parameters::T##Y > \ + cpPlugins::Pipeline::Parameters:: \ + Get##Y##List( const std::string& name ) const \ + { return( this->_GetList< T##Y, Y##List >( name ) ); } \ + void cpPlugins::Pipeline::Parameters::AddTo##Y##List( \ + const std::string& name, \ + const cpPlugins::Pipeline::Parameters::T##Y& v \ + ) \ + { this->_AddToList< T##Y, Y##List >( name, v ); } \ + void cpPlugins::Pipeline::Parameters:: \ + Clear##Y##List( const std::string& name ) \ + { this->_ClearList< Y##List >( name ); } + +// ------------------------------------------------------------------------- +cpPlugins_Pipeline_Parameters_Configure_Code( String ); +cpPlugins_Pipeline_Parameters_Configure_Code( Bool ); +cpPlugins_Pipeline_Parameters_Configure_Code( Int ); +cpPlugins_Pipeline_Parameters_Configure_Code( Uint ); +cpPlugins_Pipeline_Parameters_Configure_Code( Real ); +cpPlugins_Pipeline_Parameters_Configure_Code( OpenFileName ); +cpPlugins_Pipeline_Parameters_Configure_Code( SaveFileName ); +cpPlugins_Pipeline_Parameters_Configure_Code( PathName ); + +cpPlugins_Pipeline_Parameters_ConfigureList_Code( String ); +cpPlugins_Pipeline_Parameters_ConfigureList_Code( Bool ); +cpPlugins_Pipeline_Parameters_ConfigureList_Code( Int ); +cpPlugins_Pipeline_Parameters_ConfigureList_Code( Uint ); +cpPlugins_Pipeline_Parameters_ConfigureList_Code( Real ); +cpPlugins_Pipeline_Parameters_ConfigureList_Code( OpenFileName ); +cpPlugins_Pipeline_Parameters_ConfigureList_Code( SaveFileName ); +cpPlugins_Pipeline_Parameters_ConfigureList_Code( PathName ); + +cpPlugins_Pipeline_Parameters_GetSet_Code( Bool ); +cpPlugins_Pipeline_Parameters_GetSet_Code( Int ); +cpPlugins_Pipeline_Parameters_GetSet_Code( Uint ); +cpPlugins_Pipeline_Parameters_GetSet_Code( Real ); +cpPlugins_Pipeline_Parameters_GetSet_Code( OpenFileName ); +cpPlugins_Pipeline_Parameters_GetSet_Code( SaveFileName ); +cpPlugins_Pipeline_Parameters_GetSet_Code( PathName ); + +cpPlugins_Pipeline_Parameters_GetSetList_Code( String ); +cpPlugins_Pipeline_Parameters_GetSetList_Code( Bool ); +cpPlugins_Pipeline_Parameters_GetSetList_Code( Int ); +cpPlugins_Pipeline_Parameters_GetSetList_Code( Uint ); +cpPlugins_Pipeline_Parameters_GetSetList_Code( Real ); +cpPlugins_Pipeline_Parameters_GetSetList_Code( PathName ); + +// ------------------------------------------------------------------------- +std::vector< cpPlugins::Pipeline::Parameters::TOpenFileName > +cpPlugins::Pipeline::Parameters:: +GetOpenFileNameList( const std::string& name ) const +{ + return( this->_GetList< TOpenFileName, OpenFileNameList >( name ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +AddToOpenFileNameList( + const std::string& name, + const cpPlugins::Pipeline::Parameters::TOpenFileName& v + ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == OpenFileNameList ) + { + auto pos = v.find_last_of( "/\\" ); + if( i->second.second == "" ) + i->second.second = v.substr( 0, pos ); + i->second.second += std::string( "#" ); + i->second.second += v.substr( pos + 1 ); + this->Modified( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +ClearOpenFileNameList( const std::string& name ) +{ + this->_ClearList< OpenFileNameList >( name ); +} + +// ------------------------------------------------------------------------- +std::vector< cpPlugins::Pipeline::Parameters::TSaveFileName > +cpPlugins::Pipeline::Parameters:: +GetSaveFileNameList( const std::string& name ) const +{ + return( this->_GetList< TSaveFileName, SaveFileNameList >( name ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +AddToSaveFileNameList( + const std::string& name, + const cpPlugins::Pipeline::Parameters::TSaveFileName& v + ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == SaveFileNameList ) + { + auto pos = v.find_last_of( "/\\" ); + if( i->second.second == "" ) + i->second.second = v.substr( 0, pos ); + i->second.second += std::string( "#" ); + i->second.second += v.substr( pos + 1 ); + this->Modified( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Parameters:: +ClearSaveFileNameList( const std::string& name ) +{ + this->_ClearList< SaveFileNameList >( name ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _Enum > +void cpPlugins::Pipeline::Parameters:: +_Configure( const std::string& name ) +{ + this->m_Parameters[ name ] = TParameter( ( Self::Type )( _Enum ), "" ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _Enum > +bool cpPlugins::Pipeline::Parameters:: +_Has( const std::string& name ) const +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + return( i->second.first == ( Self::Type )( _Enum ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _Type, unsigned int _Enum > +_Type cpPlugins::Pipeline::Parameters:: +_Get( const std::string& name ) const +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == ( Self::Type )( _Enum ) ) + { + if( typeid( _Type ) != typeid( std::string ) ) + { + std::istringstream tok_str( i->second.second ); + _Type v; + tok_str >> v; + return( v ); + } + else + { + const _Type* ptr = + reinterpret_cast< const _Type* >( &( i->second.second ) ); + return( *ptr ); + + } // fi + + } // fi + + } // fi + return( _Type( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _Type, unsigned int _Enum > +void cpPlugins::Pipeline::Parameters:: +_Set( const std::string& name, const _Type& v ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == ( Self::Type )( _Enum ) ) + { + if( typeid( _Type ) != typeid( std::string ) ) + { + std::stringstream str; + str << v; + if( i->second.second != str.str( ) ) + { + i->second.second = str.str( ); + this->Modified( ); + + } // fi + } + else + { + const std::string* str = reinterpret_cast< const std::string* >( &v ); + if( i->second.second != *str ) + { + i->second.second = *str; + this->Modified( ); + + } // fi + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _Type, unsigned int _Enum > +std::vector< _Type > cpPlugins::Pipeline::Parameters:: +_GetList( const std::string& name ) const +{ + std::vector< _Type > lst; + std::vector< std::string >* slst = + reinterpret_cast< std::vector< std::string >* >( &lst ); + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == ( Self::Type )( _Enum ) ) + { + std::vector< std::string > tokens = + cpPlugins::OS::String::Tokenize( i->second.second, "#" ); + for( auto t = tokens.begin( ); t != tokens.end( ); ++t ) + { + if( typeid( _Type ) != typeid( std::string ) ) + { + std::istringstream tok_str( *t ); + _Type v; + tok_str >> v; + lst.push_back( v ); + } + else + slst->push_back( *t ); + + } // rof + + } // fi + + } // fi + return( lst ); +} + +// ------------------------------------------------------------------------- +template< class _Type, unsigned int _Enum > +void cpPlugins::Pipeline::Parameters:: +_AddToList( const std::string& name, const _Type& v ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == ( Self::Type )( _Enum ) ) + { + std::stringstream str; + if( i->second.second != "" ) + str << i->second.second << "#"; + str << v; + i->second.second = str.str( ); + this->Modified( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _Enum > +void cpPlugins::Pipeline::Parameters:: +_ClearList( const std::string& name ) +{ + auto i = this->m_Parameters.find( name ); + if( i != this->m_Parameters.end( ) ) + { + if( i->second.first == ( Self::Type )( _Enum ) ) + { + if( i->second.second != "" ) + { + i->second.second = ""; + this->Modified( ); + + } // fi + + } // fi + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Parameters.h b/lib/cpPlugins/Pipeline/Parameters.h new file mode 100644 index 0000000..4dbd871 --- /dev/null +++ b/lib/cpPlugins/Pipeline/Parameters.h @@ -0,0 +1,223 @@ +#ifndef __cpPlugins__Pipeline__Parameters__h__ +#define __cpPlugins__Pipeline__Parameters__h__ + +#include + +#include +#include +#include +#include +#include +#include + +// Some forward declarations +namespace tinyxml2 +{ + class XMLElement; + class XMLDocument; +} + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_Configure( Y ) \ + void ConfigureAs##Y( const std::string& name, const T##Y& init ); \ + bool Has##Y( const std::string& name ) const + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_ConfigureList( Y ) \ + void ConfigureAs##Y##List( const std::string& name ); \ + bool Has##Y##List( const std::string& name ) const + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_GetSet( Y ) \ + T##Y Get##Y( const std::string& name ) const; \ + void Set##Y( const std::string& name, const T##Y& v ) + +// ------------------------------------------------------------------------- +#define cpPlugins_Pipeline_Parameters_GetSetList( Y ) \ + std::vector< T##Y > Get##Y##List( const std::string& name ) const; \ + void AddTo##Y##List( const std::string& name, const T##Y& v ); \ + void Clear##Y##List( const std::string& name ) + +// ------------------------------------------------------------------------- +namespace cpPlugins +{ + namespace QT { class ParametersDialog; } + + namespace Pipeline + { + class ProcessObject; + + /** + */ + class cpPlugins_EXPORT Parameters + { + // Frienship with forward declaration to improve Qt dialog execution + friend class cpPlugins::QT::ParametersDialog; + friend std::ostream& operator<<( std::ostream& o, const Parameters& p ) + { + for( + auto i = p.m_Parameters.begin( ); + i != p.m_Parameters.end( ); + ++i + ) + o << i->first << ": (" + << i->second.first << " | " + << i->second.second << ")" + << std::endl; + return( o ); + } + + public: + typedef Parameters Self; + + enum Type + { + String , Bool , Int , + Uint , Real , OpenFileName , + SaveFileName , PathName , StringList , + BoolList , IntList , UintList , + RealList , OpenFileNameList , SaveFileNameList , + PathNameList , Choices , NoType + }; + + typedef bool TBool; + typedef long TInt; + typedef unsigned long TUint; + typedef double TReal; + typedef std::string TString; + typedef std::string TOpenFileName; + typedef std::string TSaveFileName; + typedef std::string TPathName; + + typedef std::pair< Self::Type, std::string > TParameter; + typedef std::map< std::string, TParameter > TParameters; + + public: + cpPlugins_Pipeline_Parameters_Configure( String ); + cpPlugins_Pipeline_Parameters_Configure( Bool ); + cpPlugins_Pipeline_Parameters_Configure( Int ); + cpPlugins_Pipeline_Parameters_Configure( Uint ); + cpPlugins_Pipeline_Parameters_Configure( Real ); + cpPlugins_Pipeline_Parameters_Configure( OpenFileName ); + cpPlugins_Pipeline_Parameters_Configure( SaveFileName ); + cpPlugins_Pipeline_Parameters_Configure( PathName ); + + cpPlugins_Pipeline_Parameters_ConfigureList( String ); + cpPlugins_Pipeline_Parameters_ConfigureList( Bool ); + cpPlugins_Pipeline_Parameters_ConfigureList( Int ); + cpPlugins_Pipeline_Parameters_ConfigureList( Uint ); + cpPlugins_Pipeline_Parameters_ConfigureList( Real ); + cpPlugins_Pipeline_Parameters_ConfigureList( OpenFileName ); + cpPlugins_Pipeline_Parameters_ConfigureList( SaveFileName ); + cpPlugins_Pipeline_Parameters_ConfigureList( PathName ); + + cpPlugins_Pipeline_Parameters_GetSet( Bool ); + cpPlugins_Pipeline_Parameters_GetSet( Int ); + cpPlugins_Pipeline_Parameters_GetSet( Uint ); + cpPlugins_Pipeline_Parameters_GetSet( Real ); + cpPlugins_Pipeline_Parameters_GetSet( OpenFileName ); + cpPlugins_Pipeline_Parameters_GetSet( SaveFileName ); + cpPlugins_Pipeline_Parameters_GetSet( PathName ); + + cpPlugins_Pipeline_Parameters_GetSetList( String ); + cpPlugins_Pipeline_Parameters_GetSetList( Bool ); + cpPlugins_Pipeline_Parameters_GetSetList( Int ); + cpPlugins_Pipeline_Parameters_GetSetList( Uint ); + cpPlugins_Pipeline_Parameters_GetSetList( Real ); + cpPlugins_Pipeline_Parameters_GetSetList( OpenFileName ); + cpPlugins_Pipeline_Parameters_GetSetList( SaveFileName ); + cpPlugins_Pipeline_Parameters_GetSetList( PathName ); + + public: + Parameters( ); + virtual ~Parameters( ); + + ProcessObject* GetProcessObject( ); + const ProcessObject* GetProcessObject( ) const; + void SetProcessObject( ProcessObject* po ); + virtual void Modified( ) const; + + // Parameters container configuration + void Clear( ); + + // Get methods + void GetNames( std::vector< std::string >& container ) const; + Type GetType( const std::string& name ) const; + std::string GetTypeAsString( const std::string& name ) const; + static Type GetTypeFromString( const std::string& t ); + + // Base string methods + std::string GetString( + const std::string& name, bool force = true + ) const; + void SetString( + const std::string& name, const std::string& v, bool force = true + ); + + void ConfigureAsChoices( + const std::string& name, const std::vector< std::string >& choices + ); + void ConfigureAsRealTypesChoices( const std::string& name ); + void ConfigureAsIntTypesChoices( const std::string& name ); + void ConfigureAsScalarTypesChoices( const std::string& name ); + std::vector< std::string > GetChoices( const std::string& name ) const; + std::string GetSelectedChoice( const std::string& name ) const; + bool SetSelectedChoice( + const std::string& name, const std::string& choice + ); + + std::string GetAcceptedFileExtensions( const std::string& name ) const; + void SetAcceptedFileExtensions( + const std::string& name, const std::string& extensions + ); + + // XML "streaming" + bool ToXML( + tinyxml2::XMLDocument* doc, + tinyxml2::XMLElement* parent_elem + ) const; + bool FromXML( const tinyxml2::XMLElement* filter_elem ); + + protected: + TParameters& GetRawParameters( ); + const TParameters& GetRawParameters( ) const; + + template< unsigned int _Enum > + inline void _Configure( const std::string& name ); + + template< unsigned int _Enum > + inline bool _Has( const std::string& name ) const; + + template< class _Type, unsigned int _Enum > + inline _Type _Get( const std::string& name ) const; + + template< class _Type, unsigned int _Enum > + inline void _Set( const std::string& name, const _Type& v ); + + template< class _Type, unsigned int _Enum > + inline std::vector< _Type > _GetList( const std::string& name ) const; + + template< class _Type, unsigned int _Enum > + inline void _AddToList( const std::string& name, const _Type& v ); + + template< unsigned int _Enum > + inline void _ClearList( const std::string& name ); + + private: + // Purposely not implemented + Parameters( const Self& other ); + Self& operator=( const Self& other ); + + protected: + ProcessObject* m_ProcessObject; + TParameters m_Parameters; + std::map< std::string, std::string > m_AcceptedFileExtensions; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Pipeline__Parameters__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Port.cxx b/lib/cpPlugins/Pipeline/Port.cxx new file mode 100644 index 0000000..4c980c0 --- /dev/null +++ b/lib/cpPlugins/Pipeline/Port.cxx @@ -0,0 +1,231 @@ +#include + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Port:: +Port( bool required ) + : m_Required( required ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Port:: +~Port( ) +{ +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::Port:: +IsRequired( ) const +{ + return( this->m_Required ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Port:: +Clear( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::SingleDataPort:: +SingleDataPort( bool required ) + : Superclass( required ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::SingleDataPort:: +~SingleDataPort( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::SingleDataPort:: +Add( cpPlugins::Pipeline::DataObject* o ) +{ + if( this->m_Sample.IsNull( ) ) + throw std::logic_error( + "cpPlugins::SingleDataPort: Port not yet configured" + ); + if( o != NULL ) + { + if( this->m_Sample->IsCompatible( o ) ) + this->m_Data = o; + else + throw std::logic_error( + "cpPlugins::SingleDataPort: incompatible types \"" + + std::string( typeid( *o ).name( ) ) + std::string( "\" and \"" ) + + std::string( typeid( *( this->m_Sample.GetPointer( ) ) ).name( ) ) + + std::string( "\"" ) + ); + } + else + this->m_Data = NULL; +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::DataObject* cpPlugins::Pipeline::SingleDataPort:: +Get( unsigned int i ) +{ + return( this->m_Data.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Pipeline::DataObject* cpPlugins::Pipeline::SingleDataPort:: +Get( unsigned int i ) const +{ + return( this->m_Data.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpPlugins::Pipeline::SingleDataPort:: +Size( ) const +{ + return( 1 ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::SingleDataPort:: +IsValid( ) const +{ + return( this->m_Data.IsNotNull( ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::SingleDataPort:: +Clear( ) +{ + this->m_Data = NULL; +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::OutputPort:: +OutputPort( bool required ) + : Superclass( required ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::OutputPort:: +~OutputPort( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::OutputPort:: +Set( DataObject* o ) +{ + this->m_Sample = o; + this->m_Data = o; +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::InputPort:: +InputPort( bool required ) + : Superclass( required ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::InputPort:: +~InputPort( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::MultipleInputsPort:: +MultipleInputsPort( bool required ) + : Superclass( required ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::MultipleInputsPort:: +~MultipleInputsPort( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::MultipleInputsPort:: +Add( cpPlugins::Pipeline::DataObject* o ) +{ + if( this->m_Sample.IsNull( ) ) + throw std::logic_error( + "cpPlugins::SingleDataPort: Port not yet configured" + ); + if( o != NULL ) + { + if( this->m_Sample->IsCompatible( o ) ) + { + this->m_Data.push_back( o ); + } + else + throw std::logic_error( + "cpPlugins::SingleDataPort: incompatible types \"" + + std::string( typeid( *o ).name( ) ) + std::string( "\" and \"" ) + + std::string( typeid( *( this->m_Sample.GetPointer( ) ) ).name( ) ) + + std::string( "\"" ) + ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::DataObject* +cpPlugins::Pipeline::MultipleInputsPort:: +Get( unsigned int i ) +{ + if( i < this->m_Data.size( ) ) + return( this->m_Data[ i ].GetPointer( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Pipeline::DataObject* +cpPlugins::Pipeline::MultipleInputsPort:: +Get( unsigned int i ) const +{ + if( i < this->m_Data.size( ) ) + return( this->m_Data[ i ].GetPointer( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +unsigned int cpPlugins::Pipeline::MultipleInputsPort:: +Size( ) const +{ + return( this->m_Data.size( ) ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::MultipleInputsPort:: +IsValid( ) const +{ + if( this->m_Data.size( ) > 0 ) + return( this->m_Data[ 0 ].IsNotNull( ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::MultipleInputsPort:: +Clear( ) +{ + this->m_Data.clear( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::MultipleInputsPort:: +Delete( unsigned int id ) +{ + if( id < this->m_Data.size( ) ) + { + this->m_Data[ id ] = NULL; + this->m_Data.erase( this->m_Data.begin( ) + id ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Port.h b/lib/cpPlugins/Pipeline/Port.h new file mode 100644 index 0000000..db912ff --- /dev/null +++ b/lib/cpPlugins/Pipeline/Port.h @@ -0,0 +1,127 @@ +#ifndef __cpPlugins__Pipeline__Port__h__ +#define __cpPlugins__Pipeline__Port__h__ + +#include +#include + +namespace cpPlugins +{ + namespace Pipeline + { + /** + */ + class cpPlugins_EXPORT Port + { + public: + typedef Port Self; + + public: + Port( bool required = true ); + virtual ~Port( ); + + virtual void Add( DataObject* o ) = 0; + virtual DataObject* Get( unsigned int i = 0 ) = 0; + virtual const DataObject* Get( unsigned int i = 0 ) const = 0; + virtual unsigned int Size( ) const = 0; + virtual bool IsValid( ) const = 0; + + virtual bool IsRequired( ) const; + virtual void Clear( ); + + template< class _TType > + inline void Configure( ) { this->m_Sample = _TType::New( ); } + + protected: + bool m_Required; + DataObject::Pointer m_Sample; + }; + + /** + */ + class cpPlugins_EXPORT SingleDataPort + : public Port + { + public: + typedef SingleDataPort Self; + typedef Port Superclass; + + public: + SingleDataPort( bool required = true ); + virtual ~SingleDataPort( ); + + virtual void Add( DataObject* o ) cpPlugins_OVERRIDE; + virtual DataObject* Get( unsigned int i = 0 ) cpPlugins_OVERRIDE; + virtual const DataObject* Get( unsigned int i = 0 ) const cpPlugins_OVERRIDE; + virtual unsigned int Size( ) const cpPlugins_OVERRIDE; + virtual bool IsValid( ) const cpPlugins_OVERRIDE; + virtual void Clear( ) cpPlugins_OVERRIDE; + + protected: + DataObject::Pointer m_Data; + }; + + /** + */ + class cpPlugins_EXPORT OutputPort + : public SingleDataPort + { + public: + typedef OutputPort Self; + typedef SingleDataPort Superclass; + typedef Port BaseClass; + + public: + OutputPort( bool required = true ); + virtual ~OutputPort( ); + + void Set( DataObject* o ); + }; + + /** + */ + class cpPlugins_EXPORT InputPort + : public SingleDataPort + { + public: + typedef InputPort Self; + typedef SingleDataPort Superclass; + typedef Port BaseClass; + + public: + InputPort( bool required = true ); + virtual ~InputPort( ); + }; + + /** + */ + class cpPlugins_EXPORT MultipleInputsPort + : public Port + { + public: + typedef MultipleInputsPort Self; + typedef Port Superclass; + + public: + MultipleInputsPort( bool required = true ); + virtual ~MultipleInputsPort( ); + + virtual void Add( DataObject* o ) cpPlugins_OVERRIDE; + virtual DataObject* Get( unsigned int i = 0 ) cpPlugins_OVERRIDE; + virtual const DataObject* Get( unsigned int i = 0 ) const cpPlugins_OVERRIDE; + virtual unsigned int Size( ) const cpPlugins_OVERRIDE; + virtual bool IsValid( ) const cpPlugins_OVERRIDE; + virtual void Clear( ) cpPlugins_OVERRIDE; + + void Delete( unsigned int id ); + + protected: + std::vector< DataObject::Pointer > m_Data; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Pipeline__Port__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/ProcessObject.cxx b/lib/cpPlugins/Pipeline/ProcessObject.cxx new file mode 100644 index 0000000..c8edba2 --- /dev/null +++ b/lib/cpPlugins/Pipeline/ProcessObject.cxx @@ -0,0 +1,377 @@ +#include +#include +#include +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +PrintExecutionOn( ) +{ + this->SetPrintExecution( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +PrintExecutionOff( ) +{ + this->SetPrintExecution( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::ProcessObject:: +GetPrintExecution( ) const +{ + return( this->m_PrintExecution ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::ProcessObject:: +SetPrintExecution( bool v ) +{ + this->m_PrintExecution = v; +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +SetPrintExecutionStream( std::ofstream* s ) +{ + this->m_PrintExecutionStream = s; +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Parameters* +cpPlugins::Pipeline::ProcessObject:: +GetParameters( ) +{ + return( &( this->m_Parameters ) ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Pipeline::Parameters* +cpPlugins::Pipeline::ProcessObject:: +GetParameters( ) const +{ + return( &( this->m_Parameters ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +SetITK( itk::LightObject* o ) +{ + // Polymorphism: do nothing -> this is a filter!!! +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +SetVTK( vtkObjectBase* o ) +{ + // Polymorphism: do nothing -> this is a filter!!! +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::Pipeline::ProcessObject:: +GetInputsNames( ) const +{ + std::set< std::string > names; + for( auto i = this->m_Inputs.begin( ); i != this->m_Inputs.end( ); ++i ) + names.insert( i->first ); + return( names ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::Pipeline::ProcessObject:: +GetOutputsNames( ) const +{ + std::set< std::string > names; + for( auto i = this->m_Outputs.begin( ); i != this->m_Outputs.end( ); ++i ) + names.insert( i->first ); + return( names ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::ProcessObject:: +HasInput( const std::string& n ) const +{ + auto i = this->m_Inputs.find( n ); + return( i != this->m_Inputs.end( ) ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::ProcessObject:: +HasOutput( const std::string& n ) const +{ + auto i = this->m_Outputs.find( n ); + return( i != this->m_Outputs.end( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpPlugins::Pipeline::ProcessObject:: +GetNumberOfInputs( ) const +{ + return( this->m_Inputs.size( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpPlugins::Pipeline::ProcessObject:: +GetNumberOfOutputs( ) const +{ + return( this->m_Outputs.size( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpPlugins::Pipeline::ProcessObject:: +GetInputSize( const std::string& n ) const +{ + auto it = this->m_Inputs.find( n ); + if( it != this->m_Inputs.end( ) ) + return( it->second->Size( ) ); + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::ProcessObject:: +IsInputMultiple( const std::string& n ) const +{ + auto i = this->m_Inputs.find( n ); + if( i != this->m_Inputs.end( ) ) + return( dynamic_cast< MultipleInputsPort* >( i->second ) != NULL ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +AddInput( const std::string& n, cpPlugins::Pipeline::DataObject* o ) +{ + auto it = this->m_Inputs.find( n ); + if( it != this->m_Inputs.end( ) ) + it->second->Add( o ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +SetInput( const std::string& n, cpPlugins::Pipeline::DataObject* o ) +{ + this->AddInput( n, o ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +DisconnectInput( const std::string& n, unsigned int id ) +{ + auto inIt = this->m_Inputs.find( n ); + if( inIt != this->m_Inputs.end( ) ) + { + auto multi = dynamic_cast< MultipleInputsPort* >( inIt->second ); + auto single = dynamic_cast< InputPort* >( inIt->second ); + if( multi != NULL ) + multi->Delete( id ); + else if( single != NULL ) + single->Add( NULL ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +DisconnectInputs( ) +{ + for( auto i = this->m_Inputs.begin( ); i != this->m_Inputs.end( ); ++i ) + i->second->Clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +DisconnectOutputs( ) +{ + for( auto i = this->m_Outputs.begin( ); i != this->m_Outputs.end( ); ++i ) + if( i->second->IsValid( ) ) + i->second->Get( )->DisconnectFromPipeline( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +Disconnect( ) +{ + this->DisconnectInputs( ); + this->DisconnectOutputs( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +Modified( ) const +{ + this->Superclass::Modified( ); + + cpPlugins::Pipeline::Events::Modified evt; + evt.Time = this->m_LastExecutionTime; + evt.Span = this->m_LastExecutionSpan; + this->InvokeEvent( evt ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +Update( ) +{ + // Force upstream updates + bool update = ( this->m_LastExecutionTime < this->GetMTime( ) ); + try + { + for( auto input : this->m_Inputs ) + { + for( unsigned int i = 0; i < input.second->Size( ); ++i ) + { + auto obj = input.second->Get( i ); + if( obj != NULL ) + { + auto src = obj->GetSource( ); + if( src != NULL ) + { + src->Update( ); + update |= ( this->m_LastExecutionTime < src->GetMTime( ) ); + + } // fi + } + else + { + if( input.second->IsRequired( ) ) + this->_Error( + std::string( "Required input \"" ) + input.first + + std::string( "\" in filter \"" ) + + this->m_Name + + std::string( "\" is not valid." ) + ); + + } // fi + + } // rof + + } // rof + } + catch( std::exception& err ) + { + this->_Error( err.what( ) ); + + } // yrt + + if( update || this->m_ExplicitExecution ) + { + // Show a message, if needed... + if( this->m_PrintExecution && this->m_PrintExecutionStream != NULL ) + { + *( this->m_PrintExecutionStream ) + << "cpPlugins: Updating \"" + << this->GetName( ) << " (" + << this->GetClassCategory( ) << ":" << this->GetClassName( ) + << ")\"... "; + this->m_PrintExecutionStream->flush( ); + + } // fi + + // Execute filter's algorithm and keep information about time + try + { + auto t_start = cpPlugins_CHRONO; + this->_GenerateData( ); + auto t_end = cpPlugins_CHRONO; + this->Modified( ); + this->m_LastExecutionSpan = long( t_end - t_start ); + this->m_LastExecutionTime = this->GetMTime( ); + + // End the message, if needed... + if( this->m_PrintExecution && this->m_PrintExecutionStream != NULL ) + { + *( this->m_PrintExecutionStream ) + << "done in " + << double( this->m_LastExecutionSpan ) / double( 1000 ) + << " s." << std::endl; + + } // fi + } + catch( std::exception& err ) + { + this->_Error( err.what( ) ); + + } // yrt + + } // fi +} + +// ------------------------------------------------------------------------- +QDialog* cpPlugins::Pipeline::ProcessObject:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::ParametersDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::ParametersDialog( ); + dlg->setProcessObject( this ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +AddInteractor( vtkRenderWindowInteractor* i ) +{ +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::ProcessObject:: +IsInteractive( ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::ProcessObject:: +ProcessObject( ) + : Superclass( ), + m_Name( "" ), + m_PluginName( "" ), + m_ExplicitExecution( false ), + m_LastExecutionTime( 0 ), + m_LastExecutionSpan( -1 ), + m_PrintExecution( false ), + m_PrintExecutionStream( &( std::cout ) ) +{ + this->m_Parameters.SetProcessObject( this ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::ProcessObject:: +~ProcessObject( ) +{ + for( auto i = this->m_Inputs.begin( ); i != this->m_Inputs.end( ); ++i ) + delete i->second; + for( auto o = this->m_Outputs.begin( ); o != this->m_Outputs.end( ); ++o ) + delete o->second; + + this->m_Inputs.clear( ); + this->m_Outputs.clear( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::ProcessObject:: +_Error( const std::string& error ) +{ + if( error != "" ) + itkExceptionMacro( + "Error: \"" << this->m_Name << "\": " << error + ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/ProcessObject.h b/lib/cpPlugins/Pipeline/ProcessObject.h new file mode 100644 index 0000000..77b4a3d --- /dev/null +++ b/lib/cpPlugins/Pipeline/ProcessObject.h @@ -0,0 +1,168 @@ +#ifndef __cpPlugins__Pipeline__ProcessObject__h__ +#define __cpPlugins__Pipeline__ProcessObject__h__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +class QDialog; +class vtkRenderWindowInteractor; + +// ------------------------------------------------------------------------- +namespace cpPlugins +{ + namespace Pipeline + { + /** + */ + class cpPlugins_EXPORT ProcessObject + : public Object + { + public: + typedef ProcessObject Self; + typedef Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( ProcessObject, Object ); + cpPlugins_Id_Macro( ProcessObject, Object ); + + itkBooleanMacro( ExplicitExecution ); + + itkGetStringMacro( Name ); + itkGetStringMacro( PluginName ); + itkGetConstMacro( ExplicitExecution, bool ); + itkGetConstMacro( LastExecutionSpan, long ); + + itkSetStringMacro( Name ); + itkSetStringMacro( PluginName ); + itkSetMacro( ExplicitExecution, bool ); + + public: + void PrintExecutionOn( ); + void PrintExecutionOff( ); + bool GetPrintExecution( ) const; + bool SetPrintExecution( bool v ); + void SetPrintExecutionStream( std::ofstream* s ); + + Parameters* GetParameters( ); + const Parameters* GetParameters( ) const; + + virtual void SetITK( itk::LightObject* o ); + virtual void SetVTK( vtkObjectBase* o ); + + // "Getters" + std::set< std::string > GetInputsNames( ) const; + std::set< std::string > GetOutputsNames( ) const; + bool HasInput( const std::string& n ) const; + bool HasOutput( const std::string& n ) const; + + unsigned int GetNumberOfInputs( ) const; + unsigned int GetNumberOfOutputs( ) const; + unsigned int GetInputSize( const std::string& n ) const; + bool IsInputMultiple( const std::string& n ) const; + + template< class _TType = DataObject > + inline _TType* GetInput( const std::string& n, unsigned int i = 0 ); + + template< class _TType = DataObject > + inline const _TType* GetInput( + const std::string& n, unsigned int i = 0 + ) const; + + template< class _TType = itk::LightObject > + inline _TType* GetInputData( const std::string& n, unsigned int i = 0 ); + + template< class _TType = itk::LightObject > + inline const _TType* GetInputData( + const std::string& n, unsigned int i = 0 + ) const; + + template< class _TType = DataObject > + inline _TType* GetOutput( const std::string& n ); + + template< class _TType = DataObject > + inline const _TType* GetOutput( const std::string& n ) const; + + template< class _TType = itk::LightObject > + inline _TType* GetOutputData( const std::string& n ); + + template< class _TType = itk::LightObject > + inline const _TType* GetOutputData( const std::string& n ) const; + + // "Setters" + virtual void AddInput( const std::string& n, DataObject* o ); + virtual void SetInput( const std::string& n, DataObject* o ); + + // Other interesting methods + void DisconnectInput( const std::string& n, unsigned int id ); + void DisconnectInputs( ); + void DisconnectOutputs( ); + void Disconnect( ); + + // Pipeline execution + virtual void Modified( ) const cpPlugins_OVERRIDE; + virtual void Update( ); + + // Qt dialog creation + virtual QDialog* CreateQDialog( ); + virtual void AddInteractor( vtkRenderWindowInteractor* i ); + virtual bool IsInteractive( ); + + protected: + ProcessObject( ); + virtual ~ProcessObject( ); + + // Error handling method + void _Error( const std::string& error ); + + // For configuration purposes + template< class _TType = DataObject > + inline void _ConfigureInput( + const std::string& name, bool required, bool multiple + ); + + template< class _TType = DataObject > + inline void _ConfigureOutput( const std::string& name ); + + template< class _TFilter > + inline _TFilter* _CreateITK( ); + + template< class _TFilter > + inline _TFilter* _CreateVTK( ); + + virtual void _GenerateData( ) = 0; + + private: + // Purposely not implemented + ProcessObject( const Self& ); + Self& operator=( const Self& ); + + protected: + Parameters m_Parameters; + std::string m_Name; + std::string m_PluginName; + bool m_ExplicitExecution; + + std::map< std::string, Port* > m_Inputs; + std::map< std::string, Port* > m_Outputs; + + itk::ModifiedTimeType m_LastExecutionTime; + mutable long m_LastExecutionSpan; + + bool m_PrintExecution; + std::ostream* m_PrintExecutionStream; + }; + + } // ecapseman + +} // ecapseman + +#include + +#endif // __cpPlugins__Pipeline__ProcessObject__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/ProcessObject.hxx b/lib/cpPlugins/Pipeline/ProcessObject.hxx new file mode 100644 index 0000000..47cd480 --- /dev/null +++ b/lib/cpPlugins/Pipeline/ProcessObject.hxx @@ -0,0 +1,293 @@ +#ifndef __cpPlugins__Pipeline__ProcessObject__hxx__ +#define __cpPlugins__Pipeline__ProcessObject__hxx__ + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::Pipeline::ProcessObject:: +GetInput( const std::string& n, unsigned int i ) +{ + auto it = this->m_Inputs.find( n ); + if( it != this->m_Inputs.end( ) ) + return( dynamic_cast< _TType* >( it->second->Get( i ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +const _TType* cpPlugins::Pipeline::ProcessObject:: +GetInput( const std::string& n, unsigned int i ) const +{ + auto it = this->m_Inputs.find( n ); + if( it != this->m_Inputs.end( ) ) + return( dynamic_cast< const _TType* >( it->second->Get( i ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::Pipeline::ProcessObject:: +GetInputData( const std::string& n, unsigned int i ) +{ + auto d = this->GetInput( n, i ); + if( d != NULL ) + { + auto oi = d->m_ITK.GetPointer( ); + auto ov = d->m_VTK.GetPointer( ); + if( oi != NULL && ov != NULL ) + { + auto di = dynamic_cast< _TType* >( oi ); + auto dv = dynamic_cast< _TType* >( ov ); + if ( di != NULL ) return( di ); + else if( dv != NULL ) return( dv ); + else return( NULL ); + } + else if( oi != NULL && ov == NULL ) + { + auto di = dynamic_cast< _TType* >( oi ); + if( di == NULL ) + return( d->GetVTK< _TType >( ) ); + else + return( di ); + } + else if( oi == NULL && ov != NULL ) + { + auto dv = dynamic_cast< _TType* >( ov ); + if( dv == NULL ) + return( d->GetITK< _TType >( ) ); + else + return( dv ); + } + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +const _TType* cpPlugins::Pipeline::ProcessObject:: +GetInputData( const std::string& n, unsigned int i ) const +{ + auto d = this->GetInput( n, i ); + if( d != NULL ) + { + auto oi = d->m_ITK.GetPointer( ); + auto ov = d->m_VTK.GetPointer( ); + if( oi != NULL && ov != NULL ) + { + auto di = dynamic_cast< const _TType* >( oi ); + auto dv = dynamic_cast< const _TType* >( ov ); + if ( di != NULL ) return( di ); + else if( dv != NULL ) return( dv ); + else return( NULL ); + } + else if( oi != NULL && ov == NULL ) + { + auto di = dynamic_cast< const _TType* >( oi ); + if( di == NULL ) + return( d->GetVTK< _TType >( ) ); + else + return( di ); + } + else if( oi == NULL && ov != NULL ) + { + auto dv = dynamic_cast< const _TType* >( ov ); + if( dv == NULL ) + return( d->GetITK< _TType >( ) ); + else + return( dv ); + } + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::Pipeline::ProcessObject:: +GetOutput( const std::string& n ) +{ + auto it = this->m_Outputs.find( n ); + if( it != this->m_Outputs.end( ) ) + return( dynamic_cast< _TType* >( it->second->Get( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +const _TType* cpPlugins::Pipeline::ProcessObject:: +GetOutput( const std::string& n ) const +{ + auto it = this->m_Outputs.find( n ); + if( it != this->m_Outputs.end( ) ) + return( dynamic_cast< const _TType* >( it->second->Get( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::Pipeline::ProcessObject:: +GetOutputData( const std::string& n ) +{ + auto d = this->GetOutput( n ); + if( d != NULL ) + { + auto oi = d->m_ITK.GetPointer( ); + auto ov = d->m_VTK.GetPointer( ); + if( oi != NULL && ov != NULL ) + { + auto di = dynamic_cast< _TType* >( oi ); + auto dv = dynamic_cast< _TType* >( ov ); + if ( di != NULL ) return( di ); + else if( dv != NULL ) return( dv ); + else return( NULL ); + } + else if( oi != NULL && ov == NULL ) + { + auto di = dynamic_cast< _TType* >( oi ); + if( di == NULL ) + return( d->GetVTK< _TType >( ) ); + else + return( di ); + } + else if( oi == NULL && ov != NULL ) + { + auto dv = dynamic_cast< _TType* >( ov ); + if( dv == NULL ) + return( d->GetITK< _TType >( ) ); + else + return( dv ); + } + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +const _TType* cpPlugins::Pipeline::ProcessObject:: +GetOutputData( const std::string& n ) const +{ + auto d = this->GetOutput( n ); + if( d != NULL ) + { + auto oi = d->m_ITK.GetPointer( ); + auto ov = d->m_VTK.GetPointer( ); + if( oi != NULL && ov != NULL ) + { + auto di = dynamic_cast< const _TType* >( oi ); + auto dv = dynamic_cast< const _TType* >( ov ); + if ( di != NULL ) return( di ); + else if( dv != NULL ) return( dv ); + else return( NULL ); + } + else if( oi != NULL && ov == NULL ) + { + auto di = dynamic_cast< const _TType* >( oi ); + if( di == NULL ) + return( d->GetVTK< _TType >( ) ); + else + return( di ); + } + else if( oi == NULL && ov != NULL ) + { + auto dv = dynamic_cast< const _TType* >( ov ); + if( dv == NULL ) + return( d->GetITK< _TType >( ) ); + else + return( dv ); + } + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +void cpPlugins::Pipeline::ProcessObject:: +_ConfigureInput( const std::string& name, bool required, bool multiple ) +{ + auto it = this->m_Inputs.find( name ); + if( it == this->m_Inputs.end( ) ) + { + Port* port; + if( multiple ) port = new MultipleInputsPort( required ); + else port = new InputPort( required ); + port->Configure< _TType >( ); + this->m_Inputs[ name ] = port; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TType > +void cpPlugins::Pipeline::ProcessObject:: +_ConfigureOutput( const std::string& name ) +{ + auto it = this->m_Outputs.find( name ); + if( it == this->m_Outputs.end( ) ) + { + Port* port = new OutputPort( true ); + port->Configure< _TType >( ); + port->Add( _TType::New( ) ); + port->Get( )->SetSource( this ); + this->m_Outputs[ name ] = port; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +_TFilter* cpPlugins::Pipeline::ProcessObject:: +_CreateITK( ) +{ + // TODO: why this lead to synch issues??? + _TFilter* filter = this->GetITK< _TFilter >( ); + if( filter == NULL ) + { + typename _TFilter::Pointer filter_ptr = _TFilter::New( ); + this->m_ITK = filter_ptr; + this->m_VTK = NULL; + filter = filter_ptr.GetPointer( ); + this->Modified( ); + + } // fi + return( filter ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +_TFilter* cpPlugins::Pipeline::ProcessObject:: +_CreateVTK( ) +{ + // TODO: why this lead to synch issues??? + _TFilter* filter = this->GetVTK< _TFilter >( ); + if( filter == NULL ) + { + vtkSmartPointer< _TFilter > filter_ptr = + vtkSmartPointer< _TFilter >::New( ); + this->m_ITK = NULL; + this->m_VTK = filter_ptr; + filter = filter_ptr.GetPointer( ); + this->Modified( ); + + } // fi + return( filter ); +} + +#endif // __cpPlugins__Pipeline__ProcessObject__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Widget.cxx b/lib/cpPlugins/Pipeline/Widget.cxx new file mode 100644 index 0000000..482bed9 --- /dev/null +++ b/lib/cpPlugins/Pipeline/Widget.cxx @@ -0,0 +1,46 @@ +#include + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Widget:: +AddInteractor( vtkRenderWindowInteractor* i ) +{ + if( this->m_Interactors.insert( i ).second ) + this->Modified( ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Pipeline::Widget:: +IsInteractive( ) +{ + return( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Widget:: +EnabledOn( ) +{ + this->SetEnabled( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Pipeline::Widget:: +EnabledOff( ) +{ + this->SetEnabled( false ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Widget:: +Widget( ) + : Superclass( ) +{ + this->m_Parameters.ConfigureAsString( "Text", "" ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Widget:: +~Widget( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Widget.h b/lib/cpPlugins/Pipeline/Widget.h new file mode 100644 index 0000000..91ef571 --- /dev/null +++ b/lib/cpPlugins/Pipeline/Widget.h @@ -0,0 +1,65 @@ +#ifndef __cpPlugins__Pipeline__Widget__h__ +#define __cpPlugins__Pipeline__Widget__h__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace cpPlugins +{ + namespace Pipeline + { + /** + */ + class cpPlugins_EXPORT Widget + : public ProcessObject + { + public: + typedef Widget Self; + typedef ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( Widget, ProcessObject ); + cpPlugins_Id_Macro( Widget, Object ); + + public: + virtual void AddInteractor( vtkRenderWindowInteractor* i ) cpPlugins_OVERRIDE; + virtual bool IsInteractive( ) cpPlugins_OVERRIDE; + + virtual void EnabledOn( ); + virtual void EnabledOff( ); + virtual void Clear( ) = 0; + virtual void SetEnabled( bool v ) = 0; + virtual bool GetEnabled( ) const = 0; + + protected: + Widget( ); + virtual ~Widget( ); + + private: + // Purposely not implemented + Widget( const Self& ); + Self& operator=( const Self& ); + + protected: + typedef vtkSmartPointer< vtkRenderWindowInteractor > _TInteractor; + struct _TInteractorCmp + { + bool operator()( + const _TInteractor& a, const _TInteractor& b + ) const + { return( a.GetPointer( ) < b.GetPointer( ) ); } + }; + std::set< _TInteractor, _TInteractorCmp > m_Interactors; + + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Pipeline__Widget__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/QT/OpenFileDialog.cxx b/lib/cpPlugins/QT/OpenFileDialog.cxx new file mode 100644 index 0000000..784d111 --- /dev/null +++ b/lib/cpPlugins/QT/OpenFileDialog.cxx @@ -0,0 +1,107 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::QT::OpenFileDialog:: +OpenFileDialog( QWidget* parent ) + : QFileDialog( parent ), + m_Parameters( NULL ), + m_Name( "" ) +{ + this->connect( + this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) ) + ); + this->setWindowTitle( "Open an(some) file(s)" ); +} + +// ------------------------------------------------------------------------- +cpPlugins::QT::OpenFileDialog:: +~OpenFileDialog( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::OpenFileDialog:: +SetParameters( + cpPlugins::Pipeline::Parameters* params, const std::string& name + ) +{ + if( params == NULL ) + { + this->m_Parameters = NULL; + this->m_Name = ""; + return; + + } // fi + auto param_type = params->GetType( name ); + if( + param_type != cpPlugins::Pipeline::Parameters::OpenFileName && + param_type != cpPlugins::Pipeline::Parameters::OpenFileNameList + ) + { + this->m_Parameters = NULL; + this->m_Name = ""; + return; + + } // fi + this->m_Parameters = params; + this->m_Name = name; + + QStringList filters; + auto extensions = this->m_Parameters->GetAcceptedFileExtensions( name ); + if( extensions != "" ) + filters << extensions.c_str( ); + filters << "Any file (*)"; + if( param_type == cpPlugins::Pipeline::Parameters::OpenFileName ) + this->setFileMode( QFileDialog::ExistingFile ); + else + this->setFileMode( QFileDialog::ExistingFiles ); + this->setNameFilters( filters ); + this->setAcceptMode( QFileDialog::AcceptOpen ); + if( param_type == cpPlugins::Pipeline::Parameters::OpenFileName ) + { + auto file = this->m_Parameters->GetOpenFileName( this->m_Name ); + if( file == "" ) + file = "."; + QFileInfo info( file.c_str( ) ); + this->setDirectory( info.canonicalPath( ) ); + } + else + { + auto files = this->m_Parameters->GetOpenFileNameList( this->m_Name ); + if( files.size( ) > 0 ) + { + QFileInfo info( files[ 0 ].c_str( ) ); + this->setDirectory( info.canonicalPath( ) ); + } + else + this->setDirectory( "." ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::OpenFileDialog:: +_dlg_Accepted( ) +{ + if( this->m_Parameters != NULL ) + { + auto files = this->selectedFiles( ); + auto param_type = this->m_Parameters->GetType( this->m_Name ); + if( param_type == cpPlugins::Pipeline::Parameters::OpenFileNameList ) + { + this->m_Parameters->ClearOpenFileNameList( this->m_Name ); + for( auto fIt = files.begin( ); fIt != files.end( ); ++fIt ) + this->m_Parameters->AddToOpenFileNameList( + this->m_Name, fIt->toStdString( ) + ); + } + else + this->m_Parameters->SetOpenFileName( + this->m_Name, files[ 0 ].toStdString( ) + ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/QT/OpenFileDialog.h b/lib/cpPlugins/QT/OpenFileDialog.h new file mode 100644 index 0000000..2a69404 --- /dev/null +++ b/lib/cpPlugins/QT/OpenFileDialog.h @@ -0,0 +1,41 @@ +#ifndef __cpPlugins__QT__OpenFileDialog__h__ +#define __cpPlugins__QT__OpenFileDialog__h__ + +#include +#include + +namespace cpPlugins{ namespace Pipeline { class Parameters; } } + +namespace cpPlugins +{ + namespace QT + { + /** + */ + class OpenFileDialog + : public QFileDialog + { + Q_OBJECT; + public: + OpenFileDialog( QWidget* parent = 0 ); + virtual ~OpenFileDialog( ); + + void SetParameters( + cpPlugins::Pipeline::Parameters* params, const std::string& name + ); + + protected slots: + void _dlg_Accepted( ); + + protected: + cpPlugins::Pipeline::Parameters* m_Parameters; + std::string m_Name; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__QT__OpenFileDialog__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/QT/ParametersDialog.cxx b/lib/cpPlugins/QT/ParametersDialog.cxx new file mode 100644 index 0000000..39f1276 --- /dev/null +++ b/lib/cpPlugins/QT/ParametersDialog.cxx @@ -0,0 +1,888 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::QT::ParametersDialog:: +ParametersDialog( QWidget* parent, Qt::WindowFlags f, bool manual ) + : QDialog( parent, f ), + m_ProcessObject( NULL ), + m_WidgetsUpdated( false ), + m_Manual( manual ) +{ + if( !this->m_Manual ) + { + this->m_Title = new QLabel( this ); + this->m_Title->setText( "Parameters dialog title" ); + this->m_MainLayout = new QGridLayout( this ); + this->m_ToolsLayout = new QVBoxLayout( ); + this->m_ToolsLayout->addWidget( this->m_Title ); + this->m_MainLayout->addLayout( this->m_ToolsLayout, 0, 0, 1, 1 ); + + } // fi + this->connect( + this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) ) + ); +} + +// ------------------------------------------------------------------------- +cpPlugins::QT::ParametersDialog:: +~ParametersDialog( ) +{ + if( !this->m_Manual ) + { + delete this->m_Title; + delete this->m_ToolsLayout; + delete this->m_MainLayout; + + } // fi +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::ProcessObject* +cpPlugins::QT::ParametersDialog:: +getProcessObject( ) const +{ + return( this->m_ProcessObject ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::QT::ParametersDialog:: +setProcessObject( cpPlugins::Pipeline::ProcessObject* obj ) +{ + if( this->m_ProcessObject != NULL || obj == NULL ) + return( false ); + this->m_ProcessObject = obj; + this->m_WidgetsUpdated = false; + this->_updateWidgets( ); + this->updateView( ); + return( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +updateParameters( ) +{ + if( this->m_ProcessObject == NULL ) + return; + if( this->m_Manual ) + return; + + // Check if an explicit re-execution button is needed + QCheckBox* v_bool = + this->findChild< QCheckBox* >( "___ExplicitExecution___" ); + if( v_bool != NULL ) + this->m_ProcessObject->SetExplicitExecution( v_bool->isChecked( ) ); + + // Put values + auto parameters = this->m_ProcessObject->GetParameters( ); + auto& raw_params = parameters->GetRawParameters( ); + for( auto pIt = raw_params.begin( ); pIt != raw_params.end( ); ++pIt ) + { + QString pName = pIt->first.c_str( ); + switch( pIt->second.first ) + { + case cpPlugins::Pipeline::Parameters::String: + case cpPlugins::Pipeline::Parameters::OpenFileName: + case cpPlugins::Pipeline::Parameters::SaveFileName: + case cpPlugins::Pipeline::Parameters::PathName: + case cpPlugins::Pipeline::Parameters::IntList: + case cpPlugins::Pipeline::Parameters::UintList: + case cpPlugins::Pipeline::Parameters::RealList: + case cpPlugins::Pipeline::Parameters::OpenFileNameList: + { + QLineEdit* v_string = this->findChild< QLineEdit* >( pName ); + if( v_string != NULL ) + pIt->second.second = v_string->text( ).toStdString( ); + } + break; + case cpPlugins::Pipeline::Parameters::Bool: + { + QCheckBox* v_bool = this->findChild< QCheckBox* >( pName ); + if( v_bool != NULL ) + pIt->second.second = ( v_bool->isChecked( ) )? "1": "0"; + } + break; + case cpPlugins::Pipeline::Parameters::Int: + case cpPlugins::Pipeline::Parameters::Uint: + { + QSpinBox* v_uint = this->findChild< QSpinBox* >( pName ); + if( v_uint ) + { + std::stringstream str; + str << v_uint->value( ); + pIt->second.second = str.str( ); + + } // fi + } + break; + case cpPlugins::Pipeline::Parameters::Real: + { + QDoubleSpinBox* v_double = this->findChild< QDoubleSpinBox* >( pName ); + if( v_double ) + { + std::stringstream str; + str << v_double->value( ); + pIt->second.second = str.str( ); + + } // fi + } + break; + case cpPlugins::Pipeline::Parameters::StringList: + break; + case cpPlugins::Pipeline::Parameters::BoolList: + break; + case cpPlugins::Pipeline::Parameters::SaveFileNameList: + break; + case cpPlugins::Pipeline::Parameters::PathNameList: + break; + case cpPlugins::Pipeline::Parameters::Choices: + { + QComboBox* v_choices = this->findChild< QComboBox* >( pName ); + if( v_choices != NULL ) + { + std::istringstream str_choices( pIt->second.second ); + std::string real_choices; + std::getline( str_choices, real_choices, '@' ); + pIt->second.second = + real_choices + "@" + + v_choices->currentText( ).toStdString( ); + + } // fi + } + break; + default: + break; + } // hctiws + + } // rof + this->m_ProcessObject->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +updateView( ) +{ + if( this->m_ProcessObject == NULL ) + return; + if( this->m_Manual ) + return; + + // Check if an explicit re-execution button is needed + QCheckBox* v_bool = + this->findChild< QCheckBox* >( "___ExplicitExecution___" ); + if( v_bool != NULL ) + v_bool->setChecked( this->m_ProcessObject->GetExplicitExecution( ) ); + + // Put values + auto parameters = this->m_ProcessObject->GetParameters( ); + auto& raw_params = parameters->GetRawParameters( ); + for( auto pIt = raw_params.begin( ); pIt != raw_params.end( ); ++pIt ) + { + QString pName = pIt->first.c_str( ); + switch( pIt->second.first ) + { + case cpPlugins::Pipeline::Parameters::String: + case cpPlugins::Pipeline::Parameters::OpenFileName: + case cpPlugins::Pipeline::Parameters::SaveFileName: + case cpPlugins::Pipeline::Parameters::PathName: + case cpPlugins::Pipeline::Parameters::IntList: + case cpPlugins::Pipeline::Parameters::UintList: + case cpPlugins::Pipeline::Parameters::RealList: + case cpPlugins::Pipeline::Parameters::OpenFileNameList: + { + QLineEdit* v_string = this->findChild< QLineEdit* >( pName ); + if( v_string != NULL ) + v_string->setText( pIt->second.second.c_str( ) ); + } + break; + case cpPlugins::Pipeline::Parameters::Bool: + { + QCheckBox* v_bool = this->findChild< QCheckBox* >( pName ); + if( v_bool != NULL ) + v_bool->setChecked( pIt->second.second == "1" ); + } + break; + case cpPlugins::Pipeline::Parameters::Int: + case cpPlugins::Pipeline::Parameters::Uint: + { + QSpinBox* v_uint = this->findChild< QSpinBox* >( pName ); + if( v_uint ) + { + std::istringstream tok_str( pIt->second.second ); + int v; + tok_str >> v; + v_uint->setValue( v ); + + } // fi + } + break; + case cpPlugins::Pipeline::Parameters::Real: + { + QDoubleSpinBox* v_double = this->findChild< QDoubleSpinBox* >( pName ); + if( v_double ) + { + std::istringstream tok_str( pIt->second.second ); + double v; + tok_str >> v; + v_double->setValue( v ); + + } // fi + } + break; + case cpPlugins::Pipeline::Parameters::StringList: + break; + case cpPlugins::Pipeline::Parameters::BoolList: + break; + case cpPlugins::Pipeline::Parameters::SaveFileNameList: + break; + case cpPlugins::Pipeline::Parameters::PathNameList: + break; + case cpPlugins::Pipeline::Parameters::Choices: + { + QComboBox* v_choices = this->findChild< QComboBox* >( pName ); + if( v_choices != NULL ) + { + std::istringstream str_choices( pIt->second.second ); + std::string choices, real_choice; + std::getline( str_choices, choices, '@' ); + std::getline( str_choices, real_choice, '@' ); + std::istringstream str( choices ); + std::string token; + int id = -1, cont = 0; + while( std::getline( str, token, '#' ) ) + { + if( token == real_choice ) + id = cont; + cont++; + + } // elihw + + if( id > -1 ) + v_choices->setCurrentIndex( id ); + + } // fi + } + break; + default: + break; + } // hctiws + + } // rof +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_addButtons( ) +{ + if( this->m_Manual ) + return; + + // Add buttons + this->m_Buttons = new QDialogButtonBox( + QDialogButtonBox::Ok | QDialogButtonBox::Cancel + ); + this->connect( + this->m_Buttons, SIGNAL( accepted( ) ), this, SLOT( accept( ) ) + ); + this->connect( + this->m_Buttons, SIGNAL( rejected( ) ), this, SLOT( reject( ) ) + ); + this->m_ToolsLayout->addWidget( this->m_Buttons ); + + this->updateView( ); + this->m_WidgetsUpdated = true; +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_updateWidgets( ) +{ + if( this->m_WidgetsUpdated || this->m_ProcessObject == NULL ) + return; + if( this->m_Manual ) + return; + + // Set dialog title + std::stringstream title; + title + << "Parameters for an object of class \"" + << this->m_ProcessObject->GetClassName( ) + << "\""; + this->m_Title->setText( title.str( ).c_str( ) ); + + // Check if an explicit re-execution button is needed + QCheckBox* v_bool = new QCheckBox( this ); + v_bool->setObjectName( "___ExplicitExecution___" ); + v_bool->setText( "Explicit re-execution" ); + v_bool->setChecked( this->m_ProcessObject->GetExplicitExecution( ) ); + + QHBoxLayout* new_layout = new QHBoxLayout( ); + new_layout->addWidget( v_bool ); + this->m_ToolsLayout->addLayout( new_layout ); + + // Put values + auto parameters = this->m_ProcessObject->GetParameters( ); + auto& raw_params = parameters->GetRawParameters( ); + for( auto pIt = raw_params.begin( ); pIt != raw_params.end( ); ++pIt ) + { + QWidget* w_input = NULL; + switch( pIt->second.first ) + { + case cpPlugins::Pipeline::Parameters::String: + { + QLineEdit* v_string = new QLineEdit( this ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + w_input = v_string; + } + break; + case cpPlugins::Pipeline::Parameters::Bool: + { + QCheckBox* v_bool = new QCheckBox( this ); + v_bool->setObjectName( pIt->first.c_str( ) ); + v_bool->setText( "[ON/OFF]" ); + v_bool->setChecked( pIt->second.second == "1" ); + w_input = v_bool; + } + break; + case cpPlugins::Pipeline::Parameters::Int: + case cpPlugins::Pipeline::Parameters::Uint: + { + std::istringstream tok_str( pIt->second.second ); + int v; + tok_str >> v; + QSpinBox* v_uint = new QSpinBox( this ); + v_uint->setObjectName( pIt->first.c_str( ) ); + if( pIt->second.first == cpPlugins::Pipeline::Parameters::Uint ) + v_uint->setMinimum( 0 ); + else + v_uint->setMinimum( -std::numeric_limits< int >::max( ) ); + v_uint->setMaximum( std::numeric_limits< int >::max( ) ); + v_uint->setValue( v ); + w_input = v_uint; + } + break; + case cpPlugins::Pipeline::Parameters::Real: + { + std::istringstream tok_str( pIt->second.second ); + double v; + tok_str >> v; + QDoubleSpinBox* v_double = new QDoubleSpinBox( this ); + v_double->setObjectName( pIt->first.c_str( ) ); + v_double->setDecimals( 3 ); + v_double->setMinimum( -std::numeric_limits< double >::max( ) ); + v_double->setMaximum( std::numeric_limits< double >::max( ) ); + v_double->setValue( v ); + w_input = v_double; + } + break; + case cpPlugins::Pipeline::Parameters::OpenFileName: + { + QFrame* frame = new QFrame( this ); + QHBoxLayout* layout = new QHBoxLayout( frame ); + QLineEdit* v_string = new QLineEdit( frame ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + QPushButton* v_button = new QPushButton( frame ); + v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) ); + v_button->setText( "..." ); + v_button->connect( + v_button, SIGNAL( clicked( ) ), + this, SLOT( _dlg_OpenSingleFile( ) ) + ); + layout->addWidget( v_string ); + layout->addWidget( v_button ); + w_input = frame; + } + case cpPlugins::Pipeline::Parameters::SaveFileName: + { + QFrame* frame = new QFrame( this ); + QHBoxLayout* layout = new QHBoxLayout( frame ); + QLineEdit* v_string = new QLineEdit( frame ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + QPushButton* v_button = new QPushButton( frame ); + v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) ); + v_button->setText( "..." ); + v_button->connect( + v_button, SIGNAL( clicked( ) ), + this, SLOT( _dlg_SaveSingleFile( ) ) + ); + layout->addWidget( v_string ); + layout->addWidget( v_button ); + w_input = frame; + } + break; + case cpPlugins::Pipeline::Parameters::PathName: + { + QFrame* frame = new QFrame( this ); + QHBoxLayout* layout = new QHBoxLayout( frame ); + QLineEdit* v_string = new QLineEdit( frame ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + QPushButton* v_button = new QPushButton( frame ); + v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) ); + v_button->setText( "..." ); + v_button->connect( + v_button, SIGNAL( clicked( ) ), + this, SLOT( _dlg_OpenSinglePath( ) ) + ); + layout->addWidget( v_string ); + layout->addWidget( v_button ); + w_input = frame; + } + break; + case cpPlugins::Pipeline::Parameters::StringList: + break; + case cpPlugins::Pipeline::Parameters::BoolList: + break; + case cpPlugins::Pipeline::Parameters::IntList: + { + QFrame* frame = new QFrame( this ); + QHBoxLayout* layout = new QHBoxLayout( frame ); + QLineEdit* v_string = new QLineEdit( frame ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + QPushButton* v_button = new QPushButton( frame ); + v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) ); + v_button->setText( "+" ); + v_button->connect( + v_button, SIGNAL( clicked( ) ), + this, SLOT( _dlg_AddInt( ) ) + ); + layout->addWidget( v_string ); + layout->addWidget( v_button ); + w_input = frame; + } + break; + case cpPlugins::Pipeline::Parameters::UintList: + { + QFrame* frame = new QFrame( this ); + QHBoxLayout* layout = new QHBoxLayout( frame ); + QLineEdit* v_string = new QLineEdit( frame ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + QPushButton* v_button = new QPushButton( frame ); + v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) ); + v_button->setText( "+" ); + v_button->connect( + v_button, SIGNAL( clicked( ) ), + this, SLOT( _dlg_AddUint( ) ) + ); + layout->addWidget( v_string ); + layout->addWidget( v_button ); + w_input = frame; + } + break; + case cpPlugins::Pipeline::Parameters::RealList: + { + QFrame* frame = new QFrame( this ); + QHBoxLayout* layout = new QHBoxLayout( frame ); + QLineEdit* v_string = new QLineEdit( frame ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + QPushButton* v_button = new QPushButton( frame ); + v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) ); + v_button->setText( "+" ); + v_button->connect( + v_button, SIGNAL( clicked( ) ), + this, SLOT( _dlg_AddReal( ) ) + ); + layout->addWidget( v_string ); + layout->addWidget( v_button ); + w_input = frame; + } + break; + case cpPlugins::Pipeline::Parameters::OpenFileNameList: + { + QFrame* frame = new QFrame( this ); + QHBoxLayout* layout = new QHBoxLayout( frame ); + QLineEdit* v_string = new QLineEdit( frame ); + v_string->setObjectName( pIt->first.c_str( ) ); + v_string->setMaxLength( std::numeric_limits< int >::max( ) ); + v_string->setText( pIt->second.second.c_str( ) ); + QPushButton* v_button = new QPushButton( frame ); + v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) ); + v_button->setText( "..." ); + v_button->connect( + v_button, SIGNAL( clicked( ) ), + this, SLOT( _dlg_OpenMultipleFiles( ) ) + ); + layout->addWidget( v_string ); + layout->addWidget( v_button ); + w_input = frame; + } + break; + case cpPlugins::Pipeline::Parameters::SaveFileNameList: + break; + case cpPlugins::Pipeline::Parameters::PathNameList: + break; + case cpPlugins::Pipeline::Parameters::Choices: + { + QComboBox* v_choices = new QComboBox( this ); + v_choices->setObjectName( pIt->first.c_str( ) ); + + std::istringstream str0( pIt->second.second ); + std::string choices; + std::getline( str0, choices, '@' ); + std::istringstream str1( choices ); + std::string token; + int id = 0; + while( std::getline( str1, token, '#' ) ) + v_choices->insertItem( id++, token.c_str( ) ); + w_input = v_choices; + } + break; + default: + w_input = NULL; + break; + } // hctiws + + // Ok, a representation was created + if( w_input != NULL ) + { + QHBoxLayout* new_layout = new QHBoxLayout( ); + QLabel* label = new QLabel( this ); + label->setText( QString( pIt->first.c_str( ) ) ); + new_layout->addWidget( label ); + new_layout->addWidget( w_input ); + this->m_ToolsLayout->addLayout( new_layout ); + + } // fi + + } // rof + + // Update values + this->_addButtons( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_Accepted( ) +{ + this->updateParameters( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_OpenSingleFile( ) +{ + auto parameters = this->m_ProcessObject->GetParameters( ); + QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) ); + if( btn != NULL ) + { + std::string bName = btn->objectName( ).toStdString( ); + std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) ); + QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) ); + if( line != NULL ) + { + std::string param_name = line->objectName( ).toStdString( ); + if( param_name != "" ) + { + std::string param_value = parameters->GetOpenFileName( param_name ); + if( param_value == "" ) + param_value = "."; + QStringList dialog_filters; + std::string extensions = parameters->GetAcceptedFileExtensions( param_name ); + if( extensions != "" ) + dialog_filters << extensions.c_str( ); + dialog_filters << "Any file (*)"; + + // Show dialog and check if it was accepted + QFileDialog dialog( this ); + dialog.setFileMode( QFileDialog::ExistingFile ); + dialog.setDirectory( QFileDialog::tr( param_value.c_str( ) ) ); + dialog.setNameFilters( dialog_filters ); + dialog.setAcceptMode( QFileDialog::AcceptOpen ); + if( dialog.exec( ) ) + line->setText( *( dialog.selectedFiles( ).begin( ) ) ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_SaveSingleFile( ) +{ + auto parameters = this->m_ProcessObject->GetParameters( ); + QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) ); + if( btn != NULL ) + { + std::string bName = btn->objectName( ).toStdString( ); + std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) ); + QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) ); + if( line != NULL ) + { + std::string param_name = line->objectName( ).toStdString( ); + if( param_name != "" ) + { + std::string param_value = parameters->GetSaveFileName( param_name ); + if( param_value == "" ) + param_value = "."; + QStringList dialog_filters; + std::string extensions = parameters->GetAcceptedFileExtensions( param_name ); + if( extensions != "" ) + dialog_filters << extensions.c_str( ); + dialog_filters << "Any file (*)"; + + // Show dialog and check if it was accepted + QFileDialog dialog( this ); + dialog.setFileMode( QFileDialog::AnyFile ); + dialog.setDirectory( QFileDialog::tr( param_value.c_str( ) ) ); + dialog.setNameFilters( dialog_filters ); + dialog.setAcceptMode( QFileDialog::AcceptSave ); + if( dialog.exec( ) ) + line->setText( *( dialog.selectedFiles( ).begin( ) ) ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_OpenSinglePath( ) +{ + auto parameters = this->m_ProcessObject->GetParameters( ); + QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) ); + if( btn != NULL ) + { + std::string bName = btn->objectName( ).toStdString( ); + std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) ); + QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) ); + if( line != NULL ) + { + std::string param_name = line->objectName( ).toStdString( ); + if( param_name != "" ) + { + std::string param_value = parameters->GetPathName( param_name ); + if( param_value == "" ) + param_value = "."; + + // Show dialog and check if it was accepted + QFileDialog dialog( this ); + dialog.setFileMode( QFileDialog::Directory ); + dialog.setDirectory( QFileDialog::tr( param_value.c_str( ) ) ); + dialog.setAcceptMode( QFileDialog::AcceptOpen ); + if( dialog.exec( ) ) + line->setText( *( dialog.selectedFiles( ).begin( ) ) ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_OpenMultipleFiles( ) +{ + auto parameters = this->m_ProcessObject->GetParameters( ); + QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) ); + if( btn != NULL ) + { + std::string bName = btn->objectName( ).toStdString( ); + std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) ); + + QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) ); + if( line != NULL ) + { + std::string param_name = line->objectName( ).toStdString( ); + if( param_name != "" ) + { + QStringList dialog_filters; + std::string extensions = parameters->GetAcceptedFileExtensions( param_name ); + if( extensions != "" ) + dialog_filters << extensions.c_str( ); + dialog_filters << "Any file (*)"; + + // Show dialog and check if it was accepted + QFileDialog dialog( this ); + dialog.setFileMode( QFileDialog::ExistingFiles ); + dialog.setNameFilters( dialog_filters ); + dialog.setAcceptMode( QFileDialog::AcceptOpen ); + if( dialog.exec( ) ) + { + if( dialog.selectedFiles( ).size( ) > 0 ) + { + std::stringstream str; + auto files = dialog.selectedFiles( ); + auto fIt = files.begin( ); + str << fIt->toStdString( ); + ++fIt; + for( ; fIt != files.end( ); ++fIt ) + str << "#" << fIt->toStdString( ); + line->setText( str.str( ).c_str( ) ); + + } // fi + + } // fi + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_AddInt( ) +{ + QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) ); + if( btn != NULL ) + { + std::string bName = btn->objectName( ).toStdString( ); + std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) ); + QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) ); + if( line != NULL ) + { + std::string param_name = line->objectName( ).toStdString( ); + if( param_name != "" ) + { + bool ok; + int value = + QInputDialog::getInt( + this, + ( + std::string( "Add new value to \"" ) + + param_name + + std::string( "\"" ) + ).c_str( ), + "Value:", + 0, + -std::numeric_limits< int >::max( ), + std::numeric_limits< int >::max( ), + 1, &ok + ); + if( ok ) + { + std::string values = line->text( ).toStdString( ); + if( values != "" ) + values += "#"; + std::stringstream str; + str << values << value; + line->setText( str.str( ).c_str( ) ); + + } // fi + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_AddUint( ) +{ + QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) ); + if( btn != NULL ) + { + std::string bName = btn->objectName( ).toStdString( ); + std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) ); + QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) ); + if( line != NULL ) + { + std::string param_name = line->objectName( ).toStdString( ); + if( param_name != "" ) + { + bool ok; + int value = + QInputDialog::getInt( + this, + ( + std::string( "Add new value to \"" ) + + param_name + + std::string( "\"" ) + ).c_str( ), + "Value:", + 0, 0, std::numeric_limits< int >::max( ), 1, + &ok + ); + if( ok ) + { + std::string values = line->text( ).toStdString( ); + if( values != "" ) + values += "#"; + std::stringstream str; + str << values << value; + line->setText( str.str( ).c_str( ) ); + + } // fi + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::ParametersDialog:: +_dlg_AddReal( ) +{ + QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) ); + if( btn != NULL ) + { + std::string bName = btn->objectName( ).toStdString( ); + std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) ); + QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) ); + if( line != NULL ) + { + std::string param_name = line->objectName( ).toStdString( ); + if( param_name != "" ) + { + bool ok; + double value = + QInputDialog::getDouble( + this, + ( + std::string( "Add new value to \"" ) + + param_name + + std::string( "\"" ) + ).c_str( ), + "Value:", + 0, + -std::numeric_limits< double >::max( ), + std::numeric_limits< double >::max( ), + 1, &ok + ); + if( ok ) + { + std::string values = line->text( ).toStdString( ); + if( values != "" ) + values += "#"; + std::stringstream str; + str << values << value; + line->setText( str.str( ).c_str( ) ); + + } // fi + + } // fi + + } // fi + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/QT/ParametersDialog.h b/lib/cpPlugins/QT/ParametersDialog.h new file mode 100644 index 0000000..37a6863 --- /dev/null +++ b/lib/cpPlugins/QT/ParametersDialog.h @@ -0,0 +1,69 @@ +#ifndef __cpPlugins__QT__ParametersDialog__h__ +#define __cpPlugins__QT__ParametersDialog__h__ + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + namespace QT + { + /** + */ + class cpPlugins_EXPORT ParametersDialog + : public QDialog + { + Q_OBJECT; + + public: + ParametersDialog( + QWidget* parent = 0, Qt::WindowFlags f = 0, bool manual = false + ); + virtual ~ParametersDialog( ); + + cpPlugins::Pipeline::ProcessObject* getProcessObject( ) const; + virtual bool setProcessObject( + cpPlugins::Pipeline::ProcessObject* obj + ); + + virtual void updateParameters( ); + virtual void updateView( ); + + protected: + virtual void _addButtons( ); + virtual void _updateWidgets( ); + + protected slots: + virtual void _dlg_Accepted( ); + virtual void _dlg_OpenSingleFile( ); + virtual void _dlg_SaveSingleFile( ); + virtual void _dlg_OpenSinglePath( ); + virtual void _dlg_OpenMultipleFiles( ); + virtual void _dlg_AddInt( ); + virtual void _dlg_AddUint( ); + virtual void _dlg_AddReal( ); + + protected: + cpPlugins::Pipeline::ProcessObject* m_ProcessObject; + bool m_WidgetsUpdated; + bool m_Manual; + QLabel* m_Title; + QGridLayout* m_MainLayout; + QVBoxLayout* m_ToolsLayout; + QDialogButtonBox* m_Buttons; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__QT__ParametersDialog__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/QT/SaveFileDialog.cxx b/lib/cpPlugins/QT/SaveFileDialog.cxx new file mode 100644 index 0000000..d42af95 --- /dev/null +++ b/lib/cpPlugins/QT/SaveFileDialog.cxx @@ -0,0 +1,76 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::QT::SaveFileDialog:: +SaveFileDialog( QWidget* parent ) + : QFileDialog( parent ), + m_Parameters( NULL ), + m_Name( "" ) +{ + this->connect( + this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) ) + ); + this->setWindowTitle( "Save a file" ); +} + +// ------------------------------------------------------------------------- +cpPlugins::QT::SaveFileDialog:: +~SaveFileDialog( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::SaveFileDialog:: +SetParameters( + cpPlugins::Pipeline::Parameters* params, const std::string& name + ) +{ + if( params == NULL ) + { + this->m_Parameters = NULL; + this->m_Name = ""; + return; + + } // fi + auto param_type = params->GetType( name ); + if( param_type != cpPlugins::Pipeline::Parameters::SaveFileName ) + { + this->m_Parameters = NULL; + this->m_Name = ""; + return; + + } // fi + this->m_Parameters = params; + this->m_Name = name; + + QStringList filters; + auto extensions = this->m_Parameters->GetAcceptedFileExtensions( name ); + if( extensions != "" ) + filters << extensions.c_str( ); + filters << "Any file (*)"; + this->setFileMode( QFileDialog::AnyFile ); + this->setNameFilters( filters ); + this->setAcceptMode( QFileDialog::AcceptOpen ); + auto file = this->m_Parameters->GetSaveFileName( this->m_Name ); + if( file == "" ) + file = "."; + QFileInfo info( file.c_str( ) ); + this->setDirectory( info.canonicalPath( ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::QT::SaveFileDialog:: +_dlg_Accepted( ) +{ + if( this->m_Parameters != NULL ) + { + auto files = this->selectedFiles( ); + this->m_Parameters->SetSaveFileName( + this->m_Name, files[ 0 ].toStdString( ) + ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/QT/SaveFileDialog.h b/lib/cpPlugins/QT/SaveFileDialog.h new file mode 100644 index 0000000..f290ead --- /dev/null +++ b/lib/cpPlugins/QT/SaveFileDialog.h @@ -0,0 +1,41 @@ +#ifndef __cpPlugins__QT__SaveFileDialog__h__ +#define __cpPlugins__QT__SaveFileDialog__h__ + +#include +#include + +namespace cpPlugins{ namespace Pipeline { class Parameters; } } + +namespace cpPlugins +{ + namespace QT + { + /** + */ + class SaveFileDialog + : public QFileDialog + { + Q_OBJECT; + public: + SaveFileDialog( QWidget* parent = 0 ); + virtual ~SaveFileDialog( ); + + void SetParameters( + cpPlugins::Pipeline::Parameters* params, const std::string& name + ); + + protected slots: + void _dlg_Accepted( ); + + protected: + cpPlugins::Pipeline::Parameters* m_Parameters; + std::string m_Name; + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__QT__SaveFileDialog__h__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/tinyxml2/OLD_CMakeLists.txt.old b/lib/cpPlugins/tinyxml2/OLD_CMakeLists.txt.old new file mode 100644 index 0000000..6579b71 --- /dev/null +++ b/lib/cpPlugins/tinyxml2/OLD_CMakeLists.txt.old @@ -0,0 +1,32 @@ +SET(lib_NAME cpPlugins_tinyxml2) +SET(lib_DIR third_party/tinyxml) + +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +ENDIF(MSVC) + +ADD_LIBRARY(${lib_NAME} SHARED tinyxml2.cpp tinyxml2.h) +SET_TARGET_PROPERTIES( + ${lib_NAME} PROPERTIES + VERSION "${prj_VER}" + SOVERSION "${prj_sVER}" + ) +GENERATE_EXPORT_HEADER( + ${lib_NAME} + BASE_NAME ${lib_NAME} + EXPORT_MACRO_NAME ${lib_NAME}_EXPORT + EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/lib/${lib_DIR}/${lib_NAME}_Export.h + STATIC_DEFINE ${lib_NAME}_BUILT_AS_STATIC + ) +INSTALL( + TARGETS ${lib_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + ) +INSTALL( + FILES tinyxml2.h + DESTINATION include + ) + +## eof - $RCSfile$ diff --git a/lib/cpPlugins/tinyxml2/readme.md b/lib/cpPlugins/tinyxml2/readme.md new file mode 100644 index 0000000..30424c3 --- /dev/null +++ b/lib/cpPlugins/tinyxml2/readme.md @@ -0,0 +1,324 @@ +TinyXML-2 [![TravisCI Status](https://travis-ci.org/leethomason/tinyxml2.svg?branch=master)](https://travis-ci.org/leethomason/tinyxml2) [![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/leethomason/tinyxml2?branch=master&svg=true)](https://ci.appveyor.com/project/leethomason/tinyxml2) +========= +![TinyXML-2 Logo](http://www.grinninglizard.com/tinyxml2/TinyXML2_small.png) + +TinyXML-2 is a simple, small, efficient, C++ XML parser that can be +easily integrated into other programs. + +The master is hosted on github: +https://github.com/leethomason/tinyxml2 + +The online HTML version of these docs: +http://grinninglizard.com/tinyxml2docs/index.html + +Examples are in the "related pages" tab of the HTML docs. + +What it does. +------------- + +In brief, TinyXML-2 parses an XML document, and builds from that a +Document Object Model (DOM) that can be read, modified, and saved. + +XML stands for "eXtensible Markup Language." It is a general purpose +human and machine readable markup language to describe arbitrary data. +All those random file formats created to store application data can +all be replaced with XML. One parser for everything. + +http://en.wikipedia.org/wiki/XML + +There are different ways to access and interact with XML data. +TinyXML-2 uses a Document Object Model (DOM), meaning the XML data is parsed +into a C++ objects that can be browsed and manipulated, and then +written to disk or another output stream. You can also construct an XML document +from scratch with C++ objects and write this to disk or another output +stream. You can even use TinyXML-2 to stream XML programmatically from +code without creating a document first. + +TinyXML-2 is designed to be easy and fast to learn. It is one header and +one cpp file. Simply add these to your project and off you go. +There is an example file - xmltest.cpp - to get you started. + +TinyXML-2 is released under the ZLib license, +so you can use it in open source or commercial code. The details +of the license are at the top of every source file. + +TinyXML-2 attempts to be a flexible parser, but with truly correct and +compliant XML output. TinyXML-2 should compile on any reasonably C++ +compliant system. It does not rely on exceptions, RTTI, or the STL. + +What it doesn't do. +------------------- + +TinyXML-2 doesn't parse or use DTDs (Document Type Definitions) or XSLs +(eXtensible Stylesheet Language.) There are other parsers out there +that are much more fully featured. But they are also much bigger, +take longer to set up in your project, have a higher learning curve, +and often have a more restrictive license. If you are working with +browsers or have more complete XML needs, TinyXML-2 is not the parser for you. + +TinyXML-1 vs. TinyXML-2 +----------------------- + +TinyXML-2 is now the focus of all development, well tested, and your +best choice unless you have a requirement to maintain TinyXML-1 code. + +TinyXML-2 uses a similar API to TinyXML-1 and the same +rich test cases. But the implementation of the parser is completely re-written +to make it more appropriate for use in a game. It uses less memory, is faster, +and uses far fewer memory allocations. + +TinyXML-2 has no requirement for STL, but has also dropped all STL support. All +strings are query and set as 'const char*'. This allows the use of internal +allocators, and keeps the code much simpler. + +Both parsers: + +1. Simple to use with similar APIs. +2. DOM based parser. +3. UTF-8 Unicode support. http://en.wikipedia.org/wiki/UTF-8 + +Advantages of TinyXML-2 + +1. The focus of all future dev. +2. Many fewer memory allocation (1/10th to 1/100th), uses less memory + (about 40% of TinyXML-1), and faster. +3. No STL requirement. +4. More modern C++, including a proper namespace. +5. Proper and useful handling of whitespace + +Advantages of TinyXML-1 + +1. Can report the location of parsing errors. +2. Support for some C++ STL conventions: streams and strings +3. Very mature and well debugged code base. + +Features +-------- + +### Memory Model + +An XMLDocument is a C++ object like any other, that can be on the stack, or +new'd and deleted on the heap. + +However, any sub-node of the Document, XMLElement, XMLText, etc, can only +be created by calling the appropriate XMLDocument::NewElement, NewText, etc. +method. Although you have pointers to these objects, they are still owned +by the Document. When the Document is deleted, so are all the nodes it contains. + +### White Space + +#### Whitespace Preservation (default) + +Microsoft has an excellent article on white space: http://msdn.microsoft.com/en-us/library/ms256097.aspx + +By default, TinyXML-2 preserves white space in a (hopefully) sane way that is almost complient with the +spec. (TinyXML-1 used a completely different model, much more similar to 'collapse', below.) + +As a first step, all newlines / carriage-returns / line-feeds are normalized to a +line-feed character, as required by the XML spec. + +White space in text is preserved. For example: + + Hello, World + +The leading space before the "Hello" and the double space after the comma are +preserved. Line-feeds are preserved, as in this example: + + Hello again, + World + +However, white space between elements is **not** preserved. Although not strictly +compliant, tracking and reporting inter-element space is awkward, and not normally +valuable. TinyXML-2 sees these as the same XML: + + + 1 + 2 + 3 + + + 123 + +#### Whitespace Collapse + +For some applications, it is preferable to collapse whitespace. Collapsing +whitespace gives you "HTML-like" behavior, which is sometimes more suitable +for hand typed documents. + +TinyXML-2 supports this with the 'whitespace' parameter to the XMLDocument constructor. +(The default is to preserve whitespace, as described above.) + +However, you may also use COLLAPSE_WHITESPACE, which will: + +* Remove leading and trailing whitespace +* Convert newlines and line-feeds into a space character +* Collapse a run of any number of space characters into a single space character + +Note that (currently) there is a performance impact for using COLLAPSE_WHITESPACE. +It essentially causes the XML to be parsed twice. + +### Entities + +TinyXML-2 recognizes the pre-defined "character entities", meaning special +characters. Namely: + + & & + < < + > > + " " + ' ' + +These are recognized when the XML document is read, and translated to their +UTF-8 equivalents. For instance, text with the XML of: + + Far & Away + +will have the Value() of "Far & Away" when queried from the XMLText object, +and will be written back to the XML stream/file as an ampersand. + +Additionally, any character can be specified by its Unicode code point: +The syntax ` ` or ` ` are both to the non-breaking space character. +This is called a 'numeric character reference'. Any numeric character reference +that isn't one of the special entities above, will be read, but written as a +regular code point. The output is correct, but the entity syntax isn't preserved. + +### Printing + +#### Print to file +You can directly use the convenience function: + + XMLDocument doc; + ... + doc.SaveFile( "foo.xml" ); + +Or the XMLPrinter class: + + XMLPrinter printer( fp ); + doc.Print( &printer ); + +#### Print to memory +Printing to memory is supported by the XMLPrinter. + + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + +#### Print without an XMLDocument + +When loading, an XML parser is very useful. However, sometimes +when saving, it just gets in the way. The code is often set up +for streaming, and constructing the DOM is just overhead. + +The Printer supports the streaming case. The following code +prints out a trivially simple XML file without ever creating +an XML document. + + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + +Examples +-------- + +#### Load and parse an XML file. + + /* ------ Example 1: Load and parse an XML file. ---- */ + { + XMLDocument doc; + doc.LoadFile( "dream.xml" ); + } + +#### Lookup information. + + /* ------ Example 2: Lookup information. ---- */ + { + XMLDocument doc; + doc.LoadFile( "dream.xml" ); + + // Structure of the XML file: + // - Element "PLAY" the root Element, which is the + // FirstChildElement of the Document + // - - Element "TITLE" child of the root PLAY Element + // - - - Text child of the TITLE Element + + // Navigate to the title, using the convenience function, + // with a dangerous lack of error checking. + const char* title = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->GetText(); + printf( "Name of play (1): %s\n", title ); + + // Text is just another Node to TinyXML-2. The more + // general way to get to the XMLText: + XMLText* textNode = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->FirstChild()->ToText(); + title = textNode->Value(); + printf( "Name of play (2): %s\n", title ); + } + +Using and Installing +-------------------- + +There are 2 files in TinyXML-2: +* tinyxml2.cpp +* tinyxml2.h + +And additionally a test file: +* xmltest.cpp + +Simply compile and run. There is a visual studio 2010 project included, a simple Makefile, +an XCode project, a Code::Blocks project, and a cmake CMakeLists.txt included to help you. +The top of tinyxml.h even has a simple g++ command line if you are are *nix and don't want +to use a build system. + +Versioning +---------- + +TinyXML-2 uses semantic versioning. http://semver.org/ Releases are now tagged in github. + +Note that the major version will (probably) change fairly rapidly. API changes are fairly +common. + +Documentation +------------- + +The documentation is build with Doxygen, using the 'dox' +configuration file. + +License +------- + +TinyXML-2 is released under the zlib license: + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source +distribution. + +Contributors +------------ + +Thanks very much to everyone who sends suggestions, bugs, ideas, and +encouragement. It all helps, and makes this project fun. + +The original TinyXML-1 has many contributors, who all deserve thanks +in shaping what is a very successful library. Extra thanks to Yves +Berquin and Andrew Ellerton who were key contributors. + +TinyXML-2 grew from that effort. Lee Thomason is the original author +of TinyXML-2 (and TinyXML-1) but TinyXML-2 has been and is being improved +by many contributors. + +Thanks to John Mackay at http://john.mackay.rosalilastudio.com for the TinyXML-2 logo! + + diff --git a/lib/cpPlugins/tinyxml2/tinyxml2.cpp b/lib/cpPlugins/tinyxml2/tinyxml2.cpp new file mode 100644 index 0000000..df49d0d --- /dev/null +++ b/lib/cpPlugins/tinyxml2/tinyxml2.cpp @@ -0,0 +1,2467 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml2.h" + +#include // yes, this one new style header, is in the Android SDK. +#if defined(ANDROID_NDK) || defined(__QNXNTO__) +# include +# include +#else +# include +# include +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + // Microsoft Visual Studio, version 2005 and higher. Not WinCE. + /*int _snprintf_s( + char *buffer, + size_t sizeOfBuffer, + size_t count, + const char *format [, + argument] ... + );*/ + static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) + { + va_list va; + va_start( va, format ); + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + va_end( va ); + return result; + } + + static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va ) + { + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + return result; + } + + #define TIXML_VSCPRINTF _vscprintf + #define TIXML_SSCANF sscanf_s +#elif defined _MSC_VER + // Microsoft Visual Studio 2003 and earlier or WinCE + #define TIXML_SNPRINTF _snprintf + #define TIXML_VSNPRINTF _vsnprintf + #define TIXML_SSCANF sscanf + #if (_MSC_VER < 1400 ) && (!defined WINCE) + // Microsoft Visual Studio 2003 and not WinCE. + #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have. + #else + // Microsoft Visual Studio 2003 and earlier or WinCE. + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = 512; + for (;;) { + len = len*2; + char* str = new char[len](); + const int required = _vsnprintf(str, len, format, va); + delete[] str; + if ( required != -1 ) { + TIXMLASSERT( required >= 0 ); + len = required; + break; + } + } + TIXMLASSERT( len >= 0 ); + return len; + } + #endif +#else + // GCC version 3 and higher + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_VSNPRINTF vsnprintf + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = vsnprintf( 0, 0, format, va ); + TIXMLASSERT( len >= 0 ); + return len; + } + #define TIXML_SSCANF sscanf +#endif + + +static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF +static const char LF = LINE_FEED; +static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out +static const char CR = CARRIAGE_RETURN; +static const char SINGLE_QUOTE = '\''; +static const char DOUBLE_QUOTE = '\"'; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// ef bb bf (Microsoft "lead bytes") - designates UTF-8 + +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +namespace tinyxml2 +{ + +struct Entity { + const char* pattern; + int length; + char value; +}; + +static const int NUM_ENTITIES = 5; +static const Entity entities[NUM_ENTITIES] = { + { "quot", 4, DOUBLE_QUOTE }, + { "amp", 3, '&' }, + { "apos", 4, SINGLE_QUOTE }, + { "lt", 2, '<' }, + { "gt", 2, '>' } +}; + + +StrPair::~StrPair() +{ + Reset(); +} + + +void StrPair::TransferTo( StrPair* other ) +{ + if ( this == other ) { + return; + } + // This in effect implements the assignment operator by "moving" + // ownership (as in auto_ptr). + + TIXMLASSERT( other->_flags == 0 ); + TIXMLASSERT( other->_start == 0 ); + TIXMLASSERT( other->_end == 0 ); + + other->Reset(); + + other->_flags = _flags; + other->_start = _start; + other->_end = _end; + + _flags = 0; + _start = 0; + _end = 0; +} + +void StrPair::Reset() +{ + if ( _flags & NEEDS_DELETE ) { + delete [] _start; + } + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::SetStr( const char* str, int flags ) +{ + TIXMLASSERT( str ); + Reset(); + size_t len = strlen( str ); + TIXMLASSERT( _start == 0 ); + _start = new char[ len+1 ]; + memcpy( _start, str, len+1 ); + _end = _start + len; + _flags = flags | NEEDS_DELETE; +} + + +char* StrPair::ParseText( char* p, const char* endTag, int strFlags ) +{ + TIXMLASSERT( endTag && *endTag ); + + char* start = p; + char endChar = *endTag; + size_t length = strlen( endTag ); + + // Inner loop of text parsing. + while ( *p ) { + if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { + Set( start, p, strFlags ); + return p + length; + } + ++p; + } + return 0; +} + + +char* StrPair::ParseName( char* p ) +{ + if ( !p || !(*p) ) { + return 0; + } + if ( !XMLUtil::IsNameStartChar( *p ) ) { + return 0; + } + + char* const start = p; + ++p; + while ( *p && XMLUtil::IsNameChar( *p ) ) { + ++p; + } + + Set( start, p, 0 ); + return p; +} + + +void StrPair::CollapseWhitespace() +{ + // Adjusting _start would cause undefined behavior on delete[] + TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); + // Trim leading space. + _start = XMLUtil::SkipWhiteSpace( _start ); + + if ( *_start ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( *p ) { + if ( XMLUtil::IsWhiteSpace( *p )) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p == 0 ) { + break; // don't write to q; this trims the trailing space. + } + *q = ' '; + ++q; + } + *q = *p; + ++q; + ++p; + } + *q = 0; + } +} + + +const char* StrPair::GetStr() +{ + TIXMLASSERT( _start ); + TIXMLASSERT( _end ); + if ( _flags & NEEDS_FLUSH ) { + *_end = 0; + _flags ^= NEEDS_FLUSH; + + if ( _flags ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( p < _end ) { + if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { + // CR-LF pair becomes LF + // CR alone becomes LF + // LF-CR becomes LF + if ( *(p+1) == LF ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { + if ( *(p+1) == CR ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { + // Entities handled by tinyXML2: + // - special entities in the entity table [in/out] + // - numeric character reference [in] + // 中 or 中 + + if ( *(p+1) == '#' ) { + const int buflen = 10; + char buf[buflen] = { 0 }; + int len = 0; + char* adjusted = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); + if ( adjusted == 0 ) { + *q = *p; + ++p; + ++q; + } + else { + TIXMLASSERT( 0 <= len && len <= buflen ); + TIXMLASSERT( q + len <= adjusted ); + p = adjusted; + memcpy( q, buf, len ); + q += len; + } + } + else { + bool entityFound = false; + for( int i = 0; i < NUM_ENTITIES; ++i ) { + const Entity& entity = entities[i]; + if ( strncmp( p + 1, entity.pattern, entity.length ) == 0 + && *( p + entity.length + 1 ) == ';' ) { + // Found an entity - convert. + *q = entity.value; + ++q; + p += entity.length + 2; + entityFound = true; + break; + } + } + if ( !entityFound ) { + // fixme: treat as error? + ++p; + ++q; + } + } + } + else { + *q = *p; + ++p; + ++q; + } + } + *q = 0; + } + // The loop below has plenty going on, and this + // is a less useful mode. Break it out. + if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) { + CollapseWhitespace(); + } + _flags = (_flags & NEEDS_DELETE); + } + TIXMLASSERT( _start ); + return _start; +} + + + + +// --------- XMLUtil ----------- // + +const char* XMLUtil::ReadBOM( const char* p, bool* bom ) +{ + TIXMLASSERT( p ); + TIXMLASSERT( bom ); + *bom = false; + const unsigned char* pu = reinterpret_cast(p); + // Check for BOM: + if ( *(pu+0) == TIXML_UTF_LEAD_0 + && *(pu+1) == TIXML_UTF_LEAD_1 + && *(pu+2) == TIXML_UTF_LEAD_2 ) { + *bom = true; + p += 3; + } + TIXMLASSERT( p ); + return p; +} + + +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) { + *length = 1; + } + else if ( input < 0x800 ) { + *length = 2; + } + else if ( input < 0x10000 ) { + *length = 3; + } + else if ( input < 0x200000 ) { + *length = 4; + } + else { + *length = 0; // This code won't convert this correctly anyway. + return; + } + + output += *length; + + // Scary scary fall throughs. + switch (*length) { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + break; + default: + TIXMLASSERT( false ); + } +} + + +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) +{ + // Presume an entity, and pull it out. + *length = 0; + + if ( *(p+1) == '#' && *(p+2) ) { + unsigned long ucs = 0; + TIXMLASSERT( sizeof( ucs ) >= 4 ); + ptrdiff_t delta = 0; + unsigned mult = 1; + static const char SEMICOLON = ';'; + + if ( *(p+2) == 'x' ) { + // Hexadecimal. + const char* q = p+3; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != 'x' ) { + unsigned int digit = 0; + + if ( *q >= '0' && *q <= '9' ) { + digit = *q - '0'; + } + else if ( *q >= 'a' && *q <= 'f' ) { + digit = *q - 'a' + 10; + } + else if ( *q >= 'A' && *q <= 'F' ) { + digit = *q - 'A' + 10; + } + else { + return 0; + } + TIXMLASSERT( digit >= 0 && digit < 16); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + TIXMLASSERT( mult <= UINT_MAX / 16 ); + mult *= 16; + --q; + } + } + else { + // Decimal. + const char* q = p+2; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != '#' ) { + if ( *q >= '0' && *q <= '9' ) { + const unsigned int digit = *q - '0'; + TIXMLASSERT( digit >= 0 && digit < 10); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + } + else { + return 0; + } + TIXMLASSERT( mult <= UINT_MAX / 10 ); + mult *= 10; + --q; + } + } + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + return p + delta + 1; + } + return p+1; +} + + +void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); +} + + +void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); +} + + +void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 ); +} + +/* + ToStr() of a number is a very tricky topic. + https://github.com/leethomason/tinyxml2/issues/106 +*/ +void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); +} + + +void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); +} + + +bool XMLUtil::ToInt( const char* str, int* value ) +{ + if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) +{ + if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToBool( const char* str, bool* value ) +{ + int ival = 0; + if ( ToInt( str, &ival )) { + *value = (ival==0) ? false : true; + return true; + } + if ( StringEqual( str, "true" ) ) { + *value = true; + return true; + } + else if ( StringEqual( str, "false" ) ) { + *value = false; + return true; + } + return false; +} + + +bool XMLUtil::ToFloat( const char* str, float* value ) +{ + if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToDouble( const char* str, double* value ) +{ + if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { + return true; + } + return false; +} + + +char* XMLDocument::Identify( char* p, XMLNode** node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( p ); + char* const start = p; + p = XMLUtil::SkipWhiteSpace( p ); + if( !*p ) { + *node = 0; + TIXMLASSERT( p ); + return p; + } + + // These strings define the matching patterns: + static const char* xmlHeader = { "_memPool = &_commentPool; + p += xmlHeaderLen; + } + else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLComment( this ); + returnNode->_memPool = &_commentPool; + p += commentHeaderLen; + } + else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + returnNode = text; + returnNode->_memPool = &_textPool; + p += cdataHeaderLen; + text->SetCData( true ); + } + else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode->_memPool = &_commentPool; + p += dtdHeaderLen; + } + else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + returnNode = new (_elementPool.Alloc()) XMLElement( this ); + returnNode->_memPool = &_elementPool; + p += elementHeaderLen; + } + else { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + returnNode = new (_textPool.Alloc()) XMLText( this ); + returnNode->_memPool = &_textPool; + p = start; // Back it up, all the text counts. + } + + TIXMLASSERT( returnNode ); + TIXMLASSERT( p ); + *node = returnNode; + return p; +} + + +bool XMLDocument::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLNode ----------- // + +XMLNode::XMLNode( XMLDocument* doc ) : + _document( doc ), + _parent( 0 ), + _firstChild( 0 ), _lastChild( 0 ), + _prev( 0 ), _next( 0 ), + _memPool( 0 ) +{ +} + + +XMLNode::~XMLNode() +{ + DeleteChildren(); + if ( _parent ) { + _parent->Unlink( this ); + } +} + +const char* XMLNode::Value() const +{ + // Catch an edge case: XMLDocuments don't have a a Value. Carefully return nullptr. + if ( this->ToDocument() ) + return 0; + return _value.GetStr(); +} + +void XMLNode::SetValue( const char* str, bool staticMem ) +{ + if ( staticMem ) { + _value.SetInternedStr( str ); + } + else { + _value.SetStr( str ); + } +} + + +void XMLNode::DeleteChildren() +{ + while( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_document == _document ); + XMLNode* node = _firstChild; + Unlink( node ); + + DeleteNode( node ); + } + _firstChild = _lastChild = 0; +} + + +void XMLNode::Unlink( XMLNode* child ) +{ + TIXMLASSERT( child ); + TIXMLASSERT( child->_document == _document ); + TIXMLASSERT( child->_parent == this ); + if ( child == _firstChild ) { + _firstChild = _firstChild->_next; + } + if ( child == _lastChild ) { + _lastChild = _lastChild->_prev; + } + + if ( child->_prev ) { + child->_prev->_next = child->_next; + } + if ( child->_next ) { + child->_next->_prev = child->_prev; + } + child->_parent = 0; +} + + +void XMLNode::DeleteChild( XMLNode* node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( node->_document == _document ); + TIXMLASSERT( node->_parent == this ); + Unlink( node ); + DeleteNode( node ); +} + + +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _lastChild ) { + TIXMLASSERT( _firstChild ); + TIXMLASSERT( _lastChild->_next == 0 ); + _lastChild->_next = addThis; + addThis->_prev = _lastChild; + _lastChild = addThis; + + addThis->_next = 0; + } + else { + TIXMLASSERT( _firstChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_prev == 0 ); + + _firstChild->_prev = addThis; + addThis->_next = _firstChild; + _firstChild = addThis; + + addThis->_prev = 0; + } + else { + TIXMLASSERT( _lastChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + + TIXMLASSERT( afterThis ); + + if ( afterThis->_parent != this ) { + TIXMLASSERT( false ); + return 0; + } + + if ( afterThis->_next == 0 ) { + // The last node or the only node. + return InsertEndChild( addThis ); + } + InsertChildPreamble( addThis ); + addThis->_prev = afterThis; + addThis->_next = afterThis->_next; + afterThis->_next->_prev = addThis; + afterThis->_next = addThis; + addThis->_parent = this; + return addThis; +} + + + + +const XMLElement* XMLNode::FirstChildElement( const char* name ) const +{ + for( const XMLNode* node = _firstChild; node; node = node->_next ) { + const XMLElement* element = node->ToElement(); + if ( element ) { + if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::LastChildElement( const char* name ) const +{ + for( const XMLNode* node = _lastChild; node; node = node->_prev ) { + const XMLElement* element = node->ToElement(); + if ( element ) { + if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::NextSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _next; node; node = node->_next ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!name || XMLUtil::StringEqual( name, element->Name() ))) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _prev; node; node = node->_prev ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!name || XMLUtil::StringEqual( name, element->Name() ))) { + return element; + } + } + return 0; +} + + +char* XMLNode::ParseDeep( char* p, StrPair* parentEnd ) +{ + // This is a recursive method, but thinking about it "at the current level" + // it is a pretty simple flat list: + // + // + // + // With a special case: + // + // + // + // + // Where the closing element (/foo) *must* be the next thing after the opening + // element, and the names must match. BUT the tricky bit is that the closing + // element will be read by the child. + // + // 'endTag' is the end tag for this node, it is returned by a call to a child. + // 'parentEnd' is the end tag for the parent, which is filled in and returned. + + while( p && *p ) { + XMLNode* node = 0; + + p = _document->Identify( p, &node ); + if ( node == 0 ) { + break; + } + + StrPair endTag; + p = node->ParseDeep( p, &endTag ); + if ( !p ) { + DeleteNode( node ); + if ( !_document->Error() ) { + _document->SetError( XML_ERROR_PARSING, 0, 0 ); + } + break; + } + + XMLDeclaration* decl = node->ToDeclaration(); + if ( decl ) { + // A declaration can only be the first child of a document. + // Set error, if document already has children. + if ( !_document->NoChildren() ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, decl->Value(), 0); + DeleteNode( decl ); + break; + } + } + + XMLElement* ele = node->ToElement(); + if ( ele ) { + // We read the end tag. Return it to the parent. + if ( ele->ClosingType() == XMLElement::CLOSING ) { + if ( parentEnd ) { + ele->_value.TransferTo( parentEnd ); + } + node->_memPool->SetTracked(); // created and then immediately deleted. + DeleteNode( node ); + return p; + } + + // Handle an end tag returned to this level. + // And handle a bunch of annoying errors. + bool mismatch = false; + if ( endTag.Empty() ) { + if ( ele->ClosingType() == XMLElement::OPEN ) { + mismatch = true; + } + } + else { + if ( ele->ClosingType() != XMLElement::OPEN ) { + mismatch = true; + } + else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) { + mismatch = true; + } + } + if ( mismatch ) { + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, ele->Name(), 0 ); + DeleteNode( node ); + break; + } + } + InsertEndChild( node ); + } + return 0; +} + +void XMLNode::DeleteNode( XMLNode* node ) +{ + if ( node == 0 ) { + return; + } + MemPool* pool = node->_memPool; + node->~XMLNode(); + pool->Free( node ); +} + +void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const +{ + TIXMLASSERT( insertThis ); + TIXMLASSERT( insertThis->_document == _document ); + + if ( insertThis->_parent ) + insertThis->_parent->Unlink( insertThis ); + else + insertThis->_memPool->SetTracked(); +} + +// --------- XMLText ---------- // +char* XMLText::ParseDeep( char* p, StrPair* ) +{ + const char* start = p; + if ( this->CData() ) { + p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 ); + } + return p; + } + else { + int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; + if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { + flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING; + } + + p = _value.ParseText( p, "<", flags ); + if ( p && *p ) { + return p-1; + } + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 ); + } + } + return 0; +} + + +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? + text->SetCData( this->CData() ); + return text; +} + + +bool XMLText::ShallowEqual( const XMLNode* compare ) const +{ + const XMLText* text = compare->ToText(); + return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); +} + + +bool XMLText::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLComment ---------- // + +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLComment::~XMLComment() +{ +} + + +char* XMLComment::ParseDeep( char* p, StrPair* ) +{ + // Comment parses as text. + const char* start = p; + p = _value.ParseText( p, "-->", StrPair::COMMENT ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 ); + } + return p; +} + + +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? + return comment; +} + + +bool XMLComment::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLComment* comment = compare->ToComment(); + return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); +} + + +bool XMLComment::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLDeclaration ---------- // + +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDeclaration::~XMLDeclaration() +{ + //printf( "~XMLDeclaration\n" ); +} + + +char* XMLDeclaration::ParseDeep( char* p, StrPair* ) +{ + // Declaration parses as text. + const char* start = p; + p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 ); + } + return p; +} + + +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? + return dec; +} + + +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLDeclaration* declaration = compare->ToDeclaration(); + return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); +} + + + +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLUnknown ---------- // + +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLUnknown::~XMLUnknown() +{ +} + + +char* XMLUnknown::ParseDeep( char* p, StrPair* ) +{ + // Unknown parses as text. + const char* start = p; + + p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 ); + } + return p; +} + + +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? + return text; +} + + +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLUnknown* unknown = compare->ToUnknown(); + return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); +} + + +bool XMLUnknown::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLAttribute ---------- // + +const char* XMLAttribute::Name() const +{ + return _name.GetStr(); +} + +const char* XMLAttribute::Value() const +{ + return _value.GetStr(); +} + +char* XMLAttribute::ParseDeep( char* p, bool processEntities ) +{ + // Parse using the name rules: bug fix, was using ParseText before + p = _name.ParseName( p ); + if ( !p || !*p ) { + return 0; + } + + // Skip white space before = + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '=' ) { + return 0; + } + + ++p; // move up to opening quote + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '\"' && *p != '\'' ) { + return 0; + } + + char endTag[2] = { *p, 0 }; + ++p; // move past opening quote + + p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES ); + return p; +} + + +void XMLAttribute::SetName( const char* n ) +{ + _name.SetStr( n ); +} + + +XMLError XMLAttribute::QueryIntValue( int* value ) const +{ + if ( XMLUtil::ToInt( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const +{ + if ( XMLUtil::ToUnsigned( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryBoolValue( bool* value ) const +{ + if ( XMLUtil::ToBool( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryFloatValue( float* value ) const +{ + if ( XMLUtil::ToFloat( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryDoubleValue( double* value ) const +{ + if ( XMLUtil::ToDouble( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +void XMLAttribute::SetAttribute( const char* v ) +{ + _value.SetStr( v ); +} + + +void XMLAttribute::SetAttribute( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +// --------- XMLElement ---------- // +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), + _closingType( 0 ), + _rootAttribute( 0 ) +{ +} + + +XMLElement::~XMLElement() +{ + while( _rootAttribute ) { + XMLAttribute* next = _rootAttribute->_next; + DeleteAttribute( _rootAttribute ); + _rootAttribute = next; + } +} + + +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const +{ + for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) { + return a; + } + } + return 0; +} + + +const char* XMLElement::Attribute( const char* name, const char* value ) const +{ + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return 0; + } + if ( !value || XMLUtil::StringEqual( a->Value(), value )) { + return a->Value(); + } + return 0; +} + + +const char* XMLElement::GetText() const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + return FirstChild()->Value(); + } + return 0; +} + + +void XMLElement::SetText( const char* inText ) +{ + if ( FirstChild() && FirstChild()->ToText() ) + FirstChild()->SetValue( inText ); + else { + XMLText* theText = GetDocument()->NewText( inText ); + InsertFirstChild( theText ); + } +} + + +void XMLElement::SetText( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +XMLError XMLElement::QueryIntText( int* ival ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToInt( t, ival ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToUnsigned( t, uval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryBoolText( bool* bval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToBool( t, bval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryDoubleText( double* dval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToDouble( t, dval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryFloatText( float* fval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToFloat( t, fval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + + +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) +{ + XMLAttribute* last = 0; + XMLAttribute* attrib = 0; + for( attrib = _rootAttribute; + attrib; + last = attrib, attrib = attrib->_next ) { + if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { + break; + } + } + if ( !attrib ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + if ( last ) { + last->_next = attrib; + } + else { + _rootAttribute = attrib; + } + attrib->SetName( name ); + attrib->_memPool->SetTracked(); // always created and linked. + } + return attrib; +} + + +void XMLElement::DeleteAttribute( const char* name ) +{ + XMLAttribute* prev = 0; + for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { + if ( XMLUtil::StringEqual( name, a->Name() ) ) { + if ( prev ) { + prev->_next = a->_next; + } + else { + _rootAttribute = a->_next; + } + DeleteAttribute( a ); + break; + } + prev = a; + } +} + + +char* XMLElement::ParseAttributes( char* p ) +{ + const char* start = p; + XMLAttribute* prevAttribute = 0; + + // Read the attributes. + while( p ) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( !(*p) ) { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() ); + return 0; + } + + // attribute. + if (XMLUtil::IsNameStartChar( *p ) ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + attrib->_memPool->SetTracked(); + + p = attrib->ParseDeep( p, _document->ProcessEntities() ); + if ( !p || Attribute( attrib->Name() ) ) { + DeleteAttribute( attrib ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p ); + return 0; + } + // There is a minor bug here: if the attribute in the source xml + // document is duplicated, it will not be detected and the + // attribute will be doubly added. However, tracking the 'prevAttribute' + // avoids re-scanning the attribute list. Preferring performance for + // now, may reconsider in the future. + if ( prevAttribute ) { + prevAttribute->_next = attrib; + } + else { + _rootAttribute = attrib; + } + prevAttribute = attrib; + } + // end of the tag + else if ( *p == '>' ) { + ++p; + break; + } + // end of the tag + else if ( *p == '/' && *(p+1) == '>' ) { + _closingType = CLOSED; + return p+2; // done; sealed element. + } + else { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p ); + return 0; + } + } + return p; +} + +void XMLElement::DeleteAttribute( XMLAttribute* attribute ) +{ + if ( attribute == 0 ) { + return; + } + MemPool* pool = attribute->_memPool; + attribute->~XMLAttribute(); + pool->Free( attribute ); +} + +// +// +// foobar +// +char* XMLElement::ParseDeep( char* p, StrPair* strPair ) +{ + // Read the element name. + p = XMLUtil::SkipWhiteSpace( p ); + + // The closing element is the form. It is + // parsed just like a regular element then deleted from + // the DOM. + if ( *p == '/' ) { + _closingType = CLOSING; + ++p; + } + + p = _value.ParseName( p ); + if ( _value.Empty() ) { + return 0; + } + + p = ParseAttributes( p ); + if ( !p || !*p || _closingType ) { + return p; + } + + p = XMLNode::ParseDeep( p, strPair ); + return p; +} + + + +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? + for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { + element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? + } + return element; +} + + +bool XMLElement::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLElement* other = compare->ToElement(); + if ( other && XMLUtil::StringEqual( other->Name(), Name() )) { + + const XMLAttribute* a=FirstAttribute(); + const XMLAttribute* b=other->FirstAttribute(); + + while ( a && b ) { + if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { + return false; + } + a = a->Next(); + b = b->Next(); + } + if ( a || b ) { + // different count + return false; + } + return true; + } + return false; +} + + +bool XMLElement::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this, _rootAttribute ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLDocument ----------- // + +// Warning: List must match 'enum XMLError' +const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { + "XML_SUCCESS", + "XML_NO_ATTRIBUTE", + "XML_WRONG_ATTRIBUTE_TYPE", + "XML_ERROR_FILE_NOT_FOUND", + "XML_ERROR_FILE_COULD_NOT_BE_OPENED", + "XML_ERROR_FILE_READ_ERROR", + "XML_ERROR_ELEMENT_MISMATCH", + "XML_ERROR_PARSING_ELEMENT", + "XML_ERROR_PARSING_ATTRIBUTE", + "XML_ERROR_IDENTIFYING_TAG", + "XML_ERROR_PARSING_TEXT", + "XML_ERROR_PARSING_CDATA", + "XML_ERROR_PARSING_COMMENT", + "XML_ERROR_PARSING_DECLARATION", + "XML_ERROR_PARSING_UNKNOWN", + "XML_ERROR_EMPTY_DOCUMENT", + "XML_ERROR_MISMATCHED_ELEMENT", + "XML_ERROR_PARSING", + "XML_CAN_NOT_CONVERT_TEXT", + "XML_NO_TEXT_NODE" +}; + + +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : + XMLNode( 0 ), + _writeBOM( false ), + _processEntities( processEntities ), + _errorID( XML_NO_ERROR ), + _whitespace( whitespace ), + _errorStr1( 0 ), + _errorStr2( 0 ), + _charBuffer( 0 ) +{ + // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) + _document = this; +} + + +XMLDocument::~XMLDocument() +{ + Clear(); +} + + +void XMLDocument::Clear() +{ + DeleteChildren(); + +#ifdef DEBUG + const bool hadError = Error(); +#endif + _errorID = XML_NO_ERROR; + _errorStr1 = 0; + _errorStr2 = 0; + + delete [] _charBuffer; + _charBuffer = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef DEBUG + if ( !hadError ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif +} + + +XMLElement* XMLDocument::NewElement( const char* name ) +{ + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); + ele->_memPool = &_elementPool; + ele->SetName( name ); + return ele; +} + + +XMLComment* XMLDocument::NewComment( const char* str ) +{ + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); + comment->_memPool = &_commentPool; + comment->SetValue( str ); + return comment; +} + + +XMLText* XMLDocument::NewText( const char* str ) +{ + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + text->_memPool = &_textPool; + text->SetValue( str ); + return text; +} + + +XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) +{ + TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); + XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); + dec->_memPool = &_commentPool; + dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); + return dec; +} + + +XMLUnknown* XMLDocument::NewUnknown( const char* str ) +{ + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); + unk->_memPool = &_commentPool; + unk->SetValue( str ); + return unk; +} + +static FILE* callfopen( const char* filepath, const char* mode ) +{ + TIXMLASSERT( filepath ); + TIXMLASSERT( mode ); +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filepath, mode ); + if ( err ) { + return 0; + } +#else + FILE* fp = fopen( filepath, mode ); +#endif + return fp; +} + +void XMLDocument::DeleteNode( XMLNode* node ) { + TIXMLASSERT( node ); + TIXMLASSERT(node->_document == this ); + if (node->_parent) { + node->_parent->DeleteChild( node ); + } + else { + // Isn't in the tree. + // Use the parent delete. + // Also, we need to mark it tracked: we 'know' + // it was never used. + node->_memPool->SetTracked(); + // Call the static XMLNode version: + XMLNode::DeleteNode(node); + } +} + + +XMLError XMLDocument::LoadFile( const char* filename ) +{ + Clear(); + FILE* fp = callfopen( filename, "rb" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 ); + return _errorID; + } + LoadFile( fp ); + fclose( fp ); + return _errorID; +} + +// This is likely overengineered template art to have a check that unsigned long value incremented +// by one still fits into size_t. If size_t type is larger than unsigned long type +// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit +// -Wtype-limits warning. This piece makes the compiler select code with a check when a check +// is useful and code with no check when a check is redundant depending on how size_t and unsigned long +// types sizes relate to each other. +template += sizeof(size_t))> +struct LongFitsIntoSizeTMinusOne { + static bool Fits( unsigned long value ) + { + return value < (size_t)-1; + } +}; + +template <> +bool LongFitsIntoSizeTMinusOne::Fits( unsigned long /*value*/ ) +{ + return true; +} + +XMLError XMLDocument::LoadFile( FILE* fp ) +{ + Clear(); + + fseek( fp, 0, SEEK_SET ); + if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + fseek( fp, 0, SEEK_END ); + const long filelength = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + if ( filelength == -1L ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + TIXMLASSERT( filelength >= 0 ); + + if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) { + // Cannot handle files which won't fit in buffer together with null terminator + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + if ( filelength == 0 ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + + const size_t size = filelength; + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = new char[size+1]; + size_t read = fread( _charBuffer, 1, size, fp ); + if ( read != size ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + _charBuffer[size] = 0; + + Parse(); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( const char* filename, bool compact ) +{ + FILE* fp = callfopen( filename, "w" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 ); + return _errorID; + } + SaveFile(fp, compact); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) +{ + // Clear any error from the last save, otherwise it will get reported + // for *this* call. + SetError( XML_NO_ERROR, 0, 0 ); + XMLPrinter stream( fp, compact ); + Print( &stream ); + return _errorID; +} + + +XMLError XMLDocument::Parse( const char* p, size_t len ) +{ + Clear(); + + if ( len == 0 || !p || !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + if ( len == (size_t)(-1) ) { + len = strlen( p ); + } + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = new char[ len+1 ]; + memcpy( _charBuffer, p, len ); + _charBuffer[len] = 0; + + Parse(); + if ( Error() ) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } + return _errorID; +} + + +void XMLDocument::Print( XMLPrinter* streamer ) const +{ + if ( streamer ) { + Accept( streamer ); + } + else { + XMLPrinter stdoutStreamer( stdout ); + Accept( &stdoutStreamer ); + } +} + + +void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) +{ + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); + _errorID = error; + _errorStr1 = str1; + _errorStr2 = str2; +} + +const char* XMLDocument::ErrorName() const +{ + TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT ); + const char* errorName = _errorNames[_errorID]; + TIXMLASSERT( errorName && errorName[0] ); + return errorName; +} + +void XMLDocument::PrintError() const +{ + if ( Error() ) { + static const int LEN = 20; + char buf1[LEN] = { 0 }; + char buf2[LEN] = { 0 }; + + if ( _errorStr1 ) { + TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 ); + } + if ( _errorStr2 ) { + TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 ); + } + + // Should check INT_MIN <= _errorID && _errorId <= INT_MAX, but that + // causes a clang "always true" -Wtautological-constant-out-of-range-compare warning + TIXMLASSERT( 0 <= _errorID && XML_ERROR_COUNT - 1 <= INT_MAX ); + printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n", + static_cast( _errorID ), ErrorName(), buf1, buf2 ); + } +} + +void XMLDocument::Parse() +{ + TIXMLASSERT( NoChildren() ); // Clear() must have been called previously + TIXMLASSERT( _charBuffer ); + char* p = _charBuffer; + p = XMLUtil::SkipWhiteSpace( p ); + p = const_cast( XMLUtil::ReadBOM( p, &_writeBOM ) ); + if ( !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return; + } + ParseDeep(p, 0 ); +} + +XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : + _elementJustOpened( false ), + _firstElement( true ), + _fp( file ), + _depth( depth ), + _textDepth( -1 ), + _processEntities( true ), + _compactMode( compact ) +{ + for( int i=0; i'] = true; // not required, but consistency is nice + _buffer.Push( 0 ); +} + + +void XMLPrinter::Print( const char* format, ... ) +{ + va_list va; + va_start( va, format ); + + if ( _fp ) { + vfprintf( _fp, format, va ); + } + else { + const int len = TIXML_VSCPRINTF( format, va ); + // Close out and re-start the va-args + va_end( va ); + TIXMLASSERT( len >= 0 ); + va_start( va, format ); + TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); + char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. + TIXML_VSNPRINTF( p, len+1, format, va ); + } + va_end( va ); +} + + +void XMLPrinter::PrintSpace( int depth ) +{ + for( int i=0; i 0 && *q < ENTITY_RANGE ) { + // Check for entities. If one is found, flush + // the stream up until the entity, write the + // entity, and keep looking. + if ( flag[(unsigned char)(*q)] ) { + while ( p < q ) { + const size_t delta = q - p; + // %.*s accepts type int as "precision" + const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; + Print( "%.*s", toPrint, p ); + p += toPrint; + } + bool entityPatternPrinted = false; + for( int i=0; i" ); + } + else { + if ( _textDepth < 0 && !compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + Print( "", name ); + } + + if ( _textDepth == _depth ) { + _textDepth = -1; + } + if ( _depth == 0 && !compactMode) { + Print( "\n" ); + } + _elementJustOpened = false; +} + + +void XMLPrinter::SealElementIfJustOpened() +{ + if ( !_elementJustOpened ) { + return; + } + _elementJustOpened = false; + Print( ">" ); +} + + +void XMLPrinter::PushText( const char* text, bool cdata ) +{ + _textDepth = _depth-1; + + SealElementIfJustOpened(); + if ( cdata ) { + Print( "", text ); + } + else { + PrintString( text, true ); + } +} + +void XMLPrinter::PushText( int value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( unsigned value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( bool value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( float value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( double value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushComment( const char* comment ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", comment ); +} + + +void XMLPrinter::PushDeclaration( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +void XMLPrinter::PushUnknown( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +bool XMLPrinter::VisitEnter( const XMLDocument& doc ) +{ + _processEntities = doc.ProcessEntities(); + if ( doc.HasBOM() ) { + PushHeader( true, false ); + } + return true; +} + + +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) +{ + const XMLElement* parentElem = 0; + if ( element.Parent() ) { + parentElem = element.Parent()->ToElement(); + } + const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode; + OpenElement( element.Name(), compactMode ); + while ( attribute ) { + PushAttribute( attribute->Name(), attribute->Value() ); + attribute = attribute->Next(); + } + return true; +} + + +bool XMLPrinter::VisitExit( const XMLElement& element ) +{ + CloseElement( CompactMode(element) ); + return true; +} + + +bool XMLPrinter::Visit( const XMLText& text ) +{ + PushText( text.Value(), text.CData() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLComment& comment ) +{ + PushComment( comment.Value() ); + return true; +} + +bool XMLPrinter::Visit( const XMLDeclaration& declaration ) +{ + PushDeclaration( declaration.Value() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLUnknown& unknown ) +{ + PushUnknown( unknown.Value() ); + return true; +} + +} // namespace tinyxml2 + diff --git a/lib/cpPlugins/tinyxml2/tinyxml2.h b/lib/cpPlugins/tinyxml2/tinyxml2.h new file mode 100644 index 0000000..3598786 --- /dev/null +++ b/lib/cpPlugins/tinyxml2/tinyxml2.h @@ -0,0 +1,2106 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#ifndef TINYXML2_INCLUDED +#define TINYXML2_INCLUDED + +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +#endif + +/* + TODO: intern strings instead of allocation. +*/ +/* + gcc: + g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe + + Formatting, Artistic Style: + AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h +*/ + +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) +# ifndef DEBUG +# define DEBUG +# endif +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4251) +#endif + +#ifdef _WIN32 +# ifdef TINYXML2_EXPORT +# define TINYXML2_LIB __declspec(dllexport) +# elif defined(TINYXML2_IMPORT) +# define TINYXML2_LIB __declspec(dllimport) +# else +# define TINYXML2_LIB +# endif +#else +# define TINYXML2_LIB +#endif + + +#if defined(DEBUG) +# if defined(_MSC_VER) +# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like +# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } +# elif defined (ANDROID_NDK) +# include +# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } +# else +# include +# define TIXMLASSERT assert +# endif +#else +# define TIXMLASSERT( x ) {} +#endif + + +/* Versioning, past 1.0.14: + http://semver.org/ +*/ +static const int TIXML2_MAJOR_VERSION = 3; +static const int TIXML2_MINOR_VERSION = 0; +static const int TIXML2_PATCH_VERSION = 0; + +#include +#undef TINYXML2_LIB +#define TINYXML2_LIB cpPlugins_EXPORT + +namespace tinyxml2 +{ +class XMLDocument; +class XMLElement; +class XMLAttribute; +class XMLComment; +class XMLText; +class XMLDeclaration; +class XMLUnknown; +class XMLPrinter; + +/* + A class that wraps strings. Normally stores the start and end + pointers into the XML file itself, and will apply normalization + and entity translation if actually read. Can also store (and memory + manage) a traditional char[] +*/ +class StrPair +{ +public: + enum { + NEEDS_ENTITY_PROCESSING = 0x01, + NEEDS_NEWLINE_NORMALIZATION = 0x02, + NEEDS_WHITESPACE_COLLAPSING = 0x04, + + TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_NAME = 0, + ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + COMMENT = NEEDS_NEWLINE_NORMALIZATION + }; + + StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} + ~StrPair(); + + void Set( char* start, char* end, int flags ) { + Reset(); + _start = start; + _end = end; + _flags = flags | NEEDS_FLUSH; + } + + const char* GetStr(); + + bool Empty() const { + return _start == _end; + } + + void SetInternedStr( const char* str ) { + Reset(); + _start = const_cast(str); + } + + void SetStr( const char* str, int flags=0 ); + + char* ParseText( char* in, const char* endTag, int strFlags ); + char* ParseName( char* in ); + + void TransferTo( StrPair* other ); + +private: + void Reset(); + void CollapseWhitespace(); + + enum { + NEEDS_FLUSH = 0x100, + NEEDS_DELETE = 0x200 + }; + + int _flags; + char* _start; + char* _end; + + StrPair( const StrPair& other ); // not supported + void operator=( StrPair& other ); // not supported, use TransferTo() +}; + + +/* + A dynamic array of Plain Old Data. Doesn't support constructors, etc. + Has a small initial memory pool, so that low or no usage will not + cause a call to new/delete +*/ +template +class DynArray +{ +public: + DynArray() { + _mem = _pool; + _allocated = INITIAL_SIZE; + _size = 0; + } + + ~DynArray() { + if ( _mem != _pool ) { + delete [] _mem; + } + } + + void Clear() { + _size = 0; + } + + void Push( T t ) { + TIXMLASSERT( _size < INT_MAX ); + EnsureCapacity( _size+1 ); + _mem[_size++] = t; + } + + T* PushArr( int count ) { + TIXMLASSERT( count >= 0 ); + TIXMLASSERT( _size <= INT_MAX - count ); + EnsureCapacity( _size+count ); + T* ret = &_mem[_size]; + _size += count; + return ret; + } + + T Pop() { + TIXMLASSERT( _size > 0 ); + return _mem[--_size]; + } + + void PopArr( int count ) { + TIXMLASSERT( _size >= count ); + _size -= count; + } + + bool Empty() const { + return _size == 0; + } + + T& operator[](int i) { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& operator[](int i) const { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& PeekTop() const { + TIXMLASSERT( _size > 0 ); + return _mem[ _size - 1]; + } + + int Size() const { + TIXMLASSERT( _size >= 0 ); + return _size; + } + + int Capacity() const { + TIXMLASSERT( _allocated >= INITIAL_SIZE ); + return _allocated; + } + + const T* Mem() const { + TIXMLASSERT( _mem ); + return _mem; + } + + T* Mem() { + TIXMLASSERT( _mem ); + return _mem; + } + +private: + DynArray( const DynArray& ); // not supported + void operator=( const DynArray& ); // not supported + + void EnsureCapacity( int cap ) { + TIXMLASSERT( cap > 0 ); + if ( cap > _allocated ) { + TIXMLASSERT( cap <= INT_MAX / 2 ); + int newAllocated = cap * 2; + T* newMem = new T[newAllocated]; + memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs + if ( _mem != _pool ) { + delete [] _mem; + } + _mem = newMem; + _allocated = newAllocated; + } + } + + T* _mem; + T _pool[INITIAL_SIZE]; + int _allocated; // objects allocated + int _size; // number objects in use +}; + + +/* + Parent virtual class of a pool for fast allocation + and deallocation of objects. +*/ +class MemPool +{ +public: + MemPool() {} + virtual ~MemPool() {} + + virtual int ItemSize() const = 0; + virtual void* Alloc() = 0; + virtual void Free( void* ) = 0; + virtual void SetTracked() = 0; + virtual void Clear() = 0; +}; + + +/* + Template child class to create pools of the correct type. +*/ +template< int SIZE > +class MemPoolT : public MemPool +{ +public: + MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} + ~MemPoolT() { + Clear(); + } + + void Clear() { + // Delete the blocks. + while( !_blockPtrs.Empty()) { + Block* b = _blockPtrs.Pop(); + delete b; + } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; + } + + virtual int ItemSize() const { + return SIZE; + } + int CurrentAllocs() const { + return _currentAllocs; + } + + virtual void* Alloc() { + if ( !_root ) { + // Need a new block. + Block* block = new Block(); + _blockPtrs.Push( block ); + + for( int i=0; ichunk[i].next = &block->chunk[i+1]; + } + block->chunk[COUNT-1].next = 0; + _root = block->chunk; + } + void* result = _root; + _root = _root->next; + + ++_currentAllocs; + if ( _currentAllocs > _maxAllocs ) { + _maxAllocs = _currentAllocs; + } + _nAllocs++; + _nUntracked++; + return result; + } + + virtual void Free( void* mem ) { + if ( !mem ) { + return; + } + --_currentAllocs; + Chunk* chunk = static_cast( mem ); +#ifdef DEBUG + memset( chunk, 0xfe, sizeof(Chunk) ); +#endif + chunk->next = _root; + _root = chunk; + } + void Trace( const char* name ) { + printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", + name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); + } + + void SetTracked() { + _nUntracked--; + } + + int Untracked() const { + return _nUntracked; + } + + // This number is perf sensitive. 4k seems like a good tradeoff on my machine. + // The test file is large, 170k. + // Release: VS2010 gcc(no opt) + // 1k: 4000 + // 2k: 4000 + // 4k: 3900 21000 + // 16k: 5200 + // 32k: 4300 + // 64k: 4000 21000 + enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private + +private: + MemPoolT( const MemPoolT& ); // not supported + void operator=( const MemPoolT& ); // not supported + + union Chunk { + Chunk* next; + char mem[SIZE]; + }; + struct Block { + Chunk chunk[COUNT]; + }; + DynArray< Block*, 10 > _blockPtrs; + Chunk* _root; + + int _currentAllocs; + int _nAllocs; + int _maxAllocs; + int _nUntracked; +}; + + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a XMLVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its siblings will be visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the XMLDocument, although all nodes support visiting. + + You should never change the document from a callback. + + @sa XMLNode::Accept() +*/ +class TINYXML2_LIB XMLVisitor +{ +public: + virtual ~XMLVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { + return true; + } + /// Visit a document. + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + /// Visit an element. + virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { + return true; + } + /// Visit an element. + virtual bool VisitExit( const XMLElement& /*element*/ ) { + return true; + } + + /// Visit a declaration. + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { + return true; + } + /// Visit a text node. + virtual bool Visit( const XMLText& /*text*/ ) { + return true; + } + /// Visit a comment node. + virtual bool Visit( const XMLComment& /*comment*/ ) { + return true; + } + /// Visit an unknown node. + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { + return true; + } +}; + +// WARNING: must match XMLDocument::_errorNames[] +enum XMLError { + XML_SUCCESS = 0, + XML_NO_ERROR = 0, + XML_NO_ATTRIBUTE, + XML_WRONG_ATTRIBUTE_TYPE, + XML_ERROR_FILE_NOT_FOUND, + XML_ERROR_FILE_COULD_NOT_BE_OPENED, + XML_ERROR_FILE_READ_ERROR, + XML_ERROR_ELEMENT_MISMATCH, + XML_ERROR_PARSING_ELEMENT, + XML_ERROR_PARSING_ATTRIBUTE, + XML_ERROR_IDENTIFYING_TAG, + XML_ERROR_PARSING_TEXT, + XML_ERROR_PARSING_CDATA, + XML_ERROR_PARSING_COMMENT, + XML_ERROR_PARSING_DECLARATION, + XML_ERROR_PARSING_UNKNOWN, + XML_ERROR_EMPTY_DOCUMENT, + XML_ERROR_MISMATCHED_ELEMENT, + XML_ERROR_PARSING, + XML_CAN_NOT_CONVERT_TEXT, + XML_NO_TEXT_NODE, + + XML_ERROR_COUNT +}; + + +/* + Utility functionality. +*/ +class XMLUtil +{ +public: + static const char* SkipWhiteSpace( const char* p ) { + TIXMLASSERT( p ); + while( IsWhiteSpace(*p) ) { + ++p; + } + TIXMLASSERT( p ); + return p; + } + static char* SkipWhiteSpace( char* p ) { + return const_cast( SkipWhiteSpace( const_cast(p) ) ); + } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. + static bool IsWhiteSpace( char p ) { + return !IsUTF8Continuation(p) && isspace( static_cast(p) ); + } + + inline static bool IsNameStartChar( unsigned char ch ) { + if ( ch >= 128 ) { + // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() + return true; + } + if ( isalpha( ch ) ) { + return true; + } + return ch == ':' || ch == '_'; + } + + inline static bool IsNameChar( unsigned char ch ) { + return IsNameStartChar( ch ) + || isdigit( ch ) + || ch == '.' + || ch == '-'; + } + + inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { + if ( p == q ) { + return true; + } + return strncmp( p, q, nChar ) == 0; + } + + inline static bool IsUTF8Continuation( char p ) { + return ( p & 0x80 ) != 0; + } + + static const char* ReadBOM( const char* p, bool* hasBOM ); + // p is the starting location, + // the UTF-8 value of the entity will be placed in value, and length filled in. + static const char* GetCharacterRef( const char* p, char* value, int* length ); + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + + // converts primitive types to strings + static void ToStr( int v, char* buffer, int bufferSize ); + static void ToStr( unsigned v, char* buffer, int bufferSize ); + static void ToStr( bool v, char* buffer, int bufferSize ); + static void ToStr( float v, char* buffer, int bufferSize ); + static void ToStr( double v, char* buffer, int bufferSize ); + + // converts strings to primitive types + static bool ToInt( const char* str, int* value ); + static bool ToUnsigned( const char* str, unsigned* value ); + static bool ToBool( const char* str, bool* value ); + static bool ToFloat( const char* str, float* value ); + static bool ToDouble( const char* str, double* value ); +}; + + +/** XMLNode is a base class for every object that is in the + XML Document Object Model (DOM), except XMLAttributes. + Nodes have siblings, a parent, and children which can + be navigated. A node is always in a XMLDocument. + The type of a XMLNode can be queried, and it can + be cast to its more defined type. + + A XMLDocument allocates memory for all its Nodes. + When the XMLDocument gets deleted, all its Nodes + will also be deleted. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + @endverbatim +*/ +class TINYXML2_LIB XMLNode +{ + friend class XMLDocument; + friend class XMLElement; +public: + + /// Get the XMLDocument that owns this XMLNode. + const XMLDocument* GetDocument() const { + TIXMLASSERT( _document ); + return _document; + } + /// Get the XMLDocument that owns this XMLNode. + XMLDocument* GetDocument() { + TIXMLASSERT( _document ); + return _document; + } + + /// Safely cast to an Element, or null. + virtual XMLElement* ToElement() { + return 0; + } + /// Safely cast to Text, or null. + virtual XMLText* ToText() { + return 0; + } + /// Safely cast to a Comment, or null. + virtual XMLComment* ToComment() { + return 0; + } + /// Safely cast to a Document, or null. + virtual XMLDocument* ToDocument() { + return 0; + } + /// Safely cast to a Declaration, or null. + virtual XMLDeclaration* ToDeclaration() { + return 0; + } + /// Safely cast to an Unknown, or null. + virtual XMLUnknown* ToUnknown() { + return 0; + } + + virtual const XMLElement* ToElement() const { + return 0; + } + virtual const XMLText* ToText() const { + return 0; + } + virtual const XMLComment* ToComment() const { + return 0; + } + virtual const XMLDocument* ToDocument() const { + return 0; + } + virtual const XMLDeclaration* ToDeclaration() const { + return 0; + } + virtual const XMLUnknown* ToUnknown() const { + return 0; + } + + /** The meaning of 'value' changes for the specific type. + @verbatim + Document: empty (NULL is returned, not an empty string) + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + const char* Value() const; + + /** Set the Value of an XML node. + @sa Value() + */ + void SetValue( const char* val, bool staticMem=false ); + + /// Get the parent of this node on the DOM. + const XMLNode* Parent() const { + return _parent; + } + + XMLNode* Parent() { + return _parent; + } + + /// Returns true if this node has no children. + bool NoChildren() const { + return !_firstChild; + } + + /// Get the first child node, or null if none exists. + const XMLNode* FirstChild() const { + return _firstChild; + } + + XMLNode* FirstChild() { + return _firstChild; + } + + /** Get the first child element, or optionally the first child + element with the specified name. + */ + const XMLElement* FirstChildElement( const char* name = 0 ) const; + + XMLElement* FirstChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->FirstChildElement( name )); + } + + /// Get the last child node, or null if none exists. + const XMLNode* LastChild() const { + return _lastChild; + } + + XMLNode* LastChild() { + return _lastChild; + } + + /** Get the last child element or optionally the last child + element with the specified name. + */ + const XMLElement* LastChildElement( const char* name = 0 ) const; + + XMLElement* LastChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->LastChildElement(name) ); + } + + /// Get the previous (left) sibling node of this node. + const XMLNode* PreviousSibling() const { + return _prev; + } + + XMLNode* PreviousSibling() { + return _prev; + } + + /// Get the previous (left) sibling element of this node, with an optionally supplied name. + const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; + + XMLElement* PreviousSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->PreviousSiblingElement( name ) ); + } + + /// Get the next (right) sibling node of this node. + const XMLNode* NextSibling() const { + return _next; + } + + XMLNode* NextSibling() { + return _next; + } + + /// Get the next (right) sibling element of this node, with an optionally supplied name. + const XMLElement* NextSiblingElement( const char* name = 0 ) const; + + XMLElement* NextSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->NextSiblingElement( name ) ); + } + + /** + Add a child node as the last (right) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertEndChild( XMLNode* addThis ); + + XMLNode* LinkEndChild( XMLNode* addThis ) { + return InsertEndChild( addThis ); + } + /** + Add a child node as the first (left) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertFirstChild( XMLNode* addThis ); + /** + Add a node after the specified child node. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the afterThis node + is not a child of this node, or if the node does not + belong to the same document. + */ + XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); + + /** + Delete all the children of this node. + */ + void DeleteChildren(); + + /** + Delete a child of this node. + */ + void DeleteChild( XMLNode* node ); + + /** + Make a copy of this node, but not its children. + You may pass in a Document pointer that will be + the owner of the new Node. If the 'document' is + null, then the node returned will be allocated + from the current Document. (this->GetDocument()) + + Note: if called on a XMLDocument, this will return null. + */ + virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + + /** + Test if 2 nodes are the same, but don't test children. + The 2 nodes do not need to be in the same Document. + + Note: if called on a XMLDocument, this will return false. + */ + virtual bool ShallowEqual( const XMLNode* compare ) const = 0; + + /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the XMLVisitor interface. + + This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + XMLPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( XMLVisitor* visitor ) const = 0; + +protected: + XMLNode( XMLDocument* ); + virtual ~XMLNode(); + + virtual char* ParseDeep( char*, StrPair* ); + + XMLDocument* _document; + XMLNode* _parent; + mutable StrPair _value; + + XMLNode* _firstChild; + XMLNode* _lastChild; + + XMLNode* _prev; + XMLNode* _next; + +private: + MemPool* _memPool; + void Unlink( XMLNode* child ); + static void DeleteNode( XMLNode* node ); + void InsertChildPreamble( XMLNode* insertThis ) const; + + XMLNode( const XMLNode& ); // not supported + XMLNode& operator=( const XMLNode& ); // not supported +}; + + +/** XML text. + + Note that a text node can have child element nodes, for example: + @verbatim + This is bold + @endverbatim + + A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCData() and query it with CData(). +*/ +class TINYXML2_LIB XMLText : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLText* ToText() { + return this; + } + virtual const XMLText* ToText() const { + return this; + } + + /// Declare whether this should be CDATA or standard text. + void SetCData( bool isCData ) { + _isCData = isCData; + } + /// Returns true if this is a CDATA text element. + bool CData() const { + return _isCData; + } + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} + virtual ~XMLText() {} + + char* ParseDeep( char*, StrPair* endTag ); + +private: + bool _isCData; + + XMLText( const XMLText& ); // not supported + XMLText& operator=( const XMLText& ); // not supported +}; + + +/** An XML Comment. */ +class TINYXML2_LIB XMLComment : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLComment* ToComment() { + return this; + } + virtual const XMLComment* ToComment() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLComment( XMLDocument* doc ); + virtual ~XMLComment(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLComment( const XMLComment& ); // not supported + XMLComment& operator=( const XMLComment& ); // not supported +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXML-2 will happily read or write files without a declaration, + however. + + The text of the declaration isn't interpreted. It is parsed + and written as a string. +*/ +class TINYXML2_LIB XMLDeclaration : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDeclaration* ToDeclaration() { + return this; + } + virtual const XMLDeclaration* ToDeclaration() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLDeclaration( XMLDocument* doc ); + virtual ~XMLDeclaration(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLDeclaration( const XMLDeclaration& ); // not supported + XMLDeclaration& operator=( const XMLDeclaration& ); // not supported +}; + + +/** Any tag that TinyXML-2 doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into XMLUnknowns. +*/ +class TINYXML2_LIB XMLUnknown : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLUnknown* ToUnknown() { + return this; + } + virtual const XMLUnknown* ToUnknown() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLUnknown( XMLDocument* doc ); + virtual ~XMLUnknown(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLUnknown( const XMLUnknown& ); // not supported + XMLUnknown& operator=( const XMLUnknown& ); // not supported +}; + + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not XMLNodes. You may only query the + Next() attribute in a list. +*/ +class TINYXML2_LIB XMLAttribute +{ + friend class XMLElement; +public: + /// The name of the attribute. + const char* Name() const; + + /// The value of the attribute. + const char* Value() const; + + /// The next attribute in the list. + const XMLAttribute* Next() const { + return _next; + } + + /** IntValue interprets the attribute as an integer, and returns the value. + If the value isn't an integer, 0 will be returned. There is no error checking; + use QueryIntValue() if you need error checking. + */ + int IntValue() const { + int i=0; + QueryIntValue( &i ); + return i; + } + /// Query as an unsigned integer. See IntValue() + unsigned UnsignedValue() const { + unsigned i=0; + QueryUnsignedValue( &i ); + return i; + } + /// Query as a boolean. See IntValue() + bool BoolValue() const { + bool b=false; + QueryBoolValue( &b ); + return b; + } + /// Query as a double. See IntValue() + double DoubleValue() const { + double d=0; + QueryDoubleValue( &d ); + return d; + } + /// Query as a float. See IntValue() + float FloatValue() const { + float f=0; + QueryFloatValue( &f ); + return f; + } + + /** QueryIntValue interprets the attribute as an integer, and returns the value + in the provided parameter. The function will return XML_NO_ERROR on success, + and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. + */ + XMLError QueryIntValue( int* value ) const; + /// See QueryIntValue + XMLError QueryUnsignedValue( unsigned int* value ) const; + /// See QueryIntValue + XMLError QueryBoolValue( bool* value ) const; + /// See QueryIntValue + XMLError QueryDoubleValue( double* value ) const; + /// See QueryIntValue + XMLError QueryFloatValue( float* value ) const; + + /// Set the attribute to a string value. + void SetAttribute( const char* value ); + /// Set the attribute to value. + void SetAttribute( int value ); + /// Set the attribute to value. + void SetAttribute( unsigned value ); + /// Set the attribute to value. + void SetAttribute( bool value ); + /// Set the attribute to value. + void SetAttribute( double value ); + /// Set the attribute to value. + void SetAttribute( float value ); + +private: + enum { BUF_SIZE = 200 }; + + XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + virtual ~XMLAttribute() {} + + XMLAttribute( const XMLAttribute& ); // not supported + void operator=( const XMLAttribute& ); // not supported + void SetName( const char* name ); + + char* ParseDeep( char* p, bool processEntities ); + + mutable StrPair _name; + mutable StrPair _value; + XMLAttribute* _next; + MemPool* _memPool; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TINYXML2_LIB XMLElement : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + /// Get the name of an element (which is the Value() of the node.) + const char* Name() const { + return Value(); + } + /// Set the name of the element. + void SetName( const char* str, bool staticMem=false ) { + SetValue( str, staticMem ); + } + + virtual XMLElement* ToElement() { + return this; + } + virtual const XMLElement* ToElement() const { + return this; + } + virtual bool Accept( XMLVisitor* visitor ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none + exists. For example: + + @verbatim + const char* value = ele->Attribute( "foo" ); + @endverbatim + + The 'value' parameter is normally null. However, if specified, + the attribute will only be returned if the 'name' and 'value' + match. This allow you to write code: + + @verbatim + if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); + @endverbatim + + rather than: + @verbatim + if ( ele->Attribute( "foo" ) ) { + if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); + } + @endverbatim + */ + const char* Attribute( const char* name, const char* value=0 ) const; + + /** Given an attribute name, IntAttribute() returns the value + of the attribute interpreted as an integer. 0 will be + returned if there is an error. For a method with error + checking, see QueryIntAttribute() + */ + int IntAttribute( const char* name ) const { + int i=0; + QueryIntAttribute( name, &i ); + return i; + } + /// See IntAttribute() + unsigned UnsignedAttribute( const char* name ) const { + unsigned i=0; + QueryUnsignedAttribute( name, &i ); + return i; + } + /// See IntAttribute() + bool BoolAttribute( const char* name ) const { + bool b=false; + QueryBoolAttribute( name, &b ); + return b; + } + /// See IntAttribute() + double DoubleAttribute( const char* name ) const { + double d=0; + QueryDoubleAttribute( name, &d ); + return d; + } + /// See IntAttribute() + float FloatAttribute( const char* name ) const { + float f=0; + QueryFloatAttribute( name, &f ); + return f; + } + + /** Given an attribute name, QueryIntAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + XMLError QueryIntAttribute( const char* name, int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryIntValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryUnsignedValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryBoolAttribute( const char* name, bool* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryBoolValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryDoubleAttribute( const char* name, double* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryDoubleValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryFloatAttribute( const char* name, float* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryFloatValue( value ); + } + + + /** Given an attribute name, QueryAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. It is overloaded for the primitive types, + and is a generally more convenient replacement of + QueryIntAttribute() and related functions. + + If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + int QueryAttribute( const char* name, int* value ) const { + return QueryIntAttribute( name, value ); + } + + int QueryAttribute( const char* name, unsigned int* value ) const { + return QueryUnsignedAttribute( name, value ); + } + + int QueryAttribute( const char* name, bool* value ) const { + return QueryBoolAttribute( name, value ); + } + + int QueryAttribute( const char* name, double* value ) const { + return QueryDoubleAttribute( name, value ); + } + + int QueryAttribute( const char* name, float* value ) const { + return QueryFloatAttribute( name, value ); + } + + /// Sets the named attribute to value. + void SetAttribute( const char* name, const char* value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, int value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, unsigned value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, bool value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, double value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, float value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + + /** + Delete an attribute. + */ + void DeleteAttribute( const char* name ); + + /// Return the first attribute in the list. + const XMLAttribute* FirstAttribute() const { + return _rootAttribute; + } + /// Query a specific attribute in the list. + const XMLAttribute* FindAttribute( const char* name ) const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the XMLText child + and accessing it directly. + + If the first child of 'this' is a XMLText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + */ + const char* GetText() const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, SetText() is limited compared to creating an XMLText child + and mutating it directly. + + If the first child of 'this' is a XMLText, SetText() sets its value to + the given string, otherwise it will create a first child that is an XMLText. + + This is a convenient method for setting the text of simple contained text: + @verbatim + This is text + fooElement->SetText( "Hullaballoo!" ); + Hullaballoo! + @endverbatim + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then it will not change "This is text", but rather prefix it with a text element: + @verbatim + Hullaballoo!This is text + @endverbatim + + For this XML: + @verbatim + + @endverbatim + SetText() will generate + @verbatim + Hullaballoo! + @endverbatim + */ + void SetText( const char* inText ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( int value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( unsigned value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( bool value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( double value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( float value ); + + /** + Convenience method to query the value of a child text node. This is probably best + shown by example. Given you have a document is this form: + @verbatim + + 1 + 1.4 + + @endverbatim + + The QueryIntText() and similar functions provide a safe and easier way to get to the + "value" of x and y. + + @verbatim + int x = 0; + float y = 0; // types of x and y are contrived for example + const XMLElement* xElement = pointElement->FirstChildElement( "x" ); + const XMLElement* yElement = pointElement->FirstChildElement( "y" ); + xElement->QueryIntText( &x ); + yElement->QueryFloatText( &y ); + @endverbatim + + @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted + to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. + + */ + XMLError QueryIntText( int* ival ) const; + /// See QueryIntText() + XMLError QueryUnsignedText( unsigned* uval ) const; + /// See QueryIntText() + XMLError QueryBoolText( bool* bval ) const; + /// See QueryIntText() + XMLError QueryDoubleText( double* dval ) const; + /// See QueryIntText() + XMLError QueryFloatText( float* fval ) const; + + // internal: + enum { + OPEN, // + CLOSED, // + CLOSING // + }; + int ClosingType() const { + return _closingType; + } + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + char* ParseDeep( char* p, StrPair* endTag ); + +private: + XMLElement( XMLDocument* doc ); + virtual ~XMLElement(); + XMLElement( const XMLElement& ); // not supported + void operator=( const XMLElement& ); // not supported + + XMLAttribute* FindAttribute( const char* name ) { + return const_cast(const_cast(this)->FindAttribute( name )); + } + XMLAttribute* FindOrCreateAttribute( const char* name ); + //void LinkAttribute( XMLAttribute* attrib ); + char* ParseAttributes( char* p ); + static void DeleteAttribute( XMLAttribute* attribute ); + + enum { BUF_SIZE = 200 }; + int _closingType; + // The attribute list is ordered; there is no 'lastAttribute' + // because the list needs to be scanned for dupes before adding + // a new attribute. + XMLAttribute* _rootAttribute; +}; + + +enum Whitespace { + PRESERVE_WHITESPACE, + COLLAPSE_WHITESPACE +}; + + +/** A Document binds together all the functionality. + It can be saved, loaded, and printed to the screen. + All Nodes are connected and allocated to a Document. + If the Document is deleted, all its Nodes are also deleted. +*/ +class TINYXML2_LIB XMLDocument : public XMLNode +{ + friend class XMLElement; +public: + /// constructor + XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + ~XMLDocument(); + + virtual XMLDocument* ToDocument() { + TIXMLASSERT( this == _document ); + return this; + } + virtual const XMLDocument* ToDocument() const { + TIXMLASSERT( this == _document ); + return this; + } + + /** + Parse an XML file from a character string. + Returns XML_NO_ERROR (0) on success, or + an errorID. + + You may optionally pass in the 'nBytes', which is + the number of bytes which will be parsed. If not + specified, TinyXML-2 will assume 'xml' points to a + null terminated string. + */ + XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); + + /** + Load an XML file from disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( const char* filename ); + + /** + Load an XML file from disk. You are responsible + for providing and closing the FILE*. + + NOTE: The file should be opened as binary ("rb") + not text in order for TinyXML-2 to correctly + do newline normalization. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( FILE* ); + + /** + Save the XML file to disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( const char* filename, bool compact = false ); + + /** + Save the XML file to disk. You are responsible + for providing and closing the FILE*. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( FILE* fp, bool compact = false ); + + bool ProcessEntities() const { + return _processEntities; + } + Whitespace WhitespaceMode() const { + return _whitespace; + } + + /** + Returns true if this document has a leading Byte Order Mark of UTF8. + */ + bool HasBOM() const { + return _writeBOM; + } + /** Sets whether to write the BOM when writing the file. + */ + void SetBOM( bool useBOM ) { + _writeBOM = useBOM; + } + + /** Return the root element of DOM. Equivalent to FirstChildElement(). + To get the first node, use FirstChild(). + */ + XMLElement* RootElement() { + return FirstChildElement(); + } + const XMLElement* RootElement() const { + return FirstChildElement(); + } + + /** Print the Document. If the Printer is not provided, it will + print to stdout. If you provide Printer, this can print to a file: + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Or you can use a printer to print to memory: + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + @endverbatim + */ + void Print( XMLPrinter* streamer=0 ) const; + virtual bool Accept( XMLVisitor* visitor ) const; + + /** + Create a new Element associated with + this Document. The memory for the Element + is managed by the Document. + */ + XMLElement* NewElement( const char* name ); + /** + Create a new Comment associated with + this Document. The memory for the Comment + is managed by the Document. + */ + XMLComment* NewComment( const char* comment ); + /** + Create a new Text associated with + this Document. The memory for the Text + is managed by the Document. + */ + XMLText* NewText( const char* text ); + /** + Create a new Declaration associated with + this Document. The memory for the object + is managed by the Document. + + If the 'text' param is null, the standard + declaration is used.: + @verbatim + + @endverbatim + */ + XMLDeclaration* NewDeclaration( const char* text=0 ); + /** + Create a new Unknown associated with + this Document. The memory for the object + is managed by the Document. + */ + XMLUnknown* NewUnknown( const char* text ); + + /** + Delete a node associated with this document. + It will be unlinked from the DOM. + */ + void DeleteNode( XMLNode* node ); + + void SetError( XMLError error, const char* str1, const char* str2 ); + + /// Return true if there was an error parsing the document. + bool Error() const { + return _errorID != XML_NO_ERROR; + } + /// Return the errorID. + XMLError ErrorID() const { + return _errorID; + } + const char* ErrorName() const; + + /// Return a possibly helpful diagnostic location or string. + const char* GetErrorStr1() const { + return _errorStr1; + } + /// Return a possibly helpful secondary diagnostic location or string. + const char* GetErrorStr2() const { + return _errorStr2; + } + /// If there is an error, print it to stdout. + void PrintError() const; + + /// Clear the document, resetting it to the initial state. + void Clear(); + + // internal + char* Identify( char* p, XMLNode** node ); + + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { + return 0; + } + virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { + return false; + } + +private: + XMLDocument( const XMLDocument& ); // not supported + void operator=( const XMLDocument& ); // not supported + + bool _writeBOM; + bool _processEntities; + XMLError _errorID; + Whitespace _whitespace; + const char* _errorStr1; + const char* _errorStr2; + char* _charBuffer; + + MemPoolT< sizeof(XMLElement) > _elementPool; + MemPoolT< sizeof(XMLAttribute) > _attributePool; + MemPoolT< sizeof(XMLText) > _textPool; + MemPoolT< sizeof(XMLComment) > _commentPool; + + static const char* _errorNames[XML_ERROR_COUNT]; + + void Parse(); +}; + + +/** + A XMLHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + XMLElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + XMLElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + XMLElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + XMLElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity + of such code. A XMLHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + XMLHandle docHandle( &document ); + XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + XMLHandle handleCopy = handle; + @endverbatim + + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. +*/ +class TINYXML2_LIB XMLHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + XMLHandle( XMLNode* node ) { + _node = node; + } + /// Create a handle from a node. + XMLHandle( XMLNode& node ) { + _node = &node; + } + /// Copy constructor + XMLHandle( const XMLHandle& ref ) { + _node = ref._node; + } + /// Assignment + XMLHandle& operator=( const XMLHandle& ref ) { + _node = ref._node; + return *this; + } + + /// Get the first child of this handle. + XMLHandle FirstChild() { + return XMLHandle( _node ? _node->FirstChild() : 0 ); + } + /// Get the first child element of this handle. + XMLHandle FirstChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + /// Get the last child of this handle. + XMLHandle LastChild() { + return XMLHandle( _node ? _node->LastChild() : 0 ); + } + /// Get the last child element of this handle. + XMLHandle LastChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + /// Get the previous sibling of this handle. + XMLHandle PreviousSibling() { + return XMLHandle( _node ? _node->PreviousSibling() : 0 ); + } + /// Get the previous sibling element of this handle. + XMLHandle PreviousSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + /// Get the next sibling of this handle. + XMLHandle NextSibling() { + return XMLHandle( _node ? _node->NextSibling() : 0 ); + } + /// Get the next sibling element of this handle. + XMLHandle NextSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + /// Safe cast to XMLNode. This can return null. + XMLNode* ToNode() { + return _node; + } + /// Safe cast to XMLElement. This can return null. + XMLElement* ToElement() { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + /// Safe cast to XMLText. This can return null. + XMLText* ToText() { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + /// Safe cast to XMLUnknown. This can return null. + XMLUnknown* ToUnknown() { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + /// Safe cast to XMLDeclaration. This can return null. + XMLDeclaration* ToDeclaration() { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + XMLNode* _node; +}; + + +/** + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. +*/ +class TINYXML2_LIB XMLConstHandle +{ +public: + XMLConstHandle( const XMLNode* node ) { + _node = node; + } + XMLConstHandle( const XMLNode& node ) { + _node = &node; + } + XMLConstHandle( const XMLConstHandle& ref ) { + _node = ref._node; + } + + XMLConstHandle& operator=( const XMLConstHandle& ref ) { + _node = ref._node; + return *this; + } + + const XMLConstHandle FirstChild() const { + return XMLConstHandle( _node ? _node->FirstChild() : 0 ); + } + const XMLConstHandle FirstChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + const XMLConstHandle LastChild() const { + return XMLConstHandle( _node ? _node->LastChild() : 0 ); + } + const XMLConstHandle LastChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + const XMLConstHandle PreviousSibling() const { + return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); + } + const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + const XMLConstHandle NextSibling() const { + return XMLConstHandle( _node ? _node->NextSibling() : 0 ); + } + const XMLConstHandle NextSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + + const XMLNode* ToNode() const { + return _node; + } + const XMLElement* ToElement() const { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + const XMLText* ToText() const { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + const XMLUnknown* ToUnknown() const { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + const XMLDeclaration* ToDeclaration() const { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + const XMLNode* _node; +}; + + +/** + Printing functionality. The XMLPrinter gives you more + options than the XMLDocument::Print() method. + + It can: + -# Print to memory. + -# Print to a file you provide. + -# Print XML without a XMLDocument. + + Print to Memory + + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + SomeFunction( printer.CStr() ); + @endverbatim + + Print to a File + + You provide the file pointer. + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Print without a XMLDocument + + When loading, an XML parser is very useful. However, sometimes + when saving, it just gets in the way. The code is often set up + for streaming, and constructing the DOM is just overhead. + + The Printer supports the streaming case. The following code + prints out a trivially simple XML file without ever creating + an XML document. + + @verbatim + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + @endverbatim +*/ +class TINYXML2_LIB XMLPrinter : public XMLVisitor +{ +public: + /** Construct the printer. If the FILE* is specified, + this will print to the FILE. Else it will print + to memory, and the result is available in CStr(). + If 'compact' is set to true, then output is created + with only required whitespace and newlines. + */ + XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); + virtual ~XMLPrinter() {} + + /** If streaming, write the BOM and declaration. */ + void PushHeader( bool writeBOM, bool writeDeclaration ); + /** If streaming, start writing an element. + The element must be closed with CloseElement() + */ + void OpenElement( const char* name, bool compactMode=false ); + /// If streaming, add an attribute to an open element. + void PushAttribute( const char* name, const char* value ); + void PushAttribute( const char* name, int value ); + void PushAttribute( const char* name, unsigned value ); + void PushAttribute( const char* name, bool value ); + void PushAttribute( const char* name, double value ); + /// If streaming, close the Element. + virtual void CloseElement( bool compactMode=false ); + + /// Add a text node. + void PushText( const char* text, bool cdata=false ); + /// Add a text node from an integer. + void PushText( int value ); + /// Add a text node from an unsigned. + void PushText( unsigned value ); + /// Add a text node from a bool. + void PushText( bool value ); + /// Add a text node from a float. + void PushText( float value ); + /// Add a text node from a double. + void PushText( double value ); + + /// Add a comment + void PushComment( const char* comment ); + + void PushDeclaration( const char* value ); + void PushUnknown( const char* value ); + + virtual bool VisitEnter( const XMLDocument& /*doc*/ ); + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); + virtual bool VisitExit( const XMLElement& element ); + + virtual bool Visit( const XMLText& text ); + virtual bool Visit( const XMLComment& comment ); + virtual bool Visit( const XMLDeclaration& declaration ); + virtual bool Visit( const XMLUnknown& unknown ); + + /** + If in print to memory mode, return a pointer to + the XML file in memory. + */ + const char* CStr() const { + return _buffer.Mem(); + } + /** + If in print to memory mode, return the size + of the XML file in memory. (Note the size returned + includes the terminating null.) + */ + int CStrSize() const { + return _buffer.Size(); + } + /** + If in print to memory mode, reset the buffer to the + beginning. + */ + void ClearBuffer() { + _buffer.Clear(); + _buffer.Push(0); + } + +protected: + virtual bool CompactMode( const XMLElement& ) { return _compactMode; } + + /** Prints out the space before an element. You may override to change + the space and tabs used. A PrintSpace() override should call Print(). + */ + virtual void PrintSpace( int depth ); + void Print( const char* format, ... ); + + void SealElementIfJustOpened(); + bool _elementJustOpened; + DynArray< const char*, 10 > _stack; + +private: + void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. + + bool _firstElement; + FILE* _fp; + int _depth; + int _textDepth; + bool _processEntities; + bool _compactMode; + + enum { + ENTITY_RANGE = 64, + BUF_SIZE = 200 + }; + bool _entityFlag[ENTITY_RANGE]; + bool _restrictedEntityFlag[ENTITY_RANGE]; + + DynArray< char, 20 > _buffer; +}; + + +} // tinyxml2 + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // TINYXML2_INCLUDED diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..ba1a41a --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,58 @@ + +## ===================== +## == List of plugins == +## ===================== + +SET( + _directories + GenericPlugins + VTKFilters + VTKIO + VTKWidgets + ITKAnisotropicSmoothing + ITKBinaryFunctorFilters + ITKDistanceMapFilters + ITKFiniteDifference + ITKImageGenericFilters_1 + ITKImageInterpolators + ITKIO + ITKLevelSetFilters + ITKMorphology + ITKNeighborhoodOperatorFilters + ITKParaMorphology + ITKSeparableFilters + ITKSliceFilters + ITKUnaryFunctorFilters + cpExtensions + ) + +## ========================= +## == Compile each plugin == +## ========================= + +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_BINARY_DIR}/lib + ) +FOREACH(_dir ${_directories}) + cpPlugins_BuildPluginsLibrary(cpPlugins_${_dir} ${_dir}) + TARGET_LINK_LIBRARIES(cpPlugins_${_dir} cpPluginsDataObjects) +ENDFOREACH(_dir) + +TARGET_LINK_LIBRARIES(cpPlugins_ITKDistanceMapFilters cpPlugins_ITKUnaryFunctorFilters) +TARGET_LINK_LIBRARIES(cpPlugins_ITKAnisotropicSmoothing cpPlugins_ITKFiniteDifference) +TARGET_LINK_LIBRARIES( + cpPlugins_ITKLevelSetFilters + cpPlugins_ITKAnisotropicSmoothing + cpPlugins_ITKNeighborhoodOperatorFilters + cpPlugins_ITKImageGenericFilters_1 + ) +TARGET_LINK_LIBRARIES(cpPlugins_ITKParaMorphology cpPlugins_ITKUnaryFunctorFilters) +TARGET_LINK_LIBRARIES(cpPlugins_ITKSeparableFilters cpPlugins_ITKImageGenericFilters_1) +TARGET_LINK_LIBRARIES( + cpPlugins_ITKSliceFilters + cpPlugins_ITKImageInterpolators + cpPlugins_ITKImageGenericFilters_1 + ) + +## eof - $RCSfile$ diff --git a/plugins/GenericPlugins/DataReproducer.cxx b/plugins/GenericPlugins/DataReproducer.cxx new file mode 100644 index 0000000..586e37b --- /dev/null +++ b/plugins/GenericPlugins/DataReproducer.cxx @@ -0,0 +1,49 @@ +#include "DataReproducer.h" +#include + +// ------------------------------------------------------------------------- +void cpPlugins_GenericPlugins::DataReproducer:: +AddInput( const std::string& n, cpPlugins::Pipeline::DataObject* o ) +{ + this->Superclass::AddInput( n, o ); + auto out = + dynamic_cast< cpPlugins::Pipeline::OutputPort* >( + this->m_Outputs.find( "Output" )->second + ); + out->Set( o ); +} + +// ------------------------------------------------------------------------- +void cpPlugins_GenericPlugins::DataReproducer:: +SetInput( const std::string& n, cpPlugins::Pipeline::DataObject* o ) +{ + this->Superclass::SetInput( n, o ); + auto out = + dynamic_cast< cpPlugins::Pipeline::OutputPort* >( + this->m_Outputs.find( "Output" )->second + ); + out->Set( o ); +} + +// ------------------------------------------------------------------------- +cpPlugins_GenericPlugins::DataReproducer:: +DataReproducer( ) + : Superclass( ) +{ + this->_ConfigureInput( "Input", true, false ); + this->_ConfigureOutput( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPlugins_GenericPlugins::DataReproducer:: +~DataReproducer( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins_GenericPlugins::DataReproducer:: +_GenerateData( ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/GenericPlugins/DataReproducer.h b/plugins/GenericPlugins/DataReproducer.h new file mode 100644 index 0000000..9bfcbc1 --- /dev/null +++ b/plugins/GenericPlugins/DataReproducer.h @@ -0,0 +1,33 @@ +#ifndef __cpPlugins_GenericPlugins__DataReproducer__h__ +#define __cpPlugins_GenericPlugins__DataReproducer__h__ + +#include +#include + +namespace cpPlugins_GenericPlugins +{ + /** + */ + class cpPlugins_GenericPlugins_EXPORT DataReproducer + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + DataReproducer, + cpPlugins::Pipeline::ProcessObject, + GenericPlugins + ); + + public: + virtual void AddInput( + const std::string& n, cpPlugins::Pipeline::DataObject* o + ) cpPlugins_OVERRIDE; + virtual void SetInput( + const std::string& n, cpPlugins::Pipeline::DataObject* o + ) cpPlugins_OVERRIDE; + }; + +} // ecapseman + +#endif // __cpPlugins_GenericPlugins__DataReproducer__h__ + +// eof - $RCSfile$ diff --git a/plugins/GenericPlugins/JoinBoundingBoxes.cxx b/plugins/GenericPlugins/JoinBoundingBoxes.cxx new file mode 100644 index 0000000..d3bdfb5 --- /dev/null +++ b/plugins/GenericPlugins/JoinBoundingBoxes.cxx @@ -0,0 +1,44 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins_GenericPlugins::JoinBoundingBoxes:: +JoinBoundingBoxes( ) + : Superclass( ) +{ + this->_ConfigureInput( "Inputs", true, true ); + this->_ConfigureOutput< cpInstances::DataObjects::BoundingBox >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPlugins_GenericPlugins::JoinBoundingBoxes:: +~JoinBoundingBoxes( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins_GenericPlugins::JoinBoundingBoxes:: +_GenerateData( ) +{ + typedef cpPlugins::Pipeline::DataObject _TDO; + typedef cpInstances::DataObjects::BoundingBox _TBB; + + auto out = dynamic_cast< _TBB* >( this->GetOutput( "Output" ) ); + unsigned int nInputs = this->GetInputSize( "Inputs" ); + for( unsigned int i = 0; i < nInputs; ++i ) + { + auto in = dynamic_cast< _TDO* >( this->GetInput( "Inputs", i ) ); + if( i > 0 ) + { + _TBB::Pointer bb = _TBB::New( ); + bb->SetDataObject( in ); + out->Blend( bb ); + } + else + out->SetDataObject( in ); + + } // rof +} + +// eof - $RCSfile$ diff --git a/plugins/GenericPlugins/JoinBoundingBoxes.h b/plugins/GenericPlugins/JoinBoundingBoxes.h new file mode 100644 index 0000000..6751dad --- /dev/null +++ b/plugins/GenericPlugins/JoinBoundingBoxes.h @@ -0,0 +1,25 @@ +#ifndef __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__ +#define __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__ + +#include +#include + +namespace cpPlugins_GenericPlugins +{ + /** + */ + class cpPlugins_GenericPlugins_EXPORT JoinBoundingBoxes + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + JoinBoundingBoxes, + cpPlugins::Pipeline::ProcessObject, + GenericPlugins + ); + }; + +} // ecapseman + +#endif // __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__ + +// eof - $RCSfile$ diff --git a/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.cxx b/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.cxx new file mode 100644 index 0000000..26b76b0 --- /dev/null +++ b/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.cxx @@ -0,0 +1,71 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter:: +CurvatureAnisotropicDiffusionImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + this->m_Parameters.ConfigureAsUint( "NumberOfIterations", 5 ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing", false ); + this->m_Parameters.ConfigureAsReal( "ConductanceParameter", 3 ); + this->m_Parameters.ConfigureAsReal( "TimeStep", 0.0625 ); + this->m_Parameters.ConfigureAsRealTypesChoices( "OutputResolution" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter:: +~CurvatureAnisotropicDiffusionImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter:: +_GD0( _TImage* image ) +{ + std::string out_res = + this->m_Parameters.GetSelectedChoice( "OutputResolution" ); + if( out_res == "float" ) this->_GD1< _TImage, float >( image ); + if( out_res == "double" ) this->_GD1< _TImage, double >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::Image< _TScalar, _TImage::ImageDimension > _TOutImage; + typedef + itk::CurvatureAnisotropicDiffusionImageFilter< _TImage, _TOutImage > + _TFilter; + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetNumberOfIterations( this->m_Parameters.GetUint( "NumberOfIterations" ) ); + filter->SetUseImageSpacing( this->m_Parameters.GetBool( "UseImageSpacing" ) ); + filter->SetConductanceParameter( this->m_Parameters.GetReal( "ConductanceParameter" ) ); + filter->SetTimeStep( this->m_Parameters.GetReal( "TimeStep" ) ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.h b/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.h new file mode 100644 index 0000000..dc91e06 --- /dev/null +++ b/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKAnisotropicSmoothing__CurvatureAnisotropicDiffusionImageFilter__h__ +#define __cpPluginsITKAnisotropicSmoothing__CurvatureAnisotropicDiffusionImageFilter__h__ + +#include +#include + +namespace cpPluginsITKAnisotropicSmoothing +{ + /** + */ + class cpPlugins_ITKAnisotropicSmoothing_EXPORT CurvatureAnisotropicDiffusionImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + CurvatureAnisotropicDiffusionImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageSmoothing + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKAnisotropicSmoothing__CurvatureAnisotropicDiffusionImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKAnisotropicSmoothing/ITKAnisotropicSmoothing.i b/plugins/ITKAnisotropicSmoothing/ITKAnisotropicSmoothing.i new file mode 100644 index 0000000..d87073b --- /dev/null +++ b/plugins/ITKAnisotropicSmoothing/ITKAnisotropicSmoothing.i @@ -0,0 +1,12 @@ +header #define ITK_MANUAL_INSTANTIATION + +define functions=ScalarAnisotropicDiffusionFunction;GradientNDAnisotropicDiffusionFunction;CurvatureNDAnisotropicDiffusionFunction +tinclude itk#functions#:h|hxx +instances itk::#functions#< itk::Image< #scalar_types#, #pdims# > > + +define filters=AnisotropicDiffusionImageFilter + +tinclude itk#filters#:h|hxx +instances itk::#filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.cxx b/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.cxx new file mode 100644 index 0000000..b297489 --- /dev/null +++ b/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.cxx @@ -0,0 +1,92 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter:: +BinaryArithmeticImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input1", true, false ); + this->_ConfigureInput< _TImage >( "Input2", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + std::vector< std::string > choices; + choices.push_back( "Add" ); + choices.push_back( "Subtract" ); + choices.push_back( "Multiply" ); + choices.push_back( "Divide" ); + choices.push_back( "DivideOrZero" ); + choices.push_back( "Pow" ); + this->m_Parameters.ConfigureAsChoices( "Operator", choices ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter:: +~BinaryArithmeticImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input1" ); + cpPlugins_Demangle_Image_IntPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter:: +_GD0( _TImage* image1 ) +{ + typedef itk::AddImageFilter< _TImage, _TImage > _TAdd; + typedef itk::SubtractImageFilter< _TImage, _TImage > _TSubtract; + typedef itk::MultiplyImageFilter< _TImage, _TImage > _TMultiply; + typedef itk::DivideImageFilter< _TImage, _TImage, _TImage > _TDivide; + typedef itk::DivideOrZeroOutImageFilter< _TImage, _TImage > _TDivideOrZero; + typedef itk::PowImageFilter< _TImage, _TImage > _TPow; + + auto image2 = this->GetInputData< _TImage >( "Input2" ); + if( image2 == NULL ) + this->_Error( "Incompatible second input image." ); + std::string op = this->m_Parameters.GetSelectedChoice( "Operator" ); + if( op == "Add" ) + this->_GD1< _TAdd, _TImage >( image1, image2 ); + else if( op == "Subtract" ) + this->_GD1< _TSubtract, _TImage >( image1, image2 ); + else if( op == "Multiply" ) + this->_GD1< _TMultiply, _TImage >( image1, image2 ); + else if( op == "Divide" ) + this->_GD1< _TDivide, _TImage >( image1, image2 ); + else if( op == "DivideOrZero" ) + this->_GD1< _TDivideOrZero, _TImage >( image1, image2 ); + else if( op == "Pow" ) + this->_GD1< _TPow, _TImage >( image1, image2 ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TImage > +void cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter:: +_GD1( _TImage* image1, _TImage* image2 ) +{ + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput1( image1 ); + filter->SetInput2( image2 ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.h b/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.h new file mode 100644 index 0000000..0b3b9f6 --- /dev/null +++ b/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKBinaryFunctorFilters__BinaryArithmeticImageFilter__h__ +#define __cpPluginsITKBinaryFunctorFilters__BinaryArithmeticImageFilter__h__ + +#include +#include + +namespace cpPluginsITKBinaryFunctorFilters +{ + /** + */ + class cpPlugins_ITKBinaryFunctorFilters_EXPORT BinaryArithmeticImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + BinaryArithmeticImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageArithmeticFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image1 ); + + template< class _TFilter, class _TImage > + inline void _GD1( _TImage* image1, _TImage* image2 ); + }; + +} // ecapseman + +#endif // __cpPluginsITKBinaryFunctorFilters__BinaryArithmeticImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.cxx b/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.cxx new file mode 100644 index 0000000..3202b74 --- /dev/null +++ b/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.cxx @@ -0,0 +1,74 @@ +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter:: +BinaryBooleanImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input1", true, false ); + this->_ConfigureInput< _TImage >( "Input2", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + std::vector< std::string > choices; + choices.push_back( "And" ); + choices.push_back( "Or" ); + choices.push_back( "Xor" ); + this->m_Parameters.ConfigureAsChoices( "Operator", choices ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter:: +~BinaryBooleanImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input1" ); + cpPlugins_Demangle_Image_IntPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter:: +_GD0( _TImage* image1 ) +{ + typedef itk::AndImageFilter< _TImage, _TImage > _TAnd; + typedef itk::OrImageFilter< _TImage, _TImage > _TOr; + typedef itk::XorImageFilter< _TImage, _TImage > _TXor; + + auto image2 = this->GetInputData< _TImage >( "Input2" ); + if( image2 == NULL ) + this->_Error( "Incompatible second input image." ); + std::string op = this->m_Parameters.GetSelectedChoice( "Operator" ); + if ( op == "And" ) this->_GD1< _TAnd, _TImage >( image1, image2 ); + else if( op == "Or" ) this->_GD1< _TOr, _TImage >( image1, image2 ); + else if( op == "Xor" ) this->_GD1< _TXor, _TImage >( image1, image2 ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TImage > +void cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter:: +_GD1( _TImage* image1, _TImage* image2 ) +{ + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput1( image1 ); + filter->SetInput2( image2 ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.h b/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.h new file mode 100644 index 0000000..439e178 --- /dev/null +++ b/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKBinaryFunctorFilters__BinaryBooleanImageFilter__h__ +#define __cpPluginsITKBinaryFunctorFilters__BinaryBooleanImageFilter__h__ + +#include +#include + +namespace cpPluginsITKBinaryFunctorFilters +{ + /** + */ + class cpPlugins_ITKBinaryFunctorFilters_EXPORT BinaryBooleanImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + BinaryBooleanImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageBooleanFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image1 ); + + template< class _TFilter, class _TImage > + inline void _GD1( _TImage* image1, _TImage* image2 ); + }; + +} // ecapseman + +#endif // __cpPluginsITKBinaryFunctorFilters__BinaryBooleanImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKBinaryFunctorFilters/ITKBinaryFunctorFilters.i b/plugins/ITKBinaryFunctorFilters/ITKBinaryFunctorFilters.i new file mode 100644 index 0000000..d9d98bb --- /dev/null +++ b/plugins/ITKBinaryFunctorFilters/ITKBinaryFunctorFilters.i @@ -0,0 +1,17 @@ +header #define ITK_MANUAL_INSTANTIATION + +define all_ints=#int_types#;#uint_types# +define a_filters=Add;Subtract;Multiply;Divide;DivideOrZeroOut;Pow +define a_functor=Add2;Sub2;Mult;Div;DivideOrZeroOut;Pow +define b_filters=And;Or;Xor +define b_functor=AND;OR;XOR + +tinclude itkBinaryFunctorImageFilter:h|hxx +cinclude itk#a_filters#ImageFilter.h +cinclude itk#b_filters#ImageFilter.h + +instances itk::BinaryFunctorImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Functor::#a_functor#< #scalar_types#, #scalar_types#, #scalar_types# > > + +instances itk::BinaryFunctorImageFilter< itk::Image< #all_ints#, #pdims# >, itk::Image< #all_ints#, #pdims# >, itk::Image< #all_ints#, #pdims# >, itk::Functor::#b_functor#< #all_ints#, #all_ints#, #all_ints# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.cxx b/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.cxx new file mode 100644 index 0000000..0cb9711 --- /dev/null +++ b/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.cxx @@ -0,0 +1,71 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKDistanceMapFilters::BinaryContourImageFilter:: +BinaryContourImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "BackgroundValue", 0 ); + this->m_Parameters.ConfigureAsReal( "ForegroundValue", 1 ); + this->m_Parameters.ConfigureAsBool( "FullyConnected", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKDistanceMapFilters::BinaryContourImageFilter:: +~BinaryContourImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKDistanceMapFilters::BinaryContourImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_VisualDims_1( o, _GD0 ) + this->_Error( "Invalid input image dimension." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKDistanceMapFilters::BinaryContourImageFilter:: +_GD0( _TImage* image ) +{ + cpPlugins_Demangle_Image_ScalarPixels_1( image, _GD1, _TImage::ImageDimension ) + this->_Error( "Invalid input image pixel type." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKDistanceMapFilters::BinaryContourImageFilter:: +_GD1( _TImage* image ) +{ + typedef + itk::BinaryContourImageFilter< _TImage, _TImage > + _TFilter; + + // Get parameters + double b = this->m_Parameters.GetReal( "BackgroundValue" ); + double f = this->m_Parameters.GetReal( "ForegroundValue" ); + double c = this->m_Parameters.GetBool( "FullyConnected" ); + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetBackgroundValue( ( typename _TImage::PixelType )( b ) ); + filter->SetForegroundValue( ( typename _TImage::PixelType )( f ) ); + filter->SetFullyConnected( c ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.h b/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.h new file mode 100644 index 0000000..8e16c99 --- /dev/null +++ b/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKDistanceMapFilters__BinaryContourImageFilter__h__ +#define __cpPluginsITKDistanceMapFilters__BinaryContourImageFilter__h__ + +#include +#include + +namespace cpPluginsITKDistanceMapFilters +{ + /** + */ + class cpPlugins_ITKDistanceMapFilters_EXPORT BinaryContourImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + BinaryContourImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageDistanceMaps + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKDistanceMapFilters__BinaryContourImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKDistanceMapFilters/ITKDistanceMapFilters.i b/plugins/ITKDistanceMapFilters/ITKDistanceMapFilters.i new file mode 100644 index 0000000..6a703ad --- /dev/null +++ b/plugins/ITKDistanceMapFilters/ITKDistanceMapFilters.i @@ -0,0 +1,15 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude itkImageRegionConstIterator:h|h +tinclude itkImageRegionIterator:h|h +tinclude itkProgressReporter:h|h + +tinclude itkBinaryContourImageFilter:h|hxx +instances itk::BinaryContourImageFilter< itk::Image< #scalar_types#, #vdims# >, itk::Image< #scalar_types#, #vdims# > > + +define filters=SignedMaurerDistanceMapImageFilter +** ;DanielssonDistanceMapImageFilter;SignedDanielssonDistanceMapImageFilter +tinclude itk#filters#:h|hxx +instances itk::#filters#< itk::Image< #scalar_types#, #vdims# >, itk::Image< #real_types#, #vdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.cxx b/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.cxx new file mode 100644 index 0000000..b92b881 --- /dev/null +++ b/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.cxx @@ -0,0 +1,82 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter:: +SignedMaurerDistanceMapImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "BackgroundValue", 0 ); + this->m_Parameters.ConfigureAsBool( "InsideIsPositive", true ); + this->m_Parameters.ConfigureAsBool( "SquaredDistance", false ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing", true ); + + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "OutputResolution", choices ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter:: +~SignedMaurerDistanceMapImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_VisualDims_1( o, _GD0 ) + this->_Error( "Invalid input image dimension." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter:: +_GD0( _TImage* image ) +{ + std::string out_res = + this->m_Parameters.GetSelectedChoice( "OutputResolution" ); + if( out_res == "float" ) this->_GD1< _TImage, float >( image ); + if( out_res == "double" ) this->_GD1< _TImage, double >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::Image< _TScalar, _TImage::ImageDimension > _TDMap; + typedef + itk::SignedMaurerDistanceMapImageFilter< _TImage, _TDMap > + _TFilter; + + // Get parameters + double bv = this->m_Parameters.GetReal( "BackgroundValue" ); + bool pi = this->m_Parameters.GetBool( "InsideIsPositive" ); + bool sd = this->m_Parameters.GetBool( "SquaredDistance" ); + bool us = this->m_Parameters.GetBool( "UseImageSpacing" ); + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetBackgroundValue( ( typename _TImage::PixelType )( bv ) ); + filter->SetInsideIsPositive( pi ); + filter->SetSquaredDistance( sd ); + filter->SetUseImageSpacing( us ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.h b/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.h new file mode 100644 index 0000000..825c09b --- /dev/null +++ b/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKDistanceMapFilters__SignedMaurerDistanceMapImageFilter__h__ +#define __cpPluginsITKDistanceMapFilters__SignedMaurerDistanceMapImageFilter__h__ + +#include +#include + +namespace cpPluginsITKDistanceMapFilters +{ + /** + */ + class cpPlugins_ITKDistanceMapFilters_EXPORT SignedMaurerDistanceMapImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + SignedMaurerDistanceMapImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageDistanceMaps + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKDistanceMapFilters__SignedMaurerDistanceMapImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKFiniteDifference/ITKFiniteDifference.i b/plugins/ITKFiniteDifference/ITKFiniteDifference.i new file mode 100644 index 0000000..1db9b6a --- /dev/null +++ b/plugins/ITKFiniteDifference/ITKFiniteDifference.i @@ -0,0 +1,15 @@ +header #define ITK_MANUAL_INSTANTIATION + +define base=FiniteDifferenceImageFilter;DenseFiniteDifferenceImageFilter +define functions=FiniteDifferenceFunction + +define i_reals=#real_types# +define o_reals=#real_types# + +tinclude itk#functions#:h|hxx +tinclude itk#base#:h|hxx + +instances itk::#functions#< itk::Image< #scalar_types#, #pdims# > > +instances itk::#base#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #o_reals#, #pdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKIO/DicomSeriesReader.cxx b/plugins/ITKIO/DicomSeriesReader.cxx new file mode 100644 index 0000000..18ec6f0 --- /dev/null +++ b/plugins/ITKIO/DicomSeriesReader.cxx @@ -0,0 +1,102 @@ +#include +#include + +#ifdef cpPlugins_QT4 + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKIO::DicomSeriesReaderQDialog:: +DicomSeriesReaderQDialog( QWidget* parent ) + : QDialog( parent ), + m_UI( new Ui::DicomSeriesReaderQDialog ), + m_ProcessObject( NULL ) +{ + this->m_UI->setupUi( this ); + this->connect( + this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) ) + ); + this->setWindowTitle( "Open DICOM series" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKIO::DicomSeriesReaderQDialog:: +~DicomSeriesReaderQDialog( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void cpPluginsITKIO::DicomSeriesReaderQDialog:: +setProcessObject( cpPlugins::Pipeline::ProcessObject* obj ) +{ + if( obj == NULL ) + return; + this->m_ProcessObject = obj; + auto param = this->m_ProcessObject->GetParameters( ); + auto files = param->GetOpenFileNameList( "FileNames" ); + if( files.size( ) > 0 ) + { + QFileInfo info( files[ 0 ].c_str( ) ); + this->m_UI->Selector->setStartDir( info.canonicalPath( ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPluginsITKIO::DicomSeriesReaderQDialog:: +_dlg_Accepted( ) +{ + if( this->m_ProcessObject != NULL ) + { + auto param = this->m_ProcessObject->GetParameters( ); + auto files = this->m_UI->Selector->selectedFilenames( ); + param->ClearOpenFileNameList( "FileNames" ); + for( auto fIt = files->begin( ); fIt != files->end( ); ++fIt ) + param->AddToOpenFileNameList( "FileNames", *fIt ); + + } // fi +} + +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginsITKIO::DicomSeriesReader:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + DicomSeriesReaderQDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new DicomSeriesReaderQDialog( ); + dlg->setProcessObject( this ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginsITKIO::DicomSeriesReader:: +DicomSeriesReader( ) + : Superclass( ) +{ +} +// ------------------------------------------------------------------------- +cpPluginsITKIO::DicomSeriesReader:: +~DicomSeriesReader( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKIO::DicomSeriesReader:: +_GenerateData( ) +{ + this->Superclass::_GenerateData( ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/DicomSeriesReader.h b/plugins/ITKIO/DicomSeriesReader.h new file mode 100644 index 0000000..349fe7a --- /dev/null +++ b/plugins/ITKIO/DicomSeriesReader.h @@ -0,0 +1,23 @@ +#ifndef __cpPluginsITKIO__DicomSeriesReader__h__ +#define __cpPluginsITKIO__DicomSeriesReader__h__ + +#include + +namespace cpPluginsITKIO +{ + /** + */ + class cpPlugins_ITKIO_EXPORT DicomSeriesReader + : public ImageReader + { + cpPluginsObject( DicomSeriesReader, ImageReader, IO ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + }; + +} // ecapseman + +#endif // __cpPluginsITKIO__DicomSeriesReader__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/DicomSeriesReaderQDialog.h b/plugins/ITKIO/DicomSeriesReaderQDialog.h new file mode 100644 index 0000000..3c17e3a --- /dev/null +++ b/plugins/ITKIO/DicomSeriesReaderQDialog.h @@ -0,0 +1,41 @@ +#ifndef __cpPluginsITKIO__DicomSeriesreaderQDialog__h__ +#define __cpPluginsITKIO__DicomSeriesreaderQDialog__h__ + +#include + +#ifdef cpPlugins_QT4 + +#include +#include + +namespace cpPlugins { namespace Pipeline { class ProcessObject; } } +namespace Ui { class DicomSeriesReaderQDialog; } + +namespace cpPluginsITKIO +{ + /** + */ + class DicomSeriesReaderQDialog + : public QDialog + { + Q_OBJECT; + public: + DicomSeriesReaderQDialog( QWidget* parent = 0 ); + virtual ~DicomSeriesReaderQDialog( ); + void setProcessObject( cpPlugins::Pipeline::ProcessObject* obj ); + + protected slots: + void _dlg_Accepted( ); + + protected: + Ui::DicomSeriesReaderQDialog* m_UI; + cpPlugins::Pipeline::ProcessObject* m_ProcessObject; + }; + +} // ecapseman + +#endif // cpPlugins_QT4 + +#endif // __cpPluginsITKIO__DicomSeriesreaderQDialog__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/DicomSeriesReaderQDialog.ui b/plugins/ITKIO/DicomSeriesReaderQDialog.ui new file mode 100644 index 0000000..0ab2c2e --- /dev/null +++ b/plugins/ITKIO/DicomSeriesReaderQDialog.ui @@ -0,0 +1,81 @@ + + + DicomSeriesReaderQDialog + + + + 0 + 0 + 511 + 335 + + + + + 511 + 335 + + + + Dialog + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + cpPluginsITKIO::DicomSeriesSelectorWidget + QWidget +
ITKIO/DicomSeriesSelectorWidget.h
+ 1 +
+
+ + + + ButtonBox + accepted() + DicomSeriesReaderQDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + ButtonBox + rejected() + DicomSeriesReaderQDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/plugins/ITKIO/DicomSeriesSelectorWidget.cxx b/plugins/ITKIO/DicomSeriesSelectorWidget.cxx new file mode 100644 index 0000000..98954d4 --- /dev/null +++ b/plugins/ITKIO/DicomSeriesSelectorWidget.cxx @@ -0,0 +1,182 @@ +#include + +#ifdef cpPlugins_QT4 + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKIO::DicomSeriesSelectorWidget:: +DicomSeriesSelectorWidget( QWidget* parent ) + : QWidget( parent ), + m_UI( new Ui::DicomSeriesSelectorWidget ) +{ + this->m_UI->setupUi( this ); + this->setStartDir( ".", false ); + this->connect( + this->m_UI->ChooseButton, SIGNAL( clicked( ) ), + this, SLOT( _Choose( ) ) + ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKIO::DicomSeriesSelectorWidget:: +~DicomSeriesSelectorWidget( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +QString cpPluginsITKIO::DicomSeriesSelectorWidget:: +startDir( ) const +{ + return( this->m_UI->Directory->text( ) ); +} + +// ------------------------------------------------------------------------- +void cpPluginsITKIO::DicomSeriesSelectorWidget:: +setStartDir( const QString& dir, bool build ) +{ + this->m_Series.clear( ); + + this->m_UI->Directory->setText( dir ); + if( !build ) + return; + + // Process subdirs + QApplication::setOverrideCursor( Qt::WaitCursor ); + + this->m_UI->Series->clear( ); + this->m_UI->Series->setColumnCount( 3 ); + QStringList labels; + labels << "Images count" << "Series UID" << "Series path"; + this->m_UI->Series->setHorizontalHeaderLabels( labels ); + + std::string main_dir_name = dir.toStdString( ); + std::queue< std::string > q; + q.push( main_dir_name ); + while( !( q.empty( ) ) ) + { + std::string dir_name = q.front( ); + q.pop( ); + + // Update queue + QDir dir( dir_name.c_str( ) ); + QFileInfoList contents = dir.entryInfoList( ); + QFileInfoList::const_iterator i = contents.begin( ); + std::set< std::string > files; + for( ; i != contents.end( ); ++i ) + { + if( i->isDir( ) ) + { + std::string new_dir_name = i->absoluteFilePath( ).toStdString( ); + if( new_dir_name.size( ) > dir_name.size( ) ) + q.push( new_dir_name ); + } + else + files.insert( i->absoluteFilePath( ).toStdString( ) ); + + } // rof + + if( files.size( ) > 0 ) + { + this->m_GDCMHelper.Clear( ); + this->m_GDCMHelper.SetUseSeriesDetails( true ); + this->m_GDCMHelper.SetLoadMode( 0 ); + this->m_GDCMHelper.AddRestriction( "0008|0021" ); + this->m_GDCMHelper.SetFileNames( files.begin( ), files.end( ) ); + + gdcm::FileList* flist = + this->m_GDCMHelper.GetFirstSingleSerieUIDFileSet( ); + while( flist != NULL ) + { + if( flist->size( ) > 0 ) + { + this->m_GDCMHelper.OrderFileList( flist ); + gdcm::File* file = ( *flist )[ 0 ]; + std::string id = + this->m_GDCMHelper.CreateUniqueSeriesIdentifier( file ).c_str( ); + + gdcm::FileList::iterator it; + for( it = flist->begin( ); it != flist->end( ); ++it ) + if( *it != NULL ) + this->m_Series[ id ].push_back( ( *it )->filename ); + + } // fi + flist = this->m_GDCMHelper.GetNextSingleSerieUIDFileSet( ); + + } // elihw + + } // fi + + } // elihw + + // Show series + for( auto sIt = this->m_Series.begin( ); sIt != this->m_Series.end( ); ++sIt ) + { + if( sIt->second.size( ) > 0 ) + { + QFileInfo fdir( sIt->second[ 0 ].c_str( ) ); + + unsigned long rows = this->m_UI->Series->rowCount( ); + this->m_UI->Series->insertRow( rows ); + std::stringstream str_count; + str_count << sIt->second.size( ); + QTableWidgetItem* count_item = + new QTableWidgetItem( str_count.str( ).c_str( ) ); + QTableWidgetItem* uid_item = + new QTableWidgetItem( sIt->first.c_str( ) ); + QTableWidgetItem* dir_item = + new QTableWidgetItem( fdir.dir( ).canonicalPath( ) ); + count_item->setFlags( count_item->flags( ) & ~Qt::ItemIsEditable ); + uid_item->setFlags( uid_item->flags( ) & ~Qt::ItemIsEditable ); + dir_item->setFlags( dir_item->flags( ) & ~Qt::ItemIsEditable ); + this->m_UI->Series->setItem( rows, 0, count_item ); + this->m_UI->Series->setItem( rows, 1, uid_item ); + this->m_UI->Series->setItem( rows, 2, dir_item ); + + } // fi + + } // rof + + // Restore cursor + QApplication::restoreOverrideCursor( ); +} + +// ------------------------------------------------------------------------- +std::vector< std::string >* cpPluginsITKIO::DicomSeriesSelectorWidget:: +selectedFilenames( ) +{ + auto items = this->m_UI->Series->selectedItems( ); + if( items.size( ) > 0 ) + { + std::string uid = + this->m_UI->Series-> + item( items[ 0 ]->row( ), 1 )->text( ).toStdString( ); + auto sIt = this->m_Series.find( uid ); + if( sIt != this->m_Series.end( ) ) + return( &( sIt->second ) ); + + } // fi + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpPluginsITKIO::DicomSeriesSelectorWidget:: +_Choose( ) +{ + QString qdir = + QFileDialog::getExistingDirectory( + this, tr( "Open Directory" ), + this->startDir( ), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks + ); + if( qdir.toStdString( ) != "" ) + this->setStartDir( qdir ); +} + +#endif // cpPlugins_QT4 + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/DicomSeriesSelectorWidget.h b/plugins/ITKIO/DicomSeriesSelectorWidget.h new file mode 100644 index 0000000..3ac2fbb --- /dev/null +++ b/plugins/ITKIO/DicomSeriesSelectorWidget.h @@ -0,0 +1,76 @@ +#ifndef __cpPluginsITKIO__DicomSeriesSelectorWidget__H__ +#define __cpPluginsITKIO__DicomSeriesSelectorWidget__H__ + +#include +#include + +#ifdef cpPlugins_QT4 + +#include +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class DicomSeriesSelectorWidget; +} + +// ------------------------------------------------------------------------- +namespace cpPluginsITKIO +{ + /** + */ + class cpPlugins_ITKIO_EXPORT DicomSeriesSelectorWidget + : public QWidget + { + Q_OBJECT; + + public: + typedef DicomSeriesSelectorWidget Self; + + protected: + /** + */ + class _GDCMSerieHelper + : public gdcm::SerieHelper + { + public: + _GDCMSerieHelper( ) + { + } + virtual ~_GDCMSerieHelper( ) + { + } + template< class _TIt > + void SetFileNames( _TIt b, _TIt e ) + { + for( _TIt i = b; i != e; ++i ) + this->AddFileName( *i ); + } + }; + + public: + explicit DicomSeriesSelectorWidget( QWidget* parent = 0 ); + virtual ~DicomSeriesSelectorWidget( ); + + QString startDir( ) const; + void setStartDir( const QString& dir, bool build = true ); + + std::vector< std::string >* selectedFilenames( ); + + protected slots: + void _Choose( ); + + protected: + Ui::DicomSeriesSelectorWidget* m_UI; + _GDCMSerieHelper m_GDCMHelper; + std::map< std::string, std::vector< std::string > > m_Series; + }; + +} // ecapseman + +#endif // cpPlugins_QT4 + +#endif // __cpPluginsITKIO__DicomSeriesSelectorWidget__H__ + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/DicomSeriesSelectorWidget.ui b/plugins/ITKIO/DicomSeriesSelectorWidget.ui new file mode 100644 index 0000000..d3b648f --- /dev/null +++ b/plugins/ITKIO/DicomSeriesSelectorWidget.ui @@ -0,0 +1,89 @@ + + + DicomSeriesSelectorWidget + + + + 0 + 0 + 358 + 299 + + + + Form + + + + 1 + + + 1 + + + + + + + + 101 + 14 + + + + + 101 + 14 + + + + DICOM directory: + + + + + + + true + + + true + + + + + + + + 25 + 25 + + + + + 25 + 25 + + + + ... + + + + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + + + + \ No newline at end of file diff --git a/plugins/ITKIO/ITKIO.i b/plugins/ITKIO/ITKIO.i new file mode 100644 index 0000000..372512e --- /dev/null +++ b/plugins/ITKIO/ITKIO.i @@ -0,0 +1,28 @@ +header #define ITK_MANUAL_INSTANTIATION +header #define ITKIOImageBase_HIDDEN + +define color_pixels=RGBPixel;RGBAPixel +define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor +define matrices=Matrix +define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# > + +cinclude complex +cinclude itkImage.h +cinclude itk#color_pixels#.h +cinclude itkFixedArray.h +cinclude itk#vector_pixels#.h +cinclude itk#matrices#.h +cinclude itkDiffusionTensor3D.h +cinclude itkConvertPixelBuffer.hxx + +define io=ImageFileReader;ImageSeriesReader;ImageFileWriter + +tinclude itk#io#:h|hxx +instances itk::#io#< itk::Image< #pixels#, #pdims# > > +instances itk::#io#< itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# > > +instances itk::#io#< itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# > > +instances itk::#io#< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > > +instances itk::#io#< itk::Image< itk::Offset< #pdims# >, #pdims# > > +instances itk::#io#< itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 > > + +** eof - $RCSfile$ diff --git a/plugins/ITKIO/ImageReader.cxx b/plugins/ITKIO/ImageReader.cxx new file mode 100644 index 0000000..90b032f --- /dev/null +++ b/plugins/ITKIO/ImageReader.cxx @@ -0,0 +1,269 @@ +#include +#include +#include + +#define ITKIOImageBase_HIDDEN +#include +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginsITKIO::ImageReader:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::OpenFileDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::OpenFileDialog( ); + dlg->SetParameters( &( this->m_Parameters ), "FileNames" ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginsITKIO::ImageReader:: +ImageReader( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + this->m_Parameters.Clear( ); + this->m_Parameters.ConfigureAsOpenFileNameList( "FileNames" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileNames", + "Image files (*.bmp *.png *.jpg *.jpeg *.dcm *.mhd *.nhdr *.nrrd *.tiff)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKIO::ImageReader:: +~ImageReader( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKIO::ImageReader:: +_GenerateData( ) +{ + // Get filenames + auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" ); + std::string fname = ""; + if( fnames.size( ) > 1 ) + { + std::stringstream fname_str; + fname_str << fnames[ 0 ] << cpPlugins_PATH_SEPARATOR << fnames[ 1 ]; + fname = fname_str.str( ); + } + else if( fnames.size( ) == 1 ) + fname = fnames[ 0 ]; + + if( fname != "" ) + { + // Guess image properties + itk::ImageIOBase::Pointer io = + itk::ImageIOFactory::CreateImageIO( + fname.c_str( ), itk::ImageIOFactory::ReadMode + ); + if( io.IsNotNull( ) ) + { + io->SetFileName( fname ); + io->ReadImageInformation( ); + bool success = false; + unsigned int dim = io->GetNumberOfDimensions( ); +#ifdef cpPlugins_PROCESS_DIMS_1 + if( dim == 1 ) success = this->_GD0< 1 >( io ); +#endif // cpPlugins_PROCESS_DIMS_1 +#ifdef cpPlugins_PROCESS_DIMS_2 + if( dim == 2 ) success = this->_GD0< 2 >( io ); +#endif // cpPlugins_PROCESS_DIMS_2 +#ifdef cpPlugins_PROCESS_DIMS_3 + if( dim == 3 ) success = this->_GD0< 3 >( io ); +#endif // cpPlugins_PROCESS_DIMS_3 +#ifdef cpPlugins_PROCESS_DIMS_4 + if( dim == 4 ) success = this->_GD0< 4 >( io ); +#endif // cpPlugins_PROCESS_DIMS_4 + if( !success ) + this->_Error( "Image dimension not supported." ); + } + else + this->_Error( + std::string( "Could not create an ImageIO for \"" ) + + fnames[ 0 ] + + std::string( "\"" ) + ); + } + else + this->_Error( "No image(s) given" ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _Dim > +bool cpPluginsITKIO::ImageReader:: +_GD0( itk::ImageIOBase* io ) +{ + typedef unsigned char uchar; + typedef unsigned short ushort; + typedef unsigned int uint; + typedef unsigned long ulong; + + itk::ImageIOBase::IOComponentType ct = io->GetComponentType( ); + itk::ImageIOBase::IOPixelType pt = io->GetPixelType( ); + + bool success = false; + if( pt == itk::ImageIOBase::SCALAR ) + { + if( ct == itk::ImageIOBase::CHAR ) success = this->_GD1< char, _Dim >( io ); + if( ct == itk::ImageIOBase::UCHAR ) success = this->_GD1< uchar, _Dim >( io ); + if( ct == itk::ImageIOBase::SHORT ) success = this->_GD1< short, _Dim >( io ); + if( ct == itk::ImageIOBase::USHORT ) success = this->_GD1< ushort, _Dim >( io ); + if( ct == itk::ImageIOBase::INT ) success = this->_GD1< int, _Dim >( io ); + if( ct == itk::ImageIOBase::UINT ) success = this->_GD1< uint, _Dim >( io ); + if( ct == itk::ImageIOBase::LONG ) success = this->_GD1< long, _Dim >( io ); + if( ct == itk::ImageIOBase::ULONG ) success = this->_GD1< ulong, _Dim >( io ); + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< float, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< double, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::RGB ) + { + if( ct == itk::ImageIOBase::CHAR ) success = this->_GD1< itk::RGBPixel< char >, _Dim >( io ); + if( ct == itk::ImageIOBase::UCHAR ) success = this->_GD1< itk::RGBPixel< uchar >, _Dim >( io ); + if( ct == itk::ImageIOBase::SHORT ) success = this->_GD1< itk::RGBPixel< short >, _Dim >( io ); + if( ct == itk::ImageIOBase::USHORT ) success = this->_GD1< itk::RGBPixel< ushort >, _Dim >( io ); + if( ct == itk::ImageIOBase::INT ) success = this->_GD1< itk::RGBPixel< int >, _Dim >( io ); + if( ct == itk::ImageIOBase::UINT ) success = this->_GD1< itk::RGBPixel< uint >, _Dim >( io ); + if( ct == itk::ImageIOBase::LONG ) success = this->_GD1< itk::RGBPixel< long >, _Dim >( io ); + if( ct == itk::ImageIOBase::ULONG ) success = this->_GD1< itk::RGBPixel< ulong >, _Dim >( io ); + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::RGBPixel< float >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::RGBPixel< double >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::RGBA ) + { + if( ct == itk::ImageIOBase::CHAR ) success = this->_GD1< itk::RGBAPixel< char >, _Dim >( io ); + if( ct == itk::ImageIOBase::UCHAR ) success = this->_GD1< itk::RGBAPixel< uchar >, _Dim >( io ); + if( ct == itk::ImageIOBase::SHORT ) success = this->_GD1< itk::RGBAPixel< short >, _Dim >( io ); + if( ct == itk::ImageIOBase::USHORT ) success = this->_GD1< itk::RGBAPixel< ushort >, _Dim >( io ); + if( ct == itk::ImageIOBase::INT ) success = this->_GD1< itk::RGBAPixel< int >, _Dim >( io ); + if( ct == itk::ImageIOBase::UINT ) success = this->_GD1< itk::RGBAPixel< uint >, _Dim >( io ); + if( ct == itk::ImageIOBase::LONG ) success = this->_GD1< itk::RGBAPixel< long >, _Dim >( io ); + if( ct == itk::ImageIOBase::ULONG ) success = this->_GD1< itk::RGBAPixel< ulong >, _Dim >( io ); + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::RGBAPixel< float >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::RGBAPixel< double >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::COMPLEX ) + { + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< std::complex< float >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< std::complex< double >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::COVARIANTVECTOR ) + { + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::CovariantVector< float, _Dim >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::CovariantVector< double, _Dim >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::POINT ) + { + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::Point< float, _Dim >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::Point< double, _Dim >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::VECTOR ) + { + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::Vector< float, _Dim >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::Vector< double, _Dim >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR ) + { + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::SymmetricSecondRankTensor< float, _Dim >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::SymmetricSecondRankTensor< double, _Dim >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::DIFFUSIONTENSOR3D ) + { + if( _Dim == 3 ) + { + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::DiffusionTensor3D< float >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::DiffusionTensor3D< double >, _Dim >( io ); + } + else + this->_Error( "DiffusionTensor3D dimension not supported." ); + } + else if( pt == itk::ImageIOBase::MATRIX ) + { + if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::Matrix< float, _Dim, _Dim >, _Dim >( io ); + if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::Matrix< double, _Dim, _Dim >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::OFFSET ) + { + this->_GD1< itk::Offset< _Dim >, _Dim >( io ); + } + else if( pt == itk::ImageIOBase::FIXEDARRAY ) + { + } // fi + return( success ); +} + +// ------------------------------------------------------------------------- +template< class _TPixel, unsigned int _Dim > +bool cpPluginsITKIO::ImageReader:: +_GD1( itk::ImageIOBase* io ) +{ + typedef itk::Image< _TPixel, _Dim > _TImage; + + // Get filenames + auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" ); + if( fnames.size( ) == 1 || fnames.size( ) == 2 ) + { + std::stringstream fname_str; + if( fnames.size( ) == 1 ) + fname_str << fnames[ 0 ]; + else + fname_str << fnames[ 0 ] << cpPlugins_PATH_SEPARATOR << fnames[ 1 ]; + + auto f = this->_CreateITK< itk::ImageFileReader< _TImage > >( ); + f->SetFileName( fname_str.str( ) ); + f->SetImageIO( io ); + try + { + f->Update( ); + this->GetOutput( "Output" )->SetITK( f->GetOutput( ) ); + return( true ); + } + catch( itk::ExceptionObject& err ) + { + this->_Error( err.GetDescription( ) ); + return( false ); + + } // yrt + } + else // if( fnames.size( ) > 1 ) + { + auto f = this->_CreateITK< itk::ImageSeriesReader< _TImage > >( ); + auto i = fnames.begin( ); + std::stringstream dir; + dir << *i << cpPlugins_PATH_SEPARATOR; + i++; + for( ; i != fnames.end( ); ++i ) + f->AddFileName( dir.str( ) + *i ); + f->SetImageIO( io ); + try + { + f->Update( ); + this->GetOutput( "Output" )->SetITK( f->GetOutput( ) ); + return( true ); + } + catch( itk::ExceptionObject& err ) + { + this->_Error( err.GetDescription( ) ); + return( false ); + + } // yrt + + } // fi +} + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/ImageReader.h b/plugins/ITKIO/ImageReader.h new file mode 100644 index 0000000..0e566d6 --- /dev/null +++ b/plugins/ITKIO/ImageReader.h @@ -0,0 +1,33 @@ +#ifndef __cpPluginsITKIO__ImageReader__h__ +#define __cpPluginsITKIO__ImageReader__h__ + +#include +#include + +namespace itk { class ImageIOBase; } + +namespace cpPluginsITKIO +{ + /** + */ + class cpPlugins_ITKIO_EXPORT ImageReader + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( ImageReader, cpPlugins::Pipeline::ProcessObject, IO ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + + protected: + template< unsigned int _Dim > + inline bool _GD0( itk::ImageIOBase* io ); + + template< class _TPixel, unsigned int _Dim > + inline bool _GD1( itk::ImageIOBase* io ); + }; + +} // ecapseman + +#endif // __cpPluginsITKIO__ImageReader__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/ImageWriter.cxx b/plugins/ITKIO/ImageWriter.cxx new file mode 100644 index 0000000..a40aad6 --- /dev/null +++ b/plugins/ITKIO/ImageWriter.cxx @@ -0,0 +1,93 @@ +#include +#include +#include + +#define ITKIOImageBase_HIDDEN +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginsITKIO::ImageWriter:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::SaveFileDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::SaveFileDialog( ); + dlg->SetParameters( &( this->m_Parameters ), "FileName" ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginsITKIO::ImageWriter:: +ImageWriter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileName", + "Image files (*.bmp *.png *.jpg *.jpeg *.dcm *.mhd *.nhdr *.nrrd *.tiff)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKIO::ImageWriter:: +~ImageWriter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKIO::ImageWriter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ProcessDims_1( o, _GD0 ) + cpPlugins_Demangle_Image_DiffTensors3D_1( o, _GD1 ) + this->_Error( "Invalid input image dimension." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKIO::ImageWriter:: +_GD0( _TImage* image ) +{ + cpPlugins_Demangle_Image_ScalarPixels_1( image, _GD1, _TImage::ImageDimension ) + cpPlugins_Demangle_Image_ComplexPixels_1( image, _GD1, _TImage::ImageDimension ) + cpPlugins_Demangle_Image_ColorPixels_1( image, _GD1, _TImage::ImageDimension ) + cpPlugins_Demangle_Image_VectorPixels_1( image, _GD1, _TImage::ImageDimension ) + this->_Error( "Invalid input image pixel type." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKIO::ImageWriter:: +_GD1( _TImage* image ) +{ + typedef itk::ImageFileWriter< _TImage > _TFilter; + + auto f = this->_CreateITK< _TFilter >( ); + f->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ) ); + f->SetInput( image ); + try + { + f->Update( ); + } + catch( itk::ExceptionObject& err ) + { + this->_Error( err.GetDescription( ) ); + + } // yrt +} + +// eof - $RCSfile$ diff --git a/plugins/ITKIO/ImageWriter.h b/plugins/ITKIO/ImageWriter.h new file mode 100644 index 0000000..1c0a131 --- /dev/null +++ b/plugins/ITKIO/ImageWriter.h @@ -0,0 +1,31 @@ +#ifndef __cpPluginsITKIO__ImageWriter__h__ +#define __cpPluginsITKIO__ImageWriter__h__ + +#include +#include + +namespace cpPluginsITKIO +{ + /** + */ + class cpPlugins_ITKIO_EXPORT ImageWriter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( ImageWriter, cpPlugins::Pipeline::ProcessObject, IO ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKIO__ImageWriter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/CastImageFilter.cxx b/plugins/ITKImageGenericFilters_1/CastImageFilter.cxx new file mode 100644 index 0000000..a7cf31b --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/CastImageFilter.cxx @@ -0,0 +1,64 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::CastImageFilter:: +CastImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + this->m_Parameters.ConfigureAsScalarTypesChoices( "OutputPixelType" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::CastImageFilter:: +~CastImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageGenericFilters_1::CastImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TInput > +void cpPluginsITKImageGenericFilters_1::CastImageFilter:: +_GD0( _TInput* input ) +{ + std::string o_type = + this->m_Parameters.GetSelectedChoice( "OutputPixelType" ); + if( o_type == "char" ) this->_GD1< _TInput, char >( input ); + else if( o_type == "short" ) this->_GD1< _TInput, short >( input ); + else if( o_type == "int" ) this->_GD1< _TInput, int >( input ); + else if( o_type == "long" ) this->_GD1< _TInput, long >( input ); + else if( o_type == "uchar" ) this->_GD1< _TInput, unsigned char >( input ); + else if( o_type == "ushort" ) this->_GD1< _TInput, unsigned short >( input ); + else if( o_type == "uint" ) this->_GD1< _TInput, unsigned int >( input ); + else if( o_type == "ulong" ) this->_GD1< _TInput, unsigned long >( input ); + else if( o_type == "float" ) this->_GD1< _TInput, float >( input ); + else if( o_type == "double" ) this->_GD1< _TInput, double >( input ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutputPixel > +void cpPluginsITKImageGenericFilters_1::CastImageFilter:: +_GD1( _TInput* input ) +{ + typedef itk::Image< _TOutputPixel, _TInput::ImageDimension > _TOutput; + typedef itk::CastImageFilter< _TInput, _TOutput > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( input ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/CastImageFilter.h b/plugins/ITKImageGenericFilters_1/CastImageFilter.h new file mode 100644 index 0000000..973e0d9 --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/CastImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKImageGenericFilters_1__CastImageFilter__h__ +#define __cpPluginsITKImageGenericFilters_1__CastImageFilter__h__ + +#include +#include + +namespace cpPluginsITKImageGenericFilters_1 +{ + /** + */ + class cpPlugins_ITKImageGenericFilters_1_EXPORT CastImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + CastImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageFilters + ); + + protected: + template< class _TInput > + inline void _GD0( _TInput* input ); + + template< class _TInput, class _TOutputPixel > + inline void _GD1( _TInput* input ); + }; + +} // ecapseman + +#endif // __cpPluginsITKImageGenericFilters_1__CastImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/ITKImageGenericFilters_1.i b/plugins/ITKImageGenericFilters_1/ITKImageGenericFilters_1.i new file mode 100644 index 0000000..8c62830 --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/ITKImageGenericFilters_1.i @@ -0,0 +1,21 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude itkUnaryFunctorImageFilter:h|hxx + +define filters_1=CastImageFilter;ShiftScaleImageFilter +define i_scalars=#scalar_types# +define o_scalars=#scalar_types# + +tinclude itk#filters_1#:h|hxx +instances itk::#filters_1#< itk::Image< #i_scalars#, #pdims# >, itk::Image< #o_scalars#, #pdims# > > + +tinclude itkRegionOfInterestImageFilter:h|hxx +instances itk::RegionOfInterestImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# > > + +tinclude itkMinimumMaximumImageCalculator:h|hxx +instances itk::MinimumMaximumImageCalculator< itk::Image< #scalar_types#, #pdims# > > + +tinclude cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold:h|hxx +instances cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< itk::Image< #scalar_types#, #pdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.cxx b/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.cxx new file mode 100644 index 0000000..a4e815b --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.cxx @@ -0,0 +1,63 @@ +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold:: +ImageToBoundingBoxFromThreshold( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::BoundingBox >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "LowerThreshold", 0 ); + this->m_Parameters.ConfigureAsReal( "UpperThreshold", 1 ); + this->m_Parameters.ConfigureAsUint( "PAD", 0 ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold:: +~ImageToBoundingBoxFromThreshold( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold:: +_GD0( _TImage* image ) +{ + typedef + cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage > + _TFilter; + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetImage( image ); + filter->SetLowerThreshold( this->m_Parameters.GetReal( "LowerThreshold" ) ); + filter->SetUpperThreshold( this->m_Parameters.GetReal( "UpperThreshold" ) ); + filter->SetPAD( this->m_Parameters.GetUint( "PAD" ) ); + filter->Compute( ); + + // Create output + auto reg = filter->GetRegion( ); + auto bb = this->GetOutput< cpInstances::DataObjects::BoundingBox >( "Output" ); + typename _TImage::PointType p0, p1; + image->TransformIndexToPhysicalPoint( reg.GetIndex( ), p0 ); + image->TransformIndexToPhysicalPoint( reg.GetIndex( ) + reg.GetSize( ), p1 ); + bb->SetMinimum( p0 ); + bb->SetMaximum( p1 ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.h b/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.h new file mode 100644 index 0000000..92c8613 --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKImageGenericFilters_1__ImageToBoundingBoxFromThreshold__h__ +#define __cpPluginsITKImageGenericFilters_1__ImageToBoundingBoxFromThreshold__h__ + +#include +#include + +namespace cpPluginsITKImageGenericFilters_1 +{ + /** + */ + class cpPlugins_ITKImageGenericFilters_1_EXPORT ImageToBoundingBoxFromThreshold + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + ImageToBoundingBoxFromThreshold, + cpPlugins::Pipeline::ProcessObject, + ImageFeatures + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKImageGenericFilters_1__ImageToBoundingBoxFromThreshold__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.cxx b/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.cxx new file mode 100644 index 0000000..c30cad3 --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.cxx @@ -0,0 +1,120 @@ +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator:: +MinimumMaximumImageCalculator( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + typedef cpInstances::DataObjects::Mesh _TMesh; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TMesh >( "Maximum" ); + this->_ConfigureOutput< _TMesh >( "Minimum" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator:: +~MinimumMaximumImageCalculator( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator:: +_GD0( _TImage* input ) +{ + typedef itk::MinimumMaximumImageCalculator< _TImage > _TFilter; + typedef typename _TImage::IndexType _TIndex; + typedef typename _TImage::PointType _TPoint; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetImage( input ); + filter->Compute( ); + + _TIndex min_idx = filter->GetIndexOfMinimum( ); + _TIndex max_idx = filter->GetIndexOfMaximum( ); + + _TPoint min_pnt, max_pnt; + input->TransformIndexToPhysicalPoint( min_idx, min_pnt ); + input->TransformIndexToPhysicalPoint( max_idx, max_pnt ); + + auto min_pd = this->GetOutputData< vtkPolyData >( "Minimum" ); + if( min_pd == NULL ) + { + auto points = vtkSmartPointer< vtkPoints >::New( ); + auto verts = vtkSmartPointer< vtkCellArray >::New( ); + auto lines = vtkSmartPointer< vtkCellArray >::New( ); + auto polys = vtkSmartPointer< vtkCellArray >::New( ); + auto strips = vtkSmartPointer< vtkCellArray >::New( ); + auto pd = vtkSmartPointer< vtkPolyData >::New( ); + pd->SetPoints( points ); + pd->SetVerts( verts ); + pd->SetLines( lines ); + pd->SetPolys( polys ); + pd->SetStrips( strips ); + + points->InsertNextPoint( 0, 0, 0 ); + verts->InsertNextCell( 1 ); + verts->InsertCellPoint( 0 ); + + this->GetOutput( "Minimum" )->SetVTK( pd ); + min_pd = this->GetOutputData< vtkPolyData >( "Minimum" ); + + } // fi + + if( _TImage::ImageDimension == 1 ) + min_pd->GetPoints( )->SetPoint( 0, min_pnt[ 0 ], 0, 0 ); + else if( _TImage::ImageDimension == 2 ) + min_pd->GetPoints( )->SetPoint( 0, min_pnt[ 0 ], min_pnt[ 1 ], 0 ); + else if( _TImage::ImageDimension > 2 ) + min_pd->GetPoints( )->SetPoint( 0, min_pnt[ 0 ], min_pnt[ 1 ], min_pnt[ 2 ] ); + + auto max_pd = this->GetOutputData< vtkPolyData >( "Maximum" ); + if( max_pd == NULL ) + { + auto points = vtkSmartPointer< vtkPoints >::New( ); + auto verts = vtkSmartPointer< vtkCellArray >::New( ); + auto lines = vtkSmartPointer< vtkCellArray >::New( ); + auto polys = vtkSmartPointer< vtkCellArray >::New( ); + auto strips = vtkSmartPointer< vtkCellArray >::New( ); + auto pd = vtkSmartPointer< vtkPolyData >::New( ); + pd->SetPoints( points ); + pd->SetVerts( verts ); + pd->SetLines( lines ); + pd->SetPolys( polys ); + pd->SetStrips( strips ); + + points->InsertNextPoint( 0, 0, 0 ); + verts->InsertNextCell( 1 ); + verts->InsertCellPoint( 0 ); + + this->GetOutput( "Maximum" )->SetVTK( pd ); + max_pd = this->GetOutputData< vtkPolyData >( "Maximum" ); + + } // fi + + if( _TImage::ImageDimension == 1 ) + max_pd->GetPoints( )->SetPoint( 0, max_pnt[ 0 ], 0, 0 ); + else if( _TImage::ImageDimension == 2 ) + max_pd->GetPoints( )->SetPoint( 0, max_pnt[ 0 ], max_pnt[ 1 ], 0 ); + else if( _TImage::ImageDimension > 2 ) + max_pd->GetPoints( )->SetPoint( 0, max_pnt[ 0 ], max_pnt[ 1 ], max_pnt[ 2 ] ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.h b/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.h new file mode 100644 index 0000000..a52c685 --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKImageGenericFilters_1__MinimumMaximumImageCalculator__h__ +#define __cpPluginsITKImageGenericFilters_1__MinimumMaximumImageCalculator__h__ + +#include +#include + +namespace cpPluginsITKImageGenericFilters_1 +{ + /** + */ + class cpPlugins_ITKImageGenericFilters_1_EXPORT MinimumMaximumImageCalculator + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + MinimumMaximumImageCalculator, + cpPlugins::Pipeline::ProcessObject, + ImageFeatures + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* input ); + }; + +} // ecapseman + +#endif // __cpPluginsImageGenericFilters__MinimumMaximumImageCalculator__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.cxx b/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.cxx new file mode 100644 index 0000000..52ec23b --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.cxx @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter:: +RegionOfInterestImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + typedef cpInstances::DataObjects::BoundingBox _TBBox; + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureInput< _TBBox >( "BoundingBox", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter:: +~RegionOfInterestImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter:: +_GD0( _TImage* input ) +{ + typedef cpInstances::DataObjects::BoundingBox _TBBox; + typedef itk::RegionOfInterestImageFilter< _TImage, _TImage > _TFilter; + typedef typename _TImage::IndexType _TIndex; + typedef typename _TImage::PointType _TPoint; + typedef typename _TImage::RegionType _TRegion; + typedef typename _TImage::SizeType _TSize; + + auto bb = this->GetInput< _TBBox >( "BoundingBox" ); + + _TRegion in_region = input->GetRequestedRegion( ); + _TIndex in_i0 = in_region.GetIndex( ); + _TIndex in_i1 = in_i0 + in_region.GetSize( ); + _TIndex i0, i1; + input->TransformPhysicalPointToIndex( bb->GetMinimum< _TPoint >( ), i0 ); + input->TransformPhysicalPointToIndex( bb->GetMaximum< _TPoint >( ), i1 ); + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + { + if( i0[ d ] < in_i0[ d ] ) i0[ d ] = in_i0[ d ]; + if( i1[ d ] > in_i1[ d ] ) i1[ d ] = in_i1[ d ]; + + } // rof + + _TSize size; + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + size[ d ] = i1[ d ] - i0[ d ]; + + _TRegion region; + region.SetIndex( i0 ); + region.SetSize( size ); + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( input ); + filter->SetRegionOfInterest( region ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.h b/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.h new file mode 100644 index 0000000..5d29887 --- /dev/null +++ b/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKImageGenericFilters_1__RegionOfInterestImageFilter__h__ +#define __cpPluginsITKImageGenericFilters_1__RegionOfInterestImageFilter__h__ + +#include +#include + +namespace cpPluginsITKImageGenericFilters_1 +{ + /** + */ + class cpPlugins_ITKImageGenericFilters_1_EXPORT RegionOfInterestImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + RegionOfInterestImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* input ); + }; + +} // ecapseman + +#endif // __cpPluginsITKImageGenericFilters_1__RegionOfInterestImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.cxx b/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.cxx new file mode 100644 index 0000000..16c64da --- /dev/null +++ b/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.cxx @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction:: +BSplineInterpolateImageFunction( ) + : Superclass( ) +{ + this->m_Parameters.ConfigureAsUint( "SplineOrder", 3 ); + this->m_Parameters.ConfigureAsBool( "UseImageDirection", true ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction:: +~BSplineInterpolateImageFunction( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction:: +CreateInterpolator( + itk::LightObject* image, const std::string& precision_type + ) +{ + this->m_PrecisionType = precision_type; + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( image, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction:: +_GenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction:: +_GD0( _TImage* image ) +{ + if( this->m_PrecisionType == "float" ) + this->_GD1< _TImage, float >( image ); + else if( this->m_PrecisionType == "double" ) + this->_GD1< _TImage, double >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction:: +_GD1( _TImage* image ) +{ + typedef itk::BSplineInterpolateImageFunction< _TImage, _TScalar, _TScalar > _TFunction; + + auto function = this->_CreateITK< _TFunction >( ); + function->SetSplineOrder( this->m_Parameters.GetUint( "SplineOrder" ) ); + function->SetUseImageDirection( this->m_Parameters.GetBool( "UseImageDirection" ) ); + this->GetOutput( "Output" )->SetITK( function ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.h b/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.h new file mode 100644 index 0000000..bb0ee9f --- /dev/null +++ b/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.h @@ -0,0 +1,38 @@ +#ifndef __cpPluginsITKImageInterpolators__BSplineInterpolateImageFunction__h__ +#define __cpPluginsITKImageInterpolators__BSplineInterpolateImageFunction__h__ + +#include +#include + +namespace cpPluginsITKImageInterpolators +{ + /** + */ + class cpPlugins_ITKImageInterpolators_EXPORT BSplineInterpolateImageFunction + : public InterpolateImageFunction + { + cpPluginsObject( + BSplineInterpolateImageFunction, + InterpolateImageFunction, + ITKImageInterpolators + ); + + public: + virtual void CreateInterpolator( + itk::LightObject* image, + const std::string& precision_type + ) cpPlugins_OVERRIDE; + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKImageInterpolators__BSplineInterpolateImageFunction__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKImageInterpolators/ITKImageInterpolators.i b/plugins/ITKImageInterpolators/ITKImageInterpolators.i new file mode 100644 index 0000000..c6c5f9c --- /dev/null +++ b/plugins/ITKImageInterpolators/ITKImageInterpolators.i @@ -0,0 +1,25 @@ +header #define ITK_MANUAL_INSTANTIATION + +define v=FixedArray +define i_real=#real_types# +define o_real=#real_types# +define interp=Linear + +tinclude itkImageFunction:h|hxx +tinclude itk#interp#InterpolateImageFunction:h|hxx +tinclude itkVectorLinearInterpolateImageFunction:h|hxx + +cinclude itk#v#.h +cinclude itkImage.h + +instances itk::ImageFunction< itk::Image< #scalar_types#, #pdims# >, #i_real#, #o_real# > +instances itk::#interp#InterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types# > + +instances itk::VectorLinearInterpolateImageFunction< itk::Image< itk::#v#< #i_real#, #pdims# >, #pdims# >, #o_real# > + +tinclude itkBSplineDecompositionImageFilter:h|hxx +tinclude itkBSplineInterpolateImageFunction:h|hxx +instances itk::BSplineInterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types#, #real_types# > +instances itk::BSplineDecompositionImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKImageInterpolators/InterpolateImageFunction.cxx b/plugins/ITKImageInterpolators/InterpolateImageFunction.cxx new file mode 100644 index 0000000..b58fba5 --- /dev/null +++ b/plugins/ITKImageInterpolators/InterpolateImageFunction.cxx @@ -0,0 +1,39 @@ +#include + +// ------------------------------------------------------------------------- +void cpPluginsITKImageInterpolators::InterpolateImageFunction:: +SetITK( itk::LightObject* o ) +{ + if( this->m_ITK.GetPointer( ) != o ) + this->m_ITK = o; +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageInterpolators::InterpolateImageFunction:: +SetVTK( vtkObjectBase* o ) +{ + if( this->m_VTK.GetPointer( ) != o ) + this->m_VTK = o; +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageInterpolators::InterpolateImageFunction:: +InterpolateImageFunction( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpPlugins::Pipeline::DataObject >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageInterpolators::InterpolateImageFunction:: +~InterpolateImageFunction( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageInterpolators::InterpolateImageFunction:: +_GenerateData( ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/ITKImageInterpolators/InterpolateImageFunction.h b/plugins/ITKImageInterpolators/InterpolateImageFunction.h new file mode 100644 index 0000000..d3fd440 --- /dev/null +++ b/plugins/ITKImageInterpolators/InterpolateImageFunction.h @@ -0,0 +1,54 @@ +#ifndef __cpPluginsITKImageInterpolators__InterpolateImageFunction__h__ +#define __cpPluginsITKImageInterpolators__InterpolateImageFunction__h__ + +#include +#include + +namespace cpPluginsITKImageInterpolators +{ + /** + */ + class cpPlugins_ITKImageInterpolators_EXPORT InterpolateImageFunction + : public cpPlugins::Pipeline::ProcessObject + { + public: + typedef InterpolateImageFunction Self; + typedef cpPlugins::Pipeline::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( BaseFilter, cpPlugins::Pipeline::ProcessObject ); + cpPlugins_Id_Macro( InterpolateImageFunction, ImageInterpolators ); + + public: + virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE; + + protected: + InterpolateImageFunction( ); + virtual ~InterpolateImageFunction( ); + + public: + virtual void CreateInterpolator( + itk::LightObject* image, + const std::string& precision_type + ) = 0; + + protected: + virtual void _GenerateData( ) cpPlugins_OVERRIDE; + + private: + // Purposely not implemented. + InterpolateImageFunction( const Self& other ); + Self& operator=( const Self& other ); + + protected: + std::string m_PrecisionType; + }; + +} // ecapseman + +#endif // __cpPluginsITKImageInterpolators__InterpolateImageFunction__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.cxx b/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.cxx new file mode 100644 index 0000000..5317a29 --- /dev/null +++ b/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.cxx @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKImageInterpolators::LinearInterpolateImageFunction:: +LinearInterpolateImageFunction( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPluginsITKImageInterpolators::LinearInterpolateImageFunction:: +~LinearInterpolateImageFunction( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction:: +CreateInterpolator( + itk::LightObject* image, const std::string& precision_type + ) +{ + this->m_PrecisionType = precision_type; + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( image, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction:: +_GenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction:: +_GD0( _TImage* image ) +{ + if( this->m_PrecisionType == "float" ) + this->_GD1< _TImage, float >( image ); + else if( this->m_PrecisionType == "double" ) + this->_GD1< _TImage, double >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction:: +_GD1( _TImage* image ) +{ + typedef itk::LinearInterpolateImageFunction< _TImage, _TScalar > _TFunction; + + auto function = this->_CreateITK< _TFunction >( ); + this->GetOutput( "Output" )->SetITK( function ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.h b/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.h new file mode 100644 index 0000000..a6fa94c --- /dev/null +++ b/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.h @@ -0,0 +1,38 @@ +#ifndef __cpPluginsITKImageInterpolators__LinearInterpolateImageFunction__h__ +#define __cpPluginsITKImageInterpolators__LinearInterpolateImageFunction__h__ + +#include +#include + +namespace cpPluginsITKImageInterpolators +{ + /** + */ + class cpPlugins_ITKImageInterpolators_EXPORT LinearInterpolateImageFunction + : public InterpolateImageFunction + { + cpPluginsObject( + LinearInterpolateImageFunction, + InterpolateImageFunction, + ITKImageInterpolators + ); + + public: + virtual void CreateInterpolator( + itk::LightObject* image, + const std::string& precision_type + ) cpPlugins_OVERRIDE; + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKImageInterpolators__LinearInterpolateImageFunction__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKLevelSetFilters/ITKLevelSetFilters.i b/plugins/ITKLevelSetFilters/ITKLevelSetFilters.i new file mode 100644 index 0000000..a1c4a75 --- /dev/null +++ b/plugins/ITKLevelSetFilters/ITKLevelSetFilters.i @@ -0,0 +1,28 @@ +header #define ITK_MANUAL_INSTANTIATION + +define base=ZeroCrossingImageFilter;SparseFieldLevelSetImageFilter +define filters=SegmentationLevelSetImageFilter;ThresholdSegmentationLevelSetImageFilter;LaplacianSegmentationLevelSetImageFilter +define functions=LevelSetFunction +define ls_functions=SegmentationLevelSetFunction;ThresholdSegmentationLevelSetFunction;LaplacianSegmentationLevelSetFunction + +define i_reals=#real_types# +define o_reals=#real_types# + +tinclude itk#functions#:h|hxx +tinclude itk#ls_functions#:h|hxx +tinclude itk#base#:h|hxx +tinclude itk#filters#:h|hxx +tinclude itkSparseFieldLayer:h|hxx +tinclude itkObjectStore:h|hxx + +cinclude itkLinearInterpolateImageFunction.hxx + +instances itk::SparseFieldLayer< itk::SparseFieldLevelSetNode< itk::Index< #pdims# > > > +instances itk::ObjectStore< itk::SparseFieldLevelSetNode< itk::Index< #pdims# > > > + +instances itk::#functions#< itk::Image< #i_reals#, #pdims# > > +instances itk::#ls_functions#< itk::Image< #i_reals#, #pdims# >, itk::Image< #o_reals#, #pdims# > > +instances itk::#base#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #i_reals#, #pdims# > > +instances itk::#filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #i_reals#, #pdims# >, #o_reals# > + +** eof - $RCSfile$ diff --git a/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.cxx b/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.cxx new file mode 100644 index 0000000..c45c75a --- /dev/null +++ b/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.cxx @@ -0,0 +1,72 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter:: +LaplacianSegmentationLevelSetImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Feature", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "PropagationScaling", 1 ); + this->m_Parameters.ConfigureAsReal( "CurvatureScaling", 1 ); + this->m_Parameters.ConfigureAsReal( "MaximumRMSError", 0.02 ); + this->m_Parameters.ConfigureAsReal( "IsoSurfaceValue", 0 ); + this->m_Parameters.ConfigureAsUint( "NumberOfIterations", 100 ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter:: +~LaplacianSegmentationLevelSetImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_RealPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter:: +_GD0( _TImage* image ) +{ + auto f = this->GetInputData( "Feature" ); + cpPlugins_Demangle_Image_RealPixels_2( f, _GD1, _TImage::ImageDimension, image ) + this->_Error( "Invalid feature image." ); +} + +// ------------------------------------------------------------------------- +template< class _TFeature, class _TImage > +void cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter:: +_GD1( _TFeature* feature, _TImage* image ) +{ + typedef typename _TFeature::PixelType _TScalar; + typedef + itk::LaplacianSegmentationLevelSetImageFilter< _TImage, _TFeature, _TScalar > + _TFilter; + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetFeatureImage( feature ); + filter->SetPropagationScaling( this->m_Parameters.GetReal( "PropagationScaling" ) ); + filter->SetCurvatureScaling( this->m_Parameters.GetReal( "CurvatureScaling" ) ); + filter->SetMaximumRMSError( this->m_Parameters.GetReal( "MaximumRMSError" ) ); + filter->SetIsoSurfaceValue( this->m_Parameters.GetReal( "IsoSurfaceValue" ) ); + filter->SetNumberOfIterations( this->m_Parameters.GetUint( "NumberOfIterations" ) ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.h b/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.h new file mode 100644 index 0000000..d82aa9b --- /dev/null +++ b/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKLevelSetFilters__LaplacianSegmentationLevelSetImageFilter__h__ +#define __cpPluginsITKLevelSetFilters__LaplacianSegmentationLevelSetImageFilter__h__ + +#include +#include + +namespace cpPluginsITKLevelSetFilters +{ + /** + */ + class cpPlugins_ITKLevelSetFilters_EXPORT LaplacianSegmentationLevelSetImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + LaplacianSegmentationLevelSetImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageLevelSetFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TFeature, class _TImage > + inline void _GD1( _TFeature* feature, _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKLevelSetFilters__LaplacianSegmentationLevelSetImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.cxx b/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.cxx new file mode 100644 index 0000000..9847f54 --- /dev/null +++ b/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.cxx @@ -0,0 +1,76 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter:: +ThresholdSegmentationLevelSetImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Feature", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "PropagationScaling", 1 ); + this->m_Parameters.ConfigureAsReal( "CurvatureScaling", 1 ); + this->m_Parameters.ConfigureAsReal( "MaximumRMSError", 0.02 ); + this->m_Parameters.ConfigureAsReal( "UpperThreshold", 1 ); + this->m_Parameters.ConfigureAsReal( "LowerThreshold", 0 ); + this->m_Parameters.ConfigureAsReal( "IsoSurfaceValue", 0 ); + this->m_Parameters.ConfigureAsUint( "NumberOfIterations", 100 ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter:: +~ThresholdSegmentationLevelSetImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_RealPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image dimension." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter:: +_GD0( _TImage* image ) +{ + auto f = this->GetInputData( "Feature" ); + cpPlugins_Demangle_Image_RealPixels_2( f, _GD1, _TImage::ImageDimension, image ) + this->_Error( "Invalid feature image." ); +} + +// ------------------------------------------------------------------------- +template< class _TFeature, class _TImage > +void cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter:: +_GD1( _TFeature* feature, _TImage* image ) +{ + typedef typename _TFeature::PixelType _TScalar; + typedef + itk::ThresholdSegmentationLevelSetImageFilter< _TImage, _TFeature, _TScalar > + _TFilter; + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetFeatureImage( feature ); + filter->SetPropagationScaling( this->m_Parameters.GetReal( "PropagationScaling" ) ); + filter->SetCurvatureScaling( this->m_Parameters.GetReal( "CurvatureScaling" ) ); + filter->SetMaximumRMSError( this->m_Parameters.GetReal( "MaximumRMSError" ) ); + filter->SetUpperThreshold( this->m_Parameters.GetReal( "UpperThreshold" ) ); + filter->SetLowerThreshold( this->m_Parameters.GetReal( "LowerThreshold" ) ); + filter->SetIsoSurfaceValue( this->m_Parameters.GetReal( "IsoSurfaceValue" ) ); + filter->SetNumberOfIterations( this->m_Parameters.GetUint( "NumberOfIterations" ) ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.h b/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.h new file mode 100644 index 0000000..c8a071d --- /dev/null +++ b/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKLevelSetFilters__ThresholdSegmentationLevelSetImageFilter__h__ +#define __cpPluginsITKLevelSetFilters__ThresholdSegmentationLevelSetImageFilter__h__ + +#include +#include + +namespace cpPluginsITKLevelSetFilters +{ + /** + */ + class cpPlugins_ITKLevelSetFilters_EXPORT ThresholdSegmentationLevelSetImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + ThresholdSegmentationLevelSetImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageLevelSetFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TFeature, class _TImage > + inline void _GD1( _TFeature* feature, _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKLevelSetFilters__ThresholdSegmentationLevelSetImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKMorphology/ITKMorphology.i b/plugins/ITKMorphology/ITKMorphology.i new file mode 100644 index 0000000..212fd21 --- /dev/null +++ b/plugins/ITKMorphology/ITKMorphology.i @@ -0,0 +1,7 @@ +** TODO: +header #undef ITK_MANUAL_INSTANTIATION + +tinclude itkBinaryFillholeImageFilter:h|hxx +instances itk::BinaryFillholeImageFilter< itk::Image< #scalar_types#, #vdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKNeighborhoodOperatorFilters/ITKNeighborhoodOperatorFilters.i b/plugins/ITKNeighborhoodOperatorFilters/ITKNeighborhoodOperatorFilters.i new file mode 100644 index 0000000..943b07f --- /dev/null +++ b/plugins/ITKNeighborhoodOperatorFilters/ITKNeighborhoodOperatorFilters.i @@ -0,0 +1,19 @@ +header #define ITK_MANUAL_INSTANTIATION + +define filters_1=LaplacianImageFilter +define i_reals=#real_types# +define o_reals=#real_types# + +tinclude itkNeighborhoodInnerProduct:h|hxx +instances itk::NeighborhoodInnerProduct< itk::Image< float, #pdims# >, float, double > + +tinclude itkNeighborhoodOperatorImageFilter:h|hxx +instances itk::NeighborhoodOperatorImageFilter< itk::Image< float, #pdims# >, itk::Image< float, #pdims# >, float > + +tinclude itkLaplacianOperator:h|hxx +instances itk::LaplacianOperator< float, #pdims#, itk::NeighborhoodAllocator< float > > + +tinclude itk#filters_1#:h|hxx +instances itk::#filters_1#< itk::Image< #i_reals#, #pdims# >, itk::Image< #o_reals#, #pdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.cxx b/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.cxx new file mode 100644 index 0000000..7dcf749 --- /dev/null +++ b/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.cxx @@ -0,0 +1,52 @@ +#include +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKParaMorphology::BinaryDilateParaImageFilter:: +BinaryDilateParaImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Radius", 3 ); + this->m_Parameters.ConfigureAsBool( "Circular", true ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKParaMorphology::BinaryDilateParaImageFilter:: +~BinaryDilateParaImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKParaMorphology::BinaryDilateParaImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKParaMorphology::BinaryDilateParaImageFilter:: +_GD0( _TImage* image ) +{ + typedef itk::BinaryDilateParaImageFilter< _TImage > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetRadius( this->m_Parameters.GetReal( "Radius" ) ); + filter->SetCircular( this->m_Parameters.GetBool( "Circular" ) ); + filter->SetUseImageSpacing( this->m_Parameters.GetBool( "UseImageSpacing" ) ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.h b/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.h new file mode 100644 index 0000000..1325985 --- /dev/null +++ b/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKParaMorphology__BinaryDilateParaImageFilter__h__ +#define __cpPluginsITKParaMorphology__BinaryDilateParaImageFilter__h__ + +#include +#include + +namespace cpPluginsITKParaMorphology +{ + /** + */ + class cpPlugins_ITKParaMorphology_EXPORT BinaryDilateParaImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + BinaryDilateParaImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageMorphology + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKParaMorphology__BinaryDilateParaImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.cxx b/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.cxx new file mode 100644 index 0000000..30fb4b8 --- /dev/null +++ b/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.cxx @@ -0,0 +1,52 @@ +#include +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKParaMorphology::BinaryErodeParaImageFilter:: +BinaryErodeParaImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Radius", 3 ); + this->m_Parameters.ConfigureAsBool( "Circular", true ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKParaMorphology::BinaryErodeParaImageFilter:: +~BinaryErodeParaImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKParaMorphology::BinaryErodeParaImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKParaMorphology::BinaryErodeParaImageFilter:: +_GD0( _TImage* image ) +{ + typedef itk::BinaryErodeParaImageFilter< _TImage > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetRadius( this->m_Parameters.GetReal( "Radius" ) ); + filter->SetCircular( this->m_Parameters.GetBool( "Circular" ) ); + filter->SetUseImageSpacing( this->m_Parameters.GetBool( "UseImageSpacing" ) ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.h b/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.h new file mode 100644 index 0000000..adae5e9 --- /dev/null +++ b/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKParaMorphology__BinaryErodeParaImageFilter__h__ +#define __cpPluginsITKParaMorphology__BinaryErodeParaImageFilter__h__ + +#include +#include + +namespace cpPluginsITKParaMorphology +{ + /** + */ + class cpPlugins_ITKParaMorphology_EXPORT BinaryErodeParaImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + BinaryErodeParaImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageMorphology + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKParaMorphology__BinaryErodeParaImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKParaMorphology/ITKParaMorphology.i b/plugins/ITKParaMorphology/ITKParaMorphology.i new file mode 100644 index 0000000..fade5c4 --- /dev/null +++ b/plugins/ITKParaMorphology/ITKParaMorphology.i @@ -0,0 +1,18 @@ +header #define ITK_MANUAL_INSTANTIATION + +define itk_filters=BinaryDilateParaImageFilter;BinaryErodeParaImageFilter +define i_scalars=#scalar_types# +define o_scalars=#scalar_types# +define booleans=false;true + +tinclude itkParabolicErodeDilateImageFilter:h|hxx +tinclude itk#itk_filters#:h|hxx + +cinclude itkUnaryFunctorImageFilter.hxx + +instances itk::ParabolicErodeDilateImageFilter< itk::Image< #i_scalars#, #pdims# >, #booleans#, itk::Image< #o_scalars#, #pdims# > > + +instances itk::#itk_filters#< itk::Image< #i_scalars#, #pdims# >, itk::Image< #o_scalars#, #pdims# > > + + +** eof - $RCSfile$ diff --git a/plugins/ITKSeparableFilters/ITKSeparableFilters.i b/plugins/ITKSeparableFilters/ITKSeparableFilters.i new file mode 100644 index 0000000..ad1c5f5 --- /dev/null +++ b/plugins/ITKSeparableFilters/ITKSeparableFilters.i @@ -0,0 +1,7 @@ +header #define ITK_MANUAL_INSTANTIATION + +define filters=RecursiveSeparableImageFilter;RecursiveGaussianImageFilter;SmoothingRecursiveGaussianImageFilter +tinclude itk#filters#:h|hxx +instances itk::#filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.cxx b/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.cxx new file mode 100644 index 0000000..5b79eaa --- /dev/null +++ b/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.cxx @@ -0,0 +1,74 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter:: +SmoothingRecursiveGaussianImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + this->m_Parameters.ConfigureAsRealList( "SigmaArray" ); + this->m_Parameters.ConfigureAsRealTypesChoices( "OutputResolution" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter:: +~SmoothingRecursiveGaussianImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image dimension." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter:: +_GD0( _TImage* image ) +{ + std::string out_res = + this->m_Parameters.GetSelectedChoice( "OutputResolution" ); + if( out_res == "float" ) this->_GD1< _TImage, float >( image ); + if( out_res == "double" ) this->_GD1< _TImage, double >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::Image< _TScalar, _TImage::ImageDimension > _TOutput; + typedef + itk::SmoothingRecursiveGaussianImageFilter< _TImage, _TOutput > + _TFilter; + typedef typename _TFilter::SigmaArrayType _TSigmas; + + auto param_sigmas = this->m_Parameters.GetRealList( "SigmaArray" ); + unsigned int dim = + ( param_sigmas.size( ) < _TImage::ImageDimension )? + param_sigmas.size( ): + _TImage::ImageDimension; + _TSigmas sigmas; + sigmas.Fill( param_sigmas[ dim - 1 ] ); + for( unsigned d = 0; d < dim; ++d ) + sigmas[ d ] = param_sigmas[ d ]; + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetSigmaArray( sigmas ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.h b/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.h new file mode 100644 index 0000000..edac699 --- /dev/null +++ b/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKSeparableFilters__SmoothingRecursiveGaussianImageFilter__h__ +#define __cpPluginsITKSeparableFilters__SmoothingRecursiveGaussianImageFilter__h__ + +#include +#include + +namespace cpPluginsITKSeparableFilters +{ + /** + */ + class cpPlugins_ITKSeparableFilters_EXPORT SmoothingRecursiveGaussianImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + SmoothingRecursiveGaussianImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageSeparableFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKSeparableFilters__SmoothingRecursiveGaussianImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKSliceFilters/CPRImageFilter.cxx b/plugins/ITKSliceFilters/CPRImageFilter.cxx new file mode 100644 index 0000000..60de5f5 --- /dev/null +++ b/plugins/ITKSliceFilters/CPRImageFilter.cxx @@ -0,0 +1,63 @@ +#include + +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKSliceFilters::CPRImageFilter:: +CPRImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + typedef cpInstances::Simple3DCurve _TCurve; + this->_ConfigureInput< _TImage >( "Image", true, false ); + this->_ConfigureInput< _TCurve >( "Curve", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + this->m_Parameters.ConfigureAsReal( "SliceRadius", 1 ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKSliceFilters::CPRImageFilter:: +~CPRImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKSliceFilters::CPRImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Image" ); + cpPlugins_Demangle_Image_ScalarPixels_1( o, _GD0, 3 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKSliceFilters::CPRImageFilter:: +_GD0( _TImage* image ) +{ + auto o = this->GetInputData( "Curve" ); + cpPlugins_Demangle_Simple3DCurve_All_2( o, _GD1, image ) + this->_Error( "Invalid input curve." ); +} + +// ------------------------------------------------------------------------- +template< class _TCurve, class _TImage > +void cpPluginsITKSliceFilters::CPRImageFilter:: +_GD1( _TCurve* curve, _TImage* image ) +{ + typedef cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetCurve( curve ); + filter->SetSliceRadius( this->m_Parameters.GetReal( "SliceRadius" ) ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKSliceFilters/CPRImageFilter.h b/plugins/ITKSliceFilters/CPRImageFilter.h new file mode 100644 index 0000000..a2d0802 --- /dev/null +++ b/plugins/ITKSliceFilters/CPRImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKSliceFilters__CPRImageFilter__h__ +#define __cpPluginsITKSliceFilters__CPRImageFilter__h__ + +#include +#include + +namespace cpPluginsITKSliceFilters +{ + /** + */ + class cpPlugins_ITKSliceFilters_EXPORT CPRImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + CPRImageFilter, + cpPlugins::Pipeline::ProcessObject, + ITKSliceFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TCurve, class _TImage > + inline void _GD1( _TCurve* curve, _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKSliceFilters__CPRImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKSliceFilters/ITKSliceFilters.i b/plugins/ITKSliceFilters/ITKSliceFilters.i new file mode 100644 index 0000000..ee71b1c --- /dev/null +++ b/plugins/ITKSliceFilters/ITKSliceFilters.i @@ -0,0 +1,20 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude itkImageToImageFilter:h|hxx +tinclude itkInPlaceImageFilter:h|hxx +instances itk::ImageToImageFilter< itk::Image< #scalar_types#, 3 >, itk::Image< #scalar_types#, 2 > > +instances itk::InPlaceImageFilter< itk::Image< #scalar_types#, 3 >, itk::Image< #scalar_types#, 2 > > + +tinclude itkResampleImageFilter:h|hxx +instances itk::ResampleImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, #real_types#, #real_types# > + +tinclude cpExtensions/Algorithms/IsoImageSlicer:h|hxx +tinclude itkExtractImageFilter:h|hxx +tinclude itkJoinSeriesImageFilter:h|hxx +tinclude itkImageAlgorithm:h|hxx + +cinclude cpExtensions/DataStructures/Simple3DCurve.h +tinclude cpExtensions/Algorithms/CPRImageFilter:h|hxx +instances cpExtensions::Algorithms::CPRImageFilter< itk::Image< #scalar_types#, 3 >, cpExtensions::DataStructures::Simple3DCurve< #real_types# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKSliceFilters/IsoResampleImageFilter.cxx b/plugins/ITKSliceFilters/IsoResampleImageFilter.cxx new file mode 100644 index 0000000..0e451db --- /dev/null +++ b/plugins/ITKSliceFilters/IsoResampleImageFilter.cxx @@ -0,0 +1,109 @@ +#include +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsITKSliceFilters::IsoResampleImageFilter:: +IsoResampleImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureInput< cpPlugins::Pipeline::DataObject >( "Interpolator", false, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "Scale", 1 ); + this->m_Parameters.ConfigureAsBool( "ScaleFromMinimumSpacing", true ); + this->m_Parameters.ConfigureAsRealTypesChoices( "PrecisionType" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKSliceFilters::IsoResampleImageFilter:: +~IsoResampleImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKSliceFilters::IsoResampleImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKSliceFilters::IsoResampleImageFilter:: +_GD0( _TImage* image ) +{ + typedef cpPluginsITKImageInterpolators::InterpolateImageFunction _TInterpolator; + + std::string p_type = this->m_Parameters.GetSelectedChoice( "PrecisionType" ); + auto interpolator = dynamic_cast< _TInterpolator* >( + this->GetInput( "Interpolator" )->GetSource( ) + ); + if( interpolator != NULL ) + interpolator->CreateInterpolator( image, p_type ); + if ( p_type == "float" ) this->_GD1< _TImage, float >( image ); + else if( p_type == "double" ) this->_GD1< _TImage, double >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsITKSliceFilters::IsoResampleImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::IdentityTransform< _TScalar, _TImage::ImageDimension > _TTransform; + typedef itk::ResampleImageFilter< _TImage, _TImage, _TScalar, _TScalar > _TFilter; + typedef typename _TFilter::InterpolatorType _TInterpolator; + + // Initial configuration + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + + // Associate transform + typename _TTransform::Pointer transform = _TTransform::New( ); + transform->SetIdentity( ); + filter->SetTransform( transform ); + + // Compute new spacing + typename _TImage::SpacingType in_spac = image->GetSpacing( ); + double val_spac = in_spac[ 0 ]; + if( this->m_Parameters.GetBool( "ScaleFromMinimumSpacing" ) ) + for( unsigned int d = 1; d < _TImage::ImageDimension; ++d ) + val_spac = ( in_spac[ d ] < val_spac )? in_spac[ d ]: val_spac; + else + for( unsigned int d = 1; d < _TImage::ImageDimension; ++d ) + val_spac = ( in_spac[ d ] > val_spac )? in_spac[ d ]: val_spac; + val_spac *= this->m_Parameters.GetReal( "Scale" ); + typename _TImage::SpacingType out_spac; + out_spac.Fill( val_spac ); + filter->SetOutputSpacing( out_spac ); + + // Compute new size + typename _TImage::SizeType in_size = image->GetRequestedRegion( ).GetSize( ); + typename _TImage::SizeType out_size; + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + out_size[ d ] = ( unsigned long )( + double( in_size[ d ] ) * double( in_spac[ d ] ) / val_spac + ); + filter->SetSize( out_size ); + + // New origin + filter->SetOutputOrigin( image->GetOrigin( ) ); + + // Set interpolator + auto interpolator = this->GetInputData< _TInterpolator >( "Interpolator" ); + if( interpolator != NULL ) + filter->SetInterpolator( interpolator ); + + // Update + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKSliceFilters/IsoResampleImageFilter.h b/plugins/ITKSliceFilters/IsoResampleImageFilter.h new file mode 100644 index 0000000..238e7f5 --- /dev/null +++ b/plugins/ITKSliceFilters/IsoResampleImageFilter.h @@ -0,0 +1,32 @@ +#ifndef __cpPluginsITKSliceFilters__IsoResampleImageFilter__h__ +#define __cpPluginsITKSliceFilters__IsoResampleImageFilter__h__ + +#include +#include + +namespace cpPluginsITKSliceFilters +{ + /** + */ + class cpPlugins_ITKSliceFilters_EXPORT IsoResampleImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + IsoResampleImageFilter, + cpPlugins::Pipeline::ProcessObject, + ITKSliceFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKSliceFilters__IsoResampleImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/AbsImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/AbsImageFilter.cxx new file mode 100644 index 0000000..6e7c27c --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/AbsImageFilter.cxx @@ -0,0 +1,46 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::AbsImageFilter:: +AbsImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::AbsImageFilter:: +~AbsImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKUnaryFunctorFilters::AbsImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKUnaryFunctorFilters::AbsImageFilter:: +_GD0( _TImage* image ) +{ + typedef itk::AbsImageFilter< _TImage, _TImage > _TFilter; + + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/AbsImageFilter.h b/plugins/ITKUnaryFunctorFilters/AbsImageFilter.h new file mode 100644 index 0000000..2738512 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/AbsImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKUnaryFunctorFilters__AbsImageFilter__h__ +#define __cpPluginsITKUnaryFunctorFilters__AbsImageFilter__h__ + +#include +#include + +namespace cpPluginsITKUnaryFunctorFilters +{ + /** + */ + class cpPlugins_ITKUnaryFunctorFilters_EXPORT AbsImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + AbsImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKUnaryFunctorFilters__AbsImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.cxx new file mode 100644 index 0000000..50c0338 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.cxx @@ -0,0 +1,65 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter:: +BinaryThresholdImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "LowerThresholdValue", 0 ); + this->m_Parameters.ConfigureAsReal( "UpperThresholdValue", 1 ); + this->m_Parameters.ConfigureAsUint( "InsideValue", 1 ); + this->m_Parameters.ConfigureAsUint( "OutsideValue", 0 ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter:: +~BinaryThresholdImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter:: +_GD0( _TImage* image ) +{ + typedef unsigned char _TBin; + typedef itk::Image< unsigned char, _TImage::ImageDimension > _TBinImage; + typedef itk::BinaryThresholdImageFilter< _TImage, _TBinImage > _TFilter; + typedef typename _TImage::PixelType _TPixel; + + // Get parameters + _TPixel lt = _TPixel( this->m_Parameters.GetReal( "LowerThresholdValue" ) ); + _TPixel ut = _TPixel( this->m_Parameters.GetReal( "UpperThresholdValue" ) ); + _TBin iv = _TBin( this->m_Parameters.GetUint( "InsideValue" ) ); + _TBin ov = _TBin( this->m_Parameters.GetUint( "OutsideValue" ) ); + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetLowerThreshold( lt ); + filter->SetUpperThreshold( ut ); + filter->SetInsideValue( iv ); + filter->SetOutsideValue( ov ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.h b/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.h new file mode 100644 index 0000000..a2a0773 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKUnaryFunctorFilters__BinaryThresholdImageFilter__h__ +#define __cpPluginsITKUnaryFunctorFilters__BinaryThresholdImageFilter__h__ + +#include +#include + +namespace cpPluginsITKUnaryFunctorFilters +{ + /** + */ + class cpPlugins_ITKUnaryFunctorFilters_EXPORT BinaryThresholdImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + BinaryThresholdImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageThresholdFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKUnaryFunctorFilters__BinaryThresholdImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/ITKUnaryFunctorFilters.i b/plugins/ITKUnaryFunctorFilters/ITKUnaryFunctorFilters.i new file mode 100644 index 0000000..4bf7475 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/ITKUnaryFunctorFilters.i @@ -0,0 +1,33 @@ +header #define ITK_MANUAL_INSTANTIATION + +define all_ints=#int_types#;#uint_types# +define a_filters=Abs +define a_functor=Abs +define b_filters=Not +define b_functor=NOT + +tinclude itkUnaryFunctorImageFilter:h|hxx +cinclude itk#a_filters#ImageFilter.h +cinclude itk#b_filters#ImageFilter.h + +instances itk::UnaryFunctorImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Functor::#a_functor#< #scalar_types#, #scalar_types# > > + +instances itk::UnaryFunctorImageFilter< itk::Image< #all_ints#, #pdims# >, itk::Image< #all_ints#, #pdims# >, itk::Functor::#b_functor#< #all_ints#, #all_ints# > > + +cinclude itkBinaryNotImageFilter.h +instances itk::UnaryFunctorImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Functor::BinaryNot< #scalar_types# > > + +define oa_filters=InvertIntensityImageFilter +tinclude itk#oa_filters#:h|hxx +instances itk::#oa_filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# > > + +define oam_filters=BinaryThresholdImageFilter +define i_scalars=#scalar_types# +define o_scalars=#scalar_types# +tinclude itk#oam_filters#:h|hxx +instances itk::#oam_filters#< itk::Image< #i_scalars#, #pdims# >, itk::Image< #o_scalars#, #pdims# > > + +tinclude cpExtensions/Algorithms/UnaryThresholdImageFilter:h|hxx +instances cpExtensions::Algorithms::UnaryThresholdImageFilter< itk::Image< #scalar_types#, #pdims# > > + +** eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.cxx new file mode 100644 index 0000000..e9e61b9 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.cxx @@ -0,0 +1,48 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter:: +InvertIntensityImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + this->m_Parameters.ConfigureAsUint( "Maximum", 1 ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter:: +~InvertIntensityImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter:: +_GD0( _TImage* image ) +{ + typedef itk::InvertIntensityImageFilter< _TImage > _TFilter; + + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetMaximum( this->m_Parameters.GetUint( "Maximum" ) ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.h b/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.h new file mode 100644 index 0000000..3158c0d --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKUnaryFunctorFilters__InvertIntensityImageFilter__h__ +#define __cpPluginsITKUnaryFunctorFilters__InvertIntensityImageFilter__h__ + +#include +#include + +namespace cpPluginsITKUnaryFunctorFilters +{ + /** + */ + class cpPlugins_ITKUnaryFunctorFilters_EXPORT InvertIntensityImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + InvertIntensityImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageBooleanFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKUnaryFunctorFilters__InvertIntensityImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.cxx new file mode 100644 index 0000000..8c28321 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.cxx @@ -0,0 +1,49 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter:: +UnaryBooleanImageFilter( ) + : Superclass( ) +{ + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + std::vector< std::string > choices; + choices.push_back( "Not" ); + this->m_Parameters.ConfigureAsChoices( "Operator", choices ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter:: +~UnaryBooleanImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_IntPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter:: +_GD0( _TImage* image ) +{ + typedef itk::NotImageFilter< _TImage, _TImage > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.h b/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.h new file mode 100644 index 0000000..db3ccbc --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKUnaryFunctorFilters__UnaryBooleanImageFilter__h__ +#define __cpPluginsITKUnaryFunctorFilters__UnaryBooleanImageFilter__h__ + +#include +#include + +namespace cpPluginsITKUnaryFunctorFilters +{ + /** + */ + class cpPlugins_ITKUnaryFunctorFilters_EXPORT UnaryBooleanImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + UnaryBooleanImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageBooleanFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image1 ); + }; + +} // ecapseman + +#endif // __cpPluginsITKUnaryFunctorFilters__UnaryBooleanImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.cxx new file mode 100644 index 0000000..d119094 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.cxx @@ -0,0 +1,57 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter:: +UnaryThresholdImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "Threshold", 0 ); + this->m_Parameters.ConfigureAsReal( "InsideValue", 1 ); + this->m_Parameters.ConfigureAsReal( "OutsideValue", 0 ); + this->m_Parameters.ConfigureAsBool( "Strict", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter:: +~UnaryThresholdImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter:: +_GD0( _TImage* image ) +{ + typedef + cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage > + _TFilter; + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetThreshold( this->m_Parameters.GetReal( "Threshold" ) ); + filter->SetInsideValue( this->m_Parameters.GetReal( "InsideValue" ) ); + filter->SetOutsideValue( this->m_Parameters.GetReal( "OutsideValue" ) ); + filter->SetStrict( this->m_Parameters.GetBool( "Strict" ) ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.h b/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.h new file mode 100644 index 0000000..f99e518 --- /dev/null +++ b/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.h @@ -0,0 +1,29 @@ +#ifndef __cpPluginsITKUnaryFunctorFilters__UnaryThresholdImageFilter__h__ +#define __cpPluginsITKUnaryFunctorFilters__UnaryThresholdImageFilter__h__ + +#include +#include + +namespace cpPluginsITKUnaryFunctorFilters +{ + /** + */ + class cpPlugins_ITKUnaryFunctorFilters_EXPORT UnaryThresholdImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + UnaryThresholdImageFilter, + cpPlugins::Pipeline::ProcessObject, + ImageThresholdFilters + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __cpPluginsITKUnaryFunctorFilters__UnaryThresholdImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/VTKFilters/CylinderSource.cxx b/plugins/VTKFilters/CylinderSource.cxx new file mode 100644 index 0000000..d8939cf --- /dev/null +++ b/plugins/VTKFilters/CylinderSource.cxx @@ -0,0 +1,35 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsVTKFilters::CylinderSource:: +CylinderSource( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Height", 1 ); + this->m_Parameters.ConfigureAsReal( "Radius", 1 ); + this->m_Parameters.ConfigureAsUint( "Resolution", 8 ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKFilters::CylinderSource:: +~CylinderSource( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKFilters::CylinderSource:: +_GenerateData( ) +{ + auto src = this->_CreateVTK< vtkCylinderSource >( ); + src->SetHeight( this->m_Parameters.GetReal( "Height" ) ); + src->SetRadius( this->m_Parameters.GetReal( "Radius" ) ); + src->SetResolution( this->m_Parameters.GetUint( "Resolution" ) ); + src->Update( ); + this->GetOutput( "Output" )->SetVTK( src->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/VTKFilters/CylinderSource.h b/plugins/VTKFilters/CylinderSource.h new file mode 100644 index 0000000..5c25ee5 --- /dev/null +++ b/plugins/VTKFilters/CylinderSource.h @@ -0,0 +1,25 @@ +#ifndef __cpPluginsVTKFilters__CylinderSource__h__ +#define __cpPluginsVTKFilters__CylinderSource__h__ + +#include +#include + +namespace cpPluginsVTKFilters +{ + /** + */ + class cpPlugins_VTKFilters_EXPORT CylinderSource + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + CylinderSource, + cpPlugins::Pipeline::ProcessObject, + MeshSources + ); + }; + +} // ecapseman + +#endif // __cpPluginsVTKFilters__CylinderSource__h__ + +// eof - $RCSfile$ diff --git a/plugins/VTKFilters/MarchingCubes.cxx b/plugins/VTKFilters/MarchingCubes.cxx new file mode 100644 index 0000000..b01a9dc --- /dev/null +++ b/plugins/VTKFilters/MarchingCubes.cxx @@ -0,0 +1,64 @@ +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsVTKFilters::MarchingCubes:: +MarchingCubes( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" ); + this->m_Parameters.ConfigureAsRealList( "Thresholds" ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKFilters::MarchingCubes:: +~MarchingCubes( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKFilters::MarchingCubes:: +_GenerateData( ) +{ + // Get input + auto image = this->GetInput( "Input" ); + vtkImageData* vtk_image = image->GetVTK< vtkImageData >( ); + if( vtk_image == NULL ) + this->_Error( "Input does not have a valid VTK conversion." ); + + std::vector< double > values = + this->m_Parameters.GetRealList( "Thresholds" ); + vtkPolyData* pd = NULL; + if( vtk_image->GetDataDimension( ) == 2 ) + { + vtkMarchingSquares* ms = this->_CreateVTK< vtkMarchingSquares >( ); + ms->SetInputData( vtk_image ); + for( unsigned int i = 0; i < values.size( ); ++i ) + ms->SetValue( i, values[ i ] ); + ms->Update( ); + pd = ms->GetOutput( ); + } + else if( vtk_image->GetDataDimension( ) == 3 ) + { + vtkMarchingCubes* mc = this->_CreateVTK< vtkMarchingCubes >( ); + mc->ComputeNormalsOff( ); + mc->SetInputData( vtk_image ); + for( unsigned int i = 0; i < values.size( ); ++i ) + mc->SetValue( i, values[ i ] ); + mc->Update( ); + pd = mc->GetOutput( ); + } + else + this->_Error( "Input data does not have a valid dimension." ); + + // Connect output + this->GetOutput( "Output" )->SetVTK( pd ); +} + +// eof - $RCSfile$ diff --git a/plugins/VTKFilters/MarchingCubes.h b/plugins/VTKFilters/MarchingCubes.h new file mode 100644 index 0000000..693909a --- /dev/null +++ b/plugins/VTKFilters/MarchingCubes.h @@ -0,0 +1,25 @@ +#ifndef __cpPluginsVTKFilters__MarchingCubes__h__ +#define __cpPluginsVTKFilters__MarchingCubes__h__ + +#include +#include + +namespace cpPluginsVTKFilters +{ + /** + */ + class cpPlugins_VTKFilters_EXPORT MarchingCubes + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + MarchingCubes, + cpPlugins::Pipeline::ProcessObject, + ImageToMeshFilters + ); + }; + +} // ecapseman + +#endif // __cpPluginsVTKFilters__MarchingCubes__h__ + +// eof - $RCSfile$ diff --git a/plugins/VTKFilters/SphereSource.cxx b/plugins/VTKFilters/SphereSource.cxx new file mode 100644 index 0000000..0eaac1b --- /dev/null +++ b/plugins/VTKFilters/SphereSource.cxx @@ -0,0 +1,35 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsVTKFilters::SphereSource:: +SphereSource( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Radius", 1 ); + this->m_Parameters.ConfigureAsUint( "PhiResolution", 8 ); + this->m_Parameters.ConfigureAsUint( "ThetaResolution", 8 ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKFilters::SphereSource:: +~SphereSource( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKFilters::SphereSource:: +_GenerateData( ) +{ + auto src = this->_CreateVTK< vtkSphereSource >( ); + src->SetRadius( this->m_Parameters.GetReal( "Radius" ) ); + src->SetPhiResolution( this->m_Parameters.GetUint( "PhiResolution" ) ); + src->SetThetaResolution( this->m_Parameters.GetUint( "ThetaResolution" ) ); + src->Update( ); + this->GetOutput( "Output" )->SetVTK( src->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/VTKFilters/SphereSource.h b/plugins/VTKFilters/SphereSource.h new file mode 100644 index 0000000..b0c7ac4 --- /dev/null +++ b/plugins/VTKFilters/SphereSource.h @@ -0,0 +1,26 @@ +#ifndef __cpPluginsVTKFilters__SphereSource__h__ +#define __cpPluginsVTKFilters__SphereSource__h__ + +#include +#include + +namespace cpPluginsVTKFilters +{ + /** + */ + class cpPlugins_VTKFilters_EXPORT SphereSource + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + SphereSource, + cpPlugins::Pipeline::ProcessObject, + MeshSources + ); + }; + +} // ecapseman + +#endif // __cpPluginsVTKFilters__SphereSource__h__ + + +// eof - $RCSfile$ diff --git a/plugins/VTKIO/MeshReader.cxx b/plugins/VTKIO/MeshReader.cxx new file mode 100644 index 0000000..59d2a50 --- /dev/null +++ b/plugins/VTKIO/MeshReader.cxx @@ -0,0 +1,60 @@ +#include +#include +#include + +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginsVTKIO::MeshReader:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::OpenFileDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::OpenFileDialog( ); + dlg->SetParameters( &( this->m_Parameters ), "FileName" ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginsVTKIO::MeshReader:: +MeshReader( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" ); + this->m_Parameters.Clear( ); + this->m_Parameters.ConfigureAsOpenFileName( "FileName", "" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileName", + "Mesh files (*.vtk)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKIO::MeshReader:: +~MeshReader( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKIO::MeshReader:: +_GenerateData( ) +{ + auto f = this->_CreateVTK< vtkPolyDataReader >( ); + f->SetFileName( this->m_Parameters.GetOpenFileName( "FileName" ).c_str( ) ); + f->Update( ); + this->GetOutput( "Output" )->SetVTK( f->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/VTKIO/MeshReader.h b/plugins/VTKIO/MeshReader.h new file mode 100644 index 0000000..69f9b8d --- /dev/null +++ b/plugins/VTKIO/MeshReader.h @@ -0,0 +1,24 @@ +#ifndef __cpPluginsVTKIO__MeshReader__h__ +#define __cpPluginsVTKIO__MeshReader__h__ + +#include +#include + +namespace cpPluginsVTKIO +{ + /** + */ + class cpPlugins_VTKIO_EXPORT MeshReader + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( MeshReader, cpPlugins::Pipeline::ProcessObject, IO ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + }; + +} // ecapseman + +#endif // __cpPluginsVTKIO__MeshReader__h__ + +// eof - $RCSfile$ diff --git a/plugins/VTKIO/MeshWriter.cxx b/plugins/VTKIO/MeshWriter.cxx new file mode 100644 index 0000000..fa44b2d --- /dev/null +++ b/plugins/VTKIO/MeshWriter.cxx @@ -0,0 +1,65 @@ +#include +#include +#include + +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginsVTKIO::MeshWriter:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::SaveFileDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::SaveFileDialog( ); + dlg->SetParameters( &( this->m_Parameters ), "FileName" ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginsVTKIO::MeshWriter:: +MeshWriter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::DataObjects::Mesh >( "Input", true, false ); + this->m_Parameters.Clear( ); + this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileName", + "Mesh files (*.vtk)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKIO::MeshWriter:: +~MeshWriter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKIO::MeshWriter:: +_GenerateData( ) +{ + auto mesh = this->GetInputData< vtkPolyData >( "Input" ); + if( mesh == NULL ) + this->_Error( "Invalid input mesh." ); + + auto f = this->_CreateVTK< vtkPolyDataWriter >( ); + f->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ).c_str( ) ); + f->SetInputData( mesh ); + f->SetFileTypeToBinary( ); + f->Update( ); +} + +// eof - $RCSfile$ diff --git a/plugins/VTKIO/MeshWriter.h b/plugins/VTKIO/MeshWriter.h new file mode 100644 index 0000000..2278b01 --- /dev/null +++ b/plugins/VTKIO/MeshWriter.h @@ -0,0 +1,24 @@ +#ifndef __cpPluginsVTKIO__MeshWriter__h__ +#define __cpPluginsVTKIO__MeshWriter__h__ + +#include +#include + +namespace cpPluginsVTKIO +{ + /** + */ + class cpPlugins_VTKIO_EXPORT MeshWriter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( MeshWriter, cpPlugins::Pipeline::ProcessObject, IO ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + }; + +} // ecapseman + +#endif // __cpPluginsVTKIO__MeshWriter__h__ + +// eof - $RCSfile$ diff --git a/plugins/VTKWidgets/LineWidget.cxx b/plugins/VTKWidgets/LineWidget.cxx new file mode 100644 index 0000000..24928e6 --- /dev/null +++ b/plugins/VTKWidgets/LineWidget.cxx @@ -0,0 +1,173 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::LineWidget:: +Clear( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::LineWidget:: +SetEnabled( bool v ) +{ + auto wdg = this->GetVTK< vtkLineWidget2 >( ); + if( wdg != NULL ) + { + wdg->SetEnabled( v ); + wdg->GetInteractor( )->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpPluginsVTKWidgets::LineWidget:: +GetEnabled( ) const +{ + auto wdg = this->GetVTK< const vtkLineWidget2 >( ); + if( wdg != NULL ) + { + vtkLineWidget2* w = const_cast< vtkLineWidget2* >( wdg ); + return( w->GetEnabled( ) != 0 ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::LineWidget:: +LineWidget( ) + : Superclass( ) +{ + typedef cpPlugins::Pipeline::DataObject _TData; + typedef cpInstances::DataObjects::Mesh _TMesh; + + this->_ConfigureInput< _TData >( "Input", false, false ); + this->_ConfigureOutput< _TMesh >( "Output" ); + + // Create output data + auto line = this->_CreateVTK< vtkPolyData >( ); + line->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + line->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + line->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + line->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + line->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + this->GetOutput( "Output" )->SetVTK( line ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::LineWidget:: +~LineWidget( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::LineWidget:: +_GenerateData( ) +{ + if( this->m_Interactors.size( ) == 0 ) + this->_Error( "Give at least one valid interactor." ); + + auto image = this->GetInputData< vtkImageData >( "Input" ); + if( image != NULL ) this->_GD_Image( image ); + else this->_Error( "Do not know how to create this widget." ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::LineWidget:: +TValidProps cpPluginsVTKWidgets::LineWidget:: +_GetValidActors( vtkObject* source ) +{ + TValidProps valid_props; + auto iIt = this->m_Interactors.begin( ); + for( ; iIt != this->m_Interactors.end( ); ++iIt ) + { + auto r = ( *iIt )->GetInteractorStyle( )->GetCurrentRenderer( ); + if( r != NULL ) + { + auto props = r->GetViewProps( ); + if( props != NULL ) + { + props->InitTraversal( ); + while( vtkProp* prop = props->GetNextProp( ) ) + { + auto image_actor = dynamic_cast< vtkImageSlice* >( prop ); + auto mesh_actor = dynamic_cast< vtkActor* >( prop ); + vtkObject* input = NULL; + if( image_actor != NULL ) + { + auto mapper = image_actor->GetMapper( ); + if( mapper != NULL ) + input = mapper->GetInput( ); + } + else if( mesh_actor != NULL ) + { + auto mapper = mesh_actor->GetMapper( ); + if( mapper != NULL ) + input = mapper->GetInput( ); + + } // fi + if( input != NULL ) + valid_props[ *iIt ].insert( prop ); + + } // elihw + + } // fi + + } // fi + + } // rof + return( valid_props ); +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::LineWidget:: +_GD_Image( vtkImageData* image ) +{ + auto valid_props = this->_GetValidActors( image ); + if( valid_props.size( ) == 0 ) + this->_Error( "Given image does not have a valid associated actor." ); + + vtkSmartPointer< vtkLineWidget2 > wdg = this->GetVTK< vtkLineWidget2 >( ); + if( wdg.GetPointer( ) == NULL ) + { + auto vIt = valid_props.begin( ); + auto actor = dynamic_cast< vtkImageSlice* >( *( vIt->second.begin( ) ) ); + + double bnds[ 6 ]; + actor->GetBounds( bnds ); + double p0[ 3 ], p1[ 3 ]; + p0[ 0 ] = bnds[ 0 ]; + p0[ 1 ] = bnds[ 2 ]; + p0[ 2 ] = bnds[ 4 ]; + p1[ 0 ] = bnds[ 1 ]; + p1[ 1 ] = bnds[ 3 ]; + p1[ 2 ] = bnds[ 5 ]; + + auto rep = vtkSmartPointer< vtkLineRepresentation >::New( ); + rep->SetPoint1WorldPosition( p0 ); + rep->SetPoint2WorldPosition( p1 ); + rep->PlaceWidget( bnds ); + + wdg = this->_CreateVTK< vtkLineWidget2 >( ); + wdg->SetInteractor( valid_props.begin( )->first ); + wdg->SetRepresentation( rep ); + wdg->EnabledOn( ); + } + else + dynamic_cast< vtkLineRepresentation* >( wdg->GetRepresentation( ) )-> + GetPolyData( this->GetOutputData< vtkPolyData >( "Output" ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/VTKWidgets/LineWidget.h b/plugins/VTKWidgets/LineWidget.h new file mode 100644 index 0000000..ed16240 --- /dev/null +++ b/plugins/VTKWidgets/LineWidget.h @@ -0,0 +1,40 @@ +#ifndef __cpPluginsVTKWidgets__LineWidget__h__ +#define __cpPluginsVTKWidgets__LineWidget__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkImageData; +class vtkProp; + +// ------------------------------------------------------------------------- +namespace cpPluginsVTKWidgets +{ + /** + */ + class cpPlugins_VTKWidgets_EXPORT LineWidget + : public cpPlugins::Pipeline::Widget + { + cpPluginsObject( LineWidget, cpPlugins::Pipeline::Widget, Widgets ); + + public: + virtual void Clear( ) cpPlugins_OVERRIDE; + virtual void SetEnabled( bool v ) cpPlugins_OVERRIDE; + virtual bool GetEnabled( ) const cpPlugins_OVERRIDE; + + protected: + typedef std::set< vtkProp* > TProps; + typedef std::map< vtkRenderWindowInteractor*, TProps > TValidProps; + + protected: + TValidProps _GetValidActors( vtkObject* source ); + void _GD_Image( vtkImageData* image ); + }; + +} // ecapseman + +#endif // __cpPluginsVTKWidgets__LineWidget__h__ + +// eof - $RCSfile$ diff --git a/plugins/VTKWidgets/SeedWidget.cxx b/plugins/VTKWidgets/SeedWidget.cxx new file mode 100644 index 0000000..d0db73e --- /dev/null +++ b/plugins/VTKWidgets/SeedWidget.cxx @@ -0,0 +1,380 @@ +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SeedWidget:: +Clear( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SeedWidget:: +SetEnabled( bool v ) +{ + for( auto w = this->m_Widgets.begin( ); w != this->m_Widgets.end( ); ++w ) + { + if( v ) w->second->RestartInteraction( ); + else w->second->CompleteInteraction( ); + w->second->SetEnabled( v ); + w->second->Render( ); + + } // rof +} + +// ------------------------------------------------------------------------- +bool cpPluginsVTKWidgets::SeedWidget:: +GetEnabled( ) const +{ + if( this->m_Widgets.size( ) > 0 ) + { + auto i = this->m_Widgets.begin( ); + TWidget* w = const_cast< TWidget* >( i->second.GetPointer( ) ); + return( w->GetEnabled( ) != 0 ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::SeedWidget:: +SeedWidget( ) + : Superclass( ) +{ + typedef cpPlugins::Pipeline::DataObject _TData; + typedef cpInstances::DataObjects::Mesh _TMesh; + + // Create ports + this->_ConfigureInput< _TData >( "Input", false, false ); + this->_ConfigureOutput< _TMesh >( "Output" ); + + // Create output data + auto out = this->_CreateVTK< vtkPolyData >( ); + out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + this->GetOutput( "Output" )->SetVTK( out ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::SeedWidget:: +~SeedWidget( ) +{ + /* TODO + for( auto w = this->m_Widgets.begin( ); w != this->m_Widgets.end( ); ++w ) + w->second->EnabledOff( ); + this->m_Widgets.clear( ); + */ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SeedWidget:: +_GenerateData( ) +{ + auto image = this->GetInputData< vtkImageData >( "Input" ); + if( image != NULL ) + this->_GD0_Image( image ); + else + this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SeedWidget:: +_GD0_Image( vtkImageData* image ) +{ + auto seeds = this->GetOutputData< vtkPolyData >( "Output" ); + if( this->m_Widgets.size( ) == 0 ) + { + this->m_Command = vtkSmartPointer< TCallback >::New( ); + this->m_Command->SetSeeds( seeds ); + for( + auto inIt = this->m_Interactors.begin( ); + inIt != this->m_Interactors.end( ); + ++inIt + ) + { + auto rends = ( *inIt )->GetRenderWindow( )->GetRenderers( ); + std::set< TImageActor* > all_props; + if( rends != NULL ) + { + rends->InitTraversal( ); + while( vtkRenderer* ren = rends->GetNextItem( ) ) + { + auto props = ren->GetViewProps( ); + props->InitTraversal( ); + while( vtkProp* p = props->GetNextProp( ) ) + { + auto image_actor = dynamic_cast< TImageActor* >( p ); + if( image_actor != NULL ) + { + if( image_actor->GetImage( ) == image ) + all_props.insert( image_actor ); + + } // fi + + } // elihw + + } // elihw + + } // fi + if( all_props.size( ) == 1 ) + { + if( this->m_Widgets.find( *inIt ) == this->m_Widgets.end( ) ) + { + auto act = *( all_props.begin( ) ); + auto pla = vtkSmartPointer< TPlacer >::New( ); + auto hnd = vtkSmartPointer< THandleRep >::New( ); + auto rep = vtkSmartPointer< TSeedRep >::New( ); + auto wdg = vtkSmartPointer< TWidget >::New( ); + + pla->SetImageSlice( act ); + hnd->GetProperty( )->SetColor( 1, 0, 0 ); + hnd->SetPointPlacer( pla ); + rep->SetHandleRepresentation( hnd ); + wdg->SetRepresentation( rep ); + wdg->SetInteractor( *inIt ); + act->AddObserver( vtkCommand::InteractionEvent, this->m_Command ); + wdg->AddObserver( vtkCommand::PlacePointEvent, this->m_Command ); + wdg->AddObserver( vtkCommand::CursorChangedEvent, this->m_Command ); + this->m_Widgets[ *inIt ] = wdg; + + } // fi + + } // fi + + } // rof + + // Associate input text + std::string text = this->m_Parameters.GetString( "Text" ); + std::vector< std::string > tok1, tok2; + tok1 = cpPlugins::OS::String::Tokenize( text, "#" ); + if( tok1.size( ) > seeds->GetPoints( )->GetNumberOfPoints( ) ) + { + for( auto t1 = tok1.begin( ); t1 != tok1.end( ); ++t1 ) + { + if( *t1 != "" ) + { + tok2 = cpPlugins::OS::String::Tokenize( *t1, " " ); + double x[ 3 ]; + for( unsigned int d = 0; d < 3; ++d ) + { + if( d < tok2.size( ) ) + { + std::istringstream str( tok2[ d ] ); + str >> x[ d ]; + } + else + x[ d ] = double( 0 ); + + } // rof + + seeds->GetPoints( )->InsertNextPoint( x ); + seeds->GetVerts( )->InsertNextCell( 1 ); + seeds->GetVerts( )->InsertCellPoint( + seeds->GetPoints( )->GetNumberOfPoints( ) - 1 + ); + seeds->Modified( ); + + } // fi + + } // rof + + } // fi + } + else + { + double x[ 3 ]; + std::stringstream text; + for( long i = 0; i < seeds->GetNumberOfPoints( ); ++i ) + { + seeds->GetPoint( i, x ); + text << x[ 0 ] << " " << x[ 1 ] << " " << x[ 2 ] << "#"; + + } // rof + this->m_Parameters.SetString( "Text", text.str( ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::SeedWidget::TCallback* +cpPluginsVTKWidgets::SeedWidget::TCallback:: +New( ) +{ + return( new TCallback ); +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SeedWidget::TCallback:: +Execute( vtkObject* caller, unsigned long id, void* data ) +{ + static const double EPS = 1e-5; + auto src_act = dynamic_cast< TImageActor* >( caller ); + auto src_wdg = dynamic_cast< TWidget* >( caller ); + + if( id == vtkCommand::InteractionEvent && src_act != NULL ) + { + TWidget* widget = NULL; + TSeedRep* seed_rep = NULL; + + auto w = this->m_Widgets.begin( ); + while( w != this->m_Widgets.end( ) && widget == NULL ) + { + auto rep = + dynamic_cast< vtkSeedRepresentation* >( + ( *w )->GetRepresentation( ) + ); + if( rep != NULL ) + { + auto hnd = rep->GetHandleRepresentation( ); + if( hnd != NULL ) + { + auto pla = + dynamic_cast< SeedWidget::TPlacer* >( + hnd->GetPointPlacer( ) + ); + if( pla != NULL ) + { + auto act = pla->GetImageSlice( ); + if( act == src_act ) + { + widget = *w; + seed_rep = rep; + + } // fi + + } // fi + + } // fi + + } // fi + w++; + + } // elihw + + if( widget != NULL ) + { + // Cut through given seeds + auto plane = src_act->GetSlicePlane( ); + double x[ 3 ]; + std::vector< long > ids; + for( long i = 0; i < this->m_Seeds->GetNumberOfPoints( ); ++i ) + { + this->m_Seeds->GetPoint( i, x ); + double d = plane->DistanceToPlane( x ); + if( d <= EPS ) + ids.push_back( i ); + + } // rof + + // Erase seeds + widget->CompleteInteraction( ); + widget->EnabledOff( ); + int nSeeds = seed_rep->GetNumberOfSeeds (); + for( int i = 0; i < nSeeds; ++i ) + { + seed_rep->RemoveLastHandle( ); + widget->DeleteSeed( seed_rep->GetNumberOfSeeds( ) ); + + } // rof + + if( ids.size( ) > 0 ) + { + auto ren = widget->GetInteractor( )->FindPokedRenderer( + widget->GetInteractor( )->GetEventPosition( )[ 0 ], + widget->GetInteractor( )->GetEventPosition( )[ 1 ] + ); + + // Add seeds + seed_rep->BuildRepresentation( ); + for( auto id = ids.begin( ); id != ids.end( ); ++id ) + { + this->m_Seeds->GetPoint( *id, x ); + widget->ComputeWorldToDisplay( + ren, x[ 0 ], x[ 1 ], x[ 2 ], x + ); + x[ 2 ] = double( 0 ); + int s = seed_rep->CreateHandle( x ); + vtkHandleWidget* curr_hnd = widget->CreateNewHandle( ); + seed_rep->SetSeedDisplayPosition( s, x ); + curr_hnd->SetEnabled( 1 ); + + } // rof + + } // fi + + // Reactivate widget + widget->RestartInteraction( ); + widget->EnabledOn( ); + widget->Render( ); + + } // fi + } + else if( id == vtkCommand::PlacePointEvent && src_wdg != NULL ) + { + this->m_Widgets.insert( src_wdg ); + auto rep = + dynamic_cast< vtkSeedRepresentation* >( + src_wdg->GetRepresentation( ) + ); + if( rep != NULL ) + { + unsigned long nSeeds = rep->GetNumberOfSeeds( ); + if( nSeeds > 0 ) + { + double pos[ 3 ]; + rep->GetSeedWorldPosition( nSeeds - 1, pos ); + + this->m_Seeds->GetPoints( )->InsertNextPoint( pos ); + this->m_Seeds->GetVerts( )->InsertNextCell( 1 ); + this->m_Seeds->GetVerts( )->InsertCellPoint( + this->m_Seeds->GetPoints( )->GetNumberOfPoints( ) - 1 + ); + this->m_Seeds->Modified( ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SeedWidget::TCallback:: +SetSeeds( vtkPolyData* seeds ) +{ + this->m_Seeds = seeds; +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::SeedWidget::TCallback:: +TCallback( ) + : vtkCommand( ), + m_Seeds( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::SeedWidget::TCallback:: +~TCallback( ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/VTKWidgets/SeedWidget.h b/plugins/VTKWidgets/SeedWidget.h new file mode 100644 index 0000000..0c70d35 --- /dev/null +++ b/plugins/VTKWidgets/SeedWidget.h @@ -0,0 +1,82 @@ +#ifndef __cpPluginsVTKWidgets__SeedWidget__h__ +#define __cpPluginsVTKWidgets__SeedWidget__h__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +class vtkImageData; +class vtkPointHandleRepresentation3D; +class vtkPolyData; +class vtkSeedRepresentation; +namespace cpExtensions +{ + namespace Interaction + { + class ImageSlicePointPlacer; + class SeedWidget; + } + namespace Visualization + { + class WindowLevelImageActor; + } +} + +// ------------------------------------------------------------------------- +namespace cpPluginsVTKWidgets +{ + /** + */ + class cpPlugins_VTKWidgets_EXPORT SeedWidget + : public cpPlugins::Pipeline::Widget + { + cpPluginsObject( SeedWidget, cpPlugins::Pipeline::Widget, Widgets ); + + public: + typedef vtkPointHandleRepresentation3D THandleRep; + typedef vtkSeedRepresentation TSeedRep; + typedef cpExtensions::Interaction::SeedWidget TWidget; + typedef cpExtensions::Interaction::ImageSlicePointPlacer TPlacer; + typedef cpExtensions::Visualization::WindowLevelImageActor TImageActor; + + public: + virtual void Clear( ) cpPlugins_OVERRIDE; + virtual void SetEnabled( bool v ) cpPlugins_OVERRIDE; + virtual bool GetEnabled( ) const cpPlugins_OVERRIDE; + + protected: + /** + */ + class TCallback + : public vtkCommand + { + public: + static TCallback* New( ); + virtual void Execute( + vtkObject* caller, unsigned long id, void* data + ) cpPlugins_OVERRIDE; + void SetSeeds( vtkPolyData* seeds ); + + protected: + TCallback( ); + virtual ~TCallback( ); + + protected: + vtkPolyData* m_Seeds; + std::set< TWidget* > m_Widgets; + }; + + protected: + inline void _GD0_Image( vtkImageData* image ); + + protected: + std::map< vtkRenderWindowInteractor*, vtkSmartPointer< TWidget > > m_Widgets; + vtkSmartPointer< TCallback > m_Command; + }; + +} // ecapseman + +#endif // __cpPluginsVTKWidgets__SeedWidget__h__ + +// eof - $RCSfile$ diff --git a/plugins/VTKWidgets/SplineWidget.cxx b/plugins/VTKWidgets/SplineWidget.cxx new file mode 100644 index 0000000..5f82c7e --- /dev/null +++ b/plugins/VTKWidgets/SplineWidget.cxx @@ -0,0 +1,253 @@ +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SplineWidget:: +Clear( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SplineWidget:: +SetEnabled( bool v ) +{ + auto wdg = this->GetVTK< vtkSplineWidget >( ); + if( wdg != NULL ) + { + wdg->SetEnabled( v ); + wdg->GetInteractor( )->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpPluginsVTKWidgets::SplineWidget:: +GetEnabled( ) const +{ + auto wdg = this->GetVTK< const vtkSplineWidget >( ); + if( wdg != NULL ) + { + vtkSplineWidget* w = const_cast< vtkSplineWidget* >( wdg ); + return( w->GetEnabled( ) != 0 ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::SplineWidget:: +SplineWidget( ) + : Superclass( ), + m_Configured( false ) +{ + typedef cpPlugins::Pipeline::DataObject _TData; + typedef cpInstances::DataObjects::Mesh _TMesh; + + this->_ConfigureInput< _TData >( "Input", false, false ); + this->_ConfigureOutput< _TMesh >( "Output" ); + this->m_Contour = vtkSmartPointer< vtkPolyData >::New( ); + this->m_Contour->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + this->m_Contour->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + this->m_Contour->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + this->m_Contour->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + this->m_Contour->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + this->GetOutput( "Output" )->SetVTK( this->m_Contour ); + + this->m_Parameters.ConfigureAsBool( "Extend", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsVTKWidgets::SplineWidget:: +~SplineWidget( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsVTKWidgets::SplineWidget:: +_GenerateData( ) +{ + typedef cpExtensions::Visualization::WindowLevelImageActor _TActor; + + auto image = this->GetInputData< vtkImageData >( "Input" ); + if( image == NULL ) + this->_Error( "Invalid input image." ); + if( this->m_Interactors.size( ) == 0 ) + this->_Error( "Give at least one interactor." ); + + auto wdg = this->_CreateVTK< vtkSplineWidget >( ); + if( this->m_Configured ) + { + if( this->m_Parameters.GetBool( "Extend" ) ) + { + wdg->GetPolyData( this->m_Contour.GetPointer( ) ); + + typedef itk::Vector< double, 3 > _TVector; + typedef std::vector< _TVector > _TVectors; + + unsigned long nPoints = this->m_Contour->GetNumberOfPoints( ); + unsigned long support = nPoints / 10; + _TVectors pp, qp; + for( unsigned long i = 0; i < support; ++i ) + { + double p[ 3 ], q[ 3 ]; + this->m_Contour->GetPoint( i, p ); + this->m_Contour->GetPoint( nPoints - 1 - i, q ); + + _TVector pv, qv; + pv[ 0 ] = p[ 0 ]; + pv[ 1 ] = p[ 1 ]; + pv[ 2 ] = p[ 2 ]; + qv[ 0 ] = q[ 0 ]; + qv[ 1 ] = q[ 1 ]; + qv[ 2 ] = q[ 2 ]; + pp.push_back( pv ); + qp.push_back( qv ); + + } // rof + + _TVectors pt, qt; + pt.push_back( pp[ 1 ] - pp[ 0 ] ); + qt.push_back( qp[ 1 ] - qp[ 0 ] ); + for( unsigned long i = 1; i < support - 1; ++i ) + { + pt.push_back( pp[ i + 1 ] - pp[ i - 1 ] ); + qt.push_back( qp[ i + 1 ] - qp[ i - 1 ] ); + + } // rof + pt.push_back( pp[ support - 1 ] - pp[ support - 2 ] ); + qt.push_back( qp[ support - 1 ] - qp[ support - 2 ] ); + + _TVector t0( double( 0 ) ), t1( double( 0 ) ); + long real0 = 0, real1 = 0; + for( unsigned long i = 0; i < support; ++i ) + { + double n0 = pt[ i ].GetNorm( ); + if( n0 > double( 0 ) ) + { + t0 += pt[ i ] / n0; + real0++; + + } // fi + + double n1 = qt[ i ].GetNorm( ); + if( n1 > double( 0 ) ) + { + t1 += qt[ i ] / n1; + real1++; + + } // fi + + } // rof + + if( real0 > 0 ) + t0 /= double( -real0 ); + if( real1 > 0 ) + t1 /= double( -real1 ); + + t0 *= ( pp[ 0 ] - qp[ 0 ] ).GetNorm( ); + t1 *= ( pp[ 0 ] - qp[ 0 ] ).GetNorm( ); + + _TVector p0 = pp[ 0 ] + t0; + _TVector p1 = qp[ 0 ] + t1; + + vtkSmartPointer< vtkPolyData > cnt = this->m_Contour; + this->m_Contour = vtkSmartPointer< vtkPolyData >::New( ); + this->m_Contour->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + this->m_Contour->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + this->m_Contour->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + this->m_Contour->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + this->m_Contour->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + this->GetOutput( "Output" )->SetVTK( this->m_Contour ); + + this->m_Contour->GetPoints( )-> + InsertNextPoint( p0[ 0 ], p0[ 1 ], p0[ 2 ] ); + for( unsigned long i = 0; i < nPoints; ++i ) + { + double p[ 3 ]; + cnt->GetPoints( )->GetPoint( i, p ); + this->m_Contour->GetPoints( )->InsertNextPoint( p ); + + } // rof + this->m_Contour->GetPoints( )-> + InsertNextPoint( p1[ 0 ], p1[ 1 ], p1[ 2 ] ); + this->m_Contour->Modified( ); + } + else + wdg->GetPolyData( this->m_Contour.GetPointer( ) ); + } + else + { + auto iIt = this->m_Interactors.begin( ); + vtkRenderWindowInteractor* iren = NULL; + vtkRenderer* ren = NULL; + _TActor* actor = NULL; + for( ; iIt != this->m_Interactors.end( ); ++iIt ) + { + auto r = ( *iIt )->GetInteractorStyle( )->GetCurrentRenderer( ); + if( r != NULL ) + { + auto props = r->GetViewProps( ); + if( props != NULL ) + { + props->InitTraversal( ); + while( vtkProp* prop = props->GetNextProp( ) ) + { + auto a = dynamic_cast< _TActor* >( prop ); + if( a != NULL ) + if( a->GetImage( ) == image ) + { + iren = *iIt; + actor = a; + ren = r; + + } // fi + + } // elihw + + } // fi + + } // fi + + } // rof + if( actor == NULL || ren == NULL || iren == NULL ) + this->_Error( "Invalid actor and/or renderer." ); + + // Widget configuration + wdg->SetCurrentRenderer( ren ); + wdg->SetDefaultRenderer( ren ); + wdg->SetInputData( image ); + wdg->SetProp3D( actor ); + wdg->SetInteractor( iren ); + double bnds[ 6 ]; + image->GetBounds( bnds ); + wdg->PlaceWidget( + bnds[ 0 ], bnds[ 1 ], + bnds[ 2 ], bnds[ 3 ], + bnds[ 4 ], bnds[ 5 ] + ); + wdg->ProjectToPlaneOn( ); + wdg->SetProjectionNormalToZAxes( ); + wdg->SetProjectionPosition( + ( + actor->GetBounds( )[ 4 ] + + actor->GetBounds( )[ 5 ] + ) / double( 2 ) + ); + wdg->SetHandleSize( 0.005 ); + wdg->SetNumberOfHandles( 3 ); + this->m_Configured = true; + + } // fi +} + +// eof - $RCSfile$ diff --git a/plugins/VTKWidgets/SplineWidget.h b/plugins/VTKWidgets/SplineWidget.h new file mode 100644 index 0000000..6822323 --- /dev/null +++ b/plugins/VTKWidgets/SplineWidget.h @@ -0,0 +1,83 @@ +#ifndef __cpPluginsVTKWidgets__SplineWidget__h__ +#define __cpPluginsVTKWidgets__SplineWidget__h__ + +#include +#include + +#include + +/* TODO + #include + #include + #include + #include + #include + #include + #include +*/ + +// ------------------------------------------------------------------------- +class vtkPolyData; + +// ------------------------------------------------------------------------- +namespace cpPluginsVTKWidgets +{ + /** + */ + class cpPlugins_VTKWidgets_EXPORT SplineWidget + : public cpPlugins::Pipeline::Widget + { + cpPluginsObject( SplineWidget, cpPlugins::Pipeline::Widget, Widgets ); + + public: + virtual void Clear( ) cpPlugins_OVERRIDE; + virtual void SetEnabled( bool v ) cpPlugins_OVERRIDE; + virtual bool GetEnabled( ) const cpPlugins_OVERRIDE; + + protected: + bool m_Configured; + vtkSmartPointer< vtkPolyData > m_Contour; + + /* TODO: + public: + typedef cpExtensions::Visualization::WindowLevelImageActor TImageActor; + + public: + struct TWidgetData + { + typedef cpExtensions::Interaction::SplineWidget _TWidget; + typedef cpExtensions::Interaction::ImageSlicePointPlacer _TPlacer; + + std::vector< vtkSmartPointer< _TWidget > > Widgets; + std::vector< vtkSmartPointer< _TPlacer > > Placers; + std::vector< vtkSmartPointer< vtkPointHandleRepresentation3D > > Handles; + std::vector< vtkSmartPointer< vtkSeedRepresentation > > Representations; + unsigned int ActualWidgetId; + vtkSmartPointer< vtkCommand > Command; + + TWidgetData( + SplineWidget* seedWidget, + TImageActor* actor, + vtkRenderWindowInteractor* iren + ); + virtual ~TWidgetData( ); + }; + + protected: + void _Configure( ); + + template< class _TImage > + inline void _GD0_Image( _TImage* image ); + + protected: + std::map< vtkProp*, vtkRenderWindowInteractor* > m_Props; + std::vector< TWidgetData* > m_Widgets; + bool m_Configured; + */ + }; + +} // ecapseman + +#endif // __cpPluginsVTKWidgets__SplineWidget__h__ + +// eof - $RCSfile$ diff --git a/plugins/change.csv b/plugins/change.csv new file mode 100644 index 0000000..999df74 --- /dev/null +++ b/plugins/change.csv @@ -0,0 +1 @@ +grep -rl cpPlugins_GenericPlugins . | xargs sed -i 's/cpPlugins_GenericPlugins/cpPlugins_GenericPlugins/g' diff --git a/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.cxx b/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.cxx new file mode 100644 index 0000000..21760ce --- /dev/null +++ b/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.cxx @@ -0,0 +1,46 @@ +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::PolyLineParametricPathToSimple3DCurve:: +PolyLineParametricPathToSimple3DCurve( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::PolyLineParametricPath >( + "Input", true, false + ); + this->_ConfigureOutput< cpInstances::Simple3DCurve >( "Output" ); + this->m_Parameters.ConfigureAsUint( "NumberOfSamples", 0 ); +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::PolyLineParametricPathToSimple3DCurve:: +~PolyLineParametricPathToSimple3DCurve( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginscpExtensions::PolyLineParametricPathToSimple3DCurve:: +_GenerateData( ) +{ + typedef cpExtensions::DataStructures::PolyLineParametricPath< 3 > _TPath; + typedef cpExtensions::DataStructures::Simple3DCurve< double > _TCurve; + typedef cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPath, _TCurve > _TFilter; + + auto in = this->GetInputData< _TPath >( "Input" ); + if( in == NULL ) + this->_Error( "Invalid input path." ); + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( in ); + filter->SetNumberOfSamples( this->m_Parameters.GetUint( "NumberOfSamples" ) ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.h b/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.h new file mode 100644 index 0000000..864acf6 --- /dev/null +++ b/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.h @@ -0,0 +1,26 @@ +#ifndef __cpPluginscpExtensions__PolyLineParametricPathToSimple3DCurve__h__ +#define __cpPluginscpExtensions__PolyLineParametricPathToSimple3DCurve__h__ + +#include +#include + +namespace cpPluginscpExtensions +{ + /** + */ + class cpPlugins_cpExtensions_EXPORT PolyLineParametricPathToSimple3DCurve + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + PolyLineParametricPathToSimple3DCurve, + cpPlugins::Pipeline::ProcessObject, + cpExtensions + ); + }; + +} // ecapseman + +#endif // __cpPluginscpExtensions__PolyLineParametricPathToSimple3DCurve__h__ + + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/PolyLineParametricPathWriter.cxx b/plugins/cpExtensions/PolyLineParametricPathWriter.cxx new file mode 100644 index 0000000..7ee1be3 --- /dev/null +++ b/plugins/cpExtensions/PolyLineParametricPathWriter.cxx @@ -0,0 +1,79 @@ +#include +#include + +#include +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginscpExtensions::PolyLineParametricPathWriter:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::SaveFileDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::SaveFileDialog( ); + dlg->SetParameters( &( this->m_Parameters ), "FileName" ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::PolyLineParametricPathWriter:: +PolyLineParametricPathWriter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::PolyLineParametricPath >( "Input", true, false ); + this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileName", + "PolyLineParametricPath files (*.txt)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::PolyLineParametricPathWriter:: +~PolyLineParametricPathWriter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginscpExtensions::PolyLineParametricPathWriter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_PolyLineParametricPath_All_1( o, _GD0 ) + this->_Error( "Invalid input skeleton." ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLineParametricPath > +void cpPluginscpExtensions::PolyLineParametricPathWriter:: +_GD0( _TPolyLineParametricPath* skeleton ) +{ + typedef cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLineParametricPath > _TWriter; + + auto filter = this->_CreateITK< _TWriter >( ); + filter->SetInput( skeleton ); + filter->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ) ); + try + { + filter->Update( ); + } + catch( itk::ExceptionObject& err ) + { + this->_Error( err.GetDescription( ) ); + + } // yrt +} + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/PolyLineParametricPathWriter.h b/plugins/cpExtensions/PolyLineParametricPathWriter.h new file mode 100644 index 0000000..2794132 --- /dev/null +++ b/plugins/cpExtensions/PolyLineParametricPathWriter.h @@ -0,0 +1,33 @@ +#ifndef __cpPluginscpExtensions__PolyLineParametricPathWriter__h__ +#define __cpPluginscpExtensions__PolyLineParametricPathWriter__h__ + +#include +#include + +namespace cpPluginscpExtensions +{ + /** + */ + class cpPlugins_cpExtensions_EXPORT PolyLineParametricPathWriter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + PolyLineParametricPathWriter, + cpPlugins::Pipeline::ProcessObject, + IO + ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + + protected: + template< class _TPolyLineParametricPath > + inline void _GD0( _TPolyLineParametricPath* skeleton ); + }; + +} // ecapseman + +#endif // __cpPluginscpExtensions__PolyLineParametricPathWriter__h__ + + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/SkeletonReader.cxx b/plugins/cpExtensions/SkeletonReader.cxx new file mode 100644 index 0000000..f62ff69 --- /dev/null +++ b/plugins/cpExtensions/SkeletonReader.cxx @@ -0,0 +1,93 @@ +#include +#include + +#include +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginscpExtensions::SkeletonReader:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::OpenFileDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::OpenFileDialog( ); + dlg->SetParameters( &( this->m_Parameters ), "FileName" ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::SkeletonReader:: +SkeletonReader( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpInstances::Skeleton >( "Output" ); + this->m_Parameters.ConfigureAsOpenFileName( "FileName", "" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileName", + "Skeleton files (*.txt)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::SkeletonReader:: +~SkeletonReader( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginscpExtensions::SkeletonReader:: +_GenerateData( ) +{ + std::string success = ""; +#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_1 + success = this->_GD0< 1 >( ); +#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_1 +#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_2 + if( success != "" ) success = this->_GD0< 2 >( ); +#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_2 +#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_3 + if( success != "" ) success = this->_GD0< 3 >( ); +#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_3 +#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_4 + if( success != "" ) success = this->_GD0< 4 >( ); +#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_4 + if( success != "" ) + this->_Error( success ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +std::string cpPluginscpExtensions::SkeletonReader:: +_GD0( ) +{ + typedef cpExtensions::DataStructures::Skeleton< _VDim > _TSkeleton; + typedef cpExtensions::Algorithms::SkeletonReader< _TSkeleton > _TReader; + + auto filter = this->_CreateITK< _TReader >( ); + filter->SetFileName( this->m_Parameters.GetOpenFileName( "FileName" ) ); + try + { + filter->Update( ); + } + catch( std::exception& err ) + { + return( err.what( ) ); + + } // yrt + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); + return( "" ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/SkeletonReader.h b/plugins/cpExtensions/SkeletonReader.h new file mode 100644 index 0000000..3490682 --- /dev/null +++ b/plugins/cpExtensions/SkeletonReader.h @@ -0,0 +1,33 @@ +#ifndef __cpPluginscpExtensions__SkeletonReader__h__ +#define __cpPluginscpExtensions__SkeletonReader__h__ + +#include +#include + +namespace cpPluginscpExtensions +{ + /** + */ + class cpPlugins_cpExtensions_EXPORT SkeletonReader + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + SkeletonReader, + cpPlugins::Pipeline::ProcessObject, + IO + ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + + protected: + template< unsigned int _VDim > + inline std::string _GD0( ); + }; + +} // ecapseman + +#endif // __cpPluginscpExtensions__SkeletonReader__h__ + + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/SkeletonToImageFilter.cxx b/plugins/cpExtensions/SkeletonToImageFilter.cxx new file mode 100644 index 0000000..30bdddc --- /dev/null +++ b/plugins/cpExtensions/SkeletonToImageFilter.cxx @@ -0,0 +1,54 @@ +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::SkeletonToImageFilter:: +SkeletonToImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::Skeleton >( "Skeleton", true, false ); + this->_ConfigureInput< cpInstances::DataObjects::Image >( "TemplateImage", true, false ); + this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" ); + this->m_Parameters.ConfigureAsUint( "InsideValue", 1 ); + this->m_Parameters.ConfigureAsUint( "OutsideValue", 0 ); +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::SkeletonToImageFilter:: +~SkeletonToImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginscpExtensions::SkeletonToImageFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Skeleton" ); + cpPlugins_Demangle_Skeleton_All_1( o, _GD0 ) + this->_Error( "Invalid input skeleton." ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpPluginscpExtensions::SkeletonToImageFilter:: +_GD0( _TSkeleton* skeleton ) +{ + typedef itk::ImageBase< _TSkeleton::Dimension > _TImageBase; + typedef itk::Image< unsigned char, _TSkeleton::Dimension > _TImage; + typedef cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage > _TFilter; + + auto image = this->GetInputData< _TImageBase >( "TemplateImage" ); + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetTemplateImage( image ); + filter->SetSkeleton( skeleton ); + filter->SetInsideValue( this->m_Parameters.GetUint( "InsideValue" ) ); + filter->SetOutsideValue( this->m_Parameters.GetUint( "OutsideValue" ) ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/SkeletonToImageFilter.h b/plugins/cpExtensions/SkeletonToImageFilter.h new file mode 100644 index 0000000..99aa824 --- /dev/null +++ b/plugins/cpExtensions/SkeletonToImageFilter.h @@ -0,0 +1,30 @@ +#ifndef __cpPluginscpExtensions__SkeletonToImageFilter__h__ +#define __cpPluginscpExtensions__SkeletonToImageFilter__h__ + +#include +#include + +namespace cpPluginscpExtensions +{ + /** + */ + class cpPlugins_cpExtensions_EXPORT SkeletonToImageFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + SkeletonToImageFilter, + cpPlugins::Pipeline::ProcessObject, + cpExtensions + ); + + protected: + template< class _TSkeleton > + inline void _GD0( _TSkeleton* skeleton ); + }; + +} // ecapseman + +#endif // __cpPluginscpExtensions__SkeletonToImageFilter__h__ + + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/SkeletonWriter.cxx b/plugins/cpExtensions/SkeletonWriter.cxx new file mode 100644 index 0000000..f23f600 --- /dev/null +++ b/plugins/cpExtensions/SkeletonWriter.cxx @@ -0,0 +1,79 @@ +#include +#include + +#include +#include +#include + +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginscpExtensions::SkeletonWriter:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPlugins::QT::SaveFileDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPlugins::QT::SaveFileDialog( ); + dlg->SetParameters( &( this->m_Parameters ), "FileName" ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::SkeletonWriter:: +SkeletonWriter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpInstances::Skeleton >( "Input", true, false ); + this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileName", + "Skeleton files (*.txt)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::SkeletonWriter:: +~SkeletonWriter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginscpExtensions::SkeletonWriter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Skeleton_All_1( o, _GD0 ) + this->_Error( "Invalid input skeleton." ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void cpPluginscpExtensions::SkeletonWriter:: +_GD0( _TSkeleton* skeleton ) +{ + typedef cpExtensions::Algorithms::SkeletonWriter< _TSkeleton > _TWriter; + + auto filter = this->_CreateITK< _TWriter >( ); + filter->SetInput( skeleton ); + filter->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ) ); + try + { + filter->Update( ); + } + catch( itk::ExceptionObject& err ) + { + this->_Error( err.GetDescription( ) ); + + } // yrt +} + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/SkeletonWriter.h b/plugins/cpExtensions/SkeletonWriter.h new file mode 100644 index 0000000..920ae01 --- /dev/null +++ b/plugins/cpExtensions/SkeletonWriter.h @@ -0,0 +1,33 @@ +#ifndef __cpPluginscpExtensions__SkeletonWriter__h__ +#define __cpPluginscpExtensions__SkeletonWriter__h__ + +#include +#include + +namespace cpPluginscpExtensions +{ + /** + */ + class cpPlugins_cpExtensions_EXPORT SkeletonWriter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + SkeletonWriter, + cpPlugins::Pipeline::ProcessObject, + IO + ); + + public: + virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE; + + protected: + template< class _TSkeleton > + inline void _GD0( _TSkeleton* skeleton ); + }; + +} // ecapseman + +#endif // __cpPluginscpExtensions__SkeletonWriter__h__ + + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/cpExtensions.i b/plugins/cpExtensions/cpExtensions.i new file mode 100644 index 0000000..4d3e1ea --- /dev/null +++ b/plugins/cpExtensions/cpExtensions.i @@ -0,0 +1,13 @@ +header #define ITK_MANUAL_INSTANTIATION + +tinclude cpExtensions/Algorithms/SkeletonToImageFilter:h|hxx +tinclude cpExtensions/Algorithms/SkeletonReader:h|hxx +tinclude cpExtensions/Algorithms/SkeletonWriter:h|hxx +cinclude cpExtensions/DataStructures/Skeleton.h + +instances cpExtensions::Algorithms::SkeletonToImageFilter< cpExtensions::DataStructures::Skeleton< #pdims# >, itk::Image< unsigned char, #pdims# > > + +instances cpExtensions::Algorithms::SkeletonReader< cpExtensions::DataStructures::Skeleton< #pdims# > > +instances cpExtensions::Algorithms::SkeletonWriter< cpExtensions::DataStructures::Skeleton< #pdims# > > + +** eof - $RCSfile$ diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..988fc31 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,29 @@ + +## =================== +## == List of tools == +## =================== + +SET(_pfx cpPlugins_tool_) +SET( + _tools + ExecutePipeline + PrintFileInfo + PrintDirInfo + PrintGuessInfo + RenameImageFile + ) + +## ======================= +## == Compilation rules == +## ======================= + +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_BINARY_DIR}/lib + ) +FOREACH(_t ${_tools}) + ADD_EXECUTABLE(${_pfx}${_t} ${_t}.cxx) + TARGET_LINK_LIBRARIES(${_pfx}${_t} cpPlugins) +ENDFOREACH(_t) + +## eof - $RCSfile$ diff --git a/tools/ExecutePipeline.cxx b/tools/ExecutePipeline.cxx new file mode 100644 index 0000000..2c59a03 --- /dev/null +++ b/tools/ExecutePipeline.cxx @@ -0,0 +1,7 @@ + +int main( int argc, char* argv[] ) +{ + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tools/PrintDirInfo.cxx b/tools/PrintDirInfo.cxx new file mode 100644 index 0000000..0c00f79 --- /dev/null +++ b/tools/PrintDirInfo.cxx @@ -0,0 +1,56 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " library" << std::endl; + return( 1 ); + + } // fi + + // Get plugins loader + std::string error_message = ""; + cpPlugins::Interface::Loader loader; + for( int i = 1; i < argc; ++i ) + { + try + { + loader.RegisterFromDirectory( argv[ i ] ); + } + catch( std::exception& err ) + { + error_message += err.what( ) + std::string( "\n" ); + + } // yrt + + } // rof + + if( error_message != "" ) + { + std::cerr + << "***************************************" << std::endl + << "Errors during load: " << std::endl + << error_message << std::endl + << "***************************************" << std::endl; + + } // fi + + // Show loader information + std::cout << "---------------------------" << std::endl; + std::cout << loader << std::endl; + std::cout << "---------------------------" << std::endl; + + // Close connection to loaded plugins file + loader.UnRegisterAll( ); + + // Just a last check + std::cout << "---------------------------" << std::endl; + std::cout << loader << std::endl; + std::cout << "---------------------------" << std::endl; + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tools/PrintFileInfo.cxx b/tools/PrintFileInfo.cxx new file mode 100644 index 0000000..0eb1109 --- /dev/null +++ b/tools/PrintFileInfo.cxx @@ -0,0 +1,56 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " library" << std::endl; + return( 1 ); + + } // fi + + // Get plugins loader + std::string error_message = ""; + cpPlugins::Interface::Loader loader; + for( int i = 1; i < argc; ++i ) + { + try + { + loader.Register( argv[ i ] ); + } + catch( std::exception& err ) + { + error_message += err.what( ) + std::string( "\n" ); + + } // yrt + + } // rof + + if( error_message != "" ) + { + std::cerr + << "***************************************" << std::endl + << "Errors during load: " << std::endl + << error_message << std::endl + << "***************************************" << std::endl; + + } // fi + + // Show loader information + std::cout << "---------------------------" << std::endl; + std::cout << loader << std::endl; + std::cout << "---------------------------" << std::endl; + + // Close connection to loaded plugins file + loader.UnRegisterAll( ); + + // Just a last check + std::cout << "---------------------------" << std::endl; + std::cout << loader << std::endl; + std::cout << "---------------------------" << std::endl; + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tools/PrintGuessInfo.cxx b/tools/PrintGuessInfo.cxx new file mode 100644 index 0000000..7b50afd --- /dev/null +++ b/tools/PrintGuessInfo.cxx @@ -0,0 +1,28 @@ +#include +#include +#include + +int main( int argc, char* argv[] ) +{ + // Get plugins loader + std::string error_message = ""; + cpPlugins::Interface::Loader loader; + loader.GuessEnvironment( cpPlugins::OS::FileSystem::CanonicalPath( "." ) ); + + // Show loader information + std::cout << "---------------------------" << std::endl; + std::cout << loader << std::endl; + std::cout << "---------------------------" << std::endl; + + // Close connection to loaded plugins file + loader.UnRegisterAll( ); + + // Just a last check + std::cout << "---------------------------" << std::endl; + std::cout << loader << std::endl; + std::cout << "---------------------------" << std::endl; + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tools/RenameImageFile.cxx b/tools/RenameImageFile.cxx new file mode 100644 index 0000000..60297c4 --- /dev/null +++ b/tools/RenameImageFile.cxx @@ -0,0 +1,62 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 2 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_file(s) output_file" << std::endl; + return( 1 ); + + } // fi + + // Get plugins loader + cpPlugins::Interface::Loader loader; + try + { + loader.RegisterFromDirectory( "." ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Try to get any errors + try + { + // Create filters + auto reader = loader.CreateFilter( "IO", "ImageReader", "reader" ); + auto writer = loader.CreateFilter( "IO", "ImageWriter", "writer" ); + + // Configure parameters + auto reader_params = reader->GetParameters( ); + auto writer_params = writer->GetParameters( ); + for( int i = 1; i < argc - 1; ++i ) + reader_params->AddToOpenFileNameList( "FileNames", argv[ i ] ); + writer_params->SetSaveFileName( "FileName", argv[ argc - 1 ] ); + + // Connect filters + writer->SetInput( "Input", reader->GetOutput( "Output" ) ); + + // Execute + reader->PrintExecutionOn( ); + writer->PrintExecutionOn( ); + writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Close connection to loaded plugins file + loader.UnRegisterAll( ); + return( 0 ); +} + +// eof - $RCSfile$