]> Creatis software - FrontAlgorithms.git/commitdiff
Architecture revisited.
authorLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Mon, 12 Sep 2016 20:02:01 +0000 (15:02 -0500)
committerLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Mon, 12 Sep 2016 20:02:01 +0000 (15:02 -0500)
53 files changed:
CMakeLists.txt [new file with mode: 0644]
cmake/DetectOS.cmake [new file with mode: 0644]
cmake/Functions.cmake [new file with mode: 0644]
cmake/KitwareTools.cmake [new file with mode: 0644]
cmake/Options.cmake [new file with mode: 0644]
cmake/Qt4Tools.cmake [new file with mode: 0644]
cmake/Restrictions.cmake [new file with mode: 0644]
lib/CMakeLists.txt [new file with mode: 0644]
lib/Instances/CMakeLists.txt [new file with mode: 0644]
lib/Instances/fpa_MinimumSpanningTree.i [new file with mode: 0644]
lib/fpa/Base/Algorithm.h [new file with mode: 0644]
lib/fpa/Base/Algorithm.hxx [new file with mode: 0644]
lib/fpa/Base/Dijkstra.h [new file with mode: 0644]
lib/fpa/Base/Dijkstra.hxx [new file with mode: 0644]
lib/fpa/Base/Events.h [new file with mode: 0644]
lib/fpa/Base/Functors/GaussianCost.h [new file with mode: 0644]
lib/fpa/Base/Functors/GaussianCost.hxx [new file with mode: 0644]
lib/fpa/Base/Functors/InvertCost.h [new file with mode: 0644]
lib/fpa/Base/Functors/InvertCost.hxx [new file with mode: 0644]
lib/fpa/Base/MinimumSpanningTree.h [new file with mode: 0644]
lib/fpa/Base/MinimumSpanningTree.hxx [new file with mode: 0644]
lib/fpa/Base/RegionGrow.h [new file with mode: 0644]
lib/fpa/Base/RegionGrow.hxx [new file with mode: 0644]
lib/fpa/Config.cxx [new file with mode: 0644]
lib/fpa/Config.h.in [new file with mode: 0644]
lib/fpa/Image/Algorithm.h [new file with mode: 0644]
lib/fpa/Image/Algorithm.hxx [new file with mode: 0644]
lib/fpa/Image/Dijkstra.h [new file with mode: 0644]
lib/fpa/Image/Dijkstra.hxx [new file with mode: 0644]
lib/fpa/Image/MultiplyImageAndDistanceMap.h [new file with mode: 0644]
lib/fpa/Image/MultiplyImageAndDistanceMap.hxx [new file with mode: 0644]
lib/fpa/Image/RegionGrow.h [new file with mode: 0644]
lib/fpa/Image/RegionGrow.hxx [new file with mode: 0644]
lib/fpa/VTK/Image/Observer2D.h [new file with mode: 0644]
lib/fpa/VTK/Image/Observer2D.hxx [new file with mode: 0644]
lib/fpa/VTK/Image/Observer3D.h [new file with mode: 0644]
lib/fpa/VTK/Image/Observer3D.hxx [new file with mode: 0644]
lib/fpa/VTK/Image/PathToPolyDataFilter.h [new file with mode: 0644]
lib/fpa/VTK/Image/PathToPolyDataFilter.hxx [new file with mode: 0644]
plugins/CMakeLists.txt [new file with mode: 0644]
plugins/Plugins/BaseImageFilter.cxx [new file with mode: 0644]
plugins/Plugins/BaseImageFilter.h [new file with mode: 0644]
plugins/Plugins/BaseImageFilter.hxx [new file with mode: 0644]
plugins/Plugins/GaussianCostFunctor.cxx [new file with mode: 0644]
plugins/Plugins/GaussianCostFunctor.h [new file with mode: 0644]
plugins/Plugins/ImageDijkstra.cxx [new file with mode: 0644]
plugins/Plugins/ImageDijkstra.h [new file with mode: 0644]
plugins/Plugins/ImagePathToPolyDataFilter.cxx [new file with mode: 0644]
plugins/Plugins/ImagePathToPolyDataFilter.h [new file with mode: 0644]
plugins/Plugins/InvertCostFunctor.cxx [new file with mode: 0644]
plugins/Plugins/InvertCostFunctor.h [new file with mode: 0644]
plugins/Plugins/MultiplyImageAndDistanceMap.cxx [new file with mode: 0644]
plugins/Plugins/MultiplyImageAndDistanceMap.h [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5b0669e
--- /dev/null
@@ -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 (file)
index 0000000..bba8346
--- /dev/null
@@ -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 (file)
index 0000000..f5a90f3
--- /dev/null
@@ -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 (file)
index 0000000..a120bb2
--- /dev/null
@@ -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 (file)
index 0000000..63990d9
--- /dev/null
@@ -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 (file)
index 0000000..16a0103
--- /dev/null
@@ -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 (file)
index 0000000..d177604
--- /dev/null
@@ -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 (file)
index 0000000..318a5fa
--- /dev/null
@@ -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 (file)
index 0000000..bbad1f8
--- /dev/null
@@ -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 (file)
index 0000000..53af6df
--- /dev/null
@@ -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 (file)
index 0000000..888d2e8
--- /dev/null
@@ -0,0 +1,168 @@
+#ifndef __FPA__BASE__ALGORITHM__H__
+#define __FPA__BASE__ALGORITHM__H__
+
+#include <functional>
+#include <set>
+#include <utility>
+#include <vector>
+#include <fpa/Config.h>
+#include <fpa/Base/Events.h>
+
+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 <fpa/Base/Algorithm.hxx>
+#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 (file)
index 0000000..1b33897
--- /dev/null
@@ -0,0 +1,346 @@
+#ifndef __FPA__BASE__ALGORITHM__HXX__
+#define __FPA__BASE__ALGORITHM__HXX__
+
+#include <queue>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..d4f27cd
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __FPA__BASE__DIJKSTRA__H__
+#define __FPA__BASE__DIJKSTRA__H__
+
+#include <vector>
+#include <itkFunctionBase.h>
+#include <fpa/Base/Algorithm.h>
+#include <fpa/Base/MinimumSpanningTree.h>
+
+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 <fpa/Base/Dijkstra.hxx>
+#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 (file)
index 0000000..25a7bd9
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef __FPA__BASE__DIJKSTRA__HXX__
+#define __FPA__BASE__DIJKSTRA__HXX__
+
+#include <algorithm>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..09f0637
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef __FPA__BASE__EVENTS__H__
+#define __FPA__BASE__EVENTS__H__
+
+#include <vector>
+#include <itkProcessObject.h>
+
+// -------------------------------------------------------------------------
+#define fpa_Base_NewEvent( name )                               \
+  class name                                                    \
+    : public BaseEvent                                          \
+  {                                                             \
+  public:                                                       \
+    name( ) : BaseEvent( ) { }                                  \
+    virtual ~name( ) { }                                        \
+    const char* GetEventName( ) const                           \
+    { return( "fpa::Base::##name" ); }                          \
+    bool CheckEvent( const itk::EventObject* e ) const          \
+    { return( dynamic_cast< const name* >( e ) != NULL ); }     \
+    itk::EventObject* MakeObject( ) const                       \
+    { return( new name( ) ); }                                  \
+  };
+
+// -------------------------------------------------------------------------
+#define fpa_Base_NewEventWithVertex( name, type )               \
+  class name                                                    \
+    : public BaseEventWithVertex< type >                        \
+  {                                                             \
+  public:                                                       \
+    name( ) : BaseEventWithVertex< type >( ) { }                \
+    name( const type& v, long fid )                             \
+        : BaseEventWithVertex< type >( v, fid ) { }             \
+    virtual ~name( ) { }                                        \
+    const char* GetEventName( ) const                           \
+    { return( "fpa::Base::##name" ); }                          \
+    bool CheckEvent( const itk::EventObject* e ) const          \
+    { return( dynamic_cast< const name* >( e ) != NULL ); }     \
+    itk::EventObject* MakeObject( ) const                       \
+    { return( new name( ) ); }                                  \
+  };
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    class BaseEvent
+      : public itk::AnyEvent
+    {
+    public:
+      BaseEvent( )
+        : itk::AnyEvent( )
+        { }
+      virtual ~BaseEvent( )
+        { }
+      const char* GetEventName( ) const
+        { return( "fpa::Base::BaseEvent" ); }
+      bool CheckEvent( const itk::EventObject* e ) const
+        { return( dynamic_cast< const BaseEvent* >( e ) != NULL ); }
+      itk::EventObject* MakeObject( ) const
+        { return( new BaseEvent( ) ); }
+    };
+
+    /**
+     */
+    template< class 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 (file)
index 0000000..d5c860c
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __FPA__BASE__FUNCTORS__GAUSSIANCOST__H__
+#define __FPA__BASE__FUNCTORS__GAUSSIANCOST__H__
+
+#include <fpa/Config.h>
+#include <itkFunctionBase.h>
+#include <cpExtensions/Algorithms/IterativeGaussianModelEstimator.h>
+
+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 <fpa/Base/Functors/GaussianCost.hxx>
+#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 (file)
index 0000000..de14605
--- /dev/null
@@ -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 (file)
index 0000000..7ff9366
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __FPA__BASE__FUNCTORS__INVERTCOST__H__
+#define __FPA__BASE__FUNCTORS__INVERTCOST__H__
+
+#include <fpa/Config.h>
+#include <itkFunctionBase.h>
+
+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 <fpa/Base/Functors/InvertCost.hxx>
+#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 (file)
index 0000000..9e8d832
--- /dev/null
@@ -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 (file)
index 0000000..dc0c6d1
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __FPA__BASE__MINIMUMSPANNINGTREE__H__
+#define __FPA__BASE__MINIMUMSPANNINGTREE__H__
+
+#include <functional>
+#include <map>
+#include <utility>
+#include <vector>
+#include <itkSimpleDataObjectDecorator.h>
+
+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 <fpa/Base/MinimumSpanningTree.hxx>
+#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 (file)
index 0000000..2f0a4b1
--- /dev/null
@@ -0,0 +1,278 @@
+#ifndef __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
+#define __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
+
+#include <limits>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..615059f
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef __FPA__BASE__REGIONGROW__H__
+#define __FPA__BASE__REGIONGROW__H__
+
+#include <deque>
+#include <itkFunctionBase.h>
+#include <fpa/Base/Algorithm.h>
+
+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 <fpa/Base/RegionGrow.hxx>
+#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 (file)
index 0000000..c0f8a67
--- /dev/null
@@ -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 (file)
index 0000000..b2649cd
--- /dev/null
@@ -0,0 +1,10 @@
+#include <fpa/Config.h>
+#include <string>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..470b31e
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __fpa__h__
+#define __fpa__h__
+
+#include <fpa_Export.h>
+
+/*
+ * =========================================================================
+ * 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 (file)
index 0000000..2fd40bc
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef __FPA__IMAGE__ALGORITHM__H__
+#define __FPA__IMAGE__ALGORITHM__H__
+
+#include <fpa/Base/Algorithm.h>
+#include <itkImage.h>
+#include <itkImageToImageFilter.h>
+
+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 <fpa/Image/Algorithm.hxx>
+#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 (file)
index 0000000..07c09e6
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef __FPA__IMAGE__ALGORITHM__HXX__
+#define __FPA__IMAGE__ALGORITHM__HXX__
+
+#include <itkConstNeighborhoodIterator.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..5c2460f
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __FPA__IMAGE__DIJKSTRA__H__
+#define __FPA__IMAGE__DIJKSTRA__H__
+
+#include <fpa/Base/Dijkstra.h>
+#include <fpa/Image/Algorithm.h>
+
+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 <fpa/Image/Dijkstra.hxx>
+#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 (file)
index 0000000..b81a533
--- /dev/null
@@ -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 (file)
index 0000000..3c42938
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __fpa__Image__MultiplyImageAndDistanceMap__h__
+#define __fpa__Image__MultiplyImageAndDistanceMap__h__
+
+#include <itkImageToImageFilter.h>
+
+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 <fpa/Image/MultiplyImageAndDistanceMap.hxx>
+#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 (file)
index 0000000..f78d2a1
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef __fpa__Image__MultiplyImageAndDistanceMap__hxx__
+#define __fpa__Image__MultiplyImageAndDistanceMap__hxx__
+
+#include <itkImageRegionConstIteratorWithIndex.h>
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkProgressReporter.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..cf05dd1
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __FPA__IMAGE__REGIONGROW__H__
+#define __FPA__IMAGE__REGIONGROW__H__
+
+#include <fpa/Base/RegionGrow.h>
+#include <fpa/Image/Algorithm.h>
+
+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 <fpa/Image/RegionGrow.hxx>
+#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 (file)
index 0000000..17775e7
--- /dev/null
@@ -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 (file)
index 0000000..c8582bb
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef __FPA__VTK__IMAGE__OBSERVER2D__H__
+#define __FPA__VTK__IMAGE__OBSERVER2D__H__
+
+#include <set>
+#include <itkCommand.h>
+#include <vtkActor.h>
+#include <vtkImageActor.h>
+#include <vtkImageData.h>
+#include <vtkPolyData.h>
+#include <vtkSmartPointer.h>
+
+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 <fpa/VTK/Image/Observer2D.hxx>
+#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 (file)
index 0000000..a7276ac
--- /dev/null
@@ -0,0 +1,226 @@
+#ifndef __FPA__VTK__IMAGE__OBSERVER2D__HXX__
+#define __FPA__VTK__IMAGE__OBSERVER2D__HXX__
+
+#include <vtkCellArray.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkPoints.h>
+#include <vtkPointData.h>
+#include <vtkProperty.h>
+#include <vtkRenderer.h>
+#include <vtkRendererCollection.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..84ceaa5
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef __FPA__VTK__IMAGE__OBSERVER3D__H__
+#define __FPA__VTK__IMAGE__OBSERVER3D__H__
+
+#include <map>
+
+#include <itkCommand.h>
+
+#include <vtkActor.h>
+#include <vtkPolyData.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkSmartPointer.h>
+
+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 <fpa/VTK/Observer3D.hxx>
+#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 (file)
index 0000000..409f8a2
--- /dev/null
@@ -0,0 +1,211 @@
+#ifndef __FPA__VTK__IMAGE__OBSERVER3D__HXX__
+#define __FPA__VTK__IMAGE__OBSERVER3D__HXX__
+
+#include <vtkCellArray.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkPoints.h>
+#include <vtkPointData.h>
+#include <vtkProperty.h>
+#include <vtkRenderer.h>
+#include <vtkRendererCollection.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..f454256
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__H__
+#define __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__H__
+
+#include <itkImageBase.h>
+#include <vtkPolyDataAlgorithm.h>
+
+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 <fpa/VTK/Image/PathToPolyDataFilter.hxx>
+#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 (file)
index 0000000..d66fee6
--- /dev/null
@@ -0,0 +1,178 @@
+#ifndef __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__HXX__
+#define __FPA__VTK__IMAGE__PATHTOPOLYDATAFILTER__HXX__
+
+#include <vtkCellArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkPointData.h>
+#include <vtkPoints.h>
+#include <vtkSmartPointer.h>
+#include <vtkStreamingDemandDrivenPipeline.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..da88a5b
--- /dev/null
@@ -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 (file)
index 0000000..335f9e1
--- /dev/null
@@ -0,0 +1,51 @@
+#include "BaseImageFilter.h"
+#include <cpPlugins/DataObjects/Image.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..93044e5
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __FPAPLUGINS__BASEIMAGEFILTER__H__
+#define __FPAPLUGINS__BASEIMAGEFILTER__H__
+
+#include <fpa/Config.h>
+#include <plugins/fpaPlugins_Export.h>
+#include <cpPlugins/BaseObjects/ProcessObject.h>
+
+#include <cpExtensions/QT/SimpleMPRWidget.h>
+#include <vtkRenderWindowInteractor.h>
+
+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 (file)
index 0000000..762f553
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef __FPAPLUGINS__BASEIMAGEFILTER__HXX__
+#define __FPAPLUGINS__BASEIMAGEFILTER__HXX__
+
+#include <vtkPolyData.h>
+
+/* TODO
+   #include <fpa/VTK/Image/Observer2D.h>
+   #include <fpa/VTK/Image/Observer2D.hxx>
+*/
+#include <fpa/VTK/Image/Observer3D.h>
+#include <fpa/VTK/Image/Observer3D.hxx>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..874b025
--- /dev/null
@@ -0,0 +1,59 @@
+#include "GaussianCostFunctor.h"
+
+#include <fpa/Base/Functors/GaussianCost.h>
+#include <fpa/Base/Functors/GaussianCost.hxx>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..1a2a117
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __FPAPLUGINS__GAUSSIANCOSTFUNCTOR__H__
+#define __FPAPLUGINS__GAUSSIANCOSTFUNCTOR__H__
+
+#include <plugins/fpaPlugins_Export.h>
+#include <cpPlugins/BaseObjects/ProcessObject.h>
+
+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 (file)
index 0000000..be69f49
--- /dev/null
@@ -0,0 +1,86 @@
+#include "ImageDijkstra.h"
+// TODO: #include "MinimumSpanningTree.h"
+
+#include <cpPlugins/DataObjects/Image.h>
+#include <fpa/Image/Dijkstra.h>
+
+#include <fpa/Base/Algorithm.hxx>
+#include <fpa/Base/Dijkstra.hxx>
+#include <fpa/Image/Algorithm.hxx>
+#include <fpa/Image/Dijkstra.hxx>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..4fcb4b6
--- /dev/null
@@ -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 (file)
index 0000000..eb0f689
--- /dev/null
@@ -0,0 +1,99 @@
+#include "ImagePathToPolyDataFilter.h"
+#include <cpPlugins/DataObjects/Image.h>
+#include <cpPlugins/DataObjects/Mesh.h>
+#include <fpa/Base/MinimumSpanningTree.h>
+#include <fpa/VTK/Image/PathToPolyDataFilter.h>
+#include <fpa/VTK/Image/PathToPolyDataFilter.hxx>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..738aa7f
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __FPAPLUGINS__IMAGEPATHTOPOLYDATAFILTER__H__
+#define __FPAPLUGINS__IMAGEPATHTOPOLYDATAFILTER__H__
+
+#include <plugins/fpaPlugins_Export.h>
+#include <cpPlugins/BaseObjects/ProcessObject.h>
+
+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 (file)
index 0000000..779541d
--- /dev/null
@@ -0,0 +1,51 @@
+#include "InvertCostFunctor.h"
+
+#include <fpa/Base/Functors/InvertCost.h>
+#include <fpa/Base/Functors/InvertCost.hxx>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..8e0cec2
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __FPAPLUGINS__INVERTCOSTFUNCTOR__H__
+#define __FPAPLUGINS__INVERTCOSTFUNCTOR__H__
+
+#include <plugins/fpaPlugins_Export.h>
+#include <cpPlugins/BaseObjects/ProcessObject.h>
+
+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 (file)
index 0000000..c3344b7
--- /dev/null
@@ -0,0 +1,81 @@
+#include "MultiplyImageAndDistanceMap.h"
+#include <cpPlugins/DataObjects/Image.h>
+
+#include <fpa/Image/MultiplyImageAndDistanceMap.h>
+#include <fpa/Image/MultiplyImageAndDistanceMap.hxx>
+
+/* TODO
+   #include <fpa/Image/Dijkstra.h>
+   #include <fpa/Base/Algorithm.hxx>
+   #include <fpa/Base/Dijkstra.hxx>
+   #include <fpa/Image/Algorithm.hxx>
+   #include <fpa/Image/Dijkstra.hxx>
+*/
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..8ff71be
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __fpaPlugins__MultiplyImageAndDistanceMap__h__
+#define __fpaPlugins__MultiplyImageAndDistanceMap__h__
+
+#include <fpa/Config.h>
+#include <plugins/fpaPlugins_Export.h>
+#include <cpPlugins/BaseObjects/ProcessObject.h>
+
+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$