From ea46079b5aef76c1782648ed23e70ea944649635 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Tue, 4 Oct 2016 08:11:09 -0500 Subject: [PATCH] ... --- CMakeLists.txt | 69 +++ appli/CMakeLists.txt | 6 + appli/examples/CMakeLists.txt | 4 + appli/examples/ImageDijkstra.cxx | 69 +++ cmake/DetectOS.cmake | 23 + cmake/Functions.cmake | 453 ++++++++++++++++++ cmake/KitwareTools.cmake | 19 + cmake/Options.cmake | 13 + cmake/Qt4Tools.cmake | 12 + cmake/Restrictions.cmake | 51 ++ lib/CMakeLists.txt | 20 + lib/Instances/CMakeLists.txt | 40 ++ lib/Instances/fpa_DataObjects.i | 8 + lib/Instances/fpa_Filters.i | 12 + lib/fpa/Base/Algorithm.h | 128 +++++ lib/fpa/Base/Algorithm.hxx | 237 +++++++++ lib/fpa/Base/Dijkstra.h | 93 ++++ lib/fpa/Base/Dijkstra.hxx | 135 ++++++ lib/fpa/Base/DijkstraCostFunctionBase.h | 51 ++ lib/fpa/Base/Events.h | 100 ++++ lib/fpa/Base/Functors/GaussianModel.h | 75 +++ lib/fpa/Base/Functors/GaussianModel.hxx | 50 ++ lib/fpa/Base/Functors/Inverse.h | 57 +++ lib/fpa/Base/Functors/Inverse.hxx | 32 ++ lib/fpa/Base/MinimumSpanningTree.h | 77 +++ lib/fpa/Base/MinimumSpanningTree.hxx | 232 +++++++++ lib/fpa/Config.cxx | 1 + lib/fpa/Config.h.in | 39 ++ lib/fpa/Image/Algorithm.h | 70 +++ lib/fpa/Image/Algorithm.hxx | 114 +++++ lib/fpa/Image/Dijkstra.h | 61 +++ lib/fpa/Image/Dijkstra.hxx | 35 ++ lib/fpa/Image/Functors/Base.h | 55 +++ lib/fpa/Image/Functors/SimpleDijkstraCost.h | 68 +++ lib/fpa/Image/Functors/SimpleDijkstraCost.hxx | 42 ++ lib/fpa/Image/Functors/SimpleNeighborhood.h | 65 +++ lib/fpa/Image/Functors/SimpleNeighborhood.hxx | 53 ++ lib/fpa/Image/MinimumSpanningTree.h | 63 +++ lib/fpa/Image/MinimumSpanningTree.hxx | 75 +++ plugins/CMakeLists.txt | 15 + plugins/Plugins/BaseImageFilter.cxx | 29 ++ plugins/Plugins/BaseImageFilter.h | 52 ++ .../ExtractPathFromMinimumSpanningTree.cxx | 124 +++++ .../ExtractPathFromMinimumSpanningTree.h | 29 ++ plugins/Plugins/GaussianModelCost.cxx | 55 +++ plugins/Plugins/GaussianModelCost.h | 29 ++ plugins/Plugins/ImageDijkstra.cxx | 108 +++++ plugins/Plugins/ImageDijkstra.h | 27 ++ plugins/Plugins/InvertCost.cxx | 55 +++ plugins/Plugins/InvertCost.h | 29 ++ plugins/Plugins/SimpleImageDijkstraCost.cxx | 73 +++ plugins/Plugins/SimpleImageDijkstraCost.h | 32 ++ plugins/Plugins/SimpleImageNeighborhood.cxx | 55 +++ plugins/Plugins/SimpleImageNeighborhood.h | 29 ++ 54 files changed, 3548 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 appli/CMakeLists.txt create mode 100644 appli/examples/CMakeLists.txt create mode 100644 appli/examples/ImageDijkstra.cxx create mode 100644 cmake/DetectOS.cmake create mode 100644 cmake/Functions.cmake create mode 100644 cmake/KitwareTools.cmake create mode 100644 cmake/Options.cmake create mode 100644 cmake/Qt4Tools.cmake create mode 100644 cmake/Restrictions.cmake create mode 100644 lib/CMakeLists.txt create mode 100644 lib/Instances/CMakeLists.txt create mode 100644 lib/Instances/fpa_DataObjects.i create mode 100644 lib/Instances/fpa_Filters.i create mode 100644 lib/fpa/Base/Algorithm.h create mode 100644 lib/fpa/Base/Algorithm.hxx create mode 100644 lib/fpa/Base/Dijkstra.h create mode 100644 lib/fpa/Base/Dijkstra.hxx create mode 100644 lib/fpa/Base/DijkstraCostFunctionBase.h create mode 100644 lib/fpa/Base/Events.h create mode 100644 lib/fpa/Base/Functors/GaussianModel.h create mode 100644 lib/fpa/Base/Functors/GaussianModel.hxx create mode 100644 lib/fpa/Base/Functors/Inverse.h create mode 100644 lib/fpa/Base/Functors/Inverse.hxx create mode 100644 lib/fpa/Base/MinimumSpanningTree.h create mode 100644 lib/fpa/Base/MinimumSpanningTree.hxx create mode 100644 lib/fpa/Config.cxx create mode 100644 lib/fpa/Config.h.in create mode 100644 lib/fpa/Image/Algorithm.h create mode 100644 lib/fpa/Image/Algorithm.hxx create mode 100644 lib/fpa/Image/Dijkstra.h create mode 100644 lib/fpa/Image/Dijkstra.hxx create mode 100644 lib/fpa/Image/Functors/Base.h create mode 100644 lib/fpa/Image/Functors/SimpleDijkstraCost.h create mode 100644 lib/fpa/Image/Functors/SimpleDijkstraCost.hxx create mode 100644 lib/fpa/Image/Functors/SimpleNeighborhood.h create mode 100644 lib/fpa/Image/Functors/SimpleNeighborhood.hxx create mode 100644 lib/fpa/Image/MinimumSpanningTree.h create mode 100644 lib/fpa/Image/MinimumSpanningTree.hxx create mode 100644 plugins/CMakeLists.txt create mode 100644 plugins/Plugins/BaseImageFilter.cxx create mode 100644 plugins/Plugins/BaseImageFilter.h create mode 100644 plugins/Plugins/ExtractPathFromMinimumSpanningTree.cxx create mode 100644 plugins/Plugins/ExtractPathFromMinimumSpanningTree.h create mode 100644 plugins/Plugins/GaussianModelCost.cxx create mode 100644 plugins/Plugins/GaussianModelCost.h create mode 100644 plugins/Plugins/ImageDijkstra.cxx create mode 100644 plugins/Plugins/ImageDijkstra.h create mode 100644 plugins/Plugins/InvertCost.cxx create mode 100644 plugins/Plugins/InvertCost.h create mode 100644 plugins/Plugins/SimpleImageDijkstraCost.cxx create mode 100644 plugins/Plugins/SimpleImageDijkstraCost.h create mode 100644 plugins/Plugins/SimpleImageNeighborhood.cxx create mode 100644 plugins/Plugins/SimpleImageNeighborhood.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0d6fd70 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,69 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.0) + +## ======================== +## == Project definition == +## ======================== + +SET(prj_NAME FrontAlgorithms) +SET(prj_MAJOR_VERSION 0) +SET(prj_MINOR_VERSION 1) +SET(prj_RELEASE_VERSION 0) + +## ========================== +## == Some useful policies == +## ========================== + +SET(_policies CMP0015 CMP0020 CMP0042) +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_MAJOR_VERSION}.${prj_MINOR_VERSION}.${prj_RELEASE_VERSION}" + ) +SET(prj_SHORT_VERSION "${prj_MAJOR_VERSION}") + +## ===================================== +## == Functions, packages and options == +## ===================================== + +INCLUDE(cmake/DetectOS.cmake) +INCLUDE(cmake/Restrictions.cmake) +INCLUDE(cmake/Functions.cmake) +INCLUDE(cmake/KitwareTools.cmake) +INCLUDE(cmake/Options.cmake) + +## =========================== +## == Use all valid subdirs == +## =========================== + +SET( + _include_dirs + . + lib + ) +IF(USE_cpPlugins) + LIST(APPEND _include_dirs lib/Instances) +ENDIF(USE_cpPlugins) +FOREACH(_dir ${_include_dirs}) + INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/${_dir} + ${PROJECT_BINARY_DIR}/${_dir} + ) +ENDFOREACH(_dir) + +## ======================== +## == Manage source code == +## ======================== + +SUBDIRS(lib plugins appli) + +## eof - $RCSfile$ diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt new file mode 100644 index 0000000..a5a2028 --- /dev/null +++ b/appli/CMakeLists.txt @@ -0,0 +1,6 @@ +OPTION(BUILD_EXAMPLES "Build simple examples" OFF) +IF(BUILD_EXAMPLES) + SUBDIRS(examples) +ENDIF(BUILD_EXAMPLES) + +## eof - $RCSfile$ diff --git a/appli/examples/CMakeLists.txt b/appli/examples/CMakeLists.txt new file mode 100644 index 0000000..861b670 --- /dev/null +++ b/appli/examples/CMakeLists.txt @@ -0,0 +1,4 @@ +ADD_EXECUTABLE(fpa_examples_ImageDijkstra ImageDijkstra.cxx) +TARGET_LINK_LIBRARIES(fpa_examples_ImageDijkstra ${ITK_LIBRARIES}) + +## eof - $RCSfile$ diff --git a/appli/examples/ImageDijkstra.cxx b/appli/examples/ImageDijkstra.cxx new file mode 100644 index 0000000..1b56263 --- /dev/null +++ b/appli/examples/ImageDijkstra.cxx @@ -0,0 +1,69 @@ +#include +#include +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +static const unsigned int VDim = 2; +typedef float TScalar; +typedef itk::Image< unsigned char, VDim > TInputImage; +typedef itk::Image< TScalar, VDim > TOutputImage; + +typedef itk::RandomImageSource< TInputImage > TImageSource; +typedef itk::ImageFileWriter< TOutputImage > TImageWriter; + +typedef fpa::Image::Functors::SimpleNeighborhood< TInputImage > TNeighFunction; +typedef fpa::Image::Functors::SimpleDijkstraCost< TInputImage, TScalar > TCostFunction; +typedef fpa::Base::Functors::Inverse< TScalar, TScalar > TCostConversionFunction; + +typedef fpa::Image::Dijkstra< TInputImage, TOutputImage > TFilter; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + static const unsigned long SIZE = 100; + unsigned long size[] = { SIZE, SIZE }; + + unsigned int neigh_order = 1; + TInputImage::IndexType seed0, seed1; + + seed0.Fill( 0 ); + seed1.Fill( SIZE - 1 ); + + TImageSource::Pointer source = TImageSource::New( ); + source->SetSize( size ); + source->SetSpacing( 1 ); + source->Update( ); + TInputImage::Pointer input = source->GetOutput( ); + + TNeighFunction::Pointer neigh_function = TNeighFunction::New( ); + neigh_function->SetOrder( neigh_order ); + + TCostFunction::Pointer cost_function = TCostFunction::New( ); + + TCostConversionFunction::Pointer cost_conversion_function = + TCostConversionFunction::New( ); + + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input ); + filter->SetNeighborhoodFunction( neigh_function ); + filter->SetCostFunction( cost_function ); + filter->SetCostConversionFunction( cost_conversion_function ); + filter->AddSeed( seed0, 0 ); + filter->AddSeed( seed1, 0 ); + filter->StopAtOneFrontOn( ); + filter->Update( ); + + TImageWriter::Pointer writer = TImageWriter::New( ); + writer->SetInput( filter->GetOutput( ) ); + writer->SetFileName( "dijkstra.mhd" ); + writer->Update( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/cmake/DetectOS.cmake b/cmake/DetectOS.cmake new file mode 100644 index 0000000..bba8346 --- /dev/null +++ b/cmake/DetectOS.cmake @@ -0,0 +1,23 @@ +## ===================== +## == OS-based values == +## ===================== + +SET(prj_NAME_OS "${prj_NAME}_OS_${CMAKE_SYSTEM_NAME}") +IF("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") + SET(prj_NAME_LIB_PREFIX "lib") + SET(prj_NAME_LIB_EXT ".so") + SET(prj_NAME_ENV_SEPARATOR ":") + SET(prj_NAME_PATH_SEPARATOR "/") +ELSEIF("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") + SET(prj_NAME_LIB_PREFIX "lib") + SET(prj_NAME_LIB_EXT ".dylib") + SET(prj_NAME_ENV_SEPARATOR ":") + SET(prj_NAME_PATH_SEPARATOR "/") +ELSEIF("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + SET(prj_NAME_LIB_PREFIX "") + SET(prj_NAME_LIB_EXT ".dll") + SET(prj_NAME_ENV_SEPARATOR ";") + SET(prj_NAME_PATH_SEPARATOR "\\") +ENDIF("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") + +## eof - $RCSfile$ diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake new file mode 100644 index 0000000..f5a90f3 --- /dev/null +++ b/cmake/Functions.cmake @@ -0,0 +1,453 @@ +## ------------------------------------------------------------------------- +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( + CreateLib + lib_name + lib_type + lib_source_files + lib_header_files + lib_qt_ui_files + lib_version + lib_short_version + ) +## -- Configure inputs to be cmake-path compatible +NormPaths(_sources ${lib_source_files}) +NormPaths(_headers ${lib_header_files}) +NormPaths(_qt_uis ${lib_qt_ui_files}) + +# -- Prepare Qt4-based code +IF(Qt4_FOUND) + ## -- Guess what headers sould be qt-moc'ed + Wrap_Qt_CPP(_qt_moc_sources ${_headers}) + IF(_qt_moc_sources) + SET(_sources ${_sources} ${_qt_moc_sources}) + ENDIF(_qt_moc_sources) + + ## -- 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_ui_headers ${_qt_uis}) + IF(_qt_ui_headers) + SET(_headers ${_headers} ${_qt_ui_headers}) + SET(_sources ${_sources} ${_qt_ui_headers}) + ENDIF(_qt_ui_headers) +ENDIF(Qt4_FOUND) + +## -- Ok, compile library +IF(_sources) + NormPaths(_cur_binary_dir ${CMAKE_CURRENT_BINARY_DIR}) + ADD_LIBRARY(${lib_name} SHARED ${_sources} ${_headers}) + SET_TARGET_PROPERTIES( + ${lib_name} + PROPERTIES + VERSION "${lib_version}" + SOVERSION "${lib_short_version}" + ) + 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 + ) + SET(${lib_name}_LIB ${lib_name} CACHE INTERNAL "Library ${lib_name}") +ENDIF(_sources) + +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION( + LibFromDir + lib_name + lib_type + lib_source_dir + lib_version + lib_short_version + ) + +## -- Configure inputs to be cmake-path compatible +NormPaths(_global_source_dir ${PROJECT_SOURCE_DIR}) +NormPaths(_global_binary_dir ${PROJECT_BINARY_DIR}) +NormPaths(_source_dir ${lib_source_dir}) +STRING(REPLACE "${_global_source_dir}" "" _local_source_dir ${_source_dir}) +SET(_binary_dir ${_global_binary_dir}${_local_source_dir}) + +## -- Some useful variables +SET(_sources_extensions .c .cpp .cxx) +SET(_headers_extensions .h .hpp .hxx) +SET(_qt_ui_extensions .ui) +SET(_dirs ${_source_dir} ${_binary_dir}) +SET(_sources) +SET(_headers) +SET(_qt_uis) + +## -- Glob source code +FOREACH(_d ${_dirs}) + FOREACH(_e ${_sources_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*${_e}") + SET(_sources ${_sources} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_headers_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*${_e}") + SET(_headers ${_headers} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_qt_ui_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*${_e}") + SET(_qt_uis ${_qt_uis} ${_f}) + ENDFOREACH(_e) +ENDFOREACH(_d) + +## -- Configure some files +FILE(GLOB_RECURSE _configs "${_source_dir}/*.in") +FOREACH(_c ${_configs}) + + ## -- Build input and output names + NormPaths(_input_file ${_c}) + GET_FILENAME_COMPONENT(_input_name ${_input_file} NAME) + GET_FILENAME_COMPONENT(_input_dir ${_input_file} DIRECTORY) + STRING(REPLACE ".in" "" _output_name ${_input_name}) + STRING(REPLACE "${_global_source_dir}" "" _output_dir ${_input_dir}) + SET(_output_file "${_global_binary_dir}${_output_dir}/${_output_name}") + + ## -- Configure file + CONFIGURE_FILE(${_input_file} ${_output_file} @ONLY) + + ## -- Add it to the correct list + GET_FILENAME_COMPONENT(_output_ext ${_output_name} EXT) + IF( + "${_output_ext}" STREQUAL ".h" + OR + "${_output_ext}" STREQUAL ".hpp" + OR + "${_output_ext}" STREQUAL ".hxx" + ) + SET(_headers ${_headers}) + ENDIF() + IF( + "${_output_ext}" STREQUAL ".c" + OR + "${_output_ext}" STREQUAL ".cpp" + OR + "${_output_ext}" STREQUAL ".cxx" + ) + SET(_sources ${_sources}) + ENDIF() + IF("${_output_ext}" STREQUAL ".ui") + SET(_qt_uis ${_qt_uis}) + ENDIF() +ENDFOREACH(_c) +IF(ARGN) + LIST(APPEND _sources ${ARGN}) +ENDIF(ARGN) + +## -- Create library +CreateLib( + ${lib_name} ${lib_type} + "${_sources}" "${_headers}" "${_qt_uis}" + "${lib_version}" "${lib_short_version}" + ) + +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION( + CompileInstances + out_lib_name + def_file + number_of_files + prefix + version + short_version + ) +## -- Configure inputs to be cmake-path compatible +NormPaths(_def_file ${def_file}) +GET_FILENAME_COMPONENT(_def_name ${_def_file} NAME_WE) +GET_FILENAME_COMPONENT(_def_dir ${_def_file} DIRECTORY) +NormPaths(_global_source_dir ${PROJECT_SOURCE_DIR}) +NormPaths(_global_binary_dir ${PROJECT_BINARY_DIR}) +STRING(REPLACE "${_global_source_dir}" "" _out_dir ${_def_dir}) +SET(_out_base "${_global_binary_dir}${_out_dir}") +SET(_out_header "${_out_base}/${_def_name}.h") +SET(_lib_name "${prefix}${_def_name}") +SET(_input_extra_code "${_global_source_dir}${_out_dir}/${_def_name}_extra.cxx") + +## -- Infere source code filenames +MATH(EXPR _last_range "${number_of_files}-1") +SET(_out_code) +FOREACH(_n RANGE 0 ${_last_range}) + LIST(APPEND _out_code ${_out_base}/${_def_name}_${_n}.cxx) +ENDFOREACH(_n) + +## -- Add extra code, if any +SET(_all_out_code ${_out_code}) +IF(EXISTS ${_input_extra_code}) + LIST(APPEND _all_out_code ${_input_extra_code}) +ENDIF(EXISTS ${_input_extra_code}) + +## -- Command to write source code +ADD_CUSTOM_COMMAND( + OUTPUT ${_out_header} ${_out_code} + DEPENDS ${cpPlugins_bash_BuildInstances_APP} ${_def_file} + COMMAND ${cpPlugins_bash_BuildInstances_APP} ${_def_file} ${_lib_name} ${_out_base}/${_def_name} ${number_of_files} + ) + +## -- Create library +CreateLib( + "${_lib_name}" SHARED + "${_all_out_code}" "${_out_header}" "" + "${version}" "${short_version}" + ) + +## -- Return value +SET(${out_lib_name} ${_lib_name} PARENT_SCOPE) + +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION(Wrap_cpPlugins output_lib source_dir version short_version prefix) + +## -- Configure inputs to be cmake-path compatible +NormPaths(_source_dir ${source_dir}) +NormPaths(_global_source_dir ${PROJECT_SOURCE_DIR}) +NormPaths(_global_binary_dir ${PROJECT_BINARY_DIR}) +STRING(REPLACE "${_global_source_dir}" "" _out_dir ${_source_dir}) +SET(_out_dir "${_global_binary_dir}${_out_dir}") +FILE(MAKE_DIRECTORY ${_out_dir}) +GET_FILENAME_COMPONENT(_lib_name ${_source_dir} NAME_WE) +SET(_lib_name ${prefix}${_lib_name}) + +## -- Get source code +FILE(GLOB_RECURSE _hdr_h "${_source_dir}/*.h") +FILE(GLOB_RECURSE _hdr_hxx "${_source_dir}/*.hxx") +FILE(GLOB_RECURSE _hdr_hpp "${_source_dir}/*.hpp") +FILE(GLOB_RECURSE _src_c "${_source_dir}/*.c") +FILE(GLOB_RECURSE _src_cxx "${_source_dir}/*.cxx") +FILE(GLOB_RECURSE _src_cpp "${_source_dir}/*.cpp") +FILE(GLOB_RECURSE _qt_ui "${_source_dir}/*.ui") + +## -- Identify sources to wrap +SET(_hdr_to_wrap) +FOREACH(_h ${_hdr_h}) + FILE(READ ${_h} _txt) + STRING(FIND "${_txt}" "cpPluginsObject" _res) + IF(NOT ${_res} EQUAL -1) + LIST(APPEND _hdr_to_wrap ${_h}) + ENDIF(NOT ${_res} EQUAL -1) +ENDFOREACH(_h) + +## -- Integrate all source files +SET(_all_src ${_src_c} ${_src_cpp} ${_src_cxx}) +SET(_all_hdr ${_hdr_h} ${_hdr_hpp} ${_hdr_hxx}) + +## -- Wrap plugins +IF(_hdr_to_wrap) + SET(_host ${_out_dir}/${_lib_name}_host.cxx) + ADD_CUSTOM_COMMAND( + OUTPUT ${_host} + DEPENDS ${cpPlugins_bash_HostCreator_APP} ${_hdr_to_wrap} + COMMAND ${cpPlugins_bash_HostCreator_APP} ${_lib_name} ${_host} ${_hdr_to_wrap} + ) + SET(_all_src ${_all_src} ${_host}) +ENDIF(_hdr_to_wrap) + +## -- Ok, build library +IF(_all_src) + CreateLib( + ${_lib_name} SHARED + "${_all_src}" "${_all_hdr}" "${_qt_ui}" + "${version}" "${short_version}" + ${ARGN} + ) + SET(${output_lib} ${_lib_name} PARENT_SCOPE) +ELSE(_all_src) + MESSAGE(FATAL_ERROR "No source code found to build \"${_lib_name}\"") +ENDIF(_all_src) +ENDFUNCTION() + +## ------------------------------------------------------------------------- +FUNCTION(AppFromDir output_app source_dir) + +## -- Configure inputs to be cmake-path compatible +NormPaths(_global_source_dir ${PROJECT_SOURCE_DIR}) +NormPaths(_global_binary_dir ${PROJECT_BINARY_DIR}) +NormPaths(_source_dir ${source_dir}) +STRING(REPLACE "${_global_source_dir}" "" _local_source_dir ${_source_dir}) +SET(_binary_dir ${_global_binary_dir}${_local_source_dir}) +IF(${output_app}) + SET(_app_name ${${output_app}}) +ELSE(${output_app}) + GET_FILENAME_COMPONENT(_app_name ${_source_dir} NAME_WE) +ENDIF(${output_app}) +SET(_app_name_option OFF) +IF(ARGN) + LIST(GET ARGN 0 _app_name_option) +ENDIF(ARGN) +OPTION( + BUILD_${_app_name} + "Build \"${_app_name}\" application" + ${_app_name_option} + ) + +## -- Real build commands +IF(BUILD_${_app_name}) + ## -- Some useful variables + SET(_sources_extensions .c .cpp .cxx) + SET(_headers_extensions .h .hpp .hxx) + SET(_qt_ui_extensions .ui) + SET(_dirs ${_source_dir} ${_binary_dir}) + SET(_sources) + SET(_headers) + SET(_qt_uis) + + ## -- Glob source code + FOREACH(_d ${_dirs}) + FOREACH(_e ${_sources_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*${_e}") + SET(_sources ${_sources} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_headers_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*${_e}") + SET(_headers ${_headers} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_qt_ui_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*${_e}") + SET(_qt_uis ${_qt_uis} ${_f}) + ENDFOREACH(_e) + ENDFOREACH(_d) + + ## -- Configure some files + FILE(GLOB_RECURSE _configs "${_source_dir}/*.in") + FOREACH(_c ${_configs}) + + ## -- Build input and output names + NormPaths(_input_file ${_c}) + GET_FILENAME_COMPONENT(_input_name ${_input_file} NAME) + GET_FILENAME_COMPONENT(_input_dir ${_input_file} DIRECTORY) + STRING(REPLACE ".in" "" _output_name ${_input_name}) + STRING(REPLACE "${_global_source_dir}" "" _output_dir ${_input_dir}) + SET(_output_file "${_global_binary_dir}${_output_dir}/${_output_name}") + + ## -- Configure file + CONFIGURE_FILE(${_input_file} ${_output_file} @ONLY) + + ## -- Add it to the correct list + GET_FILENAME_COMPONENT(_output_ext ${_output_name} EXT) + IF( + "${_output_ext}" STREQUAL ".h" + OR + "${_output_ext}" STREQUAL ".hpp" + OR + "${_output_ext}" STREQUAL ".hxx" + ) + SET(_headers ${_headers}) + ENDIF() + IF( + "${_output_ext}" STREQUAL ".c" + OR + "${_output_ext}" STREQUAL ".cpp" + OR + "${_output_ext}" STREQUAL ".cxx" + ) + SET(_sources ${_sources}) + ENDIF() + IF("${_output_ext}" STREQUAL ".ui") + SET(_qt_uis ${_qt_uis}) + ENDIF() + ENDFOREACH(_c) + + # -- Prepare Qt4-based code + IF(Qt4_FOUND) + + ## -- Guess what headers sould be qt-moc'ed + Wrap_Qt_CPP(_qt_moc_sources ${_headers}) + IF(_qt_moc_sources) + SET(_sources ${_sources} ${_qt_moc_sources}) + ENDIF(_qt_moc_sources) + ## -- 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_ui_headers ${_qt_uis}) + IF(_qt_ui_headers) + SET(_headers ${_headers} ${_qt_ui_headers}) + SET(_sources ${_sources} ${_qt_ui_headers}) + ENDIF(_qt_ui_headers) + ENDIF(Qt4_FOUND) + + ## -- Ok, compile application + IF(_sources) + SET(_gui_type "") + IF(WIN32) + SET(_gui_type WIN32) + ENDIF(WIN32) + IF(APPLE) + SET(_gui_type MACOSX_BUNDLE) + ENDIF(APPLE) + ADD_EXECUTABLE(${_app_name} ${_gui_type} ${_sources}) + SET(${output_app} ${_app_name} PARENT_SCOPE) + ELSE(_sources) + SET(${output_app} "" PARENT_SCOPE) + MESSAGE(FATAL_ERROR "No source code found to build \"${_app_name}\"") + ENDIF(_sources) +ENDIF(BUILD_${_app_name}) + +ENDFUNCTION() + +## eof - $RCSfile$ diff --git a/cmake/KitwareTools.cmake b/cmake/KitwareTools.cmake new file mode 100644 index 0000000..a120bb2 --- /dev/null +++ b/cmake/KitwareTools.cmake @@ -0,0 +1,19 @@ +# ====================== +# == Find ITK and VTK == +# ====================== + +FIND_PACKAGE(ITK REQUIRED) +INCLUDE(${ITK_USE_FILE}) + +FIND_PACKAGE(VTK REQUIRED) +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..63990d9 --- /dev/null +++ b/cmake/Options.cmake @@ -0,0 +1,13 @@ +## =============================== +## == Some configurable options == +## =============================== + +OPTION(USE_cpPlugins "Build cpPlugins-based code" OFF) +IF(USE_cpPlugins) + FIND_PACKAGE(cpPlugins REQUIRED) + IF(USE_QT4) + INCLUDE(cmake/Qt4Tools.cmake) + ENDIF(USE_QT4) +ENDIF(USE_cpPlugins) + +## eof - $RCSfile$ diff --git a/cmake/Qt4Tools.cmake b/cmake/Qt4Tools.cmake new file mode 100644 index 0000000..16a0103 --- /dev/null +++ b/cmake/Qt4Tools.cmake @@ -0,0 +1,12 @@ +## ================================================== +## == Find Qt4 and check if it was well configured == +## ================================================== + +SET(QT4_FOUND "0") +IF(USE_QT4) + FIND_PACKAGE(Qt4 REQUIRED) + INCLUDE(${QT_USE_FILE}) + SET(QT4_FOUND "1") +ENDIF(USE_QT4) + +## eof - $RCSfile$ diff --git a/cmake/Restrictions.cmake b/cmake/Restrictions.cmake new file mode 100644 index 0000000..d177604 --- /dev/null +++ b/cmake/Restrictions.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/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..f2f2463 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,20 @@ +## ====================================== +## == Build a library from a directory == +## ====================================== + +LibFromDir( + fpa + SHARED + ${CMAKE_CURRENT_SOURCE_DIR}/fpa + "${prj_VERSION}" "${prj_SHORT_VERSION}" + ) + +## =================================== +## == Build instances for cpPlugins == +## =================================== + +IF(USE_cpPlugins) + SUBDIRS(Instances) +ENDIF(USE_cpPlugins) + +## eof - $RCSfile$ diff --git a/lib/Instances/CMakeLists.txt b/lib/Instances/CMakeLists.txt new file mode 100644 index 0000000..be886cb --- /dev/null +++ b/lib/Instances/CMakeLists.txt @@ -0,0 +1,40 @@ +## =========================== +## == Compile each instance == +## =========================== + +FILE(GLOB _instances "${CMAKE_CURRENT_SOURCE_DIR}/*.i") +SET(_all_instances) +FOREACH(_instance ${_instances}) + CompileInstances( + _lib_name + ${_instance} ${cpPlugins_NUMBER_OF_FILES} + "" "${prj_VERSION}" "${prj_SHORT_VERSION}" + ) + LIST(APPEND _all_instances ${_lib_name}) +ENDFOREACH(_instance) +SET( + fpa_Instances ${_all_instances} + CACHE INTERNAL "All valid instances." FORCE + ) + +## =========== +## == Links == +## =========== + +TARGET_LINK_LIBRARIES(fpa_DataObjects ${cpPlugins_Images_LIB}) +TARGET_LINK_LIBRARIES(fpa_Filters fpa_DataObjects ${cpPlugins_ImageFilters_LIB}) + +## =================================== +## == Libraries to dynamically load == +## =================================== + +SET(fpa_DynLibs) +FOREACH(_lib ${fpa_Instances}) + LIST(APPEND fpa_DynLibs local@${_lib}) +ENDFOREACH(_lib) +FILE(WRITE ${PROJECT_BINARY_DIR}/cpPlugins_Libraries.config "") +FOREACH(_lib ${fpa_DynLibs}) + FILE(APPEND ${PROJECT_BINARY_DIR}/cpPlugins_Libraries.config "${_lib}\n") +ENDFOREACH(_lib) + +## eof - $RCSfile$ diff --git a/lib/Instances/fpa_DataObjects.i b/lib/Instances/fpa_DataObjects.i new file mode 100644 index 0000000..aee14d6 --- /dev/null +++ b/lib/Instances/fpa_DataObjects.i @@ -0,0 +1,8 @@ + +t fpa/Image/MinimumSpanningTree +t fpa/Base/MinimumSpanningTree + +c fpa::Base::MinimumSpanningTree< itk::Index< #process_dims# >, itk::Image< itk::Offset< #process_dims# >, #process_dims# > > +c fpa::Image::MinimumSpanningTree< #process_dims# > + +** eof - $RCSfile$ \ No newline at end of file diff --git a/lib/Instances/fpa_Filters.i b/lib/Instances/fpa_Filters.i new file mode 100644 index 0000000..70dc94d --- /dev/null +++ b/lib/Instances/fpa_Filters.i @@ -0,0 +1,12 @@ + +d i_pixels=#pixels# +d o_pixels=#pixels# + +i cpPlugins_Images.h +t fpa/Base/Algorithm +t fpa/Image/Algorithm + +c fpa::Base::Algorithm< itk::ImageToImageFilter< itk::Image< #i_pixels#, #process_dims# >, itk::Image< #o_pixels#, #process_dims# > >, itk::Index< #process_dims# >, #o_pixels# > +c fpa::Image::Algorithm< itk::Image< #i_pixels#, #process_dims# >, itk::Image< #o_pixels#, #process_dims# > > + +** eof - $RCSfile$ \ No newline at end of file diff --git a/lib/fpa/Base/Algorithm.h b/lib/fpa/Base/Algorithm.h new file mode 100644 index 0000000..662bdf1 --- /dev/null +++ b/lib/fpa/Base/Algorithm.h @@ -0,0 +1,128 @@ +#ifndef __fpa__Base__Algorithm__h__ +#define __fpa__Base__Algorithm__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TFilter, class _TVertex, class _TOutput > + class Algorithm + : public _TFilter + { + public: + typedef Algorithm Self; + typedef _TFilter Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef _TOutput TOutput; + typedef unsigned long TFrontId; + + // Different functions + typedef std::vector< TVertex > TNeighborhood; + typedef itk::FunctionBase< TVertex, TNeighborhood > TNeighborhoodFunction; + + // Minigraph to represent collisions + typedef std::pair< _TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + + protected: + struct _TQueueNode + { + TVertex Vertex; + TVertex Parent; + TOutput Result; + TFrontId FrontId; + _TQueueNode( ); + _TQueueNode( const TVertex& v ); + _TQueueNode( const TVertex& v, const _TQueueNode& n ); + }; + + public: + itkTypeMacro( Self, _TFilter ); + + fpa_Base_NewEvent( TStartEvent ); + fpa_Base_NewEvent( TEndEvent ); + fpa_Base_NewEvent( TStartLoopEvent ); + fpa_Base_NewEvent( TEndLoopEvent ); + fpa_Base_NewEventWithVertex( TPushEvent, TVertex ); + fpa_Base_NewEventWithVertex( TPopEvent, TVertex ); + fpa_Base_NewEventWithVertex( TMarkEvent, TVertex ); + + itkGetConstMacro( InitResult, _TOutput ); + itkSetMacro( InitResult, _TOutput ); + + itkBooleanMacro( StopAtOneFront ); + itkGetConstMacro( StopAtOneFront, bool ); + itkSetMacro( StopAtOneFront, bool ); + + itkGetObjectMacro( NeighborhoodFunction, TNeighborhoodFunction ); + itkSetObjectMacro( NeighborhoodFunction, TNeighborhoodFunction ); + + public: + void AddSeed( const TVertex& seed, const TOutput& value ); + + protected: + Algorithm( ); + virtual ~Algorithm( ); + + virtual void GenerateData( ) fpa_OVERRIDE; + + // Particular methods + virtual void _Loop( ); + + virtual void _BeforeGenerateData( ); + virtual void _AfterGenerateData( ); + virtual void _BeforeLoop( ); + virtual void _AfterLoop( ); + + virtual bool _ValidLoop( ) const; + virtual void _UpdateCollisions( const TVertex& a, const TVertex& b ); + + virtual void _InitMarks( ) = 0; + virtual void _InitResults( const TOutput& init_value ) = 0; + virtual bool _IsMarked( const _TVertex& v ) const = 0; + virtual void _Mark( const _TQueueNode& n ) = 0; + virtual TFrontId _GetMark( const _TVertex& v ) const = 0; + virtual void _UpdateResult( const _TQueueNode& n ) = 0; + + virtual bool _UpdateValue( _TQueueNode& v, const _TQueueNode& p ) = 0; + virtual unsigned long _QueueSize( ) const = 0; + virtual void _QueueClear( ) = 0; + virtual void _QueuePush( const _TQueueNode& node ) = 0; + virtual _TQueueNode _QueuePop( ) = 0; + + private: + // Purposely not implemented. + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + _TOutput m_InitResult; + bool m_StopAtOneFront; + typename TNeighborhoodFunction::Pointer m_NeighborhoodFunction; + std::vector< _TQueueNode > m_Seeds; + TCollisions m_Collisions; + unsigned int m_NumberOfFronts; + }; + + } // ecaseman + +} // ecaseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__Algorithm__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Algorithm.hxx b/lib/fpa/Base/Algorithm.hxx new file mode 100644 index 0000000..4ad828c --- /dev/null +++ b/lib/fpa/Base/Algorithm.hxx @@ -0,0 +1,237 @@ +#ifndef __fpa__Base__Algorithm__hxx__ +#define __fpa__Base__Algorithm__hxx__ + +#include + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode:: +_TQueueNode( ) +{ + this->Vertex.Fill( 0 ); + this->Parent.Fill( 0 ); + this->Result = _TOutput( 0 ); + this->FrontId = 0; +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode:: +_TQueueNode( const _TVertex& v ) +{ + this->Vertex = v; + this->Parent = v; + this->Result = _TOutput( 0 ); + this->FrontId = 0; +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >::_TQueueNode:: +_TQueueNode( const _TVertex& v, const _TQueueNode& n ) +{ + this->Vertex = v; + this->Parent = n.Vertex; + this->Result = n.Result; + this->FrontId = n.FrontId; +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +AddSeed( const _TVertex& seed, const TOutput& value ) +{ + _TQueueNode node( seed ); + node.FrontId = this->m_Seeds.size( ) + 1; + node.Result = value; + this->m_Seeds.push_back( node ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +Algorithm( ) + : Superclass( ), + m_InitResult( _TOutput( 0 ) ), + m_StopAtOneFront( false ) +{ +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +~Algorithm( ) +{ +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +GenerateData( ) +{ + this->InvokeEvent( TStartEvent( ) ); + this->_BeforeGenerateData( ); + this->m_NumberOfFronts = this->m_Seeds.size( ); + if( this->m_NumberOfFronts > 0 ) + { + // Prepare collisions + TCollision coll( TVertex( ), false ); + TCollisionsRow row( this->m_NumberOfFronts, coll ); + this->m_Collisions.clear( ); + this->m_Collisions.resize( this->m_NumberOfFronts, row ); + + // Put seeds on queue + this->_QueueClear( ); + for( + auto nIt = this->m_Seeds.begin( ); + nIt != this->m_Seeds.end( ); + ++nIt + ) + this->_QueuePush( *nIt ); + + // Init marks and results + this->_InitMarks( ); + this->_InitResults( this->m_InitResult ); + + // Main loop + this->_Loop( ); + + } // fi + this->_AfterGenerateData( ); + this->InvokeEvent( TEndEvent( ) ); +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_Loop( ) +{ + this->InvokeEvent( TStartLoopEvent( ) ); + this->_BeforeLoop( ); + while( this->_ValidLoop( ) ) + { + _TQueueNode node = this->_QueuePop( ); + this->InvokeEvent( TPopEvent( node.Vertex, node.FrontId ) ); + + // Process actual vertex + if( this->_IsMarked( node.Vertex ) ) + continue; + this->_Mark( node ); + this->_UpdateResult( node ); + this->InvokeEvent( TMarkEvent( node.Vertex, node.FrontId ) ); + + // Add neighbors to queue + TNeighborhood neighs = this->m_NeighborhoodFunction->Evaluate( node.Vertex ); + for( auto it = neighs.begin( ); it != neighs.end( ); ++it ) + { + if( !( this->_IsMarked( *it ) ) ) + { + _TQueueNode neigh( *it, node ); + if( this->_UpdateValue( neigh, node ) ) + { + this->_QueuePush( neigh ); + this->InvokeEvent( TPushEvent( node.Vertex, node.FrontId ) ); + + } // fi + } + else + this->_UpdateCollisions( node.Vertex, *it ); + + } // rof + + } // elihw + this->_AfterLoop( ); + this->InvokeEvent( TEndLoopEvent( ) ); +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_BeforeGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_AfterGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_BeforeLoop( ) +{ +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_AfterLoop( ) +{ +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +bool fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_ValidLoop( ) const +{ + bool r = ( this->_QueueSize( ) > 0 ); + if( this->m_StopAtOneFront ) + r &= ( this->m_NumberOfFronts > 0 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +void fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_UpdateCollisions( const TVertex& a, const TVertex& b ) +{ + auto ma = this->_GetMark( a ); + auto mb = this->_GetMark( b ); + if( ma == mb || ma == 0 || mb == 0 ) + return; + + // Mark collision, if it is new + ma--; mb--; + bool ret = false; + bool exists = this->m_Collisions[ ma ][ mb ].second; + exists &= this->m_Collisions[ mb ][ ma ].second; + if( !exists ) + { + this->m_Collisions[ ma ][ mb ].first = a; + this->m_Collisions[ ma ][ mb ].second = true; + this->m_Collisions[ mb ][ ma ].first = b; + this->m_Collisions[ mb ][ ma ].second = true; + + // Update number of fronts + unsigned long N = this->m_Seeds.size( ); + unsigned long count = 0; + std::vector< bool > m( N, false ); + std::queue< unsigned long > q; + q.push( 0 ); + while( !q.empty( ) ) + { + unsigned long f = q.front( ); + q.pop( ); + + if( m[ f ] ) + continue; + m[ f ] = true; + count++; + + for( unsigned int n = 0; n < N; ++n ) + if( this->m_Collisions[ f ][ n ].second && !m[ n ] ) + q.push( n ); + + } // elihw + this->m_NumberOfFronts = N - count; + + } // fi +} + +#endif // __fpa__Base__Algorithm__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Dijkstra.h b/lib/fpa/Base/Dijkstra.h new file mode 100644 index 0000000..5633f22 --- /dev/null +++ b/lib/fpa/Base/Dijkstra.h @@ -0,0 +1,93 @@ +#ifndef __fpa__Base__Dijkstra__h__ +#define __fpa__Base__Dijkstra__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TSuperclass, class _TMST > + class Dijkstra + : public _TSuperclass + { + public: + typedef Dijkstra Self; + typedef _TSuperclass Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TMST TMST; + typedef typename Superclass::TOutput TOutput; + typedef typename Superclass::TVertex TVertex; + + typedef itk::FunctionBase< TOutput, TOutput > TCostConversionFunction; + typedef DijkstraCostFunctionBase< TVertex, TOutput > TCostFunction; + + protected: + typedef typename Superclass::_TQueueNode _TQueueNode; + struct _TQueueNodeCompare + { + bool operator( )( const _TQueueNode& a, const _TQueueNode& b ) + { + return( b.Result < a.Result ); + } + }; + typedef std::vector< _TQueueNode > _TQueue; + + public: + itkTypeMacro( Dijkstra, Algorithm ); + + itkGetObjectMacro( CostFunction, TCostFunction ); + itkGetObjectMacro( CostConversionFunction, TCostConversionFunction ); + itkSetObjectMacro( CostFunction, TCostFunction ); + itkSetObjectMacro( CostConversionFunction, TCostConversionFunction ); + + public: + _TMST* GetMinimumSpanningTree( ); + const _TMST* GetMinimumSpanningTree( ) const; + + protected: + Dijkstra( ); + virtual ~Dijkstra( ); + + virtual void _AfterGenerateData( ) fpa_OVERRIDE; + + virtual void _UpdateResult( const _TQueueNode& n ) fpa_OVERRIDE; + virtual bool _UpdateValue( + _TQueueNode& v, const _TQueueNode& p + ) fpa_OVERRIDE; + virtual unsigned long _QueueSize( ) const fpa_OVERRIDE; + virtual void _QueueClear( ) fpa_OVERRIDE; + virtual void _QueuePush( const _TQueueNode& node ) fpa_OVERRIDE; + virtual _TQueueNode _QueuePop( ) fpa_OVERRIDE; + + private: + // Purposely not defined + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + _TQueue m_Queue; + typename TCostFunction::Pointer m_CostFunction; + typename TCostConversionFunction::Pointer m_CostConversionFunction; + + unsigned long m_MSTIndex; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__Dijkstra__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Dijkstra.hxx b/lib/fpa/Base/Dijkstra.hxx new file mode 100644 index 0000000..849ff6c --- /dev/null +++ b/lib/fpa/Base/Dijkstra.hxx @@ -0,0 +1,135 @@ +#ifndef __fpa__Base__Dijkstra__hxx__ +#define __fpa__Base__Dijkstra__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +_TMST* fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +GetMinimumSpanningTree( ) +{ + return( + dynamic_cast< _TMST* >( + this->itk::ProcessObject::GetOutput( this->m_MSTIndex ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +const _TMST* fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +GetMinimumSpanningTree( ) const +{ + return( + dynamic_cast< const _TMST* >( + this->itk::ProcessObject::GetOutput( this->m_MSTIndex ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +Dijkstra( ) + : Superclass( ) +{ + this->m_InitResult = TOutput( 0 ); + this->m_MSTIndex = this->GetNumberOfRequiredOutputs( ); + this->SetNumberOfRequiredOutputs( this->m_MSTIndex + 1 ); + this->itk::ProcessObject::SetNthOutput( this->m_MSTIndex, _TMST::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +void fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_AfterGenerateData( ) +{ + this->Superclass::_AfterGenerateData( ); + + auto mst = this->GetMinimumSpanningTree( ); + mst->ClearSeeds( ); + for( auto s = this->m_Seeds.begin( ); s != this->m_Seeds.end( ); ++s ) + mst->AddSeed( s->Vertex ); + mst->SetCollisions( this->m_Collisions ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +void fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_UpdateResult( const _TQueueNode& n ) +{ + this->Superclass::_UpdateResult( n ); + this->GetMinimumSpanningTree( )->SetParent( n.Vertex, n.Parent ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +bool fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_UpdateValue( _TQueueNode& v, const _TQueueNode& p ) +{ + v.Result = this->m_CostFunction->Evaluate( p.Vertex, v.Vertex ); + if( this->m_CostConversionFunction.IsNotNull( ) ) + v.Result = this->m_CostConversionFunction->Evaluate( v.Result ); + if( v.Result >= TOutput( 0 ) ) + { + v.Result += p.Result; + return( true ); + } + else + { + v.Result = this->m_InitResult; + return( false ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +unsigned long fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_QueueSize( ) const +{ + return( this->m_Queue.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +void fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_QueueClear( ) +{ + this->m_Queue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +void fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_QueuePush( const _TQueueNode& node ) +{ + static _TQueueNodeCompare cmp; + this->m_Queue.push_back( node ); + std::push_heap( this->m_Queue.begin( ), this->m_Queue.end( ), cmp ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass, class _TMST > +typename fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_TQueueNode fpa::Base::Dijkstra< _TSuperclass, _TMST >:: +_QueuePop( ) +{ + static _TQueueNodeCompare cmp; + std::pop_heap( this->m_Queue.begin( ), this->m_Queue.end( ), cmp ); + _TQueueNode f = this->m_Queue.back( ); + this->m_Queue.pop_back( ); + return( f ); +} + +#endif // __fpa__Base__Dijkstra__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/DijkstraCostFunctionBase.h b/lib/fpa/Base/DijkstraCostFunctionBase.h new file mode 100644 index 0000000..d3a86b2 --- /dev/null +++ b/lib/fpa/Base/DijkstraCostFunctionBase.h @@ -0,0 +1,51 @@ +#ifndef __fpa__Base__DijkstraCostFunctionBase__h__ +#define __fpa__Base__DijkstraCostFunctionBase__h__ + +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TVertex, class _TOutput > + class DijkstraCostFunctionBase + : public itk::Object + { + public: + typedef DijkstraCostFunctionBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef _TOutput TOutput; + + public: + itkTypeMacro( DijkstraCostFunctionBase, itk::Object ); + + public: + virtual TOutput Evaluate( const TVertex& a, const TVertex& b ) const = 0; + + protected: + DijkstraCostFunctionBase( ) + : Superclass( ) + { } + virtual ~DijkstraCostFunctionBase( ) + { } + + private: + // Purposely not defined + DijkstraCostFunctionBase( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Base__DijkstraCostFunctionBase__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Events.h b/lib/fpa/Base/Events.h new file mode 100644 index 0000000..17c5564 --- /dev/null +++ b/lib/fpa/Base/Events.h @@ -0,0 +1,100 @@ +#ifndef __fpa__Base__Events__h__ +#define __fpa__Base__Events__h__ + +// ------------------------------------------------------------------------- +#define fpa_Base_NewEvent( name ) \ + class name \ + : public BaseEvent \ + { \ + public: \ + name( ) : BaseEvent( ) { } \ + virtual ~name( ) { } \ + const char* GetEventName( ) const \ + { return( "fpa::Base::##name" ); } \ + bool CheckEvent( const itk::EventObject* e ) const \ + { return( dynamic_cast< const name* >( e ) != NULL ); } \ + itk::EventObject* MakeObject( ) const \ + { return( new name( ) ); } \ + }; + +// ------------------------------------------------------------------------- +#define fpa_Base_NewEventWithVertex( name, type ) \ + class name \ + : public BaseEventWithVertex< type > \ + { \ + public: \ + name( ) : BaseEventWithVertex< type >( ) { } \ + name( const type& v, long fid ) \ + : BaseEventWithVertex< type >( v, fid ) { } \ + virtual ~name( ) { } \ + const char* GetEventName( ) const \ + { return( "fpa::Base::##name" ); } \ + bool CheckEvent( const itk::EventObject* e ) const \ + { return( dynamic_cast< const name* >( e ) != NULL ); } \ + itk::EventObject* MakeObject( ) const \ + { return( new name( ) ); } \ + }; + +namespace fpa +{ + namespace Base + { + /** + */ + class BaseEvent + : public itk::AnyEvent + { + public: + BaseEvent( ) + : itk::AnyEvent( ) + { } + virtual ~BaseEvent( ) + { } + const char* GetEventName( ) const + { return( "fpa::Base::BaseEvent" ); } + bool CheckEvent( const itk::EventObject* e ) const + { return( dynamic_cast< const BaseEvent* >( e ) != NULL ); } + itk::EventObject* MakeObject( ) const + { return( new BaseEvent( ) ); } + }; + + /** + */ + template< class _TVertex > + class BaseEventWithVertex + : public BaseEvent + { + public: + BaseEventWithVertex( ) + : BaseEvent( ) + { } + BaseEventWithVertex( const _TVertex& v, long fid ) + : BaseEvent( ), + Vertex( v ), + FrontId( fid ) + { } + virtual ~BaseEventWithVertex( ) + { } + const char* GetEventName( ) const + { return( "fpa::Base::BaseEventWithVertex" ); } + bool CheckEvent( const itk::EventObject* e ) const + { + return( + dynamic_cast< const BaseEventWithVertex< _TVertex >* >( e ) != NULL + ); + } + itk::EventObject* MakeObject( ) const + { return( new BaseEventWithVertex< _TVertex >( ) ); } + + public: + _TVertex Vertex; + long FrontId; + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Base__Events__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/GaussianModel.h b/lib/fpa/Base/Functors/GaussianModel.h new file mode 100644 index 0000000..f147b26 --- /dev/null +++ b/lib/fpa/Base/Functors/GaussianModel.h @@ -0,0 +1,75 @@ +#ifndef __fpa__Base__Functors__GaussianModel__h__ +#define __fpa__Base__Functors__GaussianModel__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + /** + */ + template< class _TInput, class _TOutput > + class GaussianModel + : public itk::FunctionBase< _TInput, _TOutput > + { + public: + typedef GaussianModel Self; + typedef itk::FunctionBase< _TInput, _TOutput > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInput TInput; + typedef _TOutput TOutput; + + // Model estimator + typedef + cpExtensions::Algorithms::IterativeGaussianModelEstimator< TOutput, 1 > + TModel; + + public: + itkNewMacro( Self ); + itkTypeMacro( GaussianModel, itk::FunctionBase ); + + itkGetConstMacro( SupportSize, unsigned int ); + itkGetConstMacro( MinimumCost, TOutput ); + itkGetObjectMacro( Model, TModel ); + itkGetConstObjectMacro( Model, TModel ); + itkSetMacro( SupportSize, unsigned int ); + itkSetMacro( MinimumCost, TOutput ); + + public: + virtual TOutput Evaluate( const TInput& x ) const fpa_OVERRIDE; + + protected: + GaussianModel( ); + virtual ~GaussianModel( ); + + private: + // Purposely not implemented + GaussianModel( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_SupportSize; + TOutput m_MinimumCost; + typename TModel::Pointer m_Model; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__Functors__GaussianModel__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/GaussianModel.hxx b/lib/fpa/Base/Functors/GaussianModel.hxx new file mode 100644 index 0000000..49db8b0 --- /dev/null +++ b/lib/fpa/Base/Functors/GaussianModel.hxx @@ -0,0 +1,50 @@ +#ifndef __fpa__Base__Functors__GaussianModel__hxx__ +#define __fpa__Base__Functors__GaussianModel__hxx__ + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput > +typename fpa::Base::Functors::GaussianModel< _TInput, _TOutput >:: +TOutput fpa::Base::Functors::GaussianModel< _TInput, _TOutput >:: +Evaluate( const TInput& x ) const +{ + TOutput r = TOutput( 0 ); + if( this->m_Model->GetNumberOfSamples( ) > this->m_SupportSize ) + { + r = this->m_Model->SquaredMahalanobis( TOutput( x ) ); + if( r <= TOutput( 1 ) ) + this->m_Model->AddSample( TOutput( x ) ); + } + else + { + this->m_Model->AddSample( TOutput( x ) ); + if( this->m_Model->GetNumberOfSamples( ) > 2 ) + r = this->m_Model->SquaredMahalanobis( TOutput( x ) ); + + } // fi + if( r < this->m_MinimumCost ) + return( this->m_MinimumCost ); + else + return( r ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput > +fpa::Base::Functors::GaussianModel< _TInput, _TOutput >:: +GaussianModel( ) + : Superclass( ), + m_SupportSize( 30 ), + m_MinimumCost( TOutput( 1e-10 ) ) +{ + this->m_Model = TModel::New( ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput > +fpa::Base::Functors::GaussianModel< _TInput, _TOutput >:: +~GaussianModel( ) +{ +} + +#endif // __fpa__Base__Functors__GaussianModel__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/Inverse.h b/lib/fpa/Base/Functors/Inverse.h new file mode 100644 index 0000000..0bd1a04 --- /dev/null +++ b/lib/fpa/Base/Functors/Inverse.h @@ -0,0 +1,57 @@ +#ifndef __fpa__Base__Functors__Inverse__h__ +#define __fpa__Base__Functors__Inverse__h__ + +#include +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + /** + */ + template< class _TInput, class _TOutput > + class Inverse + : public itk::FunctionBase< _TInput, _TOutput > + { + public: + typedef Inverse Self; + typedef itk::FunctionBase< _TInput, _TOutput > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInput TInput; + typedef _TOutput TOutput; + + public: + itkNewMacro( Self ); + itkTypeMacro( Inverse, itk::FunctionBase ); + + public: + virtual TOutput Evaluate( const TInput& x ) const fpa_OVERRIDE; + + protected: + Inverse( ); + virtual ~Inverse( ); + + private: + // Purposely not implemented + Inverse( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__Functors__Inverse__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/Inverse.hxx b/lib/fpa/Base/Functors/Inverse.hxx new file mode 100644 index 0000000..e2ad9f0 --- /dev/null +++ b/lib/fpa/Base/Functors/Inverse.hxx @@ -0,0 +1,32 @@ +#ifndef __fpa__Base__Functors__Inverse__hxx__ +#define __fpa__Base__Functors__Inverse__hxx__ + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput > +typename fpa::Base::Functors::Inverse< _TInput, _TOutput >:: +TOutput fpa::Base::Functors::Inverse< _TInput, _TOutput >:: +Evaluate( const TInput& x ) const +{ + TInput sign = TInput( ( x < TInput( 0 ) )? -1: 1 ); + TOutput y = TOutput( 1 ) / ( TOutput( 1 ) + TOutput( x * sign ) ); + return( y * TOutput( sign ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput > +fpa::Base::Functors::Inverse< _TInput, _TOutput >:: +Inverse( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TOutput > +fpa::Base::Functors::Inverse< _TInput, _TOutput >:: +~Inverse( ) +{ +} + +#endif // __fpa__Base__Functors__Inverse__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MinimumSpanningTree.h b/lib/fpa/Base/MinimumSpanningTree.h new file mode 100644 index 0000000..de22019 --- /dev/null +++ b/lib/fpa/Base/MinimumSpanningTree.h @@ -0,0 +1,77 @@ +#ifndef __fpa__Base__MinimumSpanningTree__h__ +#define __fpa__Base__MinimumSpanningTree__h__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TVertex, class _TSuperclass > + class MinimumSpanningTree + : public _TSuperclass + { + public: + typedef MinimumSpanningTree Self; + typedef _TSuperclass Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef std::deque< _TVertex > TVertices; + typedef std::pair< _TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + + protected: + typedef std::vector< unsigned long > _TRow; + typedef std::vector< _TRow > _TMatrix; + + public: + itkTypeMacro( MinimumSpanningTree, _TSuperclass ); + + public: + const TCollisions& GetCollisions( ) const; + void SetCollisions( const TCollisions& collisions ); + + void ClearSeeds( ); + void AddSeed( const _TVertex& seed ); + + virtual _TVertex GetParent( const _TVertex& v ) const = 0; + virtual void SetParent( const _TVertex& v, const _TVertex& p ) = 0; + + virtual TVertices GetPath( const _TVertex& a ) const; + virtual TVertices GetPath( const _TVertex& a, const _TVertex& b ) const; + + protected: + MinimumSpanningTree( ); + virtual ~MinimumSpanningTree( ); + + private: + // Purposely not defined + MinimumSpanningTree( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TCollisions m_Collisions; + _TMatrix m_FrontPaths; + TVertices m_Seeds; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__MinimumSpanningTree__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MinimumSpanningTree.hxx b/lib/fpa/Base/MinimumSpanningTree.hxx new file mode 100644 index 0000000..8746005 --- /dev/null +++ b/lib/fpa/Base/MinimumSpanningTree.hxx @@ -0,0 +1,232 @@ +#ifndef __fpa__Base__MinimumSpanningTree__hxx__ +#define __fpa__Base__MinimumSpanningTree__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +const typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +TCollisions& fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +GetCollisions( ) const +{ + return( this->m_Collisions ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +SetCollisions( const TCollisions& collisions ) +{ + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + if( this->m_Collisions == collisions ) + return; + + this->m_Collisions = collisions; + + // Prepare a front graph + unsigned long N = this->m_Collisions.size( ); + _TMatrix dist( N, _TRow( N, _inf ) ); + this->m_FrontPaths = dist; + for( unsigned long i = 0; i < N; ++i ) + { + for( unsigned long j = 0; j < N; ++j ) + { + if( this->m_Collisions[ i ][ j ].second ) + { + dist[ i ][ j ] = 1; + dist[ j ][ i ] = 1; + this->m_FrontPaths[ i ][ j ] = j; + this->m_FrontPaths[ j ][ i ] = i; + + } // fi + + } // rof + dist[ i ][ i ] = 0; + this->m_FrontPaths[ i ][ i ] = i; + + } // rof + + // Use Floyd-Warshall to compute all possible paths between fronts + for( unsigned long k = 0; k < N; ++k ) + { + for( unsigned long i = 0; i < N; ++i ) + { + for( unsigned long j = 0; j < N; ++j ) + { + // WARNING: you don't want a numeric overflow!!! + unsigned long dik = dist[ i ][ k ]; + unsigned long dkj = dist[ k ][ j ]; + unsigned long sum = _inf; + if( dik < _inf && dkj < _inf ) + sum = dik + dkj; + + // Ok, continue Floyd-Warshall + if( sum < dist[ i ][ j ] ) + { + dist[ i ][ j ] = sum; + this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ]; + + } // fi + + } // rof + + } // rof + + } // rof + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +ClearSeeds( ) +{ + this->m_Seeds.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +AddSeed( const _TVertex& seed ) +{ + this->m_Seeds.push_back( seed ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +TVertices fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +GetPath( const _TVertex& a ) const +{ + TVertices path; + _TVertex it = a; + _TVertex p = this->GetParent( it ); + while( it != p ) + { + path.push_front( it ); + it = p; + p = this->GetParent( it ); + + } // elihw + path.push_front( it ); + return( path ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +TVertices fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +GetPath( const _TVertex& a, const _TVertex& b ) const +{ + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + + TVertices path; + TVertices pa = this->GetPath( a ); + TVertices pb = this->GetPath( b ); + if( pa.size( ) > 0 && pb.size( ) > 0 ) + { + // Find front identifiers + unsigned long ia = _inf, ib = _inf; + unsigned long N = this->m_Seeds.size( ); + for( unsigned long i = 0; i < N; ++i ) + { + if( this->m_Seeds[ i ] == pa.front( ) ) + ia = i; + if( this->m_Seeds[ i ] == pb.front( ) ) + ib = i; + + } // rof + + if( ia != ib ) + { + // Use this->m_FrontPaths from Floyd-Warshall + if( this->m_FrontPaths[ ia ][ ib ] < _inf ) + { + // Compute front path + std::vector< long > fpath; + fpath.push_back( ia ); + while( ia != ib ) + { + ia = this->m_FrontPaths[ ia ][ ib ]; + fpath.push_back( ia ); + + } // elihw + + // Continue only if both fronts are connected + unsigned int N = fpath.size( ); + if( N > 0 ) + { + // First path: from start vertex to first collision + path = this->GetPath( + a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first + ); + + // Intermediary paths + for( unsigned int i = 1; i < N - 1; ++i ) + { + TVertices ipath = + this->GetPath( + this->m_Collisions[ fpath[ i ] ][ fpath[ i - 1 ] ].first, + this->m_Collisions[ fpath[ i ] ][ fpath[ i + 1 ] ].first + ); + path.insert( path.end( ), ipath.begin( ), ipath.end( ) ); + + } // rof + + // Final path: from last collision to end point + TVertices lpath = + this->GetPath( + this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b + ); + path.insert( path.end( ), lpath.begin( ), lpath.end( ) ); + + } // fi + + } // fi + } + else + { + // Ignore common part: find common ancestor + auto aIt = pa.begin( ); + auto bIt = pb.begin( ); + while( *aIt == *bIt && aIt != pa.end( ) && bIt != pb.end( ) ) + { + ++aIt; + ++bIt; + + } // elihw + + // Glue both parts + for( --aIt; aIt != pa.end( ); ++aIt ) + path.push_front( *aIt ); + for( ; bIt != pb.end( ); ++bIt ) + path.push_back( *bIt ); + + } // fi + + } // fi + return( path ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +MinimumSpanningTree( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TSuperclass > +fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >:: +~MinimumSpanningTree( ) +{ +} + +#endif // __fpa__Base__MinimumSpanningTree__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Config.cxx b/lib/fpa/Config.cxx new file mode 100644 index 0000000..d881ac9 --- /dev/null +++ b/lib/fpa/Config.cxx @@ -0,0 +1 @@ +// eof - $RCSfile$ diff --git a/lib/fpa/Config.h.in b/lib/fpa/Config.h.in new file mode 100644 index 0000000..1050a24 --- /dev/null +++ b/lib/fpa/Config.h.in @@ -0,0 +1,39 @@ +#ifndef __fpa__Config__h__ +#define __fpa__Config__h__ + +#include + +/* + * ========================================================================= + * Version numbers and strings + * ========================================================================= + */ +#define fpa_MAJOR_VERSION @prj_MAJ_VER@ +#define fpa_MINOR_VERSION @prj_MIN_VER@ +#define fpa_RELEASE_VERSION @prj_REL_VER@ +#define fpa_VERSION "@prj_VERSION@" +#define fpa_SHORT_VERSION "@prj_SHORT_VERSION@" + +/* + * ========================================================================= + * Language related macros + * ========================================================================= + */ + +#if __cplusplus >= 201103L +# define fpa_OVERRIDE override +# define fpa_DELETE_FUNCTION =delete +# define fpa_NULLPTR nullptr +# define fpa_NOEXCEPT noexcept +# define fpa_HAS_CXX11_STATIC_ASSERT +# define fpa_HAS_CXX11_RVREF +#else +# define fpa_OVERRIDE +# define fpa_DELETE_FUNCTION +# define fpa_NULLPTR NULL +# define fpa_NOEXCEPT throw() +#endif + +#endif // __fpa__Config__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Algorithm.h b/lib/fpa/Image/Algorithm.h new file mode 100644 index 0000000..70a87a6 --- /dev/null +++ b/lib/fpa/Image/Algorithm.h @@ -0,0 +1,70 @@ +#ifndef __fpa__Image__Algorithm__h__ +#define __fpa__Image__Algorithm__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage > + class Algorithm + : public fpa::Base::Algorithm< itk::ImageToImageFilter< _TInputImage, _TOutputImage >, typename _TInputImage::IndexType, typename _TOutputImage::PixelType > + { + public: + typedef itk::ImageToImageFilter< _TInputImage, _TOutputImage > TFilter; + typedef typename _TInputImage::IndexType TVertex; + typedef typename _TOutputImage::PixelType TOutput; + + typedef Algorithm Self; + typedef fpa::Base::Algorithm< TFilter, TVertex, TOutput > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TFrontId TFrontId; + typedef typename Superclass::TNeighborhood TNeighborhood; + typedef fpa::Image::Functors::Base< itk::ImageBase< _TInputImage::ImageDimension >, itk::FunctionBase< TVertex, TNeighborhood > > TNeighborhoodFunction; + + protected: + typedef typename Superclass::_TQueueNode _TQueueNode; + + public: + itkTypeMacro( fpa::Image::Algorithm, fpa::Base::Algorithm ); + + protected: + Algorithm( ); + virtual ~Algorithm( ); + + virtual void _BeforeGenerateData( ) fpa_OVERRIDE; + virtual void _InitMarks( ) fpa_OVERRIDE; + virtual void _InitResults( const TOutput& init_value ) fpa_OVERRIDE; + virtual bool _IsMarked( const TVertex& v ) const fpa_OVERRIDE; + virtual void _Mark( const _TQueueNode& n ) fpa_OVERRIDE; + virtual TFrontId _GetMark( const TVertex& v ) const fpa_OVERRIDE; + virtual void _UpdateResult( const _TQueueNode& n ) fpa_OVERRIDE; + + private: + // Purposely not defined + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_MarksIdx; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__Algorithm__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Algorithm.hxx b/lib/fpa/Image/Algorithm.hxx new file mode 100644 index 0000000..9eb2640 --- /dev/null +++ b/lib/fpa/Image/Algorithm.hxx @@ -0,0 +1,114 @@ +#ifndef __fpa__Image__Algorithm__hxx__ +#define __fpa__Image__Algorithm__hxx__ + +// Send Piotr's code to Anna + +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +Algorithm( ) + : Superclass( ) +{ + typedef itk::Image< TFrontId, _TInputImage::ImageDimension > _TMarks; + this->m_MarksIdx = this->GetNumberOfRequiredOutputs( ); + this->itk::ProcessObject::SetNumberOfRequiredOutputs( this->m_MarksIdx + 1 ); + typename _TMarks::Pointer marks = _TMarks::New( ); + this->SetNthOutput( this->m_MarksIdx, marks ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +~Algorithm( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_BeforeGenerateData( ) +{ + this->Superclass::_BeforeGenerateData( ); + this->AllocateOutputs( ); + + TNeighborhoodFunction* neighFunc = + dynamic_cast< TNeighborhoodFunction* >( this->GetNeighborhoodFunction( ) ); + if( neighFunc == NULL ) + itkExceptionMacro( << "NeighborhoodFunction not well defined." ); + neighFunc->SetImage( this->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_InitMarks( ) +{ + typedef itk::Image< TFrontId, _TInputImage::ImageDimension > _TMarks; + _TMarks* marks = + dynamic_cast< _TMarks* >( + this->itk::ProcessObject::GetOutput( this->m_MarksIdx ) + ); + marks->FillBuffer( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_InitResults( const TOutput& init_value ) +{ + this->GetOutput( )->FillBuffer( init_value ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +bool fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_IsMarked( const TVertex& v ) const +{ + typedef itk::Image< TFrontId, _TInputImage::ImageDimension > _TMarks; + const _TMarks* marks = + dynamic_cast< const _TMarks* >( + this->itk::ProcessObject::GetOutput( this->m_MarksIdx ) + ); + return( marks->GetPixel( v ) != 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_Mark( const _TQueueNode& n ) +{ + typedef itk::Image< TFrontId, _TInputImage::ImageDimension > _TMarks; + _TMarks* marks = + dynamic_cast< _TMarks* >( + this->itk::ProcessObject::GetOutput( this->m_MarksIdx ) + ); + marks->SetPixel( n.Vertex, n.FrontId ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +typename fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +TFrontId fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_GetMark( const TVertex& v ) const +{ + typedef itk::Image< TFrontId, _TInputImage::ImageDimension > _TMarks; + const _TMarks* marks = + dynamic_cast< const _TMarks* >( + this->itk::ProcessObject::GetOutput( this->m_MarksIdx ) + ); + return( marks->GetPixel( v ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_UpdateResult( const _TQueueNode& n ) +{ + this->GetOutput( )->SetPixel( n.Vertex, n.Result ); +} + +#endif // __fpa__Image__Algorithm__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Dijkstra.h b/lib/fpa/Image/Dijkstra.h new file mode 100644 index 0000000..37c28e8 --- /dev/null +++ b/lib/fpa/Image/Dijkstra.h @@ -0,0 +1,61 @@ +#ifndef __fpa__Image__Dijkstra__h__ +#define __fpa__Image__Dijkstra__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage > + class Dijkstra + : public fpa::Base::Dijkstra< fpa::Image::Algorithm< _TInputImage, _TOutputImage >, fpa::Image::MinimumSpanningTree< _TInputImage::ImageDimension > > + { + public: + typedef Dijkstra Self; + typedef fpa::Image::Algorithm< _TInputImage, _TOutputImage > TAlgorithm; + typedef fpa::Image::MinimumSpanningTree< _TInputImage::ImageDimension > TMST; + typedef fpa::Base::Dijkstra< TAlgorithm, TMST > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TOutput TOutput; + typedef typename Superclass::TVertex TVertex; + + typedef fpa::Image::Functors::Base< _TInputImage, fpa::Base::DijkstraCostFunctionBase< TVertex, TOutput > > TCostFunction; + + protected: + typedef typename Superclass::_TQueueNode _TQueueNode; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::Dijkstra, fpa::Base::Dijkstra ); + + protected: + Dijkstra( ); + virtual ~Dijkstra( ); + + virtual void _BeforeGenerateData( ) fpa_OVERRIDE; + + private: + // Purposely not defined + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__Dijkstra__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Dijkstra.hxx b/lib/fpa/Image/Dijkstra.hxx new file mode 100644 index 0000000..2831159 --- /dev/null +++ b/lib/fpa/Image/Dijkstra.hxx @@ -0,0 +1,35 @@ +#ifndef __fpa__Image__Dijkstra__hxx__ +#define __fpa__Image__Dijkstra__hxx__ + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::Dijkstra< _TInputImage, _TOutputImage >:: +Dijkstra( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::Dijkstra< _TInputImage, _TOutputImage >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Dijkstra< _TInputImage, _TOutputImage >:: +_BeforeGenerateData( ) +{ + this->Superclass::_BeforeGenerateData( ); + + TCostFunction* cost = + dynamic_cast< TCostFunction* >( this->GetCostFunction( ) ); + if( cost == NULL ) + itkExceptionMacro( << "CostFunction not well defined." ); + cost->SetImage( this->GetInput( ) ); +} + +#endif // __fpa__Image__Dijkstra__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/Base.h b/lib/fpa/Image/Functors/Base.h new file mode 100644 index 0000000..607b7c3 --- /dev/null +++ b/lib/fpa/Image/Functors/Base.h @@ -0,0 +1,55 @@ +#ifndef __fpa__Image__Functors__Base__h__ +#define __fpa__Image__Functors__Base__h__ + +#include +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + /** + */ + template< class _TImage, class _TSuperclass > + class Base + : public _TSuperclass + { + public: + typedef Base Self; + typedef _TSuperclass Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TImage TImage; + typedef itk::ImageBase< TImage::ImageDimension > TImageBase; + + public: + itkTypeMacro( Base, itk::FunctionBase ); + + itkGetConstObjectMacro( Image, TImageBase ); + itkSetConstObjectMacro( Image, TImageBase ); + + protected: + Base( ) : Superclass( ) { } + virtual ~Base( ) { } + + private: + // Purposely not implemented + Base( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TImageBase::ConstPointer m_Image; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__Functors__Base__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/SimpleDijkstraCost.h b/lib/fpa/Image/Functors/SimpleDijkstraCost.h new file mode 100644 index 0000000..d9a0405 --- /dev/null +++ b/lib/fpa/Image/Functors/SimpleDijkstraCost.h @@ -0,0 +1,68 @@ +#ifndef __fpa__Image__Functors__SimpleDijkstraCost__h__ +#define __fpa__Image__Functors__SimpleDijkstraCost__h__ + +#include +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + /** + */ + template< class _TImage, class _TOutput > + class SimpleDijkstraCost + : public fpa::Image::Functors::Base< _TImage, fpa::Base::DijkstraCostFunctionBase< typename _TImage::IndexType, _TOutput > > + { + public: + typedef _TImage TImage; + typedef typename TImage::IndexType TIndex; + typedef _TOutput TOutput; + + typedef fpa::Base::DijkstraCostFunctionBase< TIndex, TOutput > TBaseFunctor; + typedef fpa::Image::Functors::Base< TImage, TBaseFunctor > Superclass; + typedef SimpleDijkstraCost Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( SimpleDijkstraCost, Base ); + + itkBooleanMacro( UseImageSpacing ); + itkGetConstMacro( UseImageSpacing, bool ); + itkSetMacro( UseImageSpacing, bool ); + + public: + virtual TOutput Evaluate( + const TIndex& a, const TIndex& b + ) const fpa_OVERRIDE; + + protected: + SimpleDijkstraCost( ); + virtual ~SimpleDijkstraCost( ); + + private: + // Purposely not implemented + SimpleDijkstraCost( const Self& other ); + Self& operator=( const Self& other ); + + protected: + bool m_UseImageSpacing; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__Functors__SimpleDijkstraCost__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/SimpleDijkstraCost.hxx b/lib/fpa/Image/Functors/SimpleDijkstraCost.hxx new file mode 100644 index 0000000..25b8ff4 --- /dev/null +++ b/lib/fpa/Image/Functors/SimpleDijkstraCost.hxx @@ -0,0 +1,42 @@ +#ifndef __fpa__Image__Functors__SimpleDijkstraCost__hxx__ +#define __fpa__Image__Functors__SimpleDijkstraCost__hxx__ + +// ------------------------------------------------------------------------- +template< class _TImage, class _TOutput > +typename fpa::Image::Functors::SimpleDijkstraCost< _TImage, _TOutput >:: +TOutput fpa::Image::Functors::SimpleDijkstraCost< _TImage, _TOutput >:: +Evaluate( const TIndex& a, const TIndex& b ) const +{ + const _TImage* im = + dynamic_cast< const _TImage* >( this->m_Image.GetPointer( ) ); + TOutput coeff = TOutput( 1 ); + if( this->m_UseImageSpacing ) + { + typename _TImage::PointType pa, pb; + im->TransformIndexToPhysicalPoint( a, pa ); + im->TransformIndexToPhysicalPoint( b, pb ); + coeff = TOutput( pa.EuclideanDistanceTo( pb ) ); + + } // fi + return( TOutput( im->GetPixel( a ) ) * coeff ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TOutput > +fpa::Image::Functors::SimpleDijkstraCost< _TImage, _TOutput >:: +SimpleDijkstraCost( ) + : Superclass( ), + m_UseImageSpacing( false ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TOutput > +fpa::Image::Functors::SimpleDijkstraCost< _TImage, _TOutput >:: +~SimpleDijkstraCost( ) +{ +} + +#endif // __fpa__Image__Functors__SimpleDijkstraCost__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/SimpleNeighborhood.h b/lib/fpa/Image/Functors/SimpleNeighborhood.h new file mode 100644 index 0000000..3074599 --- /dev/null +++ b/lib/fpa/Image/Functors/SimpleNeighborhood.h @@ -0,0 +1,65 @@ +#ifndef __fpa__Image__Functors__SimpleNeighborhood__h__ +#define __fpa__Image__Functors__SimpleNeighborhood__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + /** + */ + template< class _TImage > + class SimpleNeighborhood + : public fpa::Image::Functors::Base< _TImage, itk::FunctionBase< typename _TImage::IndexType, std::vector< typename _TImage::IndexType > > > + { + public: + typedef _TImage TImage; + typedef typename TImage::IndexType TIndex; + typedef std::vector< TIndex > TOutput; + typedef itk::FunctionBase< TIndex, TOutput > TBaseFunctor; + typedef fpa::Image::Functors::Base< TImage, TBaseFunctor > Superclass; + typedef SimpleNeighborhood Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( SimpleNeighborhood, Base ); + + itkGetConstMacro( Order, unsigned int ); + itkSetMacro( Order, unsigned int ); + + public: + virtual TOutput Evaluate( const TIndex& center ) const fpa_OVERRIDE; + + protected: + SimpleNeighborhood( ); + virtual ~SimpleNeighborhood( ); + + private: + // Purposely not implemented + SimpleNeighborhood( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_Order; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__Functors__SimpleNeighborhood__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/SimpleNeighborhood.hxx b/lib/fpa/Image/Functors/SimpleNeighborhood.hxx new file mode 100644 index 0000000..ce5fcc5 --- /dev/null +++ b/lib/fpa/Image/Functors/SimpleNeighborhood.hxx @@ -0,0 +1,53 @@ +#ifndef __fpa__Image__Functors__SimpleNeighborhood__hxx__ +#define __fpa__Image__Functors__SimpleNeighborhood__hxx__ + +// ------------------------------------------------------------------------- +template< class _TImage > +typename fpa::Image::Functors::SimpleNeighborhood< _TImage >:: +TOutput fpa::Image::Functors::SimpleNeighborhood< _TImage >:: +Evaluate( const TIndex& center ) const +{ + TOutput res; + typename _TImage::RegionType reg = this->m_Image->GetRequestedRegion( ); + if( this->m_Order == 1 ) + { + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + { + for( int o = -1; o <= 1; o += 2 ) + { + TIndex idx = center; + idx[ d ] += o; + if( reg.IsInside( idx ) ) + res.push_back( idx ); + + } // rof + + } // rof + } + else + { + // TODO!!! + + } // fi + return( res ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +fpa::Image::Functors::SimpleNeighborhood< _TImage >:: +SimpleNeighborhood( ) + : Superclass( ), + m_Order( 1 ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > + fpa::Image::Functors::SimpleNeighborhood< _TImage >:: +~SimpleNeighborhood( ) +{ +} + +#endif // __fpa__Image__Functors__SimpleNeighborhood__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/MinimumSpanningTree.h b/lib/fpa/Image/MinimumSpanningTree.h new file mode 100644 index 0000000..371664c --- /dev/null +++ b/lib/fpa/Image/MinimumSpanningTree.h @@ -0,0 +1,63 @@ +#ifndef __fpa__Image__MinimumSpanningTree__h__ +#define __fpa__Image__MinimumSpanningTree__h__ + +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< unsigned int _VDim > + class MinimumSpanningTree + : public fpa::Base::MinimumSpanningTree< itk::Index< _VDim >, itk::Image< itk::Offset< _VDim >, _VDim > > + { + public: + typedef itk::Index< _VDim > TVertex; + typedef itk::Offset< _VDim > TOffset; + typedef itk::Image< TOffset, _VDim > TImage; + typedef fpa::Base::MinimumSpanningTree< TVertex, TImage > Superclass; + typedef MinimumSpanningTree Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TVertices TVertices; + typedef typename TImage::PointType TPoint; + typedef std::deque< TPoint > TPoints; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Image::MinimumSpanningTree, fpa::Base::MinimumSpanningTree + ); + + public: + virtual TVertex GetParent( const TVertex& v ) const fpa_OVERRIDE; + virtual void SetParent( const TVertex& v, const TVertex& p ) fpa_OVERRIDE; + + TPoints GetEuclideanPath( const TVertex& a ) const; + TPoints GetEuclideanPath( const TVertex& a, const TVertex& b ) const; + + protected: + MinimumSpanningTree( ); + virtual ~MinimumSpanningTree( ); + + private: + // Purposely not defined + MinimumSpanningTree( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__MinimumSpanningTree__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/MinimumSpanningTree.hxx b/lib/fpa/Image/MinimumSpanningTree.hxx new file mode 100644 index 0000000..01c642d --- /dev/null +++ b/lib/fpa/Image/MinimumSpanningTree.hxx @@ -0,0 +1,75 @@ +#ifndef __fpa__Image__MinimumSpanningTree__hxx__ +#define __fpa__Image__MinimumSpanningTree__hxx__ + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::Image::MinimumSpanningTree< _VDim >:: +TVertex fpa::Image::MinimumSpanningTree< _VDim >:: +GetParent( const TVertex& v ) const +{ + TVertex p = v + this->GetPixel( v ); + return( p ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::MinimumSpanningTree< _VDim >:: +SetParent( const TVertex& v, const TVertex& p ) +{ + this->SetPixel( v, p - v ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::Image::MinimumSpanningTree< _VDim >:: +TPoints fpa::Image::MinimumSpanningTree< _VDim >:: +GetEuclideanPath( const TVertex& a ) const +{ + TVertices path = this->GetPath( a ); + TPoints points; + for( auto v = path.begin( ); v != path.end( ); ++v ) + { + TPoint p; + this->TransformIndexToPhysicalPoint( *v, p ); + points.push_back( p ); + + } // rof + return( points ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::Image::MinimumSpanningTree< _VDim >:: +TPoints fpa::Image::MinimumSpanningTree< _VDim >:: +GetEuclideanPath( const TVertex& a, const TVertex& b ) const +{ + TVertices path = this->GetPath( a, b ); + TPoints points; + for( auto v = path.begin( ); v != path.end( ); ++v ) + { + TPoint p; + this->TransformIndexToPhysicalPoint( *v, p ); + points.push_back( p ); + + } // rof + return( points ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::Image::MinimumSpanningTree< _VDim >:: +MinimumSpanningTree( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::Image::MinimumSpanningTree< _VDim >:: +~MinimumSpanningTree( ) +{ +} + +#endif // __fpa__Image__MinimumSpanningTree__hxx__ + +// eof - $RCSfile$ diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..09f152b --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,15 @@ +## ========================== +## == Build plugin library == +## ========================== + +IF(USE_cpPlugins) + Wrap_cpPlugins( + _plugin + ${CMAKE_CURRENT_SOURCE_DIR}/Plugins + ${prj_VERSION} ${prj_SHORT_VERSION} + fpa + ) + TARGET_LINK_LIBRARIES(${_plugin} ${cpPlugins_LIB} ${fpa_Instances}) +ENDIF(USE_cpPlugins) + +## eof - $RCSfile$ \ No newline at end of file diff --git a/plugins/Plugins/BaseImageFilter.cxx b/plugins/Plugins/BaseImageFilter.cxx new file mode 100644 index 0000000..cb3f433 --- /dev/null +++ b/plugins/Plugins/BaseImageFilter.cxx @@ -0,0 +1,29 @@ +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::BaseImageFilter:: +BaseImageFilter( ) + : Superclass( ) +{ + typedef cpPlugins::BaseObjects::DataObject _TData; + typedef cpPlugins::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureInput< _TData >( "Seeds", true, false ); + this->_ConfigureInput< _TData >( "Neighborhood", false, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + this->m_Parameters.ConfigureAsBool( "VisualDebug" ); + this->m_Parameters.ConfigureAsBool( "StopAtOneFront" ); + this->m_Parameters.SetBool( "VisualDebug", false ); + this->m_Parameters.SetBool( "StopAtOneFront", false ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::BaseImageFilter:: +~BaseImageFilter( ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/BaseImageFilter.h b/plugins/Plugins/BaseImageFilter.h new file mode 100644 index 0000000..30cb7d1 --- /dev/null +++ b/plugins/Plugins/BaseImageFilter.h @@ -0,0 +1,52 @@ +#ifndef __fpa__Plugins__BaseImageFilter__h__ +#define __fpa__Plugins__BaseImageFilter__h__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT BaseImageFilter + : public cpPlugins::BaseObjects::ProcessObject + { + public: + typedef BaseImageFilter Self; + typedef cpPlugins::BaseObjects::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( BaseImageFilter, cpPlugins::BaseObjects::ProcessObject ); + cpPlugins_Id_Macro( BaseImageFilter, fpaImageAlgorithm ); + + protected: + BaseImageFilter( ); + virtual ~BaseImageFilter( ); + + /* TODO + template< class _TFilter > + inline _TFilter* _ConfigureFilter( ); + + template< class _TFilter > + inline void _ExecuteFilter( _TFilter* filter ); + + template< class _TFilter > + inline void _ConfigureDebugger( _TFilter* filter ); + + template< class _TFilter > + inline void _DeconfigureDebugger( _TFilter* filter ); + */ + + private: + // Purposely not implemented. + BaseImageFilter( const Self& other ); + Self& operator=( const Self& other ); + }; + +} // ecapseman + +#endif // __fpa__Plugins__BaseImageFilter__h__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/ExtractPathFromMinimumSpanningTree.cxx b/plugins/Plugins/ExtractPathFromMinimumSpanningTree.cxx new file mode 100644 index 0000000..f6b69d1 --- /dev/null +++ b/plugins/Plugins/ExtractPathFromMinimumSpanningTree.cxx @@ -0,0 +1,124 @@ +#include +#include +#include +#include + +/* TODO + #include + #include +*/ + +// ------------------------------------------------------------------------- +fpaPlugins::ExtractPathFromMinimumSpanningTree:: +ExtractPathFromMinimumSpanningTree( ) + : Superclass( ) +{ + typedef cpPlugins::BaseObjects::DataObject _TData; + typedef cpPlugins::DataObjects::Image _TMST; + typedef cpPlugins::DataObjects::Mesh _TMesh; + + this->_ConfigureInput< _TMST >( "MST", true, false ); + this->_ConfigureInput< _TData >( "Seeds", true, false ); + this->_ConfigureOutput< _TMesh >( "Paths" ); + + this->m_Parameters.ConfigureAsUintList( "Indices" ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::ExtractPathFromMinimumSpanningTree:: +~ExtractPathFromMinimumSpanningTree( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::ExtractPathFromMinimumSpanningTree:: +_GenerateData( ) +{ + typedef fpa::Image::MinimumSpanningTree< 2 > _TMST2; + typedef fpa::Image::MinimumSpanningTree< 3 > _TMST3; + + auto mst2 = this->GetInputData< _TMST2 >( "MST" ); + auto mst3 = this->GetInputData< _TMST3 >( "MST" ); + if ( mst2 != NULL ) this->_GD0( mst2 ); + else if( mst3 != NULL ) this->_GD0( mst3 ); + else this->_Error( "Invalid input spanning tree." ); +} + +// ------------------------------------------------------------------------- +template< class _TMST > +void fpaPlugins::ExtractPathFromMinimumSpanningTree:: +_GD0( _TMST* mst ) +{ + typedef typename _TMST::IndexType _TIndex; + + // Get seeds + std::vector< _TIndex > seeds; + auto points = this->GetInputData< vtkPolyData >( "Seeds" ); + if( points != NULL ) + { + typename _TMST::PointType pnt; + typename _TMST::IndexType idx; + unsigned int dim = + ( _TMST::ImageDimension < 3 )? _TMST::ImageDimension: 3; + for( unsigned int i = 0; i < points->GetNumberOfPoints( ); ++i ) + { + double buf[ 3 ]; + points->GetPoint( i, buf ); + pnt.Fill( 0 ); + for( unsigned int d = 0; d < dim; ++d ) + pnt[ d ] = buf[ d ]; + if( mst->TransformPhysicalPointToIndex( pnt, idx ) ) + seeds.push_back( idx ); + + } // rof + + } // fi + + // Prepare result + auto mesh = this->_CreateVTK< vtkPolyData >( ); + mesh->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + mesh->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + mesh->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + mesh->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + mesh->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + /* TODO + vtkSmartPointer< vtkFloatArray > data = + vtkSmartPointer< vtkFloatArray >::New( ); + data->SetNumberOfComponents( 1 ); + mesh->GetPointData( )->SetScalars( data ); + */ + + // Compute + auto indices = this->m_Parameters.GetUintList( "Indices" ); + for( unsigned int i = 0; i < indices.size( ); i += 2 ) + { + if( i < indices.size( ) - 1 ) + { + _TIndex a = seeds[ indices[ i ] ]; + _TIndex b = seeds[ indices[ i + 1 ] ]; + + auto path = mst->GetEuclideanPath( a, b ); + for( unsigned long j = 0; j < path.size( ); ++j ) + { + auto p = path[ j ]; + if( _TMST::ImageDimension == 2 ) + mesh->GetPoints( )->InsertNextPoint( p[ 0 ], p[ 1 ], 0 ); + else if( _TMST::ImageDimension == 3 ) + mesh->GetPoints( )->InsertNextPoint( p[ 0 ], p[ 1 ], p[ 2 ] ); + if( j > 0 ) + { + mesh->GetLines( )->InsertNextCell( 2 ); + mesh->GetLines( )->InsertCellPoint( j - 1 ); + mesh->GetLines( )->InsertCellPoint( j ); + + } // fi + + } // rof + + } // fi + + } // rof + this->GetOutput( "Paths" )->SetVTK( mesh ); +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/ExtractPathFromMinimumSpanningTree.h b/plugins/Plugins/ExtractPathFromMinimumSpanningTree.h new file mode 100644 index 0000000..c3f8496 --- /dev/null +++ b/plugins/Plugins/ExtractPathFromMinimumSpanningTree.h @@ -0,0 +1,29 @@ +#ifndef __fpa__Plugins__ExtractPathFromMinimumSpanningTree__h__ +#define __fpa__Plugins__ExtractPathFromMinimumSpanningTree__h__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT ExtractPathFromMinimumSpanningTree + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + ExtractPathFromMinimumSpanningTree, + cpPlugins::BaseObjects::ProcessObject, + fpa + ); + + protected: + template< class _TMST > + inline void _GD0( _TMST* mst ); + }; + +} // ecapseman + +#endif // __fpa__Plugins__ExtractPathFromMinimumSpanningTree__h__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/GaussianModelCost.cxx b/plugins/Plugins/GaussianModelCost.cxx new file mode 100644 index 0000000..c6b962b --- /dev/null +++ b/plugins/Plugins/GaussianModelCost.cxx @@ -0,0 +1,55 @@ +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::GaussianModelCost:: +GaussianModelCost( ) + : Superclass( ) +{ + typedef cpPlugins::BaseObjects::DataObject _TData; + this->_ConfigureOutput< _TData >( "Output" ); + + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "ResultType", choices ); + this->m_Parameters.SetSelectedChoice( "ResultType", "float" ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::GaussianModelCost:: +~GaussianModelCost( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::GaussianModelCost:: +_GenerateData( ) +{ + auto rtype = this->m_Parameters.GetSelectedChoice( "ResultType" ); + if ( rtype == "float" ) this->_GD0< float >( ); + else if( rtype == "double" ) this->_GD0< double >( ); +} + +// ------------------------------------------------------------------------- +template< class _TOutput > +void fpaPlugins::GaussianModelCost:: +_GD0( ) +{ + typedef fpa::Base::Functors::GaussianModel< _TOutput, _TOutput > _TFunctor; + + auto out = this->GetOutput( "Output" ); + auto f = out->GetITK< _TFunctor >( ); + if( f == NULL ) + { + typename _TFunctor::Pointer ptr_f = _TFunctor::New( ); + f = ptr_f.GetPointer( ); + out->SetITK( f ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/GaussianModelCost.h b/plugins/Plugins/GaussianModelCost.h new file mode 100644 index 0000000..845f57f --- /dev/null +++ b/plugins/Plugins/GaussianModelCost.h @@ -0,0 +1,29 @@ +#ifndef __fpa__Plugins__GaussianModelCost__h__ +#define __fpa__Plugins__GaussianModelCost__h__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT GaussianModelCost + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + GaussianModelCost, + cpPlugins::BaseObjects::ProcessObject, + fpaFunctors + ); + + protected: + template< class _TOutput > + inline void _GD0( ); + }; + +} // ecapseman + +#endif // __fpa__Plugins__GaussianModelCost__h__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/ImageDijkstra.cxx b/plugins/Plugins/ImageDijkstra.cxx new file mode 100644 index 0000000..c5d34a4 --- /dev/null +++ b/plugins/Plugins/ImageDijkstra.cxx @@ -0,0 +1,108 @@ +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::ImageDijkstra:: +ImageDijkstra( ) + : Superclass( ) +{ + typedef cpPlugins::BaseObjects::DataObject _TData; + typedef cpPlugins::DataObjects::Image _TMST; + + this->_ConfigureInput< _TData >( "Cost", false, false ); + this->_ConfigureInput< _TData >( "CostConversion", false, false ); + this->_ConfigureOutput< _TMST >( "MST" ); + + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "ResultType", choices ); + this->m_Parameters.SetSelectedChoice( "ResultType", "float" ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::ImageDijkstra:: +~ImageDijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::ImageDijkstra:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_ImageScalars_Dims( o, _GD0 ); + else this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void fpaPlugins::ImageDijkstra:: +_GD0( _TImage* image ) +{ + typedef itk::Image< float, _TImage::ImageDimension > _TFloat; + typedef itk::Image< double, _TImage::ImageDimension > _TDouble; + + auto rtype = this->m_Parameters.GetSelectedChoice( "ResultType" ); + if ( rtype == "float" ) this->_GD1< _TImage, _TFloat >( image ); + else if( rtype == "double" ) this->_GD1< _TImage, _TDouble >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpaPlugins::ImageDijkstra:: +_GD1( _TInputImage* image ) +{ + typedef fpa::Image::Dijkstra< _TInputImage, _TOutputImage > _TFilter; + typedef typename _TFilter::TCostConversionFunction _TCostConversion; + typedef typename _TFilter::TCostFunction _TCost; + typedef typename _TFilter::TNeighborhoodFunction _TNeighborhood; + + // Get functors + auto neig = this->GetInputData< _TNeighborhood >( "Neighborhood" ); + auto cost = this->GetInputData< _TCost >( "Cost" ); + auto conv = this->GetInputData< _TCostConversion >( "CostConversion" ); + + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetNeighborhoodFunction( neig ); + filter->SetCostFunction( cost ); + filter->SetCostConversionFunction( conv ); + filter->SetStopAtOneFront( this->m_Parameters.GetBool( "StopAtOneFront" ) ); + + // Assign seeds + auto seeds = this->GetInputData< vtkPolyData >( "Seeds" ); + if( seeds != NULL ) + { + typename _TInputImage::PointType pnt; + typename _TInputImage::IndexType idx; + unsigned int dim = + ( _TInputImage::ImageDimension < 3 )? _TInputImage::ImageDimension: 3; + for( unsigned int i = 0; i < seeds->GetNumberOfPoints( ); ++i ) + { + double buf[ 3 ]; + seeds->GetPoint( i, buf ); + pnt.Fill( 0 ); + for( unsigned int d = 0; d < dim; ++d ) + pnt[ d ] = buf[ d ]; + + if( image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->AddSeed( idx, 0 ); + + } // rof + + } // fi + + // Assign outputs + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); + this->GetOutput( "MST" )->SetITK( filter->GetMinimumSpanningTree( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/ImageDijkstra.h b/plugins/Plugins/ImageDijkstra.h new file mode 100644 index 0000000..74198c3 --- /dev/null +++ b/plugins/Plugins/ImageDijkstra.h @@ -0,0 +1,27 @@ +#ifndef __fpa__Plugins__ImageDijkstra__h__ +#define __fpa__Plugins__ImageDijkstra__h__ + +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT ImageDijkstra + : public BaseImageFilter + { + cpPluginsObject( ImageDijkstra, BaseImageFilter, fpa ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TInputImage, class _TOutputImage > + inline void _GD1( _TInputImage* image ); + }; + +} // ecapseman + +#endif // __fpa__Plugins__ImageDijkstra__h__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/InvertCost.cxx b/plugins/Plugins/InvertCost.cxx new file mode 100644 index 0000000..fe77e0f --- /dev/null +++ b/plugins/Plugins/InvertCost.cxx @@ -0,0 +1,55 @@ +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::InvertCost:: +InvertCost( ) + : Superclass( ) +{ + typedef cpPlugins::BaseObjects::DataObject _TData; + this->_ConfigureOutput< _TData >( "Output" ); + + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "ResultType", choices ); + this->m_Parameters.SetSelectedChoice( "ResultType", "float" ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::InvertCost:: +~InvertCost( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::InvertCost:: +_GenerateData( ) +{ + auto rtype = this->m_Parameters.GetSelectedChoice( "ResultType" ); + if ( rtype == "float" ) this->_GD0< float >( ); + else if( rtype == "double" ) this->_GD0< double >( ); +} + +// ------------------------------------------------------------------------- +template< class _TOutput > +void fpaPlugins::InvertCost:: +_GD0( ) +{ + typedef fpa::Base::Functors::Inverse< _TOutput, _TOutput > _TFunctor; + + auto out = this->GetOutput( "Output" ); + auto f = out->GetITK< _TFunctor >( ); + if( f == NULL ) + { + typename _TFunctor::Pointer ptr_f = _TFunctor::New( ); + f = ptr_f.GetPointer( ); + out->SetITK( f ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/InvertCost.h b/plugins/Plugins/InvertCost.h new file mode 100644 index 0000000..f113068 --- /dev/null +++ b/plugins/Plugins/InvertCost.h @@ -0,0 +1,29 @@ +#ifndef __fpa__Plugins__InvertCost__h__ +#define __fpa__Plugins__InvertCost__h__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT InvertCost + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + InvertCost, + cpPlugins::BaseObjects::ProcessObject, + fpaFunctors + ); + + protected: + template< class _TOutput > + inline void _GD0( ); + }; + +} // ecapseman + +#endif // __fpa__Plugins__InvertCost__h__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/SimpleImageDijkstraCost.cxx b/plugins/Plugins/SimpleImageDijkstraCost.cxx new file mode 100644 index 0000000..6557a7f --- /dev/null +++ b/plugins/Plugins/SimpleImageDijkstraCost.cxx @@ -0,0 +1,73 @@ +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::SimpleImageDijkstraCost:: +SimpleImageDijkstraCost( ) + : Superclass( ) +{ + typedef cpPlugins::BaseObjects::DataObject _TData; + typedef cpPlugins::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TData >( "Output" ); + + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "ResultType", choices ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing" ); + + this->m_Parameters.SetSelectedChoice( "ResultType", "float" ); + this->m_Parameters.SetBool( "UseImageSpacing", false ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::SimpleImageDijkstraCost:: +~SimpleImageDijkstraCost( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::SimpleImageDijkstraCost:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_ImageScalars_Dims( o, _GD0 ); + else this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void fpaPlugins::SimpleImageDijkstraCost:: +_GD0( _TImage* image ) +{ + auto rtype = this->m_Parameters.GetSelectedChoice( "ResultType" ); + if ( rtype == "float" ) this->_GD1< _TImage, float >( image ); + else if( rtype == "double" ) this->_GD1< _TImage, double >( image ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TOutput > +void fpaPlugins::SimpleImageDijkstraCost:: +_GD1( _TImage* image ) +{ + typedef + fpa::Image::Functors::SimpleDijkstraCost< _TImage, _TOutput > + _TFunctor; + auto out = this->GetOutput( "Output" ); + auto f = out->GetITK< _TFunctor >( ); + if( f == NULL ) + { + typename _TFunctor::Pointer ptr_f = _TFunctor::New( ); + f = ptr_f.GetPointer( ); + out->SetITK( f ); + + } // fi + f->SetUseImageSpacing( this->m_Parameters.GetBool( "UseImageSpacing" ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/SimpleImageDijkstraCost.h b/plugins/Plugins/SimpleImageDijkstraCost.h new file mode 100644 index 0000000..80ae8f9 --- /dev/null +++ b/plugins/Plugins/SimpleImageDijkstraCost.h @@ -0,0 +1,32 @@ +#ifndef __fpa__Plugins__SimpleImageDijkstraCost__h__ +#define __fpa__Plugins__SimpleImageDijkstraCost__h__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT SimpleImageDijkstraCost + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + SimpleImageDijkstraCost, + cpPlugins::BaseObjects::ProcessObject, + fpaFunctors + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TOutput > + inline void _GD1( _TImage* image ); + }; + +} // ecapseman + +#endif // __fpa__Plugins__SimpleImageDijkstraCost__h__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/SimpleImageNeighborhood.cxx b/plugins/Plugins/SimpleImageNeighborhood.cxx new file mode 100644 index 0000000..0fc9837 --- /dev/null +++ b/plugins/Plugins/SimpleImageNeighborhood.cxx @@ -0,0 +1,55 @@ +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::SimpleImageNeighborhood:: +SimpleImageNeighborhood( ) + : Superclass( ) +{ + typedef cpPlugins::BaseObjects::DataObject _TData; + typedef cpPlugins::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureOutput< _TData >( "Output" ); + + this->m_Parameters.ConfigureAsUint( "Order" ); + this->m_Parameters.SetUint( "Order", 1 ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::SimpleImageNeighborhood:: +~SimpleImageNeighborhood( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::SimpleImageNeighborhood:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_ImageProcessDims( o, _GD0 ); + else this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void fpaPlugins::SimpleImageNeighborhood:: +_GD0( _TImage* image ) +{ + typedef fpa::Image::Functors::SimpleNeighborhood< _TImage > _TFunctor; + auto out = this->GetOutput( "Output" ); + auto f = out->GetITK< _TFunctor >( ); + if( f == NULL ) + { + typename _TFunctor::Pointer ptr_f = _TFunctor::New( ); + f = ptr_f.GetPointer( ); + out->SetITK( f ); + + } // fi + f->SetOrder( this->m_Parameters.GetUint( "Order" ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/SimpleImageNeighborhood.h b/plugins/Plugins/SimpleImageNeighborhood.h new file mode 100644 index 0000000..e47b42d --- /dev/null +++ b/plugins/Plugins/SimpleImageNeighborhood.h @@ -0,0 +1,29 @@ +#ifndef __fpa__Plugins__SimpleImageNeighborhood__h__ +#define __fpa__Plugins__SimpleImageNeighborhood__h__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT SimpleImageNeighborhood + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + SimpleImageNeighborhood, + cpPlugins::BaseObjects::ProcessObject, + fpaFunctors + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + }; + +} // ecapseman + +#endif // __fpa__Plugins__SimpleImageNeighborhood__h__ + +// eof - $RCSfile$ -- 2.45.1