From 56b8bb48cc05a297a3faa264f8f2a88de21ef203 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Mon, 12 Sep 2016 15:02:01 -0500 Subject: [PATCH] Architecture revisited. --- CMakeLists.txt | 72 +++ 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 | 43 ++ lib/Instances/CMakeLists.txt | 31 ++ lib/Instances/fpa_MinimumSpanningTree.i | 8 + lib/fpa/Base/Algorithm.h | 168 +++++++ lib/fpa/Base/Algorithm.hxx | 346 +++++++++++++ lib/fpa/Base/Dijkstra.h | 101 ++++ lib/fpa/Base/Dijkstra.hxx | 144 ++++++ lib/fpa/Base/Events.h | 103 ++++ lib/fpa/Base/Functors/GaussianCost.h | 74 +++ lib/fpa/Base/Functors/GaussianCost.hxx | 49 ++ lib/fpa/Base/Functors/InvertCost.h | 58 +++ lib/fpa/Base/Functors/InvertCost.hxx | 29 ++ lib/fpa/Base/MinimumSpanningTree.h | 101 ++++ lib/fpa/Base/MinimumSpanningTree.hxx | 278 +++++++++++ lib/fpa/Base/RegionGrow.h | 85 ++++ lib/fpa/Base/RegionGrow.hxx | 78 +++ lib/fpa/Config.cxx | 10 + lib/fpa/Config.h.in | 39 ++ lib/fpa/Image/Algorithm.h | 96 ++++ lib/fpa/Image/Algorithm.hxx | 133 +++++ lib/fpa/Image/Dijkstra.h | 73 +++ lib/fpa/Image/Dijkstra.hxx | 42 ++ lib/fpa/Image/MultiplyImageAndDistanceMap.h | 61 +++ lib/fpa/Image/MultiplyImageAndDistanceMap.hxx | 105 ++++ lib/fpa/Image/RegionGrow.h | 47 ++ lib/fpa/Image/RegionGrow.hxx | 21 + lib/fpa/VTK/Image/Observer2D.h | 89 ++++ lib/fpa/VTK/Image/Observer2D.hxx | 226 +++++++++ lib/fpa/VTK/Image/Observer3D.h | 86 ++++ lib/fpa/VTK/Image/Observer3D.hxx | 211 ++++++++ lib/fpa/VTK/Image/PathToPolyDataFilter.h | 83 ++++ lib/fpa/VTK/Image/PathToPolyDataFilter.hxx | 178 +++++++ plugins/CMakeLists.txt | 12 + plugins/Plugins/BaseImageFilter.cxx | 51 ++ plugins/Plugins/BaseImageFilter.h | 69 +++ plugins/Plugins/BaseImageFilter.hxx | 149 ++++++ plugins/Plugins/GaussianCostFunctor.cxx | 59 +++ plugins/Plugins/GaussianCostFunctor.h | 29 ++ plugins/Plugins/ImageDijkstra.cxx | 86 ++++ plugins/Plugins/ImageDijkstra.h | 27 ++ plugins/Plugins/ImagePathToPolyDataFilter.cxx | 99 ++++ plugins/Plugins/ImagePathToPolyDataFilter.h | 32 ++ plugins/Plugins/InvertCostFunctor.cxx | 51 ++ plugins/Plugins/InvertCostFunctor.h | 29 ++ .../Plugins/MultiplyImageAndDistanceMap.cxx | 81 ++++ plugins/Plugins/MultiplyImageAndDistanceMap.h | 31 ++ 53 files changed, 4644 insertions(+) create mode 100644 CMakeLists.txt 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_MinimumSpanningTree.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/Events.h create mode 100644 lib/fpa/Base/Functors/GaussianCost.h create mode 100644 lib/fpa/Base/Functors/GaussianCost.hxx create mode 100644 lib/fpa/Base/Functors/InvertCost.h create mode 100644 lib/fpa/Base/Functors/InvertCost.hxx create mode 100644 lib/fpa/Base/MinimumSpanningTree.h create mode 100644 lib/fpa/Base/MinimumSpanningTree.hxx create mode 100644 lib/fpa/Base/RegionGrow.h create mode 100644 lib/fpa/Base/RegionGrow.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/MultiplyImageAndDistanceMap.h create mode 100644 lib/fpa/Image/MultiplyImageAndDistanceMap.hxx create mode 100644 lib/fpa/Image/RegionGrow.h create mode 100644 lib/fpa/Image/RegionGrow.hxx create mode 100644 lib/fpa/VTK/Image/Observer2D.h create mode 100644 lib/fpa/VTK/Image/Observer2D.hxx create mode 100644 lib/fpa/VTK/Image/Observer3D.h create mode 100644 lib/fpa/VTK/Image/Observer3D.hxx create mode 100644 lib/fpa/VTK/Image/PathToPolyDataFilter.h create mode 100644 lib/fpa/VTK/Image/PathToPolyDataFilter.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/BaseImageFilter.hxx create mode 100644 plugins/Plugins/GaussianCostFunctor.cxx create mode 100644 plugins/Plugins/GaussianCostFunctor.h create mode 100644 plugins/Plugins/ImageDijkstra.cxx create mode 100644 plugins/Plugins/ImageDijkstra.h create mode 100644 plugins/Plugins/ImagePathToPolyDataFilter.cxx create mode 100644 plugins/Plugins/ImagePathToPolyDataFilter.h create mode 100644 plugins/Plugins/InvertCostFunctor.cxx create mode 100644 plugins/Plugins/InvertCostFunctor.h create mode 100644 plugins/Plugins/MultiplyImageAndDistanceMap.cxx create mode 100644 plugins/Plugins/MultiplyImageAndDistanceMap.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5b0669e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,72 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.5) + +## ======================== +## == 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) +IF(USE_cpPlugins) + SUBDIRS(plugins) +ENDIF(USE_cpPlugins) + +## 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..318a5fa --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,43 @@ + +## ========================================= +## == Manage every directory as a library == +## ========================================= + +LibFromDir( + fpa + SHARED + ${CMAKE_CURRENT_SOURCE_DIR}/fpa + "${prj_VERSION}" "${prj_SHORT_VERSION}" + ) + +## ================================== +## == Compile cpPlugins-based code == +## ================================== + +IF(USE_cpPlugins) + + ## ======================= + ## == Compile instances == + ## ======================= + + SUBDIRS(Instances) + + ## =================================== + ## == Libraries to dynamically load == + ## =================================== + + SET( + fpa_DynLibs + local@fpa + ) + 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) + +ENDIF(USE_cpPlugins) + +## eof - $RCSfile$ diff --git a/lib/Instances/CMakeLists.txt b/lib/Instances/CMakeLists.txt new file mode 100644 index 0000000..bbad1f8 --- /dev/null +++ b/lib/Instances/CMakeLists.txt @@ -0,0 +1,31 @@ +SET(_pfx "") +SET(_all_instances) + +## =========================== +## == Compile each instance == +## =========================== +FILE(GLOB _instances "${CMAKE_CURRENT_SOURCE_DIR}/*.i") + +FOREACH(_instance ${_instances}) + CompileInstances( + _lib_name + ${_instance} ${cpPlugins_NUMBER_OF_FILES} + "${_pfx}" "${prj_VERSION}" "${prj_SHORT_VERSION}" + ) + LIST(APPEND _all_instances ${_lib_name}) +ENDFOREACH(_instance) +SET( + fpa_Instances ${_all_instances} + CACHE INTERNAL "All valid instances." FORCE + ) + +## ==================== +## == Link libraries == +## ==================== + +TARGET_LINK_LIBRARIES( + ${_pfx}fpa_MinimumSpanningTree + ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${cpPlugins_Instances} + ) + +## eof - $RCSfile$ diff --git a/lib/Instances/fpa_MinimumSpanningTree.i b/lib/Instances/fpa_MinimumSpanningTree.i new file mode 100644 index 0000000..53af6df --- /dev/null +++ b/lib/Instances/fpa_MinimumSpanningTree.i @@ -0,0 +1,8 @@ + +i itkIndex.h +t fpa/Base/MinimumSpanningTree +t itkSimpleDataObjectDecorator + +c fpa::Base::MinimumSpanningTree< itk::Index< #process_dims# >, #reals#, itk::Functor::IndexLexicographicCompare< #process_dims# > > + +** eof - $RCSfile$ diff --git a/lib/fpa/Base/Algorithm.h b/lib/fpa/Base/Algorithm.h new file mode 100644 index 0000000..888d2e8 --- /dev/null +++ b/lib/fpa/Base/Algorithm.h @@ -0,0 +1,168 @@ +#ifndef __FPA__BASE__ALGORITHM__H__ +#define __FPA__BASE__ALGORITHM__H__ + +#include +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + * Base front propagation algorithm. From a series of start seeds with + * costs, a priority queue is filled and emptied updating costs. Each + * vertex could be marked as "visited", "in the front", "not yet there" + * or "freezed". + * + * @param _TVertex Vertex type. + * @param _TScalar Scalar (real computations) type. + * @param _TFilter Base class for this algorithm. It should be any + * itk-based filter (itk::ProcessObject). + * @param _TVertexCompare Vertex lexicographical compare. + * + */ + template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare = std::less< _TVertex > > + class Algorithm + : public _TFilter + { + public: + typedef Algorithm Self; + typedef _TFilter Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Template arguments + typedef _TVertex TVertex; + typedef _TScalar TScalar; + typedef _TFilter TFilter; + typedef _TVertexCompare TVertexCompare; + + // Some useful types + typedef unsigned long TFrontId; + + // Minigraph to represent collisions + typedef std::pair< TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + + enum TNodeLabel + { + FarLabel = 0, + FrontLabel, + AliveLabel + }; + + /** + * WARNING: std::set< T > objects are immutable + */ + struct TNode + { + static const TVertexCompare VertexCompare; + TVertex Vertex; + mutable TVertex Parent; + mutable TScalar Result; + mutable TFrontId FrontId; + mutable TNodeLabel Label; + bool operator<( const TNode& other ) const + { return( VertexCompare( this->Vertex, other.Vertex ) ); } + }; + typedef std::set< TNode > TNodes; + typedef std::vector< TVertex > TVertices; + + public: + itkTypeMacro( Algorithm, _TFilter ); + + itkBooleanMacro( StopAtOneFront ); + itkGetConstMacro( StopAtOneFront, bool ); + itkSetMacro( StopAtOneFront, bool ); + + itkBooleanMacro( ThrowEvents ); + itkGetConstMacro( ThrowEvents, bool ); + itkSetMacro( ThrowEvents, bool ); + + fpa_Base_NewEvent( TStartEvent ); + fpa_Base_NewEvent( TStartLoopEvent ); + fpa_Base_NewEvent( TStartBacktrackingEvent ); + fpa_Base_NewEvent( TEndEvent ); + fpa_Base_NewEvent( TEndLoopEvent ); + fpa_Base_NewEvent( TEndBacktrackingEvent ); + fpa_Base_NewEventWithVertex( TCollisionEvent, TVertex ); + fpa_Base_NewEventWithVertex( TAliveEvent, TVertex ); + fpa_Base_NewEventWithVertex( TFrontEvent, TVertex ); + fpa_Base_NewEventWithVertex( TFreezeEvent, TVertex ); + fpa_Base_NewEventWithVertex( TBacktrackingEvent, TVertex ); + + public: + virtual void InvokeEvent( const itk::EventObject& e ); + virtual void InvokeEvent( const itk::EventObject& e ) const; + + unsigned long GetNumberOfSeeds( ) const; + void AddSeed( const TVertex& s, const TScalar& v = TScalar( 0 ) ); + void AddSeed( const TNode& n ); + void RemoveSeed( const TVertex& s ); + void RemoveAllSeeds( ); + + protected: + // Methods to extend itk-based architecture + Algorithm( ); + virtual ~Algorithm( ); + virtual void GenerateData( ) fpa_OVERRIDE; + + // Front propagation generic methods + virtual void _Loop( ); + + // Front propagation methods to be overloaded + virtual void _BeforeGenerateData( ); + virtual void _AfterGenerateData( ); + virtual void _BeforeLoop( ); + virtual void _AfterLoop( ); + + virtual void _InitMarks( ) = 0; + virtual void _InitResults( ) = 0; + virtual void _DeallocateAuxiliary( ) = 0; + + virtual TFrontId _GetMark( const TVertex& v ) = 0; + virtual TFrontId _GetMark( const TNode& v ); + + virtual void _Visit( const TNode& n ) = 0; + virtual bool _NeedToStop( ); + + virtual TVertices _GetNeighborhood( const TVertex& v ) const = 0; + virtual TVertices _GetNeighborhood( const TNode& n ) const; + + virtual bool _Result( TNode& node, const TNode& parent ) = 0; + + virtual void _QueueClear( ) = 0; + virtual void _QueuePush( const TNode& node ) = 0; + virtual TNode _QueuePop( ) = 0; + virtual bool _IsQueueEmpty( ) const = 0; + + virtual bool _UpdateCollisions( const TVertex& a, const TVertex& b ); + + private: + // Purposely not implemented + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TNodes m_Seeds; + TCollisions m_Collisions; + bool m_StopAtOneFront; + bool m_ThrowEvents; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif + +#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..1b33897 --- /dev/null +++ b/lib/fpa/Base/Algorithm.hxx @@ -0,0 +1,346 @@ +#ifndef __FPA__BASE__ALGORITHM__HXX__ +#define __FPA__BASE__ALGORITHM__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +const _TVertexCompare fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +TNode::VertexCompare = _TVertexCompare( ); + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +InvokeEvent( const itk::EventObject& e ) +{ + if( this->m_ThrowEvents ) + this->Superclass::InvokeEvent( e ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +InvokeEvent( const itk::EventObject& e ) const +{ + if( this->m_ThrowEvents ) + this->Superclass::InvokeEvent( e ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +unsigned long fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +GetNumberOfSeeds( ) const +{ + return( this->m_Seeds.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +AddSeed( const TVertex& s, const TScalar& v ) +{ + TNode n; + n.Vertex = s; + n.Parent = s; + n.Result = v; + n.Label = Self::FrontLabel; + this->AddSeed( n ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +AddSeed( const TNode& n ) +{ + this->m_Seeds.insert( n ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +RemoveSeed( const TVertex& s ) +{ + TNode n; + n.Vertex = s; + typename TNodes::iterator i = this->m_Seeds.find( n ); + if( i != this->m_Seeds.end( ) ) + { + this->m_Seeds.erase( i ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +RemoveAllSeeds( ) +{ + this->m_Seeds.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +Algorithm( ) + : Superclass( ), + m_StopAtOneFront( false ), + m_ThrowEvents( false ) +{ +} + + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +~Algorithm( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +GenerateData( ) +{ + this->InvokeEvent( TStartEvent( ) ); + this->_BeforeGenerateData( ); + + unsigned int N = this->m_Seeds.size( ); + if( N > 0 ) + { + // Enumerate seeds + typename TNodes::iterator nIt = this->m_Seeds.begin( ); + for( unsigned long i = 1; nIt != this->m_Seeds.end( ); ++nIt, ++i ) + nIt->FrontId = i; + + // Prepare collisions + TCollision coll( TVertex( ), false ); + TCollisionsRow row( N, coll ); + this->m_Collisions.clear( ); + this->m_Collisions.resize( N, row ); + + // Put seeds on queue + this->_QueueClear( ); + for( nIt = this->m_Seeds.begin( ); nIt != this->m_Seeds.end( ); ++nIt ) + this->_QueuePush( *nIt ); + + // Init marks and results + this->_InitMarks( ); + this->_InitResults( ); + + // Main loop + this->_BeforeLoop( ); + this->_Loop( ); + this->_AfterLoop( ); + + // Deallocate any memory + this->_DeallocateAuxiliary( ); + + } // fi + + this->_AfterGenerateData( ); + this->InvokeEvent( TEndEvent( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_Loop( ) +{ + this->InvokeEvent( TStartLoopEvent( ) ); + this->_BeforeLoop( ); + + while( !( this->_IsQueueEmpty( ) ) ) + { + // Extract next candidate + TNode node = this->_QueuePop( ); + + // Check if it has been visited + if( this->_GetMark( node ) > 0 ) + continue; + + // Mark it as visited + this->_Visit( node ); + this->InvokeEvent( TAliveEvent( node.Vertex, node.FrontId ) ); + + // Check if there is an external stop condition + if( this->_NeedToStop( ) ) + { + this->_QueueClear( ); + continue; + + } // fi + + // Get neighborhood + TVertices neighborhood = this->_GetNeighborhood( node ); + + // Update neighborhood + auto neighIt = neighborhood.begin( ); + bool stop = false; + for( ; neighIt != neighborhood.end( ); ++neighIt ) + { + if( this->_GetMark( *neighIt ) == 0 ) + { + TNode neigh; + neigh.Vertex = *neighIt; + neigh.Parent = node.Vertex; + neigh.FrontId = node.FrontId; + if( this->_Result( neigh, node ) ) + { + this->_QueuePush( neigh ); + this->InvokeEvent( TFrontEvent( *neighIt, node.FrontId ) ); + + } // fi + } + else + stop |= this->_UpdateCollisions( node.Vertex, *neighIt ); + + } // rof + + if( stop ) + this->_QueueClear( ); + + } // elihw + + this->_AfterLoop( ); + this->InvokeEvent( TEndLoopEvent( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_BeforeGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_AfterGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_BeforeLoop( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +void fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_AfterLoop( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +typename fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +TFrontId fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_GetMark( const TNode& v ) +{ + return( this->_GetMark( v.Vertex ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +bool fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_NeedToStop( ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +typename fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +TVertices fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_GetNeighborhood( const TNode& n ) const +{ + return( this->_GetNeighborhood( n.Vertex ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TFilter, class _TVertexCompare > +bool fpa::Base:: +Algorithm< _TVertex, _TScalar, _TFilter, _TVertexCompare >:: +_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( false ); + ma--; + mb--; + + // Mark collision, if it is new + 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; + + // Stop if one front is desired + if( this->m_StopAtOneFront ) + { + // Perform a depth-first iteration on front graph + unsigned long N = this->GetNumberOfSeeds( ); + 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 + ret = ( count == N ); + this->InvokeEvent( TCollisionEvent( a, ma + 1 ) ); + this->InvokeEvent( TCollisionEvent( b, mb + 1 ) ); + + } // fi + + } // fi + return( ret ); +} + +#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..d4f27cd --- /dev/null +++ b/lib/fpa/Base/Dijkstra.h @@ -0,0 +1,101 @@ +#ifndef __FPA__BASE__DIJKSTRA__H__ +#define __FPA__BASE__DIJKSTRA__H__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TSuperclass > + class Dijkstra + : public _TSuperclass + { + public: + typedef Dijkstra Self; + typedef _TSuperclass Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Template arguments + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TFilter TFilter; + typedef typename Superclass::TVertexCompare TVertexCompare; + typedef typename Superclass::TFrontId TFrontId; + typedef typename Superclass::TCollision TCollision; + typedef typename Superclass::TCollisionsRow TCollisionsRow; + typedef typename Superclass::TCollisions TCollisions; + typedef typename Superclass::TNodeLabel TNodeLabel; + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TNodes TNodes; + typedef typename Superclass::TVertices TVertices; + + typedef itk::FunctionBase< TScalar, TScalar > TCostConversionFunction; + + typedef + fpa::Base::MinimumSpanningTree< TVertex, TScalar, TVertexCompare > + TMinimumSpanningTree; + + struct TDijkstraCmp + { + bool operator()( const TNode& a, const TNode& b ) + { return( b.Result < a.Result ); } + }; + static const TDijkstraCmp DijkstraCmp; + + public: + itkTypeMacro( Dijkstra, Algorithm ); + + itkGetObjectMacro( CostConversionFunction, TCostConversionFunction ); + itkSetObjectMacro( CostConversionFunction, TCostConversionFunction ); + + public: + TMinimumSpanningTree* GetMinimumSpanningTree( ); + const TMinimumSpanningTree* GetMinimumSpanningTree( ) const; + void GraftMinimumSpanningTree( itk::DataObject* obj ); + + protected: + // Methods to extend itk-based architecture + Dijkstra( ); + virtual ~Dijkstra( ); + + // Front propagation methods to be overloaded + virtual void _AfterGenerateData( ) fpa_OVERRIDE; + virtual void _Visit( const TNode& n ) fpa_OVERRIDE; + virtual bool _Result( TNode& node, const TNode& parent ) fpa_OVERRIDE; + virtual void _QueueClear( ) fpa_OVERRIDE; + virtual void _QueuePush( const TNode& node ) fpa_OVERRIDE; + virtual TNode _QueuePop( ) fpa_OVERRIDE; + virtual bool _IsQueueEmpty( ) const fpa_OVERRIDE; + + // Dijkstra methods to be overloaded + virtual TScalar _Cost( const TVertex& a, const TVertex& b ) const = 0; + + private: + // Purposely not implemented + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_MSTIdx; + std::vector< TNode > m_Queue; + typename TCostConversionFunction::Pointer m_CostConversionFunction; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif + +#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..25a7bd9 --- /dev/null +++ b/lib/fpa/Base/Dijkstra.hxx @@ -0,0 +1,144 @@ +#ifndef __FPA__BASE__DIJKSTRA__HXX__ +#define __FPA__BASE__DIJKSTRA__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +const typename fpa::Base::Dijkstra< _TSuperclass >::TDijkstraCmp +fpa::Base::Dijkstra< _TSuperclass >::DijkstraCmp = +fpa::Base::Dijkstra< _TSuperclass >::TDijkstraCmp( ); + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +typename fpa::Base::Dijkstra< _TSuperclass >:: +TMinimumSpanningTree* fpa::Base::Dijkstra< _TSuperclass >:: +GetMinimumSpanningTree( ) +{ + return( + dynamic_cast< TMinimumSpanningTree* >( + this->itk::ProcessObject::GetOutput( this->m_MSTIdx ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +const typename fpa::Base::Dijkstra< _TSuperclass >:: +TMinimumSpanningTree* fpa::Base::Dijkstra< _TSuperclass >:: +GetMinimumSpanningTree( ) const +{ + return( + dynamic_cast< const TMinimumSpanningTree* >( + this->itk::ProcessObject::GetOutput( this->m_MSTIdx ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +void fpa::Base::Dijkstra< _TSuperclass >:: +GraftMinimumSpanningTree( itk::DataObject* obj ) +{ + TMinimumSpanningTree* mst = dynamic_cast< TMinimumSpanningTree* >( obj ); + if( mst != NULL ) + this->GraftNthOutput( this->m_MSTIdx, mst ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +fpa::Base::Dijkstra< _TSuperclass >:: +Dijkstra( ) + : Superclass( ), + m_CostConversionFunction( NULL ) +{ + this->m_MSTIdx = this->GetNumberOfRequiredOutputs( ); + this->SetNumberOfRequiredOutputs( this->m_MSTIdx + 1 ); + typename TMinimumSpanningTree::Pointer mst = TMinimumSpanningTree::New( ); + this->itk::ProcessObject::SetNthOutput( this->m_MSTIdx, mst ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +fpa::Base::Dijkstra< _TSuperclass >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +void fpa::Base::Dijkstra< _TSuperclass >:: +_AfterGenerateData( ) +{ + this->Superclass::_AfterGenerateData( ); + this->GetMinimumSpanningTree( )->SetCollisions( this->m_Collisions ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +void fpa::Base::Dijkstra< _TSuperclass >:: +_Visit( const TNode& n ) +{ + this->Superclass::_Visit( n ); + this->GetMinimumSpanningTree( )->SetNode( + n.Vertex, n.Parent, n.FrontId, n.Result + ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +bool fpa::Base::Dijkstra< _TSuperclass >:: +_Result( TNode& node, const TNode& parent ) +{ + node.Result = this->_Cost( node.Vertex, parent.Vertex ); + if( node.Result >= TScalar( 0 ) ) + { + if( this->m_CostConversionFunction.IsNotNull( ) ) + node.Result = this->m_CostConversionFunction->Evaluate( node.Result ); + node.Result += parent.Result; + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +void fpa::Base::Dijkstra< _TSuperclass >:: +_QueueClear( ) +{ + this->m_Queue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +void fpa::Base::Dijkstra< _TSuperclass >:: +_QueuePush( const TNode& node ) +{ + this->m_Queue.push_back( node ); + std::push_heap( this->m_Queue.begin( ), this->m_Queue.end( ), DijkstraCmp ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +typename fpa::Base::Dijkstra< _TSuperclass >:: +TNode fpa::Base::Dijkstra< _TSuperclass >:: +_QueuePop( ) +{ + std::pop_heap( this->m_Queue.begin( ), this->m_Queue.end( ), DijkstraCmp ); + TNode n = this->m_Queue.back( ); + this->m_Queue.pop_back( ); + return( n ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +bool fpa::Base::Dijkstra< _TSuperclass >:: +_IsQueueEmpty( ) const +{ + return( this->m_Queue.size( ) == 0 ); +} + +#endif // __FPA__BASE__DIJKSTRA__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Events.h b/lib/fpa/Base/Events.h new file mode 100644 index 0000000..09f0637 --- /dev/null +++ b/lib/fpa/Base/Events.h @@ -0,0 +1,103 @@ +#ifndef __FPA__BASE__EVENTS__H__ +#define __FPA__BASE__EVENTS__H__ + +#include +#include + +// ------------------------------------------------------------------------- +#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 V > + class BaseEventWithVertex + : public BaseEvent + { + public: + BaseEventWithVertex( ) + : BaseEvent( ) + { } + BaseEventWithVertex( const V& 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< V >* >( e ) != NULL + ); + } + itk::EventObject* MakeObject( ) const + { return( new BaseEventWithVertex< V >( ) ); } + + public: + V Vertex; + long FrontId; + }; + + } // ecapseman + +} // ecapseman + +#endif // __FPA__BASE__EVENTS__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/GaussianCost.h b/lib/fpa/Base/Functors/GaussianCost.h new file mode 100644 index 0000000..d5c860c --- /dev/null +++ b/lib/fpa/Base/Functors/GaussianCost.h @@ -0,0 +1,74 @@ +#ifndef __FPA__BASE__FUNCTORS__GAUSSIANCOST__H__ +#define __FPA__BASE__FUNCTORS__GAUSSIANCOST__H__ + +#include +#include +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + /** + */ + template< class _TResult > + class GaussianCost + : public itk::FunctionBase< _TResult, _TResult > + { + public: + typedef GaussianCost Self; + typedef itk::FunctionBase< _TResult, _TResult > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Template arguments + typedef _TResult TResult; + typedef + cpExtensions::Algorithms::IterativeGaussianModelEstimator< TResult, 1 > + TModel; + + public: + itkNewMacro( Self ); + itkTypeMacro( GaussianCost, Algorithm ); + + itkGetConstMacro( SupportSize, unsigned int ); + itkGetConstMacro( MinimumCost, _TResult ); + itkGetObjectMacro( Model, TModel ); + itkGetConstObjectMacro( Model, TModel ); + itkSetMacro( SupportSize, unsigned int ); + itkSetMacro( MinimumCost, _TResult ); + + public: + virtual _TResult Evaluate( const _TResult& x ) const fpa_OVERRIDE; + + protected: + // Methods to extend itk-based architecture + GaussianCost( ); + virtual ~GaussianCost( ); + + private: + // Purposely not implemented + GaussianCost( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_SupportSize; + _TResult m_MinimumCost; + typename TModel::Pointer m_Model; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __FPA__BASE__FUNCTORS__GAUSSIANCOST__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/GaussianCost.hxx b/lib/fpa/Base/Functors/GaussianCost.hxx new file mode 100644 index 0000000..de14605 --- /dev/null +++ b/lib/fpa/Base/Functors/GaussianCost.hxx @@ -0,0 +1,49 @@ +#ifndef __FPA__BASE__FUNCTORS__GAUSSIANCOST__HXX__ +#define __FPA__BASE__FUNCTORS__GAUSSIANCOST__HXX__ + +// ------------------------------------------------------------------------- +template< class _TResult > +_TResult fpa::Base::Functors::GaussianCost< _TResult >:: +Evaluate( const _TResult& x ) const +{ + _TResult r = _TResult( 0 ); + if( this->m_Model->GetNumberOfSamples( ) > this->m_SupportSize ) + { + r = this->m_Model->SquaredMahalanobis( x ); + if( r <= _TResult( 1 ) ) + this->m_Model->AddSample( x ); + } + else + { + this->m_Model->AddSample( x ); + if( this->m_Model->GetNumberOfSamples( ) > 2 ) + r = this->m_Model->SquaredMahalanobis( x ); + + } // fi + if( r < this->m_MinimumCost ) + return( this->m_MinimumCost ); + else + return( r ); +} + +// ------------------------------------------------------------------------- +template< class _TResult > +fpa::Base::Functors::GaussianCost< _TResult >:: +GaussianCost( ) + : Superclass( ), + m_SupportSize( 30 ), + m_MinimumCost( _TResult( 1e-10 ) ) +{ + this->m_Model = TModel::New( ); +} + +// ------------------------------------------------------------------------- +template< class _TResult > +fpa::Base::Functors::GaussianCost< _TResult >:: +~GaussianCost( ) +{ +} + +#endif // __FPA__BASE__FUNCTORS__GAUSSIANCOST__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/InvertCost.h b/lib/fpa/Base/Functors/InvertCost.h new file mode 100644 index 0000000..7ff9366 --- /dev/null +++ b/lib/fpa/Base/Functors/InvertCost.h @@ -0,0 +1,58 @@ +#ifndef __FPA__BASE__FUNCTORS__INVERTCOST__H__ +#define __FPA__BASE__FUNCTORS__INVERTCOST__H__ + +#include +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + /** + */ + template< class _TResult > + class InvertCost + : public itk::FunctionBase< _TResult, _TResult > + { + public: + typedef InvertCost Self; + typedef itk::FunctionBase< _TResult, _TResult > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Template arguments + typedef _TResult TResult; + + public: + itkNewMacro( Self ); + itkTypeMacro( InvertCost, Algorithm ); + + public: + virtual _TResult Evaluate( const _TResult& x ) const fpa_OVERRIDE; + + protected: + // Methods to extend itk-based architecture + InvertCost( ); + virtual ~InvertCost( ); + + private: + // Purposely not implemented + InvertCost( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __FPA__BASE__FUNCTORS__INVERTCOST__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/InvertCost.hxx b/lib/fpa/Base/Functors/InvertCost.hxx new file mode 100644 index 0000000..9e8d832 --- /dev/null +++ b/lib/fpa/Base/Functors/InvertCost.hxx @@ -0,0 +1,29 @@ +#ifndef __FPA__BASE__FUNCTORS__INVERTCOST__HXX__ +#define __FPA__BASE__FUNCTORS__INVERTCOST__HXX__ + +// ------------------------------------------------------------------------- +template< class _TResult > +_TResult fpa::Base::Functors::InvertCost< _TResult >:: +Evaluate( const _TResult& x ) const +{ + return( _TResult( 1 ) / ( _TResult( 1 ) + x ) ); +} + +// ------------------------------------------------------------------------- +template< class _TResult > +fpa::Base::Functors::InvertCost< _TResult >:: +InvertCost( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TResult > +fpa::Base::Functors::InvertCost< _TResult >:: +~InvertCost( ) +{ +} + +#endif // __FPA__BASE__FUNCTORS__INVERTCOST__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MinimumSpanningTree.h b/lib/fpa/Base/MinimumSpanningTree.h new file mode 100644 index 0000000..dc0c6d1 --- /dev/null +++ b/lib/fpa/Base/MinimumSpanningTree.h @@ -0,0 +1,101 @@ +#ifndef __FPA__BASE__MINIMUMSPANNINGTREE__H__ +#define __FPA__BASE__MINIMUMSPANNINGTREE__H__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TVertex, class _TScalar, class _TVertexCompare = std::less< _TVertex > > + class MinimumSpanningTree + : public itk::SimpleDataObjectDecorator< std::map< _TVertex, std::pair< _TVertex, std::pair< _TScalar, long > >, _TVertexCompare > > + { + public: + typedef std::pair< _TScalar, long > TData; + typedef std::pair< _TVertex, TData > TParent; + typedef std::map< _TVertex, TParent, _TVertexCompare > TContainer; + typedef itk::SimpleDataObjectDecorator< TContainer > Superclass; + typedef MinimumSpanningTree Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef _TScalar TScalar; + typedef _TVertexCompare TVertexCompare; + + typedef std::vector< TVertex > TVertices; + typedef std::pair< TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + + typedef std::multimap< double, _TVertex > TNodeQueue; + + protected: + typedef std::vector< unsigned long > _TRow; + typedef std::vector< _TRow > _TMatrix; + + public: + itkNewMacro( Self ); + itkTypeMacro( MinimumSpanningTree, itk::SimpleDataObjectDecorator ); + + itkBooleanMacro( FillNodeQueue ); + + itkGetConstReferenceMacro( Collisions, TCollisions ); + itkGetConstReferenceMacro( NodeQueue, TNodeQueue ); + itkGetConstMacro( FillNodeQueue, bool ); + + itkSetMacro( FillNodeQueue, bool ); + + public: + void SetCollisions( const TCollisions& collisions ); + TVertices GetPath( const _TVertex& a ) const; + TVertices GetPath( const _TVertex& a, const _TVertex& b ) const; + + virtual void SetNode( + const _TVertex& vertex, + const _TVertex& parent, + const long& fid = -1, + const _TScalar& result = _TScalar( 0 ) + ); + virtual void Clear( ); + + protected: + MinimumSpanningTree( ); + virtual ~MinimumSpanningTree( ); + + virtual bool _HasVertex( const _TVertex& a ) const; + virtual long _FrontId( const _TVertex& a ) const; + virtual void _Path( TVertices& path, const _TVertex& a ) const; + + private: + // Purposely not implemented + MinimumSpanningTree( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TCollisions m_Collisions; + _TMatrix m_FrontPaths; + TNodeQueue m_NodeQueue; + bool m_FillNodeQueue; + + static const unsigned long INF_VALUE; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif + +#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..2f0a4b1 --- /dev/null +++ b/lib/fpa/Base/MinimumSpanningTree.hxx @@ -0,0 +1,278 @@ +#ifndef __FPA__BASE__MINIMUMSPANNINGTREE__HXX__ +#define __FPA__BASE__MINIMUMSPANNINGTREE__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +const unsigned long fpa::Base:: +MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >::INF_VALUE = + std::numeric_limits< unsigned long >::max( ); + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +void fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +SetCollisions( const TCollisions& collisions ) +{ + // Prepare a front graph + this->m_Collisions = collisions; + unsigned long nSeeds = this->m_Collisions.size( ); + _TMatrix dist( nSeeds, _TRow( nSeeds, Self::INF_VALUE ) ); + this->m_FrontPaths = dist; + for( unsigned long i = 0; i < nSeeds; ++i ) + { + for( unsigned long j = 0; j < nSeeds; ++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 < nSeeds; ++k ) + { + for( unsigned long i = 0; i < nSeeds; ++i ) + { + for( unsigned long j = 0; j < nSeeds; ++j ) + { + // WARNING: you don't want a numeric overflow!!! + unsigned long dik = dist[ i ][ k ]; + unsigned long dkj = dist[ k ][ j ]; + unsigned long sum = Self::INF_VALUE; + if( dik < Self::INF_VALUE && dkj < Self::INF_VALUE ) + 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 _TScalar, class _TVertexCompare > +typename +fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +TVertices +fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +GetPath( const _TVertex& a ) const +{ + TVertices path; + if( this->_HasVertex( a ) ) + this->_Path( path, a ); + return( path ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +typename +fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +TVertices +fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +GetPath( const _TVertex& a, const _TVertex& b ) const +{ + TVertices path; + + // Check existence + if( !this->_HasVertex( a ) || !this->_HasVertex( b ) ) + return( path ); + + // Get front ids + long fa = this->_FrontId( a ) - 1; + long fb = this->_FrontId( b ) - 1; + + if( fa == fb ) + { + // Get paths + TVertices ap, bp; + this->_Path( ap, a ); + this->_Path( bp, b ); + + // Ignore common part: find common ancestor + auto raIt = ap.rbegin( ); + auto rbIt = bp.rbegin( ); + while( *raIt == *rbIt && raIt != ap.rend( ) && rbIt != bp.rend( ) ) + { + ++raIt; + ++rbIt; + + } // elihw + if( raIt != ap.rbegin( ) ) --raIt; + if( rbIt != bp.rbegin( ) ) --rbIt; + + // Add part from a + for( auto iaIt = ap.begin( ); iaIt != ap.end( ) && *iaIt != *raIt; ++iaIt ) + path.push_back( *iaIt ); + + // Add part from b + for( ; rbIt != bp.rend( ); ++rbIt ) + path.push_back( *rbIt ); + } + else + { + // Use this->m_FrontPaths from Floyd-Warshall + if( this->m_FrontPaths[ fa ][ fb ] < Self::INF_VALUE ) + { + // Compute front path + std::vector< long > fpath; + fpath.push_back( fa ); + while( fa != fb ) + { + fa = this->m_FrontPaths[ fa ][ fb ]; + fpath.push_back( fa ); + + } // 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( ) ); + + // Remove repeated vertices + auto p = path.begin( ); + auto q = p; + q++; + while( q != path.end( ) ) + { + if( *q == *p ) + { + p = path.erase( p ); + q = p; + } + else + ++p; + ++q; + + } // elihw + + } // fi + + } // fi + + } // fi + return( path ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +void fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +SetNode( + const _TVertex& vertex, const _TVertex& parent, + const long& fid, const _TScalar& result + ) +{ + this->Get( )[ vertex ] = TParent( parent, TData( result, fid ) ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +void fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +Clear( ) +{ + this->Get( ).clear( ); + this->m_NodeQueue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +MinimumSpanningTree( ) + : Superclass( ), + m_FillNodeQueue( false ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +~MinimumSpanningTree( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +bool fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +_HasVertex( const _TVertex& a ) const +{ + return( this->Get( ).find( a ) != this->Get( ).end( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +long fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +_FrontId( const _TVertex& a ) const +{ + static const long MAX_ID = std::numeric_limits< long >::max( ); + auto i = this->Get( ).find( a ); + if( i != this->Get( ).end( ) ) + return( i->second.second.second ); + else + return( MAX_ID ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TScalar, class _TVertexCompare > +void fpa::Base::MinimumSpanningTree< _TVertex, _TScalar, _TVertexCompare >:: +_Path( TVertices& path, const _TVertex& a ) const +{ + auto& m = this->Get( ); + auto it = m.find( a ); + if( it != m.end( ) ) + { + do + { + path.push_back( it->first ); + it = m.find( it->second.first ); + + } while( it->first != it->second.first ); + path.push_back( it->first ); + + } // fi +} + +#endif // __FPA__BASE__MINIMUMSPANNINGTREE__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/RegionGrow.h b/lib/fpa/Base/RegionGrow.h new file mode 100644 index 0000000..615059f --- /dev/null +++ b/lib/fpa/Base/RegionGrow.h @@ -0,0 +1,85 @@ +#ifndef __FPA__BASE__REGIONGROW__H__ +#define __FPA__BASE__REGIONGROW__H__ + +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TSuperclass > + class RegionGrow + : public _TSuperclass + { + public: + typedef RegionGrow Self; + typedef _TSuperclass Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Template arguments + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TFilter TFilter; + typedef typename Superclass::TVertexCompare TVertexCompare; + typedef typename Superclass::TFrontId TFrontId; + typedef typename Superclass::TCollision TCollision; + typedef typename Superclass::TCollisionsRow TCollisionsRow; + typedef typename Superclass::TCollisions TCollisions; + typedef typename Superclass::TNodeLabel TNodeLabel; + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TNodes TNodes; + typedef typename Superclass::TVertices TVertices; + + typedef itk::FunctionBase< TVertex, bool > TRegionGrowFunction; + + public: + itkTypeMacro( RegionGrow, Algorithm ); + + itkGetObjectMacro( RegionGrowFunction, TRegionGrowFunction ); + itkGetConstMacro( InsideValue, TScalar ); + itkGetConstMacro( OutsideValue, TScalar ); + + itkSetObjectMacro( RegionGrowFunction, TRegionGrowFunction ); + itkSetMacro( InsideValue, TScalar ); + itkSetMacro( OutsideValue, TScalar ); + + protected: + // Methods to extend itk-based architecture + RegionGrow( ); + virtual ~RegionGrow( ); + + // Front propagation methods to be overloaded + virtual bool _Result( TNode& node, const TNode& parent ) fpa_OVERRIDE; + virtual void _QueueClear( ) fpa_OVERRIDE; + virtual void _QueuePush( const TNode& node ) fpa_OVERRIDE; + virtual TNode _QueuePop( ) fpa_OVERRIDE; + virtual bool _IsQueueEmpty( ) const fpa_OVERRIDE; + + private: + // Purposely not implemented + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); + + protected: + std::deque< TNode > m_Queue; + typename TRegionGrowFunction::Pointer m_RegionGrowFunction; + TScalar m_InsideValue; + TScalar m_OutsideValue; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif + +#endif // __FPA__BASE__REGIONGROW__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/RegionGrow.hxx b/lib/fpa/Base/RegionGrow.hxx new file mode 100644 index 0000000..c0f8a67 --- /dev/null +++ b/lib/fpa/Base/RegionGrow.hxx @@ -0,0 +1,78 @@ +#ifndef __FPA__BASE__REGIONGROW__HXX__ +#define __FPA__BASE__REGIONGROW__HXX__ + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +fpa::Base::RegionGrow< _TSuperclass >:: +RegionGrow( ) + : Superclass( ), + m_RegionGrowFunction( NULL ), + m_InsideValue( TScalar( 1 ) ), + m_OutsideValue( TScalar( 0 ) ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +fpa::Base::RegionGrow< _TSuperclass >:: +~RegionGrow( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +bool fpa::Base::RegionGrow< _TSuperclass >:: +_Result( TNode& node, const TNode& parent ) +{ + if( this->m_RegionGrowFunction.IsNotNull( ) ) + { + bool res = this->m_RegionGrowFunction->Evaluate( node.Vertex ); + node.Result = ( res )? this->m_InsideValue: this->m_OutsideValue; + return( res ); + } + else + { + node.Result = this->m_OutsideValue; + return( false ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +void fpa::Base::RegionGrow< _TSuperclass >:: +_QueueClear( ) +{ + this->m_Queue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +void fpa::Base::RegionGrow< _TSuperclass >:: +_QueuePush( const TNode& node ) +{ + this->m_Queue.push_back( node ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +typename fpa::Base::RegionGrow< _TSuperclass >:: +TNode fpa::Base::RegionGrow< _TSuperclass >:: +_QueuePop( ) +{ + TNode n = this->m_Queue.front( ); + this->m_Queue.pop_front( ); + return( n ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +bool fpa::Base::RegionGrow< _TSuperclass >:: +_IsQueueEmpty( ) const +{ + return( this->m_Queue.size( ) == 0 ); +} + +#endif // __FPA__BASE__REGIONGROW__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Config.cxx b/lib/fpa/Config.cxx new file mode 100644 index 0000000..b2649cd --- /dev/null +++ b/lib/fpa/Config.cxx @@ -0,0 +1,10 @@ +#include +#include + +// ------------------------------------------------------------------------- +std::string fpa_EXPORT GetVersion( ) +{ + return( fpa_VERSION ); +} + +// eof - $RCSfile$ diff --git a/lib/fpa/Config.h.in b/lib/fpa/Config.h.in new file mode 100644 index 0000000..470b31e --- /dev/null +++ b/lib/fpa/Config.h.in @@ -0,0 +1,39 @@ +#ifndef __fpa__h__ +#define __fpa__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__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Algorithm.h b/lib/fpa/Image/Algorithm.h new file mode 100644 index 0000000..2fd40bc --- /dev/null +++ b/lib/fpa/Image/Algorithm.h @@ -0,0 +1,96 @@ +#ifndef __FPA__IMAGE__ALGORITHM__H__ +#define __FPA__IMAGE__ALGORITHM__H__ + +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage > + class Algorithm + : public fpa::Base::Algorithm< typename _TInputImage::IndexType, typename _TOutputImage::PixelType, itk::ImageToImageFilter< _TInputImage, _TOutputImage >, typename _TInputImage::IndexType::LexicographicCompare > + { + public: + typedef fpa::Base::Algorithm< typename _TInputImage::IndexType, typename _TOutputImage::PixelType, itk::ImageToImageFilter< _TInputImage, _TOutputImage >, typename _TInputImage::IndexType::LexicographicCompare > Superclass; + typedef Algorithm Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Input types + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + itkConceptMacro( + ImagesSameDimension, + ( + itk::Concept:: + SameDimension< + TInputImage::ImageDimension, + TOutputImage::ImageDimension + > + ) + ); + + // Template arguments + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TFilter TFilter; + typedef typename Superclass::TVertexCompare TVertexCompare; + typedef typename Superclass::TFrontId TFrontId; + typedef typename Superclass::TCollision TCollision; + typedef typename Superclass::TCollisionsRow TCollisionsRow; + typedef typename Superclass::TCollisions TCollisions; + typedef typename Superclass::TNodeLabel TNodeLabel; + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TNodes TNodes; + typedef typename Superclass::TVertices TVertices; + + typedef itk::Image< TFrontId, TInputImage::ImageDimension > TMarkImage; + + public: + itkTypeMacro( Algorithm, _TFilter ); + + itkGetConstMacro( NeighborhoodOrder, unsigned short ); + itkSetMacro( NeighborhoodOrder, unsigned short ); + + protected: + // Methods to extend itk-imaged architecture + Algorithm( ); + virtual ~Algorithm( ); + + // Front propagation methods to be overloaded + virtual void _BeforeGenerateData( ) fpa_OVERRIDE; + virtual void _InitMarks( ) fpa_OVERRIDE; + virtual void _InitResults( ) fpa_OVERRIDE; + virtual void _DeallocateAuxiliary( ) fpa_OVERRIDE; + virtual TFrontId _GetMark( const TVertex& v ) fpa_OVERRIDE; + virtual void _Visit( const TNode& n ) fpa_OVERRIDE; + virtual TVertices _GetNeighborhood( + const TVertex& v + ) const fpa_OVERRIDE; + + private: + // Purposely not implemented + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned short m_NeighborhoodOrder; + typename TMarkImage::Pointer m_Marks; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif + +#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..07c09e6 --- /dev/null +++ b/lib/fpa/Image/Algorithm.hxx @@ -0,0 +1,133 @@ +#ifndef __FPA__IMAGE__ALGORITHM__HXX__ +#define __FPA__IMAGE__ALGORITHM__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +Algorithm( ) + : Superclass( ), + m_NeighborhoodOrder( 1 ) +{ +} + +// ------------------------------------------------------------------------- +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( ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_InitMarks( ) +{ + TOutputImage* out = this->GetOutput( ); + this->m_Marks = TMarkImage::New( ); + this->m_Marks->CopyInformation( out ); + this->m_Marks->SetRequestedRegion( out->GetRequestedRegion( ) ); + this->m_Marks->SetBufferedRegion( out->GetBufferedRegion( ) ); + this->m_Marks->Allocate( ); + this->m_Marks->FillBuffer( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_InitResults( ) +{ + this->GetOutput( )->FillBuffer( TScalar( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_DeallocateAuxiliary( ) +{ + this->m_Marks = NULL; +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +typename fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +TFrontId fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_GetMark( const TVertex& v ) +{ + if( this->m_Marks->GetRequestedRegion( ).IsInside( v ) ) + return( this->m_Marks->GetPixel( v ) ); + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_Visit( const TNode& n ) +{ + if( this->m_Marks->GetRequestedRegion( ).IsInside( n.Vertex ) ) + { + this->m_Marks->SetPixel( n.Vertex, n.FrontId ); + this->GetOutput( )->SetPixel( n.Vertex, n.Result ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +typename fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +TVertices fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_GetNeighborhood( const TVertex& v ) const +{ + TVertices neighs; + auto reg = this->GetInput( )->GetRequestedRegion( ); + if( this->m_NeighborhoodOrder == 1 ) + { + for( unsigned int d = 0; d < _TInputImage::ImageDimension; d++ ) + { + for( int i = -1; i <= 1; i += 2 ) + { + TVertex n = v; + n[ d ] += i; + if( reg.IsInside( n ) ) + neighs.push_back( n ); + + } // rof + + } // rof + } + else + { + typedef itk::ConstNeighborhoodIterator< _TInputImage > _TNeighIt; + typename _TInputImage::SizeType nSize; + nSize.Fill( 1 ); + + _TNeighIt nIt( nSize, this->GetInput( ), reg ); + nIt.SetLocation( v ); + for( unsigned int i = 0; i < nIt.Size( ); i++ ) + { + TVertex n = nIt.GetIndex( i ); + if( n == v ) + continue; + if( reg.IsInside( n ) ) + neighs.push_back( n ); + + } // rof + + } // fi + return( neighs ); +} + +#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..5c2460f --- /dev/null +++ b/lib/fpa/Image/Dijkstra.h @@ -0,0 +1,73 @@ +#ifndef __FPA__IMAGE__DIJKSTRA__H__ +#define __FPA__IMAGE__DIJKSTRA__H__ + +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage = _TInputImage > + class Dijkstra + : public fpa::Base::Dijkstra< fpa::Image::Algorithm< _TInputImage, _TOutputImage > > + { + public: + typedef fpa::Base::Dijkstra< fpa::Image::Algorithm< _TInputImage, _TOutputImage > > Superclass; + typedef Dijkstra Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Template arguments + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TFilter TFilter; + typedef typename Superclass::TVertexCompare TVertexCompare; + typedef typename Superclass::TFrontId TFrontId; + typedef typename Superclass::TCollision TCollision; + typedef typename Superclass::TCollisionsRow TCollisionsRow; + typedef typename Superclass::TCollisions TCollisions; + typedef typename Superclass::TNodeLabel TNodeLabel; + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TNodes TNodes; + typedef typename Superclass::TVertices TVertices; + + public: + itkNewMacro( Self ); + itkTypeMacro( Dijkstra, fpa::Base::Dijkstra ); + + itkBooleanMacro( UseImageSpacing ); + itkGetConstMacro( UseImageSpacing, bool ); + itkSetMacro( UseImageSpacing, bool ); + + protected: + Dijkstra( ); + virtual ~Dijkstra( ); + + // Dijkstra methods to be overloaded + virtual TScalar _Cost( + const TVertex& a, const TVertex& b + ) const fpa_OVERRIDE; + + private: + // Purposely not implemented + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + bool m_UseImageSpacing; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif + +#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..b81a533 --- /dev/null +++ b/lib/fpa/Image/Dijkstra.hxx @@ -0,0 +1,42 @@ +#ifndef __FPA__IMAGE__DIJKSTRA__HXX__ +#define __FPA__IMAGE__DIJKSTRA__HXX__ + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::Dijkstra< _TInputImage, _TOutputImage >:: +Dijkstra( ) + : Superclass( ), + m_UseImageSpacing( false ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::Dijkstra< _TInputImage, _TOutputImage >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +typename fpa::Image::Dijkstra< _TInputImage, _TOutputImage >:: +TScalar fpa::Image::Dijkstra< _TInputImage, _TOutputImage >:: +_Cost( const TVertex& a, const TVertex& b ) const +{ + auto input = this->GetInput( ); + TScalar coeff = TScalar( 1 ); + if( this->m_UseImageSpacing ) + { + typename _TInputImage::PointType pa, pb; + input->TransformIndexToPhysicalPoint( a, pa ); + input->TransformIndexToPhysicalPoint( b, pb ); + coeff = TScalar( pa.EuclideanDistanceTo( pb ) ); + + } // fi + TScalar va = TScalar( input->GetPixel( a ) ); + return( va * coeff ); +} + +#endif // __FPA__IMAGE__DIJKSTRA__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/MultiplyImageAndDistanceMap.h b/lib/fpa/Image/MultiplyImageAndDistanceMap.h new file mode 100644 index 0000000..3c42938 --- /dev/null +++ b/lib/fpa/Image/MultiplyImageAndDistanceMap.h @@ -0,0 +1,61 @@ +#ifndef __fpa__Image__MultiplyImageAndDistanceMap__h__ +#define __fpa__Image__MultiplyImageAndDistanceMap__h__ + +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInput, class _TDistanceMap > + class MultiplyImageAndDistanceMap + : public itk::ImageToImageFilter< _TInput, _TInput > + { + public: + typedef MultiplyImageAndDistanceMap Self; + typedef itk::ImageToImageFilter< _TInput, _TInput > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInput TInput; + typedef _TDistanceMap TDistanceMap; + + typedef typename TInput::RegionType TRegion; + + public: + itkNewMacro( Self ); + itkTypeMacro( MultiplyImageAndDistanceMap, itkImageToImageFilter ); + + public: + _TDistanceMap* GetDistanceMap( ); + const _TDistanceMap* GetDistanceMap( ) const; + void SetDistanceMap( _TDistanceMap* dmap ); + + protected: + MultiplyImageAndDistanceMap( ); + virtual ~MultiplyImageAndDistanceMap( ); + + virtual void ThreadedGenerateData( + const TRegion& region, + itk::ThreadIdType threadId + ) fpa_OVERRIDE; + + private: + // Purposely not implemented. + MultiplyImageAndDistanceMap( const Self& ); + void operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__MultiplyImageAndDistanceMap__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/MultiplyImageAndDistanceMap.hxx b/lib/fpa/Image/MultiplyImageAndDistanceMap.hxx new file mode 100644 index 0000000..f78d2a1 --- /dev/null +++ b/lib/fpa/Image/MultiplyImageAndDistanceMap.hxx @@ -0,0 +1,105 @@ +#ifndef __fpa__Image__MultiplyImageAndDistanceMap__hxx__ +#define __fpa__Image__MultiplyImageAndDistanceMap__hxx__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TInput, class _TDistanceMap > +_TDistanceMap* +fpa::Image::MultiplyImageAndDistanceMap< _TInput, _TDistanceMap >:: +GetDistanceMap( ) +{ + return( + dynamic_cast< _TDistanceMap* >( + this->itk::ProcessObject::GetInput( 1 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TDistanceMap > +const _TDistanceMap* +fpa::Image::MultiplyImageAndDistanceMap< _TInput, _TDistanceMap >:: +GetDistanceMap( ) const +{ + return( + dynamic_cast< const _TDistanceMap* >( + this->itk::ProcessObject::GetInput( 1 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TDistanceMap > +void fpa::Image::MultiplyImageAndDistanceMap< _TInput, _TDistanceMap >:: +SetDistanceMap( _TDistanceMap* dmap ) +{ + this->itk::ProcessObject::SetNthInput( 1, dmap ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TDistanceMap > +fpa::Image::MultiplyImageAndDistanceMap< _TInput, _TDistanceMap >:: +MultiplyImageAndDistanceMap( ) + : Superclass( ) +{ + this->SetNumberOfRequiredInputs( 2 ); +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TDistanceMap > +fpa::Image::MultiplyImageAndDistanceMap< _TInput, _TDistanceMap >:: +~MultiplyImageAndDistanceMap( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInput, class _TDistanceMap > +void fpa::Image::MultiplyImageAndDistanceMap< _TInput, _TDistanceMap >:: +ThreadedGenerateData( const TRegion& region, itk::ThreadIdType threadId ) +{ + typedef typename _TInput::PixelType _TPixel; + const typename TRegion::SizeType& regionSize = region.GetSize( ); + if( regionSize[ 0 ] == 0 ) + return; + const _TInput* input = this->GetInput( ); + const _TDistanceMap* dmap = this->GetDistanceMap( ); + _TInput* output = this->GetOutput( ); + itk::ProgressReporter pr( this, threadId, region.GetNumberOfPixels( ) ); + + // Prepare iterators + itk::ImageRegionConstIteratorWithIndex< _TInput > iIt( input, region ); + itk::ImageRegionConstIteratorWithIndex< _TDistanceMap > dIt( dmap, region ); + itk::ImageRegionIteratorWithIndex< _TInput > oIt( output, region ); + iIt.GoToBegin( ); + dIt.GoToBegin( ); + oIt.GoToBegin( ); + for( + ; !iIt.IsAtEnd( ) && !dIt.IsAtEnd( ) && !oIt.IsAtEnd( ); + ++iIt, ++dIt, ++oIt + ) + { + double d = double( dIt.Get( ) ); + if( !( d >= double( 0 ) ) ) + { + /* TODO + double v = double( iIt.Get( ) ); + if( v >= 0 ) + oIt.Set( _TPixel( v / std::fabs( d ) ) ); + else + oIt.Set( _TPixel( v * std::fabs( d ) ) ); + */ + oIt.Set( _TPixel( 0 ) ); + } + else + oIt.Set( iIt.Get( ) ); + pr.CompletedPixel( ); + + } // rof +} + +#endif // __fpa__Image__MultiplyImageAndDistanceMap__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/RegionGrow.h b/lib/fpa/Image/RegionGrow.h new file mode 100644 index 0000000..cf05dd1 --- /dev/null +++ b/lib/fpa/Image/RegionGrow.h @@ -0,0 +1,47 @@ +#ifndef __FPA__IMAGE__REGIONGROW__H__ +#define __FPA__IMAGE__REGIONGROW__H__ + +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage = _TInputImage > + class RegionGrow + : public fpa::Base::RegionGrow< fpa::Image::Algorithm< _TInputImage, _TOutputImage > > + { + public: + typedef fpa::Base::RegionGrow< fpa::Image::Algorithm< _TInputImage, _TOutputImage > > Superclass; + typedef RegionGrow Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( RegionGrow, fpa::Base::RegionGrow ); + + protected: + RegionGrow( ); + virtual ~RegionGrow( ); + + private: + // Purposely not implemented + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif + +#endif // __FPA__IMAGE__REGIONGROW__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/RegionGrow.hxx b/lib/fpa/Image/RegionGrow.hxx new file mode 100644 index 0000000..17775e7 --- /dev/null +++ b/lib/fpa/Image/RegionGrow.hxx @@ -0,0 +1,21 @@ +#ifndef __FPA__IMAGE__REGIONGROW__HXX__ +#define __FPA__IMAGE__REGIONGROW__HXX__ + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::RegionGrow< _TInputImage, _TOutputImage >:: +RegionGrow( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +fpa::Image::RegionGrow< _TInputImage, _TOutputImage >:: +~RegionGrow( ) +{ +} + +#endif // __FPA__IMAGE__REGIONGROW__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/Observer2D.h b/lib/fpa/VTK/Image/Observer2D.h new file mode 100644 index 0000000..c8582bb --- /dev/null +++ b/lib/fpa/VTK/Image/Observer2D.h @@ -0,0 +1,89 @@ +#ifndef __FPA__VTK__IMAGE__OBSERVER2D__H__ +#define __FPA__VTK__IMAGE__OBSERVER2D__H__ + +#include +#include +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace VTK + { + namespace Image + { + /** + */ + template< class _TFilter, class _TRenderWindow > + class Observer2D + : public itk::Command + { + public: + typedef Observer2D Self; + typedef itk::Command Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TFilter TFilter; + typedef _TRenderWindow TRenderWindow; + typedef typename TFilter::TInputImage TImage; + typedef typename TFilter::TVertex TVertex; + + typedef std::set< TVertex > TVertices; + + public: + itkNewMacro( Self ); + itkTypeMacro( Observer2D, itkCommand ); + + itkGetConstMacro( RenderPercentage, double ); + itkSetMacro( RenderPercentage, double ); + + public: + void SetRenderWindow( _TRenderWindow* rw ); + void SetPixel( + typename TImage::IndexType idx, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha + ); + void Render( ); + void Execute( itk::Object* c, const itk::EventObject& e ) fpa_OVERRIDE + { this->Execute( ( const itk::Object* )( c ), e ); } + void Execute( const itk::Object* c, const itk::EventObject& e ) fpa_OVERRIDE; + + protected: + Observer2D( ); + virtual ~Observer2D( ); + + private: + // Purposely not implemented + Observer2D( const Self& ); + void operator=( const Self& ); + + protected: + vtkSmartPointer< vtkImageData > m_Stencil; + vtkSmartPointer< vtkImageActor > m_StencilActor; + + _TRenderWindow* m_RenderWindow; + unsigned long m_Count; + unsigned long m_RenderCount; + double m_RenderPercentage; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __FPA__VTK__IMAGE__OBSERVER2D__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/Observer2D.hxx b/lib/fpa/VTK/Image/Observer2D.hxx new file mode 100644 index 0000000..a7276ac --- /dev/null +++ b/lib/fpa/VTK/Image/Observer2D.hxx @@ -0,0 +1,226 @@ +#ifndef __FPA__VTK__IMAGE__OBSERVER2D__HXX__ +#define __FPA__VTK__IMAGE__OBSERVER2D__HXX__ + +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +void fpa::VTK::Image::Observer2D< _TFilter, _TRenderWindow >:: +SetRenderWindow( _TRenderWindow* rw ) +{ + this->m_RenderWindow = rw; +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +void fpa::VTK::Image::Observer2D< _TFilter, _TRenderWindow >:: +SetPixel( + typename TImage::IndexType idx, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha + ) +{ + this->m_Stencil->SetScalarComponentFromDouble + ( idx[ 0 ], idx[ 1 ], 0, 0, red ); + this->m_Stencil->SetScalarComponentFromDouble + ( idx[ 0 ], idx[ 1 ], 0, 1, green ); + this->m_Stencil->SetScalarComponentFromDouble + ( idx[ 0 ], idx[ 1 ], 0, 2, blue ); + this->m_Stencil->SetScalarComponentFromDouble + ( idx[ 0 ], idx[ 1 ], 0, 3, alpha ); + this->m_Stencil->Modified( ); + this->m_StencilActor->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +void fpa::VTK::Image::Observer2D< _TFilter, _TRenderWindow >:: +Render( ) +{ + if( this->m_RenderWindow != NULL ) + this->m_RenderWindow->Render( ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +void fpa::VTK::Image::Observer2D< _TFilter, _TRenderWindow >:: +Execute( const itk::Object* c, const itk::EventObject& e ) +{ + typedef typename _TFilter::TStartEvent _TStartEvent; + typedef typename _TFilter::TStartLoopEvent _TStartLoopEvent; + typedef typename _TFilter::TEndEvent _TEndEvent; + typedef typename _TFilter::TEndLoopEvent _TEndLoopEvent; + typedef typename _TFilter::TAliveEvent _TAliveEvent; + typedef typename _TFilter::TFrontEvent _TFrontEvent; + typedef typename _TFilter::TFreezeEvent _TFreezeEvent; + + typedef typename _TFilter::TStartBacktrackingEvent _TStartBacktrackingEvent; + typedef typename _TFilter::TEndBacktrackingEvent _TEndBacktrackingEvent; + typedef typename _TFilter::TBacktrackingEvent _TBacktrackingEvent; + + static unsigned char Colors[][4] = + { + { 0, 0, 127, 127 }, + { 0, 127, 127, 127 }, + { 127, 0, 127, 127 }, + { 127, 127, 0, 127 }, + { 0, 0, 63, 127 }, + { 0, 63, 63, 127 }, + { 63, 0, 63, 127 }, + { 63, 63, 0, 127 }, + { 63, 63, 127, 127 }, + { 63, 127, 127, 127 }, + { 127, 63, 127, 127 }, + { 127, 127, 63, 127 }, + { 127, 127, 63, 127 }, + { 127, 63, 63, 127 }, + { 63, 127, 63, 127 }, + { 63, 63, 127, 127 } + }; + + auto filter = dynamic_cast< const _TFilter* >( c ); + if( this->m_RenderWindow == NULL || filter == NULL ) + return; + + const _TStartEvent* startEvt = dynamic_cast< const _TStartEvent* >( &e ); + const _TStartBacktrackingEvent* startBackEvt = + dynamic_cast< const _TStartBacktrackingEvent* >( &e ); + if( startEvt != NULL || startBackEvt != NULL ) + { + const TImage* img = filter->GetInput( ); + unsigned int minD = TImage::ImageDimension; + minD = ( minD < 3 )? minD: 3; + + int e[ 6 ] = { 0 }; + typename TImage::RegionType reg = img->GetRequestedRegion( ); + for( unsigned int i = 0; i < minD; i++ ) + { + e[ ( i << 1 ) + 0 ] = reg.GetIndex( )[ i ]; + e[ ( i << 1 ) + 1 ] = reg.GetIndex( )[ i ] + reg.GetSize( )[ i ] - 1; + + } // rof + + typename TImage::SpacingType spac = img->GetSpacing( ); + double s[ 3 ] = { 1, 1, 1 }; + for( unsigned int i = 0; i < minD; i++ ) + s[ i ] = double( spac[ i ] ); + + typename TImage::PointType orig = img->GetOrigin( ); + double o[ 3 ] = { 0 }; + for( unsigned int i = 0; i < minD; i++ ) + o[ i ] = double( orig[ i ] ); + + this->m_Stencil->SetExtent( e ); + this->m_Stencil->SetSpacing( s ); + this->m_Stencil->SetOrigin( o ); + this->m_Stencil->AllocateScalars( VTK_UNSIGNED_CHAR, 4 ); + for( unsigned int i = 0; i < 3; i++ ) + this->m_Stencil->GetPointData( )-> + GetScalars( )->FillComponent( i, 255 ); + this->m_Stencil->GetPointData( )->GetScalars( )->FillComponent( 3, 0 ); + + this->m_StencilActor->SetInputData( this->m_Stencil ); + this->m_StencilActor->InterpolateOff( ); + + this->m_Count = 0; + this->m_RenderCount = reg.GetNumberOfPixels( ); + + vtkRenderer* ren = + this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); + ren->AddActor( this->m_StencilActor ); + return; + + } // fi + + const _TAliveEvent* aliveEvt = dynamic_cast< const _TAliveEvent* >( &e ); + const _TFrontEvent* frontEvt = dynamic_cast< const _TFrontEvent* >( &e ); + if( aliveEvt != NULL || frontEvt != NULL ) + { + if( aliveEvt != NULL ) + this->SetPixel( + aliveEvt->Vertex, + Colors[ aliveEvt->FrontId ][ 0 ], + Colors[ aliveEvt->FrontId ][ 1 ], + Colors[ aliveEvt->FrontId ][ 2 ], + Colors[ aliveEvt->FrontId ][ 3 ] + ); + else if( frontEvt != NULL ) + this->SetPixel( frontEvt->Vertex, 255, 0, 0, 255 ); + this->m_Count++; + + // Render visual debug + double per = double( this->m_RenderCount ) * this->m_RenderPercentage; + if( double( this->m_Count ) >= per ) + this->Render( ); + if( double( this->m_Count ) >= per ) + this->m_Count = 0; + + return; + + } // fi + + const _TEndEvent* endEvt = dynamic_cast< const _TEndEvent* >( &e ); + if( endEvt != NULL ) + { + vtkRenderer* ren = + this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); + ren->RemoveActor( this->m_StencilActor ); + this->Render( ); + return; + + } // fi + + const _TBacktrackingEvent* backEvt = + dynamic_cast< const _TBacktrackingEvent* >( &e ); + const _TEndBacktrackingEvent* endBackEvt = + dynamic_cast< const _TEndBacktrackingEvent* >( &e ); + if( backEvt != NULL ) + { + this->SetPixel( backEvt->Vertex, 0, 0, 255, 255 ); + return; + + } // fi + + if( endBackEvt != NULL ) + { + this->m_RenderWindow->Render( ); + /* TODO: DEBUG + std::cout << "Press enter: " << std::ends; + int aux; + std::cin >> aux; + */ + return; + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +fpa::VTK::Image::Observer2D< _TFilter, _TRenderWindow >:: +Observer2D( ) + : Superclass( ), + m_RenderWindow( NULL ), + m_RenderPercentage( double( 0.01 ) ) +{ + this->m_Stencil = vtkSmartPointer< vtkImageData >::New( ); + this->m_StencilActor = vtkSmartPointer< vtkImageActor >::New( ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +fpa::VTK::Image::Observer2D< _TFilter, _TRenderWindow >:: +~Observer2D( ) +{ +} + +#endif // __FPA__VTK__IMAGE__OBSERVER2D__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/Observer3D.h b/lib/fpa/VTK/Image/Observer3D.h new file mode 100644 index 0000000..84ceaa5 --- /dev/null +++ b/lib/fpa/VTK/Image/Observer3D.h @@ -0,0 +1,86 @@ +#ifndef __FPA__VTK__IMAGE__OBSERVER3D__H__ +#define __FPA__VTK__IMAGE__OBSERVER3D__H__ + +#include + +#include + +#include +#include +#include +#include + +namespace fpa +{ + namespace VTK + { + namespace Image + { + /** + */ + template< class _TFilter, class _TRenderWindow > + class Observer3D + : public itk::Command + { + public: + typedef Observer3D Self; + typedef itk::Command Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TFilter TFilter; + typedef _TRenderWindow TRenderWindow; + typedef typename TFilter::TInputImage TImage; + typedef typename TFilter::TVertex TVertex; + typedef typename TFilter::TVertexCompare TVertexCompare; + + typedef std::set< TVertex > TVertices; + + public: + itkNewMacro( Self ); + itkTypeMacro( Observer3D, itkCommand ); + + itkGetConstMacro( RenderPercentage, double ); + itkSetMacro( RenderPercentage, double ); + + public: + void SetRenderWindow( _TRenderWindow* rw ); + void Render( ); + void Execute( itk::Object* c, const itk::EventObject& e ) fpa_OVERRIDE + { this->Execute( ( const itk::Object* )( c ), e ); } + void Execute( const itk::Object* c, const itk::EventObject& e ) fpa_OVERRIDE; + + protected: + Observer3D( ); + virtual ~Observer3D( ); + + private: + Observer3D( const Self& ); // Not impl. + void operator=( const Self& ); // Not impl. + + protected: + vtkSmartPointer< vtkPolyData > m_PolyData; + vtkSmartPointer< vtkPolyDataMapper > m_PolyDataMapper; + vtkSmartPointer< vtkActor > m_PolyDataActor; + std::map< TVertex, unsigned long, TVertexCompare > m_PointsToReplace; + std::map< TVertex, unsigned long, TVertexCompare > m_PointsInFront; + + _TRenderWindow* m_RenderWindow; + unsigned long m_Count; + unsigned long m_RenderCount; + double m_RenderPercentage; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __FPA__VTK__IMAGE__OBSERVER3D__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/Observer3D.hxx b/lib/fpa/VTK/Image/Observer3D.hxx new file mode 100644 index 0000000..409f8a2 --- /dev/null +++ b/lib/fpa/VTK/Image/Observer3D.hxx @@ -0,0 +1,211 @@ +#ifndef __FPA__VTK__IMAGE__OBSERVER3D__HXX__ +#define __FPA__VTK__IMAGE__OBSERVER3D__HXX__ + +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +void fpa::VTK::Image::Observer3D< _TFilter, _TRenderWindow >:: +SetRenderWindow( _TRenderWindow* rw ) +{ + this->m_RenderWindow = rw; +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +void fpa::VTK::Image::Observer3D< _TFilter, _TRenderWindow >:: +Render( ) +{ + if( this->m_RenderWindow != NULL ) + this->m_RenderWindow->Render( ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +void fpa::VTK::Image::Observer3D< _TFilter, _TRenderWindow >:: +Execute( const itk::Object* c, const itk::EventObject& e ) +{ + typedef typename _TFilter::TStartEvent _TStartEvent; + typedef typename _TFilter::TStartLoopEvent _TStartLoopEvent; + typedef typename _TFilter::TEndEvent _TEndEvent; + typedef typename _TFilter::TEndLoopEvent _TEndLoopEvent; + typedef typename _TFilter::TAliveEvent _TAliveEvent; + typedef typename _TFilter::TFrontEvent _TFrontEvent; + typedef typename _TFilter::TFreezeEvent _TFreezeEvent; + + typedef typename _TFilter::TStartBacktrackingEvent _TStartBacktrackingEvent; + typedef typename _TFilter::TEndBacktrackingEvent _TEndBacktrackingEvent; + typedef typename _TFilter::TBacktrackingEvent _TBacktrackingEvent; + + static unsigned char Colors[][4] = + { + { 0, 0, 127, 127 }, + { 0, 127, 127, 127 }, + { 127, 0, 127, 127 }, + { 127, 127, 0, 127 }, + { 0, 0, 63, 127 }, + { 0, 63, 63, 127 }, + { 63, 0, 63, 127 }, + { 63, 63, 0, 127 }, + { 63, 63, 127, 127 }, + { 63, 127, 127, 127 }, + { 127, 63, 127, 127 }, + { 127, 127, 63, 127 }, + { 127, 127, 63, 127 }, + { 127, 63, 63, 127 }, + { 63, 127, 63, 127 }, + { 63, 63, 127, 127 } + }; + + auto filter = dynamic_cast< const _TFilter* >( c ); + if( this->m_RenderWindow == NULL || filter == NULL ) + return; + auto image = filter->GetInput( ); + if( image == NULL ) + return; + + const _TStartEvent* startEvt = dynamic_cast< const _TStartEvent* >( &e ); + const _TStartBacktrackingEvent* startBackEvt = + dynamic_cast< const _TStartBacktrackingEvent* >( &e ); + if( startEvt != NULL || startBackEvt != NULL ) + { + this->m_Count = 0; + this->m_RenderCount = + image->GetLargestPossibleRegion( ).GetNumberOfPixels( ); + this->m_PointsToReplace.clear( ); + this->m_PointsInFront.clear( ); + + vtkRenderer* ren = + this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); + ren->AddActor( this->m_PolyDataActor ); + return; + + } // fi + + const _TFrontEvent* frontEvt = dynamic_cast< const _TFrontEvent* >( &e ); + if( frontEvt != NULL ) + { + typename TImage::PointType pnt; + image->TransformIndexToPhysicalPoint( frontEvt->Vertex, pnt ); + if( this->m_PointsToReplace.empty( ) ) + { + unsigned long nPoints = this->m_PolyData->GetNumberOfPoints( ); + this->m_PolyData->GetPoints( )-> + InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + this->m_PolyData->GetVerts( )->InsertNextCell( 1 ); + this->m_PolyData->GetVerts( )->InsertCellPoint( nPoints ); + this->m_PointsInFront[ frontEvt->Vertex ] = nPoints; + } + else + { + auto pIt = this->m_PointsToReplace.begin( ); + this->m_PolyData->GetPoints( )-> + SetPoint( pIt->second, pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + this->m_PointsToReplace.erase( pIt ); + + } // fi + this->m_PolyData->Modified( ); + this->m_PolyDataMapper->Modified( ); + this->m_PolyDataActor->Modified( ); + + // Render visual debug + this->m_Count++; + double per = double( this->m_RenderCount ) * this->m_RenderPercentage; + if( double( this->m_Count ) >= per ) + this->Render( ); + if( double( this->m_Count ) >= per ) + this->m_Count = 0; + + return; + + } // fi + + const _TAliveEvent* aliveEvt = dynamic_cast< const _TAliveEvent* >( &e ); + if( aliveEvt != NULL ) + { + auto pIt = this->m_PointsInFront.find( aliveEvt->Vertex ); + if( pIt != this->m_PointsInFront.end( ) ) + { + this->m_PointsToReplace[ pIt->first ] = pIt->second; + this->m_PointsInFront.erase( pIt ); + + } // fi + return; + + } // fi + + const _TEndEvent* endEvt = dynamic_cast< const _TEndEvent* >( &e ); + if( endEvt != NULL ) + { + vtkRenderer* ren = + this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); + ren->RemoveActor( this->m_PolyDataActor ); + this->Render( ); + return; + + } // fi + + const _TBacktrackingEvent* backEvt = + dynamic_cast< const _TBacktrackingEvent* >( &e ); + const _TEndBacktrackingEvent* endBackEvt = + dynamic_cast< const _TEndBacktrackingEvent* >( &e ); + if( backEvt != NULL ) + { + // TODO: + return; + + } // fi + + if( endBackEvt != NULL ) + { + this->m_RenderWindow->Render( ); + + /* TODO: DEBUG + std::cout << "Press enter: " << std::ends; + int aux; + std::cin >> aux; + */ + return; + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +fpa::VTK::Image::Observer3D< _TFilter, _TRenderWindow >:: +Observer3D( ) + : Superclass( ), + m_RenderWindow( NULL ), + m_RenderPercentage( double( 0.000001 ) ) +{ + this->m_PolyData = vtkSmartPointer< vtkPolyData >::New( ); + this->m_PolyDataMapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_PolyDataActor =vtkSmartPointer< vtkActor >::New( ); + + vtkSmartPointer< vtkPoints > points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > verts = + vtkSmartPointer< vtkCellArray >::New( ); + this->m_PolyData->SetPoints( points ); + this->m_PolyData->SetVerts( verts ); + this->m_PolyDataMapper->SetInputData( this->m_PolyData ); + this->m_PolyDataActor->SetMapper( this->m_PolyDataMapper ); + this->m_PolyDataActor->GetProperty( )->SetColor( 0, 1, 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TRenderWindow > +fpa::VTK::Image::Observer3D< _TFilter, _TRenderWindow >:: +~Observer3D( ) +{ +} + +#endif // __FPA__VTK__IMAGE__OBSERVER3D__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/PathToPolyDataFilter.h b/lib/fpa/VTK/Image/PathToPolyDataFilter.h new file mode 100644 index 0000000..f454256 --- /dev/null +++ b/lib/fpa/VTK/Image/PathToPolyDataFilter.h @@ -0,0 +1,83 @@ +#ifndef __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__H__ +#define __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__H__ + +#include +#include + +namespace fpa +{ + namespace VTK + { + namespace Image + { + /** + */ + template< class _TMinimumSpanningTree > + class PathToPolyDataFilter + : public vtkPolyDataAlgorithm + { + public: + typedef PathToPolyDataFilter Self; + typedef _TMinimumSpanningTree TMinimumSpanningTree; + typedef typename TMinimumSpanningTree::TVertex TVertex; + typedef itk::ImageBase< TVertex::Dimension > TImage; + + public: + vtkTypeMacro( PathToPolyDataFilter, vtkPolyDataAlgorithm ); + + vtkGetMacro( Seed0, TVertex ); + vtkGetMacro( Seed1, TVertex ); + + vtkSetMacro( Seed0, TVertex ); + vtkSetMacro( Seed1, TVertex ); + + public: + static Self* New( ); + + const TMinimumSpanningTree* GetMinimumSpanningTree( ) const; + const TImage* GetImage( ) const; + void SetMinimumSpanningTree( const TMinimumSpanningTree* mst ); + void SetImage( const TImage* image ); + + protected: + PathToPolyDataFilter( ); + virtual ~PathToPolyDataFilter( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + virtual void _PrepareOutput( vtkPolyData* out ); + + private: + // Purposely not implemented + PathToPolyDataFilter( const Self& ); + void operator=( const Self& ); + + protected: + const TMinimumSpanningTree* m_MST; + const TImage* m_Image; + TVertex Seed0; + TVertex Seed1; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/PathToPolyDataFilter.hxx b/lib/fpa/VTK/Image/PathToPolyDataFilter.hxx new file mode 100644 index 0000000..d66fee6 --- /dev/null +++ b/lib/fpa/VTK/Image/PathToPolyDataFilter.hxx @@ -0,0 +1,178 @@ +#ifndef __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__HXX__ +#define __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__HXX__ + +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +typename fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +Self* fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +const typename fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +TMinimumSpanningTree* +fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +GetMinimumSpanningTree( ) const +{ + return( this->m_MST ); +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +const typename fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +TImage* fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +GetImage( ) const +{ + return( this->m_Image ); +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +void fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +SetMinimumSpanningTree( const TMinimumSpanningTree* mst ) +{ + if( this->m_MST != mst ) + { + this->m_MST = mst; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +void fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +SetImage( const TImage* image ) +{ + if( this->m_Image != image ) + { + this->m_Image = image; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +PathToPolyDataFilter( ) + : vtkPolyDataAlgorithm( ), + m_MST( NULL ), + m_Image( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +~PathToPolyDataFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +int fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + if( this->m_MST == NULL || this->m_Image == NULL ) + return( 0 ); + auto path = this->m_MST->GetPath( this->Seed0, this->Seed1 ); + if( path.size( ) == 0 ) + return( 0 ); + + // Prepare output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + this->_PrepareOutput( out ); + vtkPoints* points = out->GetPoints( ); + vtkCellArray* lines = out->GetLines( ); + + unsigned int i = 0; + for( auto pIt = path.begin( ); pIt != path.end( ); ++pIt, ++i ) + { + typename TImage::PointType p; + this->m_Image->TransformIndexToPhysicalPoint( *pIt, p ); + if( TImage::ImageDimension == 1 ) + points->InsertNextPoint( double( p[ 0 ] ), double( 0 ), double( 0 ) ); + else if( TImage::ImageDimension == 2 ) + points->InsertNextPoint( double( p[ 0 ] ), double( p[ 1 ] ), double( 0 ) ); + else if( TImage::ImageDimension > 2 ) + points->InsertNextPoint( double( p[ 0 ] ), double( p[ 1 ] ), double( p[ 2 ] ) ); + + if( i > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( i - 1 ); + lines->InsertCellPoint( i ); + + } // fi + + } // rof + out->Modified( ); + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +int fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + vtkInformation* out = output->GetInformationObject( 0 ); + out->Set( CAN_HANDLE_PIECE_REQUEST( ), 1 ); + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TMinimumSpanningTree > +void fpa::VTK::Image::PathToPolyDataFilter< _TMinimumSpanningTree >:: +_PrepareOutput( vtkPolyData* out ) +{ + // Prepare points + vtkPoints* points = out->GetPoints( ); + if( points == NULL ) + { + points = vtkPoints::New( ); + out->SetPoints( points ); + points->Delete( ); + + } // fi + + // Prepare points + vtkCellArray* lines = out->GetLines( ); + if( lines == NULL ) + { + lines = vtkCellArray::New( ); + out->SetLines( lines ); + out->SetVerts( vtkCellArray::New( ) ); + out->SetPolys( vtkCellArray::New( ) ); + out->SetStrips( vtkCellArray::New( ) ); + lines->Delete( ); + + } // fi +} + +#endif // __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..da88a5b --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,12 @@ +## ========================== +## == Build plugin library == +## ========================== +Wrap_cpPlugins( + _plugin + ${CMAKE_CURRENT_SOURCE_DIR}/Plugins + ${prj_VERSION} ${prj_SHORT_VERSION} + fpa + ) +TARGET_LINK_LIBRARIES(${_plugin} ${cpPlugins_LIB} ${fpa_Instances}) + +## eof - $RCSfile$ diff --git a/plugins/Plugins/BaseImageFilter.cxx b/plugins/Plugins/BaseImageFilter.cxx new file mode 100644 index 0000000..335f9e1 --- /dev/null +++ b/plugins/Plugins/BaseImageFilter.cxx @@ -0,0 +1,51 @@ +#include "BaseImageFilter.h" +#include + +// ------------------------------------------------------------------------- +bool fpaPlugins::BaseImageFilter:: +IsInteractive( ) +{ + return( true ); +} + +// ------------------------------------------------------------------------- +/* TODO + void fpaPlugins::BaseImageFilter:: + SetInteractionObjects( const std::vector< void* >& objs ) + { + if( objs.size( ) > 0 ) + this->m_SingleInteractor = + reinterpret_cast< vtkRenderWindowInteractor* >( objs[ 0 ] ); + if( objs.size( ) > 1 ) + this->m_MPRViewer = reinterpret_cast< TMPRWidget* >( objs[ 1 ] ); + } +*/ + +// ------------------------------------------------------------------------- +fpaPlugins::BaseImageFilter:: +BaseImageFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpPlugins::DataObjects::Image >( "Input", true, false ); + this->_ConfigureInput< cpPlugins::BaseObjects::DataObject >( "Seeds", true, false ); + this->_ConfigureOutput< cpPlugins::DataObjects::Image >( "Output" ); + + this->m_Parameters.ConfigureAsBool( "VisualDebug" ); + this->m_Parameters.ConfigureAsBool( "StopAtOneFront" ); + this->m_Parameters.SetBool( "VisualDebug", false ); + this->m_Parameters.SetBool( "StopAtOneFront", false ); + + std::vector< std::string > orders; + orders.push_back( "1" ); + orders.push_back( "2" ); + this->m_Parameters.ConfigureAsChoices( "NeighborhoodOrder", orders ); + this->m_Parameters.SetSelectedChoice( "NeighborhoodOrder", "1" ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::BaseImageFilter:: +~BaseImageFilter( ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/BaseImageFilter.h b/plugins/Plugins/BaseImageFilter.h new file mode 100644 index 0000000..93044e5 --- /dev/null +++ b/plugins/Plugins/BaseImageFilter.h @@ -0,0 +1,69 @@ +#ifndef __FPAPLUGINS__BASEIMAGEFILTER__H__ +#define __FPAPLUGINS__BASEIMAGEFILTER__H__ + +#include +#include +#include + +#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; + + typedef cpExtensions::QT::SimpleMPRWidget TMPRWidget; + + public: + itkTypeMacro( BaseImageFilter, cpPlugins::BaseObjects::ProcessObject ); + cpPlugins_Id_Macro( BaseImageFilter, fpaImageAlgorithm ); + + public: + virtual bool IsInteractive( ) fpa_OVERRIDE; + /* TODO + virtual void SetInteractionObjects( + const std::vector< void* >& objs + ) override; + */ + + protected: + BaseImageFilter( ); + virtual ~BaseImageFilter( ); + + 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 ); + + protected: + std::set< unsigned long > m_Observers; + }; + +} // ecapseman + +#include "BaseImageFilter.hxx" + +#endif // __FPAPLUGINS__BASEIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/BaseImageFilter.hxx b/plugins/Plugins/BaseImageFilter.hxx new file mode 100644 index 0000000..762f553 --- /dev/null +++ b/plugins/Plugins/BaseImageFilter.hxx @@ -0,0 +1,149 @@ +#ifndef __FPAPLUGINS__BASEIMAGEFILTER__HXX__ +#define __FPAPLUGINS__BASEIMAGEFILTER__HXX__ + +#include + +/* TODO + #include + #include +*/ +#include +#include + +// ------------------------------------------------------------------------- +template< class _TFilter > +_TFilter* fpaPlugins::BaseImageFilter:: +_ConfigureFilter( ) +{ + typedef typename _TFilter::TInputImage _TImage; + static const unsigned int Dim = _TImage::ImageDimension; + + auto image = this->GetInputData< _TImage >( "Input" ); + if( image == NULL ) + return( NULL ); + auto seeds = this->GetInputData< vtkPolyData >( "Seeds" )->GetPoints( ); + + // Create filter and connect input + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + + // Set numeric parameters + filter->SetNeighborhoodOrder( + this->m_Parameters.GetSelectedChoice( "NeighborhoodOrder" )[ 0 ] - '0' + ); + filter->SetStopAtOneFront( this->m_Parameters.GetBool( "StopAtOneFront" ) ); + + // Assign seeds + filter->RemoveAllSeeds( ); + if( seeds != NULL ) + { + typename _TImage::PointType pnt; + typename _TImage::IndexType idx; + unsigned int dim = + ( _TImage::ImageDimension < 3 )? _TImage::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 + + // Ok! + return( filter ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpaPlugins::BaseImageFilter:: +_ExecuteFilter( _TFilter* filter ) +{ + // Go!!! + this->_ConfigureDebugger( filter ); + filter->Update( ); + this->_DeconfigureDebugger( filter ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpaPlugins::BaseImageFilter:: +_ConfigureDebugger( _TFilter* filter ) +{ + typedef typename _TFilter::TInputImage _TImage; + typedef fpa::VTK::Image::Observer3D< _TFilter, vtkRenderWindow > _3D; + + /* TODO + typedef fpa::VTK::Image::Observer2D< _TFilter, vtkRenderWindow > _2D; + */ + + this->m_Observers.clear( ); + if( this->m_Parameters.GetBool( "VisualDebug" ) ) + { + if( _TImage::ImageDimension == 2 ) + { + } + else if( _TImage::ImageDimension == 3 ) + { + /* TODO + auto iren = this->m_MPRViewer->GetInteractor( 3 ); + if( iren != NULL ) + { + typename _3D::Pointer debugger = _3D::New( ); + debugger->SetRenderWindow( iren->GetRenderWindow( ) ); + debugger->SetRenderPercentage( 0.001 ); + this->m_Observers.insert( + filter->AddObserver( itk::AnyEvent( ), debugger ) + ); + filter->ThrowEventsOn( ); + + } // fi + */ + + } // fi + + /* TODO + if( this->m_SingleInteractor != NULL ) + { + if( _TImage::ImageDimension == 2 ) + { + } + else if( _TImage::ImageDimension == 3 ) + { + } // fi + + } // fi + + */ + } // fi +} + +// ------------------------------------------------------------------------- +template< class F > +void fpaPlugins::BaseImageFilter:: +_DeconfigureDebugger( F* filter ) +{ + /* TODO + if( filter != NULL ) + { + auto oIt = this->m_Observers.begin( ); + for( ; oIt != this->m_Observers.end( ); ++oIt ) + filter->RemoveObserver( *oIt ); + + } // fi + this->m_Observers.clear( ); + */ +} + +#endif // __FPAPLUGINS__BASEIMAGEFILTER__HXX__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/GaussianCostFunctor.cxx b/plugins/Plugins/GaussianCostFunctor.cxx new file mode 100644 index 0000000..874b025 --- /dev/null +++ b/plugins/Plugins/GaussianCostFunctor.cxx @@ -0,0 +1,59 @@ +#include "GaussianCostFunctor.h" + +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::GaussianCostFunctor:: +GaussianCostFunctor( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpPlugins::BaseObjects::DataObject >( "Output" ); + this->_ConfigureOutput< cpPlugins::BaseObjects::DataObject >( "Estimator" ); + 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" ); + this->m_Parameters.ConfigureAsUint( "SupportSize" ); + this->m_Parameters.ConfigureAsReal( "MinimumCost" ); + this->m_Parameters.SetUint( "SupportSize", 30 ); + this->m_Parameters.SetReal( "MinimumCost", 1e-5 ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::GaussianCostFunctor:: +~GaussianCostFunctor( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::GaussianCostFunctor:: +_GenerateData( ) +{ + auto rtype = this->m_Parameters.GetSelectedChoice( "ResultType" ); + if ( rtype == "float" ) this->_GD0< float >( ); + else if( rtype == "double" ) this->_GD0< double >( ); +} + +// ------------------------------------------------------------------------- +template< class _TResult > +void fpaPlugins::GaussianCostFunctor:: +_GD0( ) +{ + typedef fpa::Base::Functors::GaussianCost< _TResult > _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->SetSupportSize( this->m_Parameters.GetUint( "SupportSize" ) ); + f->SetMinimumCost( this->m_Parameters.GetReal( "MinimumCost" ) ); + this->GetOutput( "Estimator" )->SetITK( f->GetModel( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/GaussianCostFunctor.h b/plugins/Plugins/GaussianCostFunctor.h new file mode 100644 index 0000000..1a2a117 --- /dev/null +++ b/plugins/Plugins/GaussianCostFunctor.h @@ -0,0 +1,29 @@ +#ifndef __FPAPLUGINS__GAUSSIANCOSTFUNCTOR__H__ +#define __FPAPLUGINS__GAUSSIANCOSTFUNCTOR__H__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT GaussianCostFunctor + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + GaussianCostFunctor, + cpPlugins::BaseObjects::ProcessObject, + fpaFunctors + ); + + protected: + template< class _TResult > + inline void _GD0( ); + }; + +} // ecapseman + +#endif // __FPAPLUGINS__GAUSSIANCOSTFUNCTOR__H__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/ImageDijkstra.cxx b/plugins/Plugins/ImageDijkstra.cxx new file mode 100644 index 0000000..be69f49 --- /dev/null +++ b/plugins/Plugins/ImageDijkstra.cxx @@ -0,0 +1,86 @@ +#include "ImageDijkstra.h" +// TODO: #include "MinimumSpanningTree.h" + +#include +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::ImageDijkstra:: +ImageDijkstra( ) + : Superclass( ) +{ + this->_ConfigureInput< cpPlugins::BaseObjects::DataObject >( "CostFunctor", false, false ); + this->_ConfigureOutput< cpPlugins::BaseObjects::DataObject >( "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" ); + this->m_Parameters.ConfigureAsBool( "FillNodeQueue" ); + this->m_Parameters.SetBool( "FillNodeQueue", false ); +} + +// ------------------------------------------------------------------------- +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 ) +{ + 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 _TInputImage, class _TOutput > +void fpaPlugins::ImageDijkstra:: +_GD1( _TInputImage* input ) +{ + typedef itk::Image< _TOutput, _TInputImage::ImageDimension > _TOutputImage; + typedef fpa::Image::Dijkstra< _TInputImage, _TOutputImage > _TFilter; + typedef typename _TFilter::TCostConversionFunction _TCostFunctor; + + // Get functor + auto base_functor = + this->GetInputData< itk::LightObject >( "CostFunctor" ); + _TCostFunctor* functor = NULL; + if( base_functor != NULL ) + { + functor = dynamic_cast< _TCostFunctor* >( base_functor ); + if( functor == NULL ) + this->_Error( "Given cost functor is invalid." ); + + } // fi + + // Create filter + _TFilter* filter = this->_ConfigureFilter< _TFilter >( ); + // TODO: filter->SetFillNodeQueue( this->m_Parameters.GetBool( "FillNodeQueue" ) ); + filter->SetCostConversionFunction( functor ); + + // Go!!! + this->_ExecuteFilter( filter ); + + // Connect remaining output + 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..4fcb4b6 --- /dev/null +++ b/plugins/Plugins/ImageDijkstra.h @@ -0,0 +1,27 @@ +#ifndef __FPAPLUGINS__IMAGEDIJKSTRA__H__ +#define __FPAPLUGINS__IMAGEDIJKSTRA__H__ + +#include "BaseImageFilter.h" + +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 _TOutput > + inline void _GD1( _TInputImage* input ); + }; + +} // ecapseman + +#endif // __FPAPLUGINS__IMAGEDIJKSTRA__H__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/ImagePathToPolyDataFilter.cxx b/plugins/Plugins/ImagePathToPolyDataFilter.cxx new file mode 100644 index 0000000..eb0f689 --- /dev/null +++ b/plugins/Plugins/ImagePathToPolyDataFilter.cxx @@ -0,0 +1,99 @@ +#include "ImagePathToPolyDataFilter.h" +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::ImagePathToPolyDataFilter:: +ImagePathToPolyDataFilter( ) + : Superclass( ) +{ + this->_ConfigureInput< cpPlugins::BaseObjects::DataObject >( "MST", true, false ); + this->_ConfigureInput< cpPlugins::DataObjects::Image >( "Image", true, false ); + this->_ConfigureInput< cpPlugins::BaseObjects::DataObject >( "Seeds", true, false ); + this->_ConfigureOutput< cpPlugins::DataObjects::Mesh >( "Output" ); + + this->m_Parameters.ConfigureAsUint( "Seed0" ); + this->m_Parameters.ConfigureAsUint( "Seed1" ); + this->m_Parameters.SetUint( "Seed0", 0 ); + this->m_Parameters.SetUint( "Seed1", 1 ); +} + +// ------------------------------------------------------------------------- +fpaPlugins::ImagePathToPolyDataFilter:: +~ImagePathToPolyDataFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::ImagePathToPolyDataFilter:: +_GenerateData( ) +{ + auto i2 = this->GetInputData< itk::ImageBase< 2 > >( "Image" ); + auto i3 = this->GetInputData< itk::ImageBase< 3 > >( "Image" ); + if( i2 != NULL ) + this->_GD0( i2 ); + else if( i3 != NULL ) + this->_GD0( i3 ); + else + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void fpaPlugins::ImagePathToPolyDataFilter:: +_GD0( _TImage* image ) +{ + typedef typename _TImage::IndexType _TIndex; + typedef typename _TIndex::LexicographicCompare _TComp; + typedef fpa::Base::MinimumSpanningTree< _TIndex, float, _TComp > _TFloat; + typedef fpa::Base::MinimumSpanningTree< _TIndex, double, _TComp > _TDouble; + + auto mf = this->GetInputData< _TFloat >( "MST" ); + auto md = this->GetInputData< _TDouble >( "MST" ); + if( mf != NULL ) + this->_GD1( image, mf ); + else if( md != NULL ) + this->_GD1( image, md ); + else + this->_Error( "No valid input minimum spanning tree." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TMST > +void fpaPlugins::ImagePathToPolyDataFilter:: +_GD1( _TImage* image, _TMST* mst ) +{ + typedef fpa::VTK::Image::PathToPolyDataFilter< _TMST > _TFilter; + auto seeds = this->GetInputData< vtkPolyData >( "Seeds" )->GetPoints( ); + if( seeds->GetNumberOfPoints( ) < 2 ) + this->_Error( "Not enough seeds." ); + + auto filter = this->_CreateVTK< _TFilter >( ); + filter->SetImage( image ); + filter->SetMinimumSpanningTree( mst ); + + typename _TImage::PointType pnt; + typename _TImage::IndexType idx; + unsigned int dim = + ( _TImage::ImageDimension < 3 )? _TImage::ImageDimension: 3; + double buf[ 3 ]; + seeds->GetPoint( this->m_Parameters.GetUint( "Seed0" ), buf ); + pnt.Fill( 0 ); + for( unsigned int d = 0; d < dim; ++d ) + pnt[ d ] = buf[ d ]; + if( image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->SetSeed0( idx ); + seeds->GetPoint( this->m_Parameters.GetUint( "Seed1" ), buf ); + pnt.Fill( 0 ); + for( unsigned int d = 0; d < dim; ++d ) + pnt[ d ] = buf[ d ]; + if( image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->SetSeed1( idx ); + filter->Update( ); + this->GetOutput( "Output" )->SetVTK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/ImagePathToPolyDataFilter.h b/plugins/Plugins/ImagePathToPolyDataFilter.h new file mode 100644 index 0000000..738aa7f --- /dev/null +++ b/plugins/Plugins/ImagePathToPolyDataFilter.h @@ -0,0 +1,32 @@ +#ifndef __FPAPLUGINS__IMAGEPATHTOPOLYDATAFILTER__H__ +#define __FPAPLUGINS__IMAGEPATHTOPOLYDATAFILTER__H__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT ImagePathToPolyDataFilter + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + ImagePathToPolyDataFilter, + cpPlugins::BaseObjects::ProcessObject, + fpaImageAlgorithm + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TMST > + inline void _GD1( _TImage* image, _TMST* mst ); + }; + +} // ecapseman + +#endif // __FPAPLUGINS__IMAGEPATHTOPOLYDATAFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/InvertCostFunctor.cxx b/plugins/Plugins/InvertCostFunctor.cxx new file mode 100644 index 0000000..779541d --- /dev/null +++ b/plugins/Plugins/InvertCostFunctor.cxx @@ -0,0 +1,51 @@ +#include "InvertCostFunctor.h" + +#include +#include + +// ------------------------------------------------------------------------- +fpaPlugins::InvertCostFunctor:: +InvertCostFunctor( ) + : Superclass( ) +{ + this->_ConfigureOutput< cpPlugins::BaseObjects::DataObject >( "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::InvertCostFunctor:: +~InvertCostFunctor( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::InvertCostFunctor:: +_GenerateData( ) +{ + auto rtype = this->m_Parameters.GetSelectedChoice( "ResultType" ); + if ( rtype == "float" ) this->_GD0< float >( ); + else if( rtype == "double" ) this->_GD0< double >( ); +} + +// ------------------------------------------------------------------------- +template< class _TResult > +void fpaPlugins::InvertCostFunctor:: +_GD0( ) +{ + typedef fpa::Base::Functors::InvertCost< _TResult > _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/InvertCostFunctor.h b/plugins/Plugins/InvertCostFunctor.h new file mode 100644 index 0000000..8e0cec2 --- /dev/null +++ b/plugins/Plugins/InvertCostFunctor.h @@ -0,0 +1,29 @@ +#ifndef __FPAPLUGINS__INVERTCOSTFUNCTOR__H__ +#define __FPAPLUGINS__INVERTCOSTFUNCTOR__H__ + +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT InvertCostFunctor + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + InvertCostFunctor, + cpPlugins::BaseObjects::ProcessObject, + fpaFunctors + ); + + protected: + template< class _TResult > + inline void _GD0( ); + }; + +} // ecapseman + +#endif // __FPAPLUGINS__INVERTCOSTFUNCTOR__H__ + +// eof - $RCSfile$ diff --git a/plugins/Plugins/MultiplyImageAndDistanceMap.cxx b/plugins/Plugins/MultiplyImageAndDistanceMap.cxx new file mode 100644 index 0000000..c3344b7 --- /dev/null +++ b/plugins/Plugins/MultiplyImageAndDistanceMap.cxx @@ -0,0 +1,81 @@ +#include "MultiplyImageAndDistanceMap.h" +#include + +#include +#include + +/* TODO + #include + #include + #include + #include + #include +*/ + +// ------------------------------------------------------------------------- +fpaPlugins::MultiplyImageAndDistanceMap:: +MultiplyImageAndDistanceMap( ) + : Superclass( ) +{ + typedef cpPlugins::DataObjects::Image _TImage; + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureInput< _TImage >( "DistanceMap", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); + + /* TODO + this->_ConfigureOutput< cpPlugins::BaseObjects::DataObject >( "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" ); + this->m_Parameters.ConfigureAsBool( "FillNodeQueue" ); + this->m_Parameters.SetBool( "FillNodeQueue", false ); + */ +} + +// ------------------------------------------------------------------------- +fpaPlugins::MultiplyImageAndDistanceMap:: +~MultiplyImageAndDistanceMap( ) +{ +} + +// ------------------------------------------------------------------------- +void fpaPlugins::MultiplyImageAndDistanceMap:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_ImageScalars_Dims( o, _GD0 ); + else this->_Error( "Invalid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void fpaPlugins::MultiplyImageAndDistanceMap:: +_GD0( _TImage* image ) +{ + typedef itk::Image< float, _TImage::ImageDimension > _TFloat; + typedef itk::Image< double, _TImage::ImageDimension > _TDouble; + + auto f = this->GetInputData< _TFloat >( "DistanceMap" ); + auto d = this->GetInputData< _TDouble >( "DistanceMap" ); + if ( f != NULL ) this->_GD1( image, f ); + else if( d != NULL ) this->_GD1( image, d ); + else this->_Error( "Invalid distance map." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TDistanceMap > + void fpaPlugins::MultiplyImageAndDistanceMap:: +_GD1( _TImage* input, _TDistanceMap* dmap ) +{ + typedef fpa::Image::MultiplyImageAndDistanceMap< _TImage, _TDistanceMap > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( input ); + filter->SetDistanceMap( dmap ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/Plugins/MultiplyImageAndDistanceMap.h b/plugins/Plugins/MultiplyImageAndDistanceMap.h new file mode 100644 index 0000000..8ff71be --- /dev/null +++ b/plugins/Plugins/MultiplyImageAndDistanceMap.h @@ -0,0 +1,31 @@ +#ifndef __fpaPlugins__MultiplyImageAndDistanceMap__h__ +#define __fpaPlugins__MultiplyImageAndDistanceMap__h__ + +#include +#include +#include + +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT MultiplyImageAndDistanceMap + : public cpPlugins::BaseObjects::ProcessObject + { + cpPluginsObject( + MultiplyImageAndDistanceMap, cpPlugins::BaseObjects::ProcessObject, fpa + ); + + protected: + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TDistanceMap > + inline void _GD1( _TImage* input, _TDistanceMap* dmap ); + }; + +} // ecapseman + +#endif // __fpaPlugins__MultiplyImageAndDistanceMap__h__ + +// eof - $RCSfile$ -- 2.45.1