]> Creatis software - FrontAlgorithms.git/commitdiff
...
authorLeonardo Flórez-Valencia <leonardo.florez@gmail.com>
Mon, 19 Jun 2017 04:05:45 +0000 (23:05 -0500)
committerLeonardo Flórez-Valencia <leonardo.florez@gmail.com>
Mon, 19 Jun 2017 04:05:45 +0000 (23:05 -0500)
63 files changed:
CMakeLists.txt [new file with mode: 0644]
cmake/fpaBaseConfig.cmake [new file with mode: 0644]
cmake/fpaConfig.cmake.in [new file with mode: 0644]
data/binary_test_2D_00.png [new file with mode: 0644]
data/input_mori_binary.png [new file with mode: 0644]
lib/CMakeLists.txt [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/DijkstraBase.h [new file with mode: 0644]
lib/fpa/Base/DijkstraBase.hxx [new file with mode: 0644]
lib/fpa/Base/Functors/Dijkstra/Function.h [new file with mode: 0644]
lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h [new file with mode: 0644]
lib/fpa/Base/Functors/RegionGrow/Tautology.h [new file with mode: 0644]
lib/fpa/Base/Graph.h [new file with mode: 0644]
lib/fpa/Base/Graph.hxx [new file with mode: 0644]
lib/fpa/Base/MarksInterface.h [new file with mode: 0644]
lib/fpa/Base/MarksInterface.hxx [new file with mode: 0644]
lib/fpa/Base/MarksInterfaceWithCollisions.h [new file with mode: 0644]
lib/fpa/Base/MarksInterfaceWithCollisions.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/Base/SeedsInterface.h [new file with mode: 0644]
lib/fpa/Base/SeedsInterface.hxx [new file with mode: 0644]
lib/fpa/CMakeLists.txt [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/Functors/Dijkstra/Function.h [new file with mode: 0644]
lib/fpa/Image/Functors/Dijkstra/Gaussian.h [new file with mode: 0644]
lib/fpa/Image/Functors/Dijkstra/Identity.h [new file with mode: 0644]
lib/fpa/Image/Functors/Dijkstra/Invert.h [new file with mode: 0644]
lib/fpa/Image/LabelledSeedsInterface.h [new file with mode: 0644]
lib/fpa/Image/LabelledSeedsInterface.hxx [new file with mode: 0644]
lib/fpa/Image/MinimumSpanningTree.h [new file with mode: 0644]
lib/fpa/Image/PathsToImageFilter.h [new file with mode: 0644]
lib/fpa/Image/PathsToImageFilter.hxx [new file with mode: 0644]
lib/fpa/Image/PolyLineParametricPath.h [new file with mode: 0644]
lib/fpa/Image/PolyLineParametricPath.hxx [new file with mode: 0644]
lib/fpa/Image/RandomWalker.h [new file with mode: 0644]
lib/fpa/Image/RandomWalker.hxx [new file with mode: 0644]
lib/fpa/Image/RegionGrow.h [new file with mode: 0644]
lib/fpa/Image/Skeleton.h [new file with mode: 0644]
lib/fpa/Image/Skeleton.hxx [new file with mode: 0644]
lib/fpa/Image/SkeletonFilter.h [new file with mode: 0644]
lib/fpa/Image/SkeletonFilter.hxx [new file with mode: 0644]
lib/fpa/Image/VisualDebugger.h [new file with mode: 0644]
lib/fpa/Image/VisualDebugger.hxx [new file with mode: 0644]
lib/fpa/Image/VisualDebugger2D.h [new file with mode: 0644]
lib/fpa/Image/VisualDebugger2D.hxx [new file with mode: 0644]
lib/fpa/Version.cxx.in [new file with mode: 0644]
tests/CMakeLists.txt [new file with mode: 0644]
tests/image/BaseFunctions.h [new file with mode: 0644]
tests/image/CMakeLists.txt [new file with mode: 0644]
tests/image/Dijkstra_Gaussian.cxx [new file with mode: 0644]
tests/image/Dijkstra_Identity.cxx [new file with mode: 0644]
tests/image/RandomWalker.cxx [new file with mode: 0644]
tests/image/RegionGrow_Tautology.cxx [new file with mode: 0644]
tests/image/SkeletonFilter.cxx [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..095eff9
--- /dev/null
@@ -0,0 +1,85 @@
+cmake_minimum_required(VERSION 3.0)
+
+## ========================
+## == Project definition ==
+## ========================
+
+set(prj_MAJ_VERSION 0)
+set(prj_MIN_VERSION 1)
+set(prj_REL_VERSION 0)
+set(prj_VERSION "${prj_MAJ_VERSION}.${prj_MIN_VERSION}.${prj_REL_VERSION}")
+set(prj_SHORT_VERSION "${prj_MAJ_VERSION}")
+project(fpa VERSION ${prj_VERSION})
+
+## ==========================
+## == Some useful policies ==
+## ==========================
+
+set(_policies CMP0015 CMP0020 CMP0042 CMP0053)
+foreach(_p ${_policies})
+  if(POLICY ${_p})
+    cmake_policy(SET ${_p} NEW)
+  endif(POLICY ${_p})
+endforeach(_p)
+
+## ===============================
+## == Some basic configurations ==
+## ===============================
+
+include(cmake/fpaBaseConfig.cmake)
+
+## ==========================
+## == Find needed packages ==
+## ==========================
+
+find_package(ivq CONFIG QUIET)
+if(NOT ivq_FOUND)
+  find_package(ITK CONFIG REQUIRED)
+  include(${ITK_USE_FILE})
+endif(NOT ivq_FOUND)
+
+## =========================
+## == Installation values ==
+## =========================
+
+set(config_install_dir "lib/cmake/${PROJECT_NAME}")
+set(include_install_dir "include")
+set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
+set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
+set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
+set(targets_export_name "${PROJECT_NAME}Targets")
+set(namespace "${PROJECT_NAME}::")
+
+## ===========================
+## == Build different parts ==
+## ===========================
+
+subdirs(lib tests)
+
+## ===============================
+## == Global installation rules ==
+## ===============================
+
+include(CMakePackageConfigHelpers)
+write_basic_package_version_file(
+  "${version_config}" COMPATIBILITY SameMajorVersion
+  )
+configure_package_config_file(
+  "cmake/${PROJECT_NAME}Config.cmake.in"
+  "${project_config}"
+  INSTALL_DESTINATION "${config_install_dir}"
+  )
+install(
+  FILES
+  "${project_config}"
+  "${version_config}"
+  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}BaseConfig.cmake"
+  DESTINATION "${config_install_dir}"
+  )
+install(
+  EXPORT "${targets_export_name}"
+  NAMESPACE "${namespace}"
+  DESTINATION "${config_install_dir}"
+  )
+
+## eof - $RCSfile$
diff --git a/cmake/fpaBaseConfig.cmake b/cmake/fpaBaseConfig.cmake
new file mode 100644 (file)
index 0000000..4e9cb25
--- /dev/null
@@ -0,0 +1,65 @@
+## =========================================================
+## == If working on a MacOSX, activate the use of RPATH's ==
+## =========================================================
+
+set(EXECUTABLE_TYPE "" CACHE STRING "Executable linking." FORCE)
+if(APPLE)
+  set(EXECUTABLE_TYPE "MACOSX_BUNDLE" CACHE STRING "Executable linking." FORCE)
+  set(CMAKE_MACOSX_RPATH true CACHE BOOL "Use RPATH's on MacOSX systems." FORCE)
+  mark_as_advanced(CMAKE_MACOSX_RPATH)
+elseif(WIN32)
+  set(EXECUTABLE_TYPE "WIN32" CACHE STRING "Executable linking." FORCE)
+endif(APPLE)
+mark_as_advanced(EXECUTABLE_TYPE)
+
+## =======================================================================
+## == Force c++11 language version                                      ==
+## == NOTE: It seems that by default on Visual Studio Compiler supports ==
+## ==       c++11, so it only need to be tested on other OS.            ==
+## =======================================================================
+
+if(NOT MSVC)
+  include(CheckCXXCompilerFlag)
+  check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11)
+  if(COMPILER_SUPPORTS_CXX11)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+  else(COMPILER_SUPPORTS_CXX11)
+    check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
+    if(COMPILER_SUPPORTS_CXX0X)
+      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+    else(COMPILER_SUPPORTS_CXX0X)
+      message(
+        FATAL_ERROR
+        "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support."
+        )
+    endif(COMPILER_SUPPORTS_CXX0X)
+  endif(COMPILER_SUPPORTS_CXX11)
+endif(NOT MSVC)
+
+## ===================================================
+## == Prepare header generator to build shared libs ==
+## ===================================================
+
+include(GenerateExportHeader)
+
+## ==================================================
+## == Do not allow to build inside the source tree ==
+## ==================================================
+
+if(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR})
+  message(FATAL_ERROR "Building in the source tree is not allowed.")
+endif(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR})
+
+## =================================================
+## == Where to put targets (executables and libs) ==
+## =================================================
+
+set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
+set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
+mark_as_advanced(
+  CMAKE_BACKWARDS_COMPATIBILITY
+  EXECUTABLE_OUTPUT_PATH
+  LIBRARY_OUTPUT_PATH
+  )
+
+## eof - $RCSfile$
diff --git a/cmake/fpaConfig.cmake.in b/cmake/fpaConfig.cmake.in
new file mode 100644 (file)
index 0000000..26692f3
--- /dev/null
@@ -0,0 +1,16 @@
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/fpaBaseConfig.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
+check_required_components("@PROJECT_NAME@")
+
+## ==============
+## == Find ITK ==
+## ==============
+
+set(ITK_DIR @ITK_DIR@)
+
+find_package(ITK CONFIG REQUIRED)
+include(${ITK_USE_FILE})
+
+## eof - $RCSfile$
diff --git a/data/binary_test_2D_00.png b/data/binary_test_2D_00.png
new file mode 100644 (file)
index 0000000..fbe9d39
Binary files /dev/null and b/data/binary_test_2D_00.png differ
diff --git a/data/input_mori_binary.png b/data/input_mori_binary.png
new file mode 100644 (file)
index 0000000..d605247
Binary files /dev/null and b/data/input_mori_binary.png differ
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f4c0955
--- /dev/null
@@ -0,0 +1,8 @@
+
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_BINARY_DIR}
+  )
+subdirs(fpa)
+
+## eof - $RCSfile$
diff --git a/lib/fpa/Base/Algorithm.h b/lib/fpa/Base/Algorithm.h
new file mode 100644 (file)
index 0000000..e5b6f2b
--- /dev/null
@@ -0,0 +1,127 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Algorithm__h__
+#define __fpa__Base__Algorithm__h__
+
+#include <fpa/Config.h>
+
+#include <vector>
+#include <itkObject.h>
+#include <itkEventObject.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+    class Algorithm
+      : public _TFilter,
+        public _TMarksInterface,
+        public _TSeedsInterface
+    {
+    public:
+      typedef Algorithm                       Self;
+      typedef _TFilter                        Superclass;
+      typedef _TMarksInterface                TMarksInterface;
+      typedef _TSeedsInterface                TSeedsInterface;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename _TSeedsInterface::TInputValue  TInputValue;
+      typedef typename _TSeedsInterface::TOutputValue TOutputValue;
+      typedef typename _TSeedsInterface::TNode        TNode;
+      typedef typename _TSeedsInterface::TSeeds       TSeeds;
+      typedef typename _TSeedsInterface::TVertex      TVertex;
+
+      typedef std::vector< TVertex > TNeighborhood;
+
+      /**
+       */
+      class TEvent
+        : public itk::EventObject
+      {
+      public:
+        typedef TEvent           Self;
+        typedef itk::EventObject Superclass;
+
+      public:
+        TEvent( );
+        TEvent( const TVertex& v, unsigned long fid, bool intoq );
+        virtual ~TEvent( );
+        virtual const char* GetEventName( ) const override;
+        virtual bool CheckEvent( const itk::EventObject* e ) const override;
+        virtual itk::EventObject* MakeObject( ) const override;
+
+      private:
+        // Purposely not implemented.
+        Self& operator=( const Self& other );
+
+      public:
+        TVertex       Vertex;
+        unsigned long FrontId;
+        bool          IntoQueue;
+      };
+
+    public:
+      itkTypeMacro( fpa::Base::Algorithm, _TFilter );
+
+      itkBooleanMacro( VisualDebug );
+
+      itkGetConstMacro( InitValue, TOutputValue );
+      itkGetConstMacro( VisualDebug, bool );
+
+      itkSetMacro( InitValue, TOutputValue );
+      itkSetMacro( VisualDebug, bool );
+
+    public:
+      virtual void InvokeEvent( const itk::EventObject& e );
+      virtual void InvokeEvent( const itk::EventObject& e ) const;
+
+    protected:
+      Algorithm( );
+      virtual ~Algorithm( );
+
+      virtual void GenerateData( ) override;
+      virtual void _BeforeGenerateData( );
+      virtual void _AfterGenerateData( );
+
+      virtual void _QueueInit( );
+
+      virtual void _ConfigureOutput( const TOutputValue& v ) = 0;
+      virtual TNeighborhood _GetNeighbors( const TVertex& v ) const = 0;
+      virtual TInputValue _GetInputValue( const TVertex& v ) const = 0;
+      virtual TOutputValue _GetOutputValue( const TVertex& v ) const = 0;
+
+      virtual TOutputValue _ComputeOutputValue( const TNode& n ) = 0;
+      virtual void _UpdateOutputValue( const TNode& n ) = 0;
+      virtual void _QueueClear( ) = 0;
+      virtual void _QueuePush( const TNode& node ) = 0;
+      virtual unsigned long _QueueSize( ) const = 0;
+      virtual TNode _QueuePop( ) = 0;
+
+    private:
+      // Purposely not implemented
+      Algorithm( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      bool m_VisualDebug;
+      TOutputValue m_InitValue;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/Algorithm.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__Algorithm__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/Algorithm.hxx b/lib/fpa/Base/Algorithm.hxx
new file mode 100644 (file)
index 0000000..383db74
--- /dev/null
@@ -0,0 +1,212 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Algorithm__hxx__
+#define __fpa__Base__Algorithm__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent::
+TEvent( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent::
+TEvent( const TVertex& v, unsigned long fid, bool intoq )
+  : Superclass( ),
+    Vertex( v ),
+    FrontId( fid ),
+    IntoQueue( intoq )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent::
+~TEvent( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+const char* 
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent::
+GetEventName( ) const
+{
+  return( "fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent" );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+bool
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent::
+CheckEvent( const itk::EventObject* e ) const
+{
+  return( dynamic_cast< const Self* >( e ) != NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+itk::EventObject* 
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent::
+MakeObject( ) const
+{
+  return( new Self );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+InvokeEvent( const itk::EventObject& e )
+{
+  TEvent a;
+  if( a.CheckEvent( &e ) )
+  {
+    if( this->m_VisualDebug )
+      this->Superclass::InvokeEvent( e );
+  }
+  else
+    this->Superclass::InvokeEvent( e );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+InvokeEvent( const itk::EventObject& e ) const
+{
+  TEvent a;
+  if( a.CheckEvent( &e ) )
+  {
+    if( this->m_VisualDebug )
+      this->Superclass::InvokeEvent( e );
+  }
+  else
+    this->Superclass::InvokeEvent( e );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+Algorithm( )
+  : Superclass( ),
+    _TMarksInterface( this ),
+    _TSeedsInterface( this ),
+    m_VisualDebug( false )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+~Algorithm( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GenerateData( )
+{
+  this->InvokeEvent( itk::StartEvent( ) );
+
+  // Init objects
+  this->_BeforeGenerateData( );
+  this->_ConfigureOutput( this->m_InitValue );
+  this->_InitMarks( this->GetNumberOfSeeds( ) );
+
+  // Init queue
+  this->_QueueInit( );
+  typename TSeeds::const_iterator sIt = this->BeginSeeds( );
+  for( ; sIt != this->EndSeeds( ); ++sIt )
+  {
+    this->_QueuePush( *sIt );
+    this->InvokeEvent( TEvent( sIt->Vertex, sIt->FrontId, true ) );
+
+  } // rof
+
+  // Main loop
+  while( this->_QueueSize( ) > 0 )
+  {
+    // Get next candidate
+    TNode node = this->_QueuePop( );
+    this->InvokeEvent( TEvent( node.Vertex, node.FrontId, false ) );
+    if( !( this->_IsMarked( node.Vertex ) ) )
+    {
+      // Mark it
+      if( this->_Mark( node.Vertex, node.FrontId ) )
+      {
+        // Update output value
+        this->_UpdateOutputValue( node );
+
+        // Add neighborhood
+        TNeighborhood neighbors = this->_GetNeighbors( node.Vertex );
+        typename TNeighborhood::const_iterator nIt = neighbors.begin( );
+        bool coll = false;
+        while( nIt != neighbors.end( ) && !coll )
+        {
+          if( this->_IsMarked( *nIt ) )
+          {
+            // Invoke stop at collisions
+            if( this->_Collisions( node.Vertex, *nIt ) )
+            {
+              this->_QueueClear( );
+              coll = true;
+
+            } // fi
+          }
+          else
+          {
+            TNode nnode;
+            nnode.Vertex = *nIt;
+            nnode.Parent = node.Vertex;
+            nnode.FrontId = node.FrontId;
+            nnode.Value = this->_ComputeOutputValue( nnode );
+            this->_QueuePush( nnode );
+            this->InvokeEvent( TEvent( nnode.Vertex, nnode.FrontId, true ) );
+
+          } // fi
+          ++nIt;
+
+        } // elihw
+
+      } // fi
+
+    } // fi
+
+  } // elihw
+
+  // Finish
+  this->_AfterGenerateData( );
+  this->InvokeEvent( itk::EndEvent( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+_BeforeGenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+_AfterGenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::
+_QueueInit( )
+{
+  this->_QueueClear( );
+}
+
+#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..10489db
--- /dev/null
@@ -0,0 +1,69 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Dijkstra__h__
+#define __fpa__Base__Dijkstra__h__
+
+#include <fpa/Base/DijkstraBase.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TAlgorithm, class _TMST >
+    class Dijkstra
+      : public fpa::Base::DijkstraBase< _TAlgorithm >
+    {
+    public:
+      typedef Dijkstra                               Self;
+      typedef fpa::Base::DijkstraBase< _TAlgorithm > Superclass;
+      typedef itk::SmartPointer< Self >              Pointer;
+      typedef itk::SmartPointer< const Self >        ConstPointer;
+
+      typedef _TMST TMST;
+
+      typedef typename Superclass::TNode        TNode;
+      typedef typename Superclass::TInputValue  TInputValue;
+      typedef typename Superclass::TOutputValue TOutputValue;
+      typedef typename Superclass::TFrontId     TFrontId;
+      typedef typename Superclass::TVertex      TVertex;
+
+      typedef typename Superclass::TQueue          TQueue;
+      typedef typename Superclass::TQueueOrder     TQueueOrder;
+      typedef typename Superclass::TWeightFunction TWeightFunction;
+
+    public:
+      TMST* GetMinimumSpanningTree( );
+      const TMST* GetMinimumSpanningTree( ) const;
+
+    protected:
+      Dijkstra( );
+      virtual ~Dijkstra( );
+
+      virtual void _AfterGenerateData( ) override;
+      virtual void _UpdateOutputValue( const TNode& n ) override;
+
+    private:
+      // Purposely not implemented.
+      Dijkstra( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      unsigned int m_MSTIdx;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/Dijkstra.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__Dijkstra__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/Dijkstra.hxx b/lib/fpa/Base/Dijkstra.hxx
new file mode 100644 (file)
index 0000000..93a102d
--- /dev/null
@@ -0,0 +1,74 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Dijkstra__hxx__
+#define __fpa__Base__Dijkstra__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm, class _TMST >
+typename fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+TMST* fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+GetMinimumSpanningTree( )
+{
+  dynamic_cast< TMST* >(
+    this->itk::ProcessObject::GetOutput( this->m_MSTIdx )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm, class _TMST >
+const typename fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+TMST* fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+GetMinimumSpanningTree( ) const
+{
+  dynamic_cast< const TMST* >(
+    this->itk::ProcessObject::GetOutput( this->m_MSTIdx )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm, class _TMST >
+fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+Dijkstra( )
+  : Superclass( )
+{
+  this->m_MSTIdx = this->GetNumberOfRequiredOutputs( );
+  this->itk::ProcessObject::SetNumberOfRequiredOutputs( this->m_MSTIdx + 1 );
+  this->SetNthOutput( this->m_MSTIdx, TMST::New( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm, class _TMST >
+fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+~Dijkstra( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm, class _TMST >
+void fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+_AfterGenerateData( )
+{
+  typedef typename Superclass::TSeedsInterface::TSeeds::iterator _TIt;
+
+  TMST* mst = this->GetMinimumSpanningTree( );
+  mst->ClearSeeds( );
+  mst->SetCollisions( this->m_Collisions );
+  for( _TIt sIt = this->BeginSeeds( ); sIt != this->EndSeeds( ); ++sIt )
+    mst->AddSeed( sIt->Vertex );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm, class _TMST >
+void fpa::Base::Dijkstra< _TAlgorithm, _TMST >::
+_UpdateOutputValue( const TNode& n )
+{
+  this->Superclass::_UpdateOutputValue( n );
+  this->GetMinimumSpanningTree( )->SetParent( n.Vertex, n.Parent );
+}
+
+#endif // __fpa__Base__Dijkstra__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/DijkstraBase.h b/lib/fpa/Base/DijkstraBase.h
new file mode 100644 (file)
index 0000000..fd36890
--- /dev/null
@@ -0,0 +1,91 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__DijkstraBase__h__
+#define __fpa__Base__DijkstraBase__h__
+
+#include <vector>
+
+#include <itkConceptChecking.h>
+#include <fpa/Base/Functors/Dijkstra/Function.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TAlgorithm >
+    class DijkstraBase
+      : public _TAlgorithm
+    {
+    public:
+      typedef DijkstraBase                    Self;
+      typedef _TAlgorithm                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename _TAlgorithm::TNode        TNode;
+      typedef typename _TAlgorithm::TInputValue  TInputValue;
+      typedef typename _TAlgorithm::TOutputValue TOutputValue;
+      typedef typename _TAlgorithm::TVertex      TVertex;
+
+      typedef std::vector< TNode > TQueue;
+      struct TQueueOrder
+      {
+        bool operator()( const TNode& a, const TNode& b ) const
+          {
+            return( b.Value < a.Value );
+          }
+      };
+      typedef fpa::Base::Functors::Dijkstra::Function< TVertex, TOutputValue > TWeightFunction;
+
+    public:
+      itkConceptMacro(
+        Check_TOutputValue,
+        ( itk::Concept::IsFloatingPoint< TOutputValue > )
+        );
+
+    public:
+      itkGetObjectMacro( WeightFunction, TWeightFunction );
+      itkSetObjectMacro( WeightFunction, TWeightFunction );
+
+    public:
+      virtual itk::ModifiedTimeType GetMTime( ) const override;
+
+    protected:
+      DijkstraBase( );
+      virtual ~DijkstraBase( );
+
+      virtual TOutputValue _ComputeOutputValue( const TNode& n ) override;
+      virtual void _QueueInit( ) override;
+      virtual void _QueueClear( ) override;
+      virtual TNode _QueuePop( ) override;
+      virtual void _QueuePush( const TNode& node ) override;
+      virtual unsigned long _QueueSize( ) const override;
+
+    private:
+      // Purposely not implemented.
+      DijkstraBase( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TWeightFunction::Pointer m_WeightFunction;
+
+      TQueue      m_Queue;
+      TQueueOrder m_QueueOrder;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/DijkstraBase.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__DijkstraBase__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/DijkstraBase.hxx b/lib/fpa/Base/DijkstraBase.hxx
new file mode 100644 (file)
index 0000000..a78554b
--- /dev/null
@@ -0,0 +1,114 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__DijkstraBase__hxx__
+#define __fpa__Base__DijkstraBase__hxx__
+
+#include <algorithm>
+#include <limits>
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+itk::ModifiedTimeType fpa::Base::DijkstraBase< _TAlgorithm >::
+GetMTime( ) const
+{
+  itk::ModifiedTimeType t = this->Superclass::GetMTime( );
+  if( this->m_WeightFunction.IsNotNull( ) )
+  {
+    itk::ModifiedTimeType q = this->m_WeightFunction->GetMTime( );
+    t = ( q < t )? q: t;
+
+  } // fi
+  return( t );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+fpa::Base::DijkstraBase< _TAlgorithm >::
+DijkstraBase( )
+  : Superclass( )
+{
+  this->SetInitValue( std::numeric_limits< TOutputValue >::max( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+fpa::Base::DijkstraBase< _TAlgorithm >::
+~DijkstraBase( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+typename fpa::Base::DijkstraBase< _TAlgorithm >::
+TOutputValue fpa::Base::DijkstraBase< _TAlgorithm >::
+_ComputeOutputValue( const TNode& n )
+{
+  TOutputValue c = this->m_WeightFunction->Evaluate( n.Vertex, n.Parent );
+  return( c + this->_GetOutputValue( n.Parent ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::DijkstraBase< _TAlgorithm >::
+_QueueInit( )
+{
+  typedef typename Superclass::TSeedsInterface::TSeeds::iterator _TIt;
+
+  this->Superclass::_QueueInit( );
+  for( _TIt sIt = this->BeginSeeds( ); sIt != this->EndSeeds( ); ++sIt )
+    sIt->Value = TOutputValue( 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::DijkstraBase< _TAlgorithm >::
+_QueueClear( )
+{
+  this->m_Queue.clear( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+typename fpa::Base::DijkstraBase< _TAlgorithm >::
+TNode fpa::Base::DijkstraBase< _TAlgorithm >::
+_QueuePop( )
+{
+  std::pop_heap(
+    this->m_Queue.begin( ), this->m_Queue.end( ), this->m_QueueOrder
+    );
+  TNode n = this->m_Queue.back( );
+  this->m_Queue.pop_back( );
+  return( n );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::DijkstraBase< _TAlgorithm >::
+_QueuePush( const TNode& node )
+{
+  bool push_needed =  ( node.Parent == node.Vertex );
+  push_needed     |= !( node.Value < this->_GetOutputValue( node.Parent ) );
+  if( push_needed )
+  {
+    this->m_Queue.push_back( node );
+    std::push_heap(
+      this->m_Queue.begin( ), this->m_Queue.end( ), this->m_QueueOrder
+      );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+unsigned long fpa::Base::DijkstraBase< _TAlgorithm >::
+_QueueSize( ) const
+{
+  return( this->m_Queue.size( ) );
+}
+
+#endif // __fpa__Base__DijkstraBase__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/Functors/Dijkstra/Function.h b/lib/fpa/Base/Functors/Dijkstra/Function.h
new file mode 100644 (file)
index 0000000..013cb99
--- /dev/null
@@ -0,0 +1,64 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Functors__Dijkstra__Function__h__
+#define __fpa__Base__Functors__Dijkstra__Function__h__
+
+#include <itkObject.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    namespace Functors
+    {
+      namespace Dijkstra
+      {
+        /**
+         */
+        template< class _TVertex, class _TOutputValue >
+        class Function
+          : public itk::Object
+        {
+        public:
+          typedef Function                        Self;
+          typedef itk::Object                     Superclass;
+          typedef itk::SmartPointer< Self >       Pointer;
+          typedef itk::SmartPointer< const Self > ConstPointer;
+
+        public:
+          itkTypeMacro( fpa::Base::Functors::Dijkstra::Function, itk::Object );
+
+        public:
+          virtual _TOutputValue Evaluate(
+            const _TVertex& v, const _TVertex& p
+            ) const = 0;
+
+        protected:
+          Function( )
+            : Superclass( )
+            {
+            }
+          virtual ~Function( )
+            {
+            }
+
+        private:
+          // Purposely not implemented
+          Function( const Self& other );
+          Self& operator=( const Self& other );
+        };
+
+      } // ecapseman
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Base__Functors__Dijkstra__Function__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h b/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h
new file mode 100644 (file)
index 0000000..ce533f6
--- /dev/null
@@ -0,0 +1,86 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Functors__RegionGrow__BinaryThreshold__h__
+#define __fpa__Base__Functors__RegionGrow__BinaryThreshold__h__
+
+#include <limits>
+#include <itkFunctionBase.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    namespace Functors
+    {
+      namespace RegionGrow
+      {
+        /**
+         */
+        template< class _TValue >
+        class BinaryThreshold
+          : public itk::FunctionBase< _TValue, bool >
+        {
+        public:
+          typedef BinaryThreshold                    Self;
+          typedef itk::FunctionBase< _TValue, bool > Superclass;
+          typedef itk::SmartPointer< Self >          Pointer;
+          typedef itk::SmartPointer< const Self >    ConstPointer;
+
+        public:
+          itkNewMacro( Self );
+          itkTypeMacro(
+            fpa::Base::Functors::RegionGrow::BinaryThreshold,
+            itk::FunctionBase
+            );
+
+          itkGetConstMacro( Lower, _TValue );
+          itkGetConstMacro( Upper, _TValue );
+
+          itkSetMacro( Lower, _TValue );
+          itkSetMacro( Upper, _TValue );
+
+        public:
+          virtual bool Evaluate( const _TValue& input ) const override
+            {
+              return( this->m_Lower < input && input < this->m_Upper );
+            }
+
+        protected:
+          BinaryThreshold( )
+            : Superclass( )
+            {
+              this->m_Upper = std::numeric_limits< _TValue >::max( );
+              if( std::numeric_limits< _TValue >::is_integer )
+                this->m_Lower = std::numeric_limits< _TValue >::min( );
+              else
+                this->m_Lower = -this->m_Upper;
+            }
+
+          virtual ~BinaryThreshold( )
+            {
+            }
+
+        private:
+          // Purposely not implemented
+          BinaryThreshold( const Self& other );
+          Self& operator=( const Self& other );
+
+        protected:
+          _TValue m_Lower;
+          _TValue m_Upper;
+        };
+
+      } // ecapseman
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Base__Functors__RegionGrow__BinaryThreshold__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/Functors/RegionGrow/Tautology.h b/lib/fpa/Base/Functors/RegionGrow/Tautology.h
new file mode 100644 (file)
index 0000000..a024b59
--- /dev/null
@@ -0,0 +1,69 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Functors__RegionGrow__Tautology__h__
+#define __fpa__Base__Functors__RegionGrow__Tautology__h__
+
+#include <itkFunctionBase.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    namespace Functors
+    {
+      namespace RegionGrow
+      {
+        /**
+         */
+        template< class _TValue >
+        class Tautology
+          : public itk::FunctionBase< _TValue, bool >
+        {
+        public:
+          typedef Tautology                          Self;
+          typedef itk::FunctionBase< _TValue, bool > Superclass;
+          typedef itk::SmartPointer< Self >          Pointer;
+          typedef itk::SmartPointer< const Self >    ConstPointer;
+
+        public:
+          itkNewMacro( Self );
+          itkTypeMacro(
+            fpa::Base::Functors::RegionGrow::Tautology,
+            itk::FunctionBase
+            );
+
+        public:
+          virtual bool Evaluate( const _TValue& input ) const override
+            {
+              return( true );
+            }
+
+        protected:
+          Tautology( )
+            : Superclass( )
+            {
+            }
+          virtual ~Tautology( )
+            {
+            }
+
+        private:
+          // Purposely not implemented
+          Tautology( const Self& other );
+          Self& operator=( const Self& other );
+        };
+
+      } // ecapseman
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Base__Functors__RegionGrow__Tautology__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/Graph.h b/lib/fpa/Base/Graph.h
new file mode 100644 (file)
index 0000000..41b2fb9
--- /dev/null
@@ -0,0 +1,170 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Graph__h__
+#define __fpa__Base__Graph__h__
+
+#include <map>
+#include <set>
+#include <vector>
+#include <itkDataObject.h>
+#include <itkObjectFactory.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /** \brief A generic graph with templated index types.
+     *
+     *  @param _TVertex Vertex type.
+     *  @param _TCost   Cost type.
+     *  @param _TIndex  Index type (it should be a strict weak ordering type).
+     */
+    template< class _TVertex, class _TCost, class _TIndex = unsigned long, class _TIndexCompare = std::less< _TIndex > >
+    class Graph
+      : public itk::DataObject
+    {
+    public:
+      typedef Graph                           Self;
+      typedef itk::DataObject                 Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TVertex       TVertex;
+      typedef _TCost         TCost;
+      typedef _TIndex        TIndex;
+      typedef _TIndexCompare TIndexCompare;
+
+      // Base types
+      typedef std::map< TIndex, TVertex, TIndexCompare >    TVertices;
+      typedef std::vector< TCost >                          TEdges;
+      typedef std::map< TIndex, TEdges, TIndexCompare >     TMatrixRow;
+      typedef std::map< TIndex, TMatrixRow, TIndexCompare > TMatrix;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Graph, itk::DataObject );
+
+    public:
+      /*! \brief Iterators over vertices.
+       *         These allow you to iterate over all of graph's vertices.
+       *
+       * Typical iteration should be done as:
+       *
+       *  TGraph g;
+       *  ...
+       *  TGraph::TVertices::[const_]iterator vIt = g.BeginVertices( );
+       *  for( ; vIt != g.EndVertices( ); ++vIt )
+       *  {
+       *    vIt->first;  --> this is the vertex's index <--
+       *    vIt->second; --> this is the vertex's value <--
+       *  }
+       */
+      inline typename TVertices::iterator BeginVertices( )
+        { return( this->m_Vertices.begin( ) ); }
+      inline typename TVertices::iterator EndVertices( )
+        { return( this->m_Vertices.end( ) ); }
+      inline typename TVertices::const_iterator BeginVertices( ) const
+        { return( this->m_Vertices.begin( ) ); }
+      inline typename TVertices::const_iterator EndVertices( ) const
+        { return( this->m_Vertices.end( ) ); }
+
+      /*! \brief Iterators over edges.
+       *         These allow you to iterate over all of graph's edges.
+       *
+       * Typical iteration should be done as:
+       *
+       *  TGraph g;
+       *  ...
+       *  TGraph::TMatrix::[const_]iterator mIt = g.BeginEdgesRows( );
+       *  for( ; mIt != g.EndEdgesRows( ); ++mIt )
+       *  {
+       *    mIt->first; --> this is the row index. <--
+       *    TGraph::TMatrixRow::[const_]iterator rIt = mIt->second.begin( );
+       *    for( ; rIt != mIt->second.end( ); ++rIt )
+       *    {
+       *      rIt->first;  --> this is the column index.
+       *      TGraph::TEdges::[const_]iterator eIt = rIt->second.begin( );
+       *      for( ; eIt != rIt->second.end( ); ++eIt )
+       *        *eIt; --> this is the cost between mIt->first and rIt->first
+       *    }
+       *  }
+       */
+      inline typename TMatrix::iterator BeginEdgesRows( )
+        { return( this->m_Matrix.begin( ) ); }
+      inline typename TMatrix::iterator EndEdgetsRows( )
+        { return( this->m_Matrix.end( ) ); }
+      inline typename TMatrix::const_iterator BeginEdgesRows( ) const
+        { return( this->m_Matrix.begin( ) ); }
+      inline typename TMatrix::const_iterator EndEdgesRows( ) const
+        { return( this->m_Matrix.end( ) ); }
+
+      /*! \brief Clear all vertices and edges.
+       */
+      void Clear( );
+
+      /*! \brief Clear all edges.
+       */
+      inline void ClearEdges( )
+        { this->m_Matrix.clear( ); }
+
+      /*! \brief Vertex manipulation methods.
+       *         Names are self-explanatory.
+       */
+      inline bool HasVertexIndex( const TIndex& i ) const
+        { return( this->m_Vertices.find( i ) != this->m_Vertices.end( ) ); }
+      inline void SetVertex( const TIndex& index, TVertex& vertex )
+        { this->m_Vertices[ index ] = vertex; }
+      inline TVertex& GetVertex( const TIndex& index )
+        { return( this->m_Vertices[ index ] ); }
+      inline const TVertex& GetVertex( const TIndex& index ) const
+        { return( this->m_Vertices[ index ] ); }
+      bool RenameVertex( const TIndex& old_index, const TIndex& new_index );
+      void RemoveVertex( const TIndex& index );
+
+      /*! \brief Edge manipulation methods.
+       *         Names are self-explanatory.
+       */
+      inline void AddEdge( const TIndex& orig, const TIndex& dest, const TCost& cost )
+        { this->m_Matrix[ orig ][ dest ].push_back( cost ); }
+      TEdges& GetEdges( const TIndex& orig, const TIndex& dest );
+      const TEdges& GetEdges( const TIndex& orig, const TIndex& dest ) const;
+      bool HasEdge( const TIndex& orig, const TIndex& dest ) const;
+      void RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost );
+      void RemoveEdges( const TIndex& orig, const TIndex& dest );
+
+      /*! \brief Returns graph's sinks.
+       *
+       *  A sink is a special vertex which does not have any "exiting" edges.
+       *
+       *  @return Sinks ordered by their index.
+       */
+      std::set< TIndex, TIndexCompare > GetSinks( ) const;
+
+    protected:
+      Graph( );
+      virtual ~Graph( );
+
+    private:
+      // Purposely not implemented
+      Graph( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TVertices m_Vertices;
+      TMatrix   m_Matrix;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/Graph.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__Graph__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/Graph.hxx b/lib/fpa/Base/Graph.hxx
new file mode 100644 (file)
index 0000000..03f85a8
--- /dev/null
@@ -0,0 +1,272 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Graph__hxx__
+#define __fpa__Base__Graph__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+Clear( )
+{
+  this->m_Vertices.clear( );
+  this->m_Matrix.clear( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+bool fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RenameVertex( const TIndex& old_index, const TIndex& new_index )
+{
+  typename TVertices::iterator old_v = this->m_Vertices.find( old_index );
+  typename TVertices::iterator new_v = this->m_Vertices.find( new_index );
+  if( old_v != this->m_Vertices.end( ) && new_v == this->m_Vertices.end( ) )
+  {
+    // Replace vertex
+    this->m_Vertices[ new_index ] = old_v->second;
+    this->m_Vertices.erase( old_index );
+
+    // Duplicate edges
+    typename TMatrix::iterator mIt = this->m_Matrix.begin( );
+    typename TMatrix::iterator found_row = this->m_Matrix.end( );
+    for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    {
+      if( mIt->first == old_index )
+        found_row = mIt;
+
+      typename TMatrixRow::iterator rIt = mIt->second.begin( );
+      for( ; rIt != mIt->second.end( ); ++rIt )
+      {
+        if( mIt->first == old_index )
+          this->m_Matrix[ new_index ][ rIt->first ] = rIt->second;
+        else if( rIt->first == old_index )
+          this->m_Matrix[ mIt->first ][ new_index ] = rIt->second;
+
+      } // rof
+
+    } // rof
+
+    // Delete old edges
+    if( found_row != this->m_Matrix.end( ) )
+      this->m_Matrix.erase( found_row );
+
+    mIt = this->m_Matrix.begin( );
+    for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    {
+      typename TMatrixRow::iterator rIt = mIt->second.begin( );
+      while( rIt != mIt->second.end( ) )
+      {
+        if( rIt->first == old_index )
+        {
+          mIt->second.erase( rIt );
+          rIt = mIt->second.begin( );
+        }
+        else
+          ++rIt;
+
+      } // elihw
+
+    } // rof
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RemoveVertex( const TIndex& index )
+{
+  typename TVertices::iterator i = this->m_Vertices.find( index );
+  if( i != this->m_Vertices.end( ) )
+  {
+    // Delete vertex
+    this->m_Vertices.erase( i );
+
+    // Delete edges starting from given vertex
+    typename TMatrix::iterator mIt = this->m_Matrix.find( index );
+    if( mIt != this->m_Matrix.end( ) )
+      this->m_Matrix.erase( mIt );
+
+    // Delete edges arriving to given vertex
+    mIt = this->m_Matrix.begin( );
+    for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    {
+      typename TMatrixRow::iterator rIt = mIt->second.begin( );
+      while( rIt != mIt->second.end( ) )
+      {
+        if( rIt->first == index )
+        {
+          mIt->second.erase( rIt );
+          rIt = mIt->second.begin( );
+        }
+        else
+          ++rIt;
+
+      } // elihw
+
+    } // rof
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+typename
+fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+TEdges&
+fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+GetEdges( const TIndex& orig, const TIndex& dest )
+{
+  static TEdges null_edges;
+  typename TMatrix::iterator o = this->m_Matrix.find( orig );
+  if( o != this->m_Matrix.find( orig ) )
+  {
+    typename TMatrixRow::iterator d = o->second.find( dest );
+    if( d == o->second.end( ) )
+    {
+      null_edges.clear( );
+      return( null_edges );
+    }
+    else
+      return( d->second );
+  }
+  else
+  {
+    null_edges.clear( );
+    return( null_edges );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+const typename 
+fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+TEdges&
+fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+GetEdges( const TIndex& orig, const TIndex& dest ) const
+{
+  static const TEdges null_edges;
+  typename TMatrix::iterator o = this->m_Matrix.find( orig );
+  if( o != this->m_Matrix.find( orig ) )
+  {
+    typename TMatrixRow::iterator d = o->second.find( dest );
+    if( d == o->second.end( ) )
+      return( null_edges );
+    else
+      return( d->second );
+  }
+  else
+    return( null_edges );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+bool fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+HasEdge( const TIndex& orig, const TIndex& dest ) const
+{
+  typename TMatrix::const_iterator mIt = this->m_Matrix.find( orig );
+  if( mIt != this->m_Matrix.end( ) )
+    return( mIt->second.find( dest ) != mIt->second.end( ) );
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost )
+{
+  typename TMatrix::iterator m = this->m_Matrix.find( orig );
+  if( m != this->m_Matrix.end( ) )
+  {
+    typename TMatrixRow::iterator r = m->second.find( dest );
+    if( r != m->second.end( ) )
+    {
+      typename TEdges::iterator e = r->second.end( );
+      for(
+        typename TEdges::iterator i = r->second.begin( );
+        i != r->second.end( ) && e == r->second.end( );
+        ++i
+        )
+        if( *i == cost )
+          e = i;
+      if( e != r->second.end( ) )
+      {
+        r->second.erase( e );
+        if( r->second.size( ) == 0 )
+        {
+          m->second.erase( r );
+          if( m->second.size( ) == 0 )
+            this->m_Matrix.erase( m );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RemoveEdges( const TIndex& orig, const TIndex& dest )
+{
+  typename TMatrix::iterator m = this->m_Matrix.find( orig );
+  if( m != this->m_Matrix.end( ) )
+  {
+    typename TMatrixRow::iterator r = m->second.find( dest );
+    if( r != m->second.end( ) )
+    {
+      m->second.erase( r );
+      if( m->second.size( ) == 0 )
+        this->m_Matrix.erase( m );
+
+    } // fi
+
+  } // fi
+
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+std::set< _TIndex, _TIndexCompare >
+fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+GetSinks( ) const
+{
+  std::set< _TIndex, _TIndexCompare > sinks;
+
+  typename TVertices::iterator vIt = this->m_Vertices.begin( );
+  for( ; vIt != this->m_Vertices.end( ); ++vIt )
+    sinks.insert( vIt->first );
+  typename TMatrix::iterator mIt = this->m_Matrix.begin( );
+  for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    sinks.erase( mIt->first );
+
+  return( sinks );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+Graph( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+~Graph( )
+{
+}
+
+#endif // __fpa__Base__Graph__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/MarksInterface.h b/lib/fpa/Base/MarksInterface.h
new file mode 100644 (file)
index 0000000..3b99765
--- /dev/null
@@ -0,0 +1,50 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MarksInterface__h__
+#define __fpa__Base__MarksInterface__h__
+
+#include <itkProcessObject.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TVertex >
+    class MarksInterface
+    {
+    public:
+      typedef _TVertex       TVertex;
+      typedef MarksInterface Self;
+
+    protected:
+      MarksInterface( itk::ProcessObject* filter );
+      virtual ~MarksInterface( );
+
+      virtual bool _IsMarked( const TVertex& v ) const = 0;
+      virtual unsigned long _GetMark( const TVertex& v ) const = 0;
+      virtual bool _Mark( const TVertex& v, unsigned long frontId ) = 0;
+
+      virtual void _InitMarks( unsigned long nSeeds );
+      virtual bool _Collisions( const TVertex& a, const TVertex& b );
+
+    protected:
+      unsigned int m_NumberOfSeeds;
+      itk::ProcessObject* m_Filter;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/MarksInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__MarksInterface__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/MarksInterface.hxx b/lib/fpa/Base/MarksInterface.hxx
new file mode 100644 (file)
index 0000000..cd37eb5
--- /dev/null
@@ -0,0 +1,43 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MarksInterface__hxx__
+#define __fpa__Base__MarksInterface__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+fpa::Base::MarksInterface< _TVertex >::
+MarksInterface( itk::ProcessObject* filter )
+  : m_NumberOfSeeds( 0 ),
+    m_Filter( filter )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+fpa::Base::MarksInterface< _TVertex >::
+~MarksInterface( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterface< _TVertex >::
+_InitMarks( unsigned long nSeeds )
+{
+  this->m_NumberOfSeeds = nSeeds;
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+bool fpa::Base::MarksInterface< _TVertex >::
+_Collisions( const TVertex& a, const TVertex& b )
+{
+  return( false );
+}
+
+#endif // __fpa__Base__MarksInterface__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/MarksInterfaceWithCollisions.h b/lib/fpa/Base/MarksInterfaceWithCollisions.h
new file mode 100644 (file)
index 0000000..3d6f10e
--- /dev/null
@@ -0,0 +1,62 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MarksInterfaceWithCollisions__h__
+#define __fpa__Base__MarksInterfaceWithCollisions__h__
+
+#include <fpa/Base/MarksInterface.h>
+#include <utility>
+#include <vector>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TVertex >
+    class MarksInterfaceWithCollisions
+      : public fpa::Base::MarksInterface< _TVertex >
+    {
+    public:
+      typedef _TVertex                             TVertex;
+      typedef MarksInterfaceWithCollisions         Self;
+      typedef fpa::Base::MarksInterface< TVertex > Superclass;
+
+      // Minigraph to represent collisions
+      typedef std::pair< TVertex, bool >    TCollision;
+      typedef std::vector< TCollision >     TCollisionsRow;
+      typedef std::vector< TCollisionsRow > TCollisions;
+
+    public:
+      bool StopAtOneFront( ) const;
+      void StopAtOneFrontOn( );
+      void StopAtOneFrontOff( );
+      void SetStopAtOneFront( bool v );
+
+    protected:
+      MarksInterfaceWithCollisions( itk::ProcessObject* filter );
+      virtual ~MarksInterfaceWithCollisions( );
+
+      virtual void _InitMarks( unsigned long nSeeds ) override;
+      virtual bool _Collisions( const TVertex& a, const TVertex& b ) override;
+
+    protected:
+      bool         m_StopAtOneFront;
+      TCollisions  m_Collisions;
+      unsigned int m_NumberOfFronts;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/MarksInterfaceWithCollisions.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__MarksInterfaceWithCollisions__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/MarksInterfaceWithCollisions.hxx b/lib/fpa/Base/MarksInterfaceWithCollisions.hxx
new file mode 100644 (file)
index 0000000..1230931
--- /dev/null
@@ -0,0 +1,133 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MarksInterfaceWithCollisions__hxx__
+#define __fpa__Base__MarksInterfaceWithCollisions__hxx__
+
+#include <queue>
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+bool fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+StopAtOneFront( ) const
+{
+  return( this->m_StopAtOneFront );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+StopAtOneFrontOn( )
+{
+  this->SetStopAtOneFront( true );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+StopAtOneFrontOff( )
+{
+  this->SetStopAtOneFront( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+SetStopAtOneFront( bool v )
+{
+  if( this->m_StopAtOneFront != v )
+  {
+    this->m_StopAtOneFront = v;
+    if( this->m_Filter != NULL )
+      this->m_Filter->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+MarksInterfaceWithCollisions( itk::ProcessObject* filter )
+  : Superclass( filter ),
+    m_StopAtOneFront( false ),
+    m_NumberOfFronts( 0 )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+~MarksInterfaceWithCollisions( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+_InitMarks( unsigned long nSeeds )
+{
+  this->Superclass::_InitMarks( nSeeds );
+  this->m_NumberOfFronts = nSeeds;
+  TCollision coll( TVertex( ), false );
+  TCollisionsRow row( this->m_NumberOfFronts, coll );
+  this->m_Collisions.clear( );
+  this->m_Collisions.resize( this->m_NumberOfFronts, row );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+bool fpa::Base::MarksInterfaceWithCollisions< _TVertex >::
+_Collisions( const TVertex& a, const TVertex& b )
+{
+  unsigned long ma = this->_GetMark( a );
+  unsigned long mb = this->_GetMark( b );
+  if( ma == mb || ma == 0 || mb == 0 )
+    return( false );
+
+  // Mark collision, if it is new
+  ma--; mb--;
+  bool ret = false;
+  bool exists = this->m_Collisions[ ma ][ mb ].second;
+  exists     &= this->m_Collisions[ mb ][ ma ].second;
+  if( !exists )
+  {
+    this->m_Collisions[ ma ][ mb ].first = a;
+    this->m_Collisions[ ma ][ mb ].second = true;
+    this->m_Collisions[ mb ][ ma ].first = b;
+    this->m_Collisions[ mb ][ ma ].second = true;
+
+    // Update number of fronts
+    unsigned long count = 0;
+    std::vector< bool > m( this->m_NumberOfSeeds, 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 < this->m_NumberOfSeeds; ++n )
+        if( this->m_Collisions[ f ][ n ].second && !m[ n ] )
+          q.push( n );
+
+    } // elihw
+    this->m_NumberOfFronts = this->m_NumberOfSeeds - count + 1;
+
+  } // fi
+  return(
+    this->m_StopAtOneFront &&
+    this->m_NumberOfSeeds > 1 &&
+    this->m_NumberOfFronts == 1
+    );
+}
+
+#endif // __fpa__Base__MarksInterfaceWithCollisions__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/MinimumSpanningTree.h b/lib/fpa/Base/MinimumSpanningTree.h
new file mode 100644 (file)
index 0000000..35cb6e4
--- /dev/null
@@ -0,0 +1,77 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MinimumSpanningTree__h__
+#define __fpa__Base__MinimumSpanningTree__h__
+
+#include <vector>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TVertex, class _Superclass >
+    class MinimumSpanningTree
+      : public _Superclass
+    {
+    public:
+      typedef MinimumSpanningTree             Self;
+      typedef _Superclass                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TVertex                      TVertex;
+      typedef std::pair< TVertex, bool >    TCollision;
+      typedef std::vector< TCollision >     TCollisionsRow;
+      typedef std::vector< TCollisionsRow > TCollisions;
+      typedef std::vector< TVertex >        TVertices;
+
+    protected:
+      typedef std::vector< unsigned long > _TRow;
+      typedef std::vector< _TRow >         _TMatrix;
+
+    public:
+      itkTypeMacro( fpa::Base::MinimumSpanningTree, _Superclass );
+
+    public:
+      const TCollisions& GetCollisions( ) const;
+      void SetCollisions( const TCollisions& collisions );
+
+      void ClearSeeds( );
+      void AddSeed( const TVertex& seed );
+
+      virtual TVertex GetParent( const TVertex& v ) const = 0;
+      virtual void SetParent( const TVertex& v, const TVertex& p ) = 0;
+
+      virtual TVertices GetPath( const TVertex& a ) const;
+      virtual TVertices GetPath( const TVertex& a, const TVertex& b ) const;
+
+    protected:
+      MinimumSpanningTree( );
+      virtual ~MinimumSpanningTree( );
+
+    private:
+      MinimumSpanningTree( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TCollisions m_Collisions;
+      _TMatrix    m_FrontPaths;
+      std::vector< TVertex > m_Seeds;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/MinimumSpanningTree.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__MinimumSpanningTree__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/MinimumSpanningTree.hxx b/lib/fpa/Base/MinimumSpanningTree.hxx
new file mode 100644 (file)
index 0000000..c5838f3
--- /dev/null
@@ -0,0 +1,237 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MinimumSpanningTree__hxx__
+#define __fpa__Base__MinimumSpanningTree__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+const typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+TCollisions& fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+GetCollisions( ) const
+{
+  return( this->m_Collisions );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+SetCollisions( const TCollisions& collisions )
+{
+  static const unsigned long _inf =
+    std::numeric_limits< unsigned long >::max( );
+  if( this->m_Collisions == collisions )
+    return;
+
+  this->m_Collisions = collisions;
+
+  // Prepare a front graph
+  unsigned long N = this->m_Collisions.size( );
+  _TMatrix dist( N, _TRow( N, _inf ) );
+  this->m_FrontPaths = dist;
+  for( unsigned long i = 0; i < N; ++i )
+  {
+    for( unsigned long j = 0; j < N; ++j )
+    {
+      if( this->m_Collisions[ i ][ j ].second )
+      {
+        dist[ i ][ j ] = 1;
+        dist[ j ][ i ] = 1;
+        this->m_FrontPaths[ i ][ j ] = j;
+        this->m_FrontPaths[ j ][ i ] = i;
+
+      } // fi
+
+    } // rof
+    dist[ i ][ i ] = 0;
+    this->m_FrontPaths[ i ][ i ] = i;
+
+  } // rof
+
+  // Use Floyd-Warshall to compute all possible paths between fronts
+  for( unsigned long k = 0; k < N; ++k )
+  {
+    for( unsigned long i = 0; i < N; ++i )
+    {
+      for( unsigned long j = 0; j < N; ++j )
+      {
+        // WARNING: you don't want a numeric overflow!!!
+        unsigned long dik = dist[ i ][ k ];
+        unsigned long dkj = dist[ k ][ j ];
+        unsigned long sum = _inf;
+        if( dik < _inf && dkj < _inf )
+          sum = dik + dkj;
+
+        // Ok, continue Floyd-Warshall
+        if( sum < dist[ i ][ j ] )
+        {
+          dist[ i ][ j ] = sum;
+          this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ];
+
+        } // fi
+
+      } // rof
+
+    } // rof
+
+  } // rof
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+ClearSeeds( )
+{
+  this->m_Seeds.clear( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+AddSeed( const _TVertex& seed )
+{
+  this->m_Seeds.push_back( seed );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+TVertices fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+GetPath( const _TVertex& a ) const
+{
+  TVertices vertices;
+  _TVertex it = a;
+  _TVertex p = this->GetParent( it );
+  while( it != p )
+  {
+    vertices.push_back( it );
+    it = p;
+    p = this->GetParent( it );
+
+  } // elihw
+  vertices.push_back( it );
+  return( vertices );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+TVertices fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+GetPath( const _TVertex& a, const _TVertex& b ) const
+{
+  static const unsigned long _inf =
+    std::numeric_limits< unsigned long >::max( );
+
+  TVertices vertices;
+  TVertices pa = this->GetPath( a );
+  TVertices pb = this->GetPath( b );
+  if( pa.size( ) > 0 && pb.size( ) > 0 )
+  {
+    // Find front identifiers
+    unsigned long ia = _inf, ib = _inf;
+    unsigned long N = this->m_Seeds.size( );
+    for( unsigned long i = 0; i < N; ++i )
+    {
+      if( this->m_Seeds[ i ] == pa[ pa.size( ) - 1 ] )
+        ia = i;
+      if( this->m_Seeds[ i ] == pb[ pb.size( ) - 1 ] )
+        ib = i;
+
+    } // rof
+
+    // Check if there is a front-jump between given seeds
+    if( ia != ib )
+    {
+      // Compute front path
+      std::vector< long > fpath;
+      fpath.push_back( ia );
+      while( ia != ib )
+      {
+        ia = this->m_FrontPaths[ ia ][ ib ];
+        fpath.push_back( ia );
+
+      } // elihw
+
+      // Continue only if both fronts are connected
+      unsigned int N = fpath.size( );
+      if( N > 0 )
+      {
+        // First path: from start vertex to first collision
+        vertices = 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
+              );
+          for( long id = 0; id < ipath.size( ); ++id )
+            vertices.push_back( ipath[ id ] );
+
+        } // rof
+
+        // Final path: from last collision to end point
+        TVertices lpath =
+          this->GetPath(
+            this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b
+            );
+        for( long id = 0; id < lpath.size( ); ++id )
+          vertices.push_back( lpath[ id ] );
+
+      } // fi
+    }
+    else
+    {
+      // Ignore common part: find common ancestor
+      long aIt = pa.size( ) - 1;
+      long bIt = pb.size( ) - 1;
+      bool cont = true;
+      while( aIt >= 0 && bIt >= 0 && cont )
+      {
+        cont = ( pa[ aIt ] == pb[ bIt ] );
+        aIt--;
+        bIt--;
+
+      } // elihw
+      aIt++;
+      bIt++;
+
+      // Glue both parts
+      for( long cIt = 0; cIt <= aIt; ++cIt )
+        vertices.push_back( pa[ cIt ] );
+      for( ; bIt >= 0; --bIt )
+        vertices.push_back( pb[ bIt ] );
+
+    } // fi
+
+  } // fi
+  return( vertices );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+MinimumSpanningTree( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _Superclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >::
+~MinimumSpanningTree( )
+{
+}
+
+#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..796c90b
--- /dev/null
@@ -0,0 +1,96 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__RegionGrow__h__
+#define __fpa__Base__RegionGrow__h__
+
+#include <deque>
+
+#include <itkConceptChecking.h>
+#include <itkFunctionBase.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TAlgorithm >
+    class RegionGrow
+      : public _TAlgorithm
+    {
+    public:
+      typedef RegionGrow                      Self;
+      typedef _TAlgorithm                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename _TAlgorithm::TNode        TNode;
+      typedef typename _TAlgorithm::TInputValue  TInputValue;
+      typedef typename _TAlgorithm::TOutputValue TOutputValue;
+      typedef typename _TAlgorithm::TFrontId     TFrontId;
+      typedef typename _TAlgorithm::TVertex      TVertex;
+
+      typedef std::deque< TNode >                    TQueue;
+      typedef itk::FunctionBase< TInputValue, bool > TValuePredicate;
+      typedef itk::FunctionBase< TVertex, bool >     TVertexPredicate;
+
+    public:
+      itkConceptMacro(
+        Check_TOutputValue,
+        ( itk::Concept::IsUnsignedInteger< TOutputValue > )
+        );
+
+    public:
+      itkGetObjectMacro( ValuePredicate, TValuePredicate );
+      itkGetObjectMacro( VertexPredicate, TVertexPredicate );
+      itkGetConstMacro( InsideValue, TOutputValue );
+
+      itkSetMacro( InsideValue, TOutputValue );
+
+    public:
+      virtual itk::ModifiedTimeType GetMTime( ) const override;
+      virtual TOutputValue GetOutsideValue( ) const;
+      virtual void SetOutsideValue( const TOutputValue& v );
+
+      void SetPredicate( TValuePredicate* p );
+      void SetPredicate( TVertexPredicate* p );
+
+    protected:
+      RegionGrow( );
+      virtual ~RegionGrow( );
+
+      virtual TOutputValue _ComputeOutputValue( const TNode& n ) override;
+      virtual void _QueueInit( ) override;
+      virtual void _QueueClear( ) override;
+      virtual TNode _QueuePop( ) override;
+      virtual void _QueuePush( const TNode& node ) override;
+      virtual unsigned long _QueueSize( ) const override;
+
+    private:
+      // Purposely not implemented.
+      RegionGrow( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TValuePredicate::Pointer  m_ValuePredicate;
+      typename TVertexPredicate::Pointer m_VertexPredicate;
+
+      TOutputValue m_InsideValue;
+
+      TQueue m_Queue;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/RegionGrow.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#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..18bb132
--- /dev/null
@@ -0,0 +1,155 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__RegionGrow__hxx__
+#define __fpa__Base__RegionGrow__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+itk::ModifiedTimeType fpa::Base::RegionGrow< _TAlgorithm >::
+GetMTime( ) const
+{
+  itk::ModifiedTimeType t = this->Superclass::GetMTime( );
+  if( this->m_ValuePredicate.IsNotNull( ) )
+  {
+    itk::ModifiedTimeType q = this->m_ValuePredicate->GetMTime( );
+    t = ( q < t )? q: t;
+
+  } // fi
+  if( this->m_VertexPredicate.IsNotNull( ) )
+  {
+    itk::ModifiedTimeType q = this->m_VertexPredicate->GetMTime( );
+    t = ( q < t )? q: t;
+
+  } // fi
+
+  return( t );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+typename fpa::Base::RegionGrow< _TAlgorithm >::
+TOutputValue fpa::Base::RegionGrow< _TAlgorithm >::
+GetOutsideValue( ) const
+{
+  return( this->GetInitValue( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::RegionGrow< _TAlgorithm >::
+SetOutsideValue( const TOutputValue& v )
+{
+  this->SetInitValue( v );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::RegionGrow< _TAlgorithm >::
+SetPredicate( TValuePredicate* p )
+{
+  if( this->m_ValuePredicate.GetPointer( ) != p )
+  {
+    this->m_ValuePredicate = p;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::RegionGrow< _TAlgorithm >::
+SetPredicate( TVertexPredicate* p )
+{
+  if( this->m_VertexPredicate.GetPointer( ) != p )
+  {
+    this->m_VertexPredicate = p;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+fpa::Base::RegionGrow< _TAlgorithm >::
+RegionGrow( )
+  : Superclass( ),
+    m_InsideValue( TOutputValue( 1 ) )
+{
+  this->SetInitValue( TOutputValue( 0 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+fpa::Base::RegionGrow< _TAlgorithm >::
+~RegionGrow( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+typename fpa::Base::RegionGrow< _TAlgorithm >::
+TOutputValue fpa::Base::RegionGrow< _TAlgorithm >::
+_ComputeOutputValue( const TNode& n )
+{
+  TInputValue value = this->_GetInputValue( n.Vertex );
+  bool inside = false;
+  if( this->m_ValuePredicate.IsNotNull( ) )
+    inside = this->m_ValuePredicate->Evaluate( value );
+  if( this->m_VertexPredicate.IsNotNull( ) )
+    inside &= this->m_VertexPredicate->Evaluate( n.Vertex );
+  return( ( inside )? this->m_InsideValue: this->m_InitValue );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::RegionGrow< _TAlgorithm >::
+_QueueInit( )
+{
+  typedef typename Superclass::TSeedsInterface::TSeeds::iterator _TIt;
+
+  this->Superclass::_QueueInit( );
+  for( _TIt sIt = this->BeginSeeds( ); sIt != this->EndSeeds( ); ++sIt )
+    sIt->Value = this->m_InsideValue;
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::RegionGrow< _TAlgorithm >::
+_QueueClear( )
+{
+  this->m_Queue.clear( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+typename fpa::Base::RegionGrow< _TAlgorithm >::
+TNode fpa::Base::RegionGrow< _TAlgorithm >::
+_QueuePop( )
+{
+  TNode n = this->m_Queue.front( );
+  this->m_Queue.pop_front( );
+  return( n );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+void fpa::Base::RegionGrow< _TAlgorithm >::
+_QueuePush( const TNode& node )
+{
+  this->m_Queue.push_back( node );
+}
+
+// -------------------------------------------------------------------------
+template< class _TAlgorithm >
+unsigned long fpa::Base::RegionGrow< _TAlgorithm >::
+_QueueSize( ) const
+{
+  return( this->m_Queue.size( ) );
+}
+
+#endif // __fpa__Base__RegionGrow__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/SeedsInterface.h b/lib/fpa/Base/SeedsInterface.h
new file mode 100644 (file)
index 0000000..e9c67c3
--- /dev/null
@@ -0,0 +1,86 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__SeedsInterface__h__
+#define __fpa__Base__SeedsInterface__h__
+
+#include <functional>
+#include <set>
+
+#include <itkConceptChecking.h>
+#include <itkProcessObject.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare = std::greater< _TVertex > >
+    class SeedsInterface
+    {
+    public:
+      itkConceptMacro(
+        Check_TFrontId,
+        ( itk::Concept::IsUnsignedInteger< _TFrontId > )
+        );
+
+    public:
+      typedef _TVertex       TVertex;
+      typedef _TInputValue   TInputValue;
+      typedef _TOutputValue  TOutputValue;
+      typedef _TFrontId      TFrontId;
+      typedef _TCompare      TCompare;
+      typedef SeedsInterface Self;
+
+      struct TNode
+      {
+        TVertex  Vertex;
+        TVertex  Parent;
+        TFrontId FrontId;
+
+        // Hack to hide the fact that seed values need to be initialized
+        mutable TOutputValue Value;
+      };
+      struct TNodeCompare
+      {
+        bool operator()( const TNode& a, const TNode& b ) const
+          {
+            TCompare cmp;
+            return( cmp( a.Vertex, b.Vertex ) );
+          }
+      };
+      typedef std::set< TNode, TNodeCompare > TSeeds;
+
+    public:
+      unsigned int GetNumberOfSeeds( ) const;
+      const TSeeds& GetSeeds( ) const;
+      typename TSeeds::const_iterator BeginSeeds( ) const;
+      typename TSeeds::const_iterator EndSeeds( ) const;
+
+      virtual void AddSeed( const TVertex& seed );
+      virtual void RemoveSeed( const TVertex& seed );
+      virtual void ClearSeeds( );
+
+    protected:
+      SeedsInterface( itk::ProcessObject* filter );
+      virtual ~SeedsInterface( );
+
+    protected:
+      TSeeds m_Seeds;
+      itk::ProcessObject* m_Filter;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/SeedsInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__SeedsInterface__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Base/SeedsInterface.hxx b/lib/fpa/Base/SeedsInterface.hxx
new file mode 100644 (file)
index 0000000..5c27216
--- /dev/null
@@ -0,0 +1,117 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__SeedsInterface__hxx__
+#define __fpa__Base__SeedsInterface__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+unsigned int
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+GetNumberOfSeeds( ) const
+{
+  return( this->m_Seeds.size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+const typename
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+TSeeds&
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+GetSeeds( ) const
+{
+  return( this->m_Seeds );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+typename
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+TSeeds::const_iterator
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+BeginSeeds( ) const
+{
+  return( this->m_Seeds.begin( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+typename
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+TSeeds::const_iterator
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+EndSeeds( ) const
+{
+  return( this->m_Seeds.end( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+void
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+AddSeed( const TVertex& seed )
+{
+  TNode node;
+  node.Vertex = seed;
+  node.Parent = seed;
+  node.FrontId = TFrontId( this->m_Seeds.size( ) + 1 );
+  if( this->m_Seeds.insert( node ).second && this->m_Filter != NULL )
+    this->m_Filter->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+void
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+RemoveSeed( const TVertex& seed )
+{
+  TNode node;
+  node.Vertex = seed;
+  node.Parent = seed;
+  typename TSeeds::const_iterator i = this->m_Seeds.find( node );
+  if( i != this->m_Seeds.end( ) )
+  {
+    this->m_Seeds.erase( i );
+    if( this->m_Filter != NULL )
+      this->m_Filter->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+void
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+ClearSeeds( )
+{
+  if( this->m_Seeds.size( ) > 0 )
+  {
+    this->m_Seeds.clear( );
+    if( this->m_Filter != NULL )
+      this->m_Filter->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+SeedsInterface( itk::ProcessObject* filter )
+  : m_Filter( filter )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+~SeedsInterface( )
+{
+  this->m_Seeds.clear( );
+}
+
+#endif // __fpa__Base__SeedsInterface__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/CMakeLists.txt b/lib/fpa/CMakeLists.txt
new file mode 100644 (file)
index 0000000..264f589
--- /dev/null
@@ -0,0 +1,69 @@
+
+## =====================
+## == Get source code ==
+## =====================
+
+configure_file(Version.cxx.in "${CMAKE_CURRENT_BINARY_DIR}/Version.cxx" @ONLY)
+configure_file(Config.h.in "${CMAKE_CURRENT_BINARY_DIR}/Config.h" @ONLY)
+file(GLOB_RECURSE _base_src "${CMAKE_CURRENT_SOURCE_DIR}/Base/*.cxx")
+file(GLOB_RECURSE _base_hdr "${CMAKE_CURRENT_SOURCE_DIR}/Base/*.h")
+file(GLOB_RECURSE _base_hrc "${CMAKE_CURRENT_SOURCE_DIR}/Base/*.hxx")
+file(GLOB_RECURSE _image_src "${CMAKE_CURRENT_SOURCE_DIR}/Image/*.cxx")
+file(GLOB_RECURSE _image_hdr "${CMAKE_CURRENT_SOURCE_DIR}/Image/*.h")
+file(GLOB_RECURSE _image_hrc "${CMAKE_CURRENT_SOURCE_DIR}/Image/*.hxx")
+
+set(_src
+  ${_base_src} ${_image_src}
+  "${CMAKE_CURRENT_BINARY_DIR}/Version.cxx"
+  )
+set(
+  _hdr
+  ${_base_hdr} ${_image_hdr}
+  "${CMAKE_CURRENT_BINARY_DIR}/Config.h"
+  )
+set(_hrc ${_base_hrc} ${_image_hrc})
+
+## =====================
+## == Compile library ==
+## =====================
+
+add_library(fpa SHARED ${_src} ${_hdr} ${_hrc})
+generate_export_header(fpa)
+set_property(TARGET fpa PROPERTY VERSION ${prj_VERSION})
+set_property(TARGET fpa PROPERTY SOVERSION ${prj_SHORT_VERSION})
+set_property(
+  TARGET fpa PROPERTY INTERFACE_fpa_MAJOR_VERSION ${prj_MAJ_VERSION}
+  )
+set_property(
+  TARGET fpa APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ${prj_MAJ_VERSION}
+  )
+target_link_libraries(fpa PUBLIC ${VTK_LIBRARIES} ${ITK_LIBRARIES})
+
+## ========================
+## == Installation rules ==
+## ========================
+
+install(
+  TARGETS fpa
+  EXPORT "${targets_export_name}"
+  LIBRARY DESTINATION "lib"
+  ARCHIVE DESTINATION "lib"
+  RUNTIME DESTINATION "bin"
+  INCLUDES DESTINATION "${include_install_dir}"
+  )
+install(
+  DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+  DESTINATION "${include_install_dir}"
+  FILES_MATCHING PATTERN "*.h"
+  )
+install(
+  DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+  DESTINATION "${include_install_dir}"
+  FILES_MATCHING PATTERN "*.hxx"
+  )
+install(
+  FILES "${CMAKE_CURRENT_BINARY_DIR}/fpa_export.h"
+  DESTINATION "${include_install_dir}/fpa"
+  )
+
+## eof - $RCSfile$
diff --git a/lib/fpa/Config.h.in b/lib/fpa/Config.h.in
new file mode 100644 (file)
index 0000000..18294bf
--- /dev/null
@@ -0,0 +1,18 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Config__h__
+#define __fpa__Config__h__
+
+#define ivq_FOUND @ivq_FOUND@
+#if ivq_FOUND == 1
+#  define USE_ivq
+#else
+#  undef USE_ivq
+#endif
+
+#endif // __fpa__Config__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Algorithm.h b/lib/fpa/Image/Algorithm.h
new file mode 100644 (file)
index 0000000..5547ff0
--- /dev/null
@@ -0,0 +1,88 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Algorithm__h__
+#define __fpa__Image__Algorithm__h__
+
+#include <itkImage.h>
+#include <itkImageToImageFilter.h>
+
+#include <fpa/Base/Algorithm.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+    class Algorithm
+      : public fpa::Base::Algorithm< itk::ImageToImageFilter< _TInputImage, _TOutputImage >, _TMarksInterface, _TSeedsInterface >
+    {
+    public:
+      typedef _TInputImage     TInputImage;
+      typedef _TOutputImage    TOutputImage;
+      typedef _TMarksInterface TMarksInterface;
+      typedef _TSeedsInterface TSeedsInterface;
+      typedef itk::ImageToImageFilter< TInputImage, TOutputImage > TFilter;
+
+      typedef Algorithm Self;
+      typedef fpa::Base::Algorithm< TFilter, TMarksInterface, TSeedsInterface > Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename TInputImage::PixelType    TInputValue;
+      typedef typename TOutputImage::PixelType   TOutputValue;
+      typedef typename Superclass::TFrontId      TFrontId;
+      typedef typename Superclass::TNeighborhood TNeighborhood;
+      typedef typename Superclass::TNode         TNode;
+      typedef typename Superclass::TVertex       TVertex;
+
+      typedef itk::Image< TFrontId, TInputImage::ImageDimension > TMarks;
+
+    public:
+      itkTypeMacro( fpa::Image::Algorithm, fpa::Base::Algorithm );
+
+      itkGetConstMacro( NeigborhoodOrder, unsigned int );
+      itkSetMacro( NeigborhoodOrder, unsigned int );
+
+    public:
+      TMarks* GetMarks( );
+      const TMarks* GetMarks( ) const;
+
+    protected:
+      Algorithm( );
+      virtual ~Algorithm( );
+
+      virtual void _ConfigureOutput( const TOutputValue& v ) override;
+      virtual TNeighborhood _GetNeighbors( const TVertex& v ) const override;
+      virtual TInputValue _GetInputValue( const TVertex& v ) const override;
+      virtual TOutputValue _GetOutputValue( const TVertex& v ) const override;
+      virtual void _UpdateOutputValue( const TNode& n ) override;
+      virtual bool _IsMarked( const TVertex& v ) const override;
+      virtual unsigned long _GetMark( const TVertex& v ) const override;
+      virtual bool _Mark( const TVertex& v, unsigned long frontId ) override;
+
+    private:
+      // Purposely not implemented.
+      Algorithm( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      unsigned long m_MarksIdx;
+      unsigned int  m_NeigborhoodOrder;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/Algorithm.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__Algorithm__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Algorithm.hxx b/lib/fpa/Image/Algorithm.hxx
new file mode 100644 (file)
index 0000000..0ae9b90
--- /dev/null
@@ -0,0 +1,176 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Algorithm__hxx__
+#define __fpa__Image__Algorithm__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+typename
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+TMarks*
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+GetMarks( )
+{
+  dynamic_cast< TMarks* >(
+    this->itk::ProcessObject::GetOutput( this->m_MarksIdx )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+const typename
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+TMarks*
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+GetMarks( ) const
+{
+  dynamic_cast< const TMarks* >(
+    this->itk::ProcessObject::GetOutput( this->m_MarksIdx )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+Algorithm( )
+  : Superclass( ),
+    m_NeigborhoodOrder( 1 )
+{
+  this->m_MarksIdx = this->GetNumberOfRequiredOutputs( );
+  this->itk::ProcessObject::SetNumberOfRequiredOutputs( this->m_MarksIdx + 1 );
+  this->SetNthOutput( this->m_MarksIdx, TMarks::New( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+~Algorithm( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+void
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_ConfigureOutput( const TOutputValue& v )
+{
+  const TInputImage* in = this->GetInput( );
+
+  TOutputImage* out = this->GetOutput( );
+  out->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) );
+  out->SetRequestedRegion( in->GetRequestedRegion( ) );
+  out->SetBufferedRegion( in->GetBufferedRegion( ) );
+  out->SetSpacing( in->GetSpacing( ) );
+  out->SetOrigin( in->GetOrigin( ) );
+  out->SetDirection( in->GetDirection( ) );
+  out->Allocate( );
+  out->FillBuffer( v );
+
+  TMarks* marks = this->GetMarks( );
+  marks->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) );
+  marks->SetRequestedRegion( in->GetRequestedRegion( ) );
+  marks->SetBufferedRegion( in->GetBufferedRegion( ) );
+  marks->SetSpacing( in->GetSpacing( ) );
+  marks->SetOrigin( in->GetOrigin( ) );
+  marks->SetDirection( in->GetDirection( ) );
+  marks->Allocate( );
+  marks->FillBuffer( TFrontId( 0 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+typename
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+TNeighborhood fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_GetNeighbors( const TVertex& v ) const
+{
+  typename TInputImage::RegionType region =
+    this->GetInput( )->GetRequestedRegion( );
+  TNeighborhood neighborhood;
+  if( this->m_NeigborhoodOrder != 1 )
+  {
+    // TODO
+  }
+  else
+  {
+    for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d )
+    {
+      for( int s = -1; s <= 1; s += 2 )
+      {
+        TVertex n = v;
+        n[ d ] += s;
+        if( region.IsInside( n ) )
+          neighborhood.push_back( n );
+
+      } // rof
+
+    } // rof
+
+  } // fi
+  return( neighborhood );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+typename
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+TInputValue
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_GetInputValue( const TVertex& v ) const
+{
+  return( this->GetInput( )->GetPixel( v ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+typename
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+TOutputValue fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_GetOutputValue( const TVertex& v ) const
+{
+  return( this->GetOutput( )->GetPixel( v ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+void
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_UpdateOutputValue( const TNode& n )
+{
+  this->GetOutput( )->SetPixel( n.Vertex, n.Value );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+bool
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_IsMarked( const TVertex& v ) const
+{
+  return( this->GetMarks( )->GetPixel( v ) > 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+unsigned long
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_GetMark( const TVertex& v ) const
+{
+  return( ( unsigned long )( this->GetMarks( )->GetPixel( v ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface >
+bool
+fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >::
+_Mark( const TVertex& v, unsigned long frontId )
+{
+  this->GetMarks( )->SetPixel( v, TFrontId( frontId ) );
+  return( true );
+}
+
+#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..d5a1bb9
--- /dev/null
@@ -0,0 +1,103 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Dijkstra__h__
+#define __fpa__Image__Dijkstra__h__
+
+#include <fpa/Base/Dijkstra.h>
+#include <fpa/Base/MarksInterfaceWithCollisions.h>
+#include <fpa/Base/SeedsInterface.h>
+#include <fpa/Image/Algorithm.h>
+#include <fpa/Image/MinimumSpanningTree.h>
+#include <fpa/Image/Functors/Dijkstra/Identity.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TInputImage, class _TOutputImage, class _TFrontId = unsigned char >
+    class Dijkstra
+      : public fpa::Base::Dijkstra< fpa::Image::Algorithm< _TInputImage, _TOutputImage, fpa::Base::MarksInterfaceWithCollisions< typename _TInputImage::IndexType >, fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::PixelType, typename _TOutputImage::PixelType, _TFrontId, typename _TInputImage::IndexType::LexicographicCompare > >, fpa::Image::MinimumSpanningTree< _TInputImage::ImageDimension > >
+    {
+    public:
+      typedef _TInputImage  TInputImage;
+      typedef _TOutputImage TOutputImage;
+      typedef _TFrontId     TFrontId;
+
+      typedef typename TInputImage::IndexType        TVertex;
+      typedef typename TVertex::LexicographicCompare TVertexCompare;
+      typedef typename TInputImage::PixelType        TInputValue;
+      typedef typename TOutputImage::PixelType       TOutputValue;
+
+      typedef fpa::Base::MarksInterfaceWithCollisions< TVertex > TMarksInterface;
+      typedef fpa::Base::SeedsInterface< TVertex, TInputValue, TOutputValue, TFrontId, TVertexCompare > TSeedsInterface;
+      typedef fpa::Image::Algorithm< TInputImage, TOutputImage, TMarksInterface, TSeedsInterface > TAlgorithm;
+      typedef fpa::Image::MinimumSpanningTree< TInputImage::ImageDimension > TMST;
+
+      typedef Dijkstra                                Self;
+      typedef fpa::Base::Dijkstra< TAlgorithm, TMST > Superclass;
+      typedef itk::SmartPointer< Self >               Pointer;
+      typedef itk::SmartPointer< const Self >         ConstPointer;
+
+      typedef fpa::Image::Functors::Dijkstra::Function< TInputImage, TOutputValue > TWeightFunction;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( fpa::Image::Dijkstra, fpa::Base::Dijkstra );
+
+    protected:
+      Dijkstra( )
+        : Superclass( )
+        {
+          typedef fpa::Image::Functors::Dijkstra::Identity< TInputImage, TOutputValue > _TDefaultFunction;
+          this->SetWeightFunction( _TDefaultFunction::New( ) );
+        }
+      virtual ~Dijkstra( )
+        {
+        }
+
+      virtual void _ConfigureOutput( const TOutputValue& v ) override
+        {
+          this->Superclass::_ConfigureOutput( v );
+          const TInputImage* in = this->GetInput( );
+
+          TMST* mst = this->GetMinimumSpanningTree( );
+          mst->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) );
+          mst->SetRequestedRegion( in->GetRequestedRegion( ) );
+          mst->SetBufferedRegion( in->GetBufferedRegion( ) );
+          mst->SetSpacing( in->GetSpacing( ) );
+          mst->SetOrigin( in->GetOrigin( ) );
+          mst->SetDirection( in->GetDirection( ) );
+          mst->Allocate( );
+
+          typename TMST::PixelType zero;
+          zero.Fill( 0 );
+          mst->FillBuffer( zero );
+        }
+
+      virtual void _BeforeGenerateData( ) override
+        {
+          this->Superclass::_BeforeGenerateData( );
+          TWeightFunction* wf =
+            dynamic_cast< TWeightFunction* >( this->GetWeightFunction( ) );
+          if( wf != NULL )
+            wf->SetImage( this->GetInput( ) );
+        }
+
+    private:
+      // Purposely not implemented.
+      Dijkstra( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Image__Dijkstra__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Functors/Dijkstra/Function.h b/lib/fpa/Image/Functors/Dijkstra/Function.h
new file mode 100644 (file)
index 0000000..e9fa0b2
--- /dev/null
@@ -0,0 +1,69 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Functors__Dijkstra__Function__h__
+#define __fpa__Image__Functors__Dijkstra__Function__h__
+
+#include <fpa/Base/Functors/Dijkstra/Function.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    namespace Functors
+    {
+      namespace Dijkstra
+      {
+        /**
+         */
+        template< class _TInputImage, class _TOutputValue >
+        class Function
+          : public fpa::Base::Functors::Dijkstra::Function< typename _TInputImage::IndexType, _TOutputValue >
+        {
+        public:
+          typedef typename _TInputImage::IndexType TVertex;
+          typedef Function Self;
+          typedef fpa::Base::Functors::Dijkstra::Function< TVertex, _TOutputValue > Superclass;
+          typedef itk::SmartPointer< Self >       Pointer;
+          typedef itk::SmartPointer< const Self > ConstPointer;
+
+        public:
+          itkTypeMacro(
+            fpa::Image::Functors::Dijkstra::Function,
+            fpa::Base::Functors::Dijkstra::Function
+            );
+
+          itkGetConstObjectMacro( Image, _TInputImage );
+          itkSetConstObjectMacro( Image, _TInputImage );
+
+        protected:
+          Function( )
+            : Superclass( )
+            {
+            }
+          virtual ~Function( )
+            {
+            }
+
+        private:
+          // Purposely not implemented
+          Function( const Self& other );
+          Self& operator=( const Self& other );
+
+        protected:
+          typename _TInputImage::ConstPointer m_Image;
+        };
+
+      } // ecapseman
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Image__Functors__Dijkstra__Function__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Functors/Dijkstra/Gaussian.h b/lib/fpa/Image/Functors/Dijkstra/Gaussian.h
new file mode 100644 (file)
index 0000000..5187312
--- /dev/null
@@ -0,0 +1,104 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Functors__Dijkstra__Gaussian__h__
+#define __fpa__Image__Functors__Dijkstra__Gaussian__h__
+
+#include <cmath>
+#include <fpa/Image/Functors/Dijkstra/Function.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    namespace Functors
+    {
+      namespace Dijkstra
+      {
+        /**
+         */
+        template< class _TInputImage, class _TOutputValue >
+        class Gaussian
+          : public fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue >
+        {
+        public:
+          typedef Gaussian Self;
+          typedef fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > Superclass;
+          typedef itk::SmartPointer< Self >       Pointer;
+          typedef itk::SmartPointer< const Self > ConstPointer;
+
+          typedef typename Superclass::TVertex TVertex;
+
+        public:
+          itkNewMacro( Self );
+          itkTypeMacro(
+            fpa::Image::Functors::Dijkstra::Gaussian,
+            fpa::Image::Functors::Dijkstra::Function
+            );
+
+        public:
+          double GetAlpha( ) const
+            {
+              return( double( 1 ) - this->m_Alpha );
+            }
+          double GetBeta( ) const
+            {
+              return( std::sqrt( this->m_Beta ) );
+            }
+          void SetAlpha( const double& v )
+            {
+              this->m_Alpha = double( 1 ) - v;
+              this->Modified( );
+            }
+          void SetBeta( const double& v )
+            {
+              this->m_Beta = v * v;
+              this->Modified( );
+            }
+
+          virtual _TOutputValue Evaluate(
+            const TVertex& v, const TVertex& p
+            ) const override
+            {
+              double d = double( this->m_Image->GetPixel( v ) );
+              d       -= double( this->m_Image->GetPixel( p ) );
+              d = ( d * d ) / this->m_Beta;
+              return(
+                _TOutputValue( double( 1 ) - ( this->m_Alpha * std::exp( -d ) ) )
+                );
+            }
+
+        protected:
+          Gaussian( )
+            : Superclass( ),
+              m_Alpha( double( 1 ) ),
+              m_Beta( double( 1 ) )
+            {
+            }
+          virtual ~Gaussian( )
+            {
+            }
+
+        private:
+          // Purposely not implemented
+          Gaussian( const Self& other );
+          Self& operator=( const Self& other );
+
+        protected:
+          double m_Alpha;
+          double m_Beta;
+        };
+
+      } // ecapseman
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Image__Functors__Dijkstra__Gaussian__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Functors/Dijkstra/Identity.h b/lib/fpa/Image/Functors/Dijkstra/Identity.h
new file mode 100644 (file)
index 0000000..3a0b370
--- /dev/null
@@ -0,0 +1,73 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Functors__Dijkstra__Identity__h__
+#define __fpa__Image__Functors__Dijkstra__Identity__h__
+
+#include <fpa/Image/Functors/Dijkstra/Function.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    namespace Functors
+    {
+      namespace Dijkstra
+      {
+        /**
+         */
+        template< class _TInputImage, class _TOutputValue >
+        class Identity
+          : public fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue >
+        {
+        public:
+          typedef Identity Self;
+          typedef fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > Superclass;
+          typedef itk::SmartPointer< Self >       Pointer;
+          typedef itk::SmartPointer< const Self > ConstPointer;
+
+          typedef typename Superclass::TVertex TVertex;
+
+        public:
+          itkNewMacro( Self );
+          itkTypeMacro(
+            fpa::Image::Functors::Dijkstra::Identity,
+            fpa::Image::Functors::Dijkstra::Function
+            );
+
+        public:
+          virtual _TOutputValue Evaluate(
+            const TVertex& v, const TVertex& p
+            ) const override
+            {
+              return( _TOutputValue( this->m_Image->GetPixel( v ) ) );
+            }
+
+        protected:
+          Identity( )
+            : Superclass( )
+            {
+            }
+          virtual ~Identity( )
+            {
+            }
+
+        private:
+          // Purposely not implemented
+          Identity( const Self& other );
+          Self& operator=( const Self& other );
+        };
+
+      } // ecapseman
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Image__Functors__Dijkstra__Identity__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Functors/Dijkstra/Invert.h b/lib/fpa/Image/Functors/Dijkstra/Invert.h
new file mode 100644 (file)
index 0000000..8341f2e
--- /dev/null
@@ -0,0 +1,94 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Functors__Dijkstra__Invert__h__
+#define __fpa__Image__Functors__Dijkstra__Invert__h__
+
+#include <cmath>
+#include <fpa/Image/Functors/Dijkstra/Function.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    namespace Functors
+    {
+      namespace Dijkstra
+      {
+        /**
+         */
+        template< class _TInputImage, class _TOutputValue >
+        class Invert
+          : public fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue >
+        {
+        public:
+          typedef Invert Self;
+          typedef fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > Superclass;
+          typedef itk::SmartPointer< Self >       Pointer;
+          typedef itk::SmartPointer< const Self > ConstPointer;
+
+          typedef typename Superclass::TVertex TVertex;
+
+        public:
+          itkNewMacro( Self );
+          itkTypeMacro(
+            fpa::Image::Functors::Dijkstra::Invert,
+            fpa::Image::Functors::Dijkstra::Function
+            );
+
+          itkGetConstMacro( Alpha, double );
+          itkGetConstMacro( Beta, double );
+
+          itkSetMacro( Alpha, double );
+          itkSetMacro( Beta, double );
+
+        public:
+          virtual _TOutputValue Evaluate(
+            const TVertex& v, const TVertex& p
+            ) const override
+            {
+              double a = double( this->m_Image->GetPixel( v ) );
+              double d = this->m_Alpha;
+              d += std::pow( double( a ), this->m_Beta );
+              double x = -1;
+              if( std::fabs( d ) > double( 0 ) )
+                x =
+                  double( 1 ) /
+                  ( this->m_Alpha + std::pow( double( a ), this->m_Beta ) );
+              return( _TOutputValue( x ) );
+            }
+
+        protected:
+          Invert( )
+            : Superclass( ),
+              m_Alpha( double( 1 ) ),
+              m_Beta( double( 1 ) )
+            {
+            }
+          virtual ~Invert( )
+            {
+            }
+
+        private:
+          // Purposely not implemented
+          Invert( const Self& other );
+          Self& operator=( const Self& other );
+
+        protected:
+          double m_Alpha;
+          double m_Beta;
+        };
+
+      } // ecapseman
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Image__Functors__Dijkstra__Invert__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/LabelledSeedsInterface.h b/lib/fpa/Image/LabelledSeedsInterface.h
new file mode 100644 (file)
index 0000000..2492b84
--- /dev/null
@@ -0,0 +1,62 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__LabelledSeedsInterface__h__
+#define __fpa__Image__LabelledSeedsInterface__h__
+
+#include <fpa/Base/SeedsInterface.h>
+
+#include <itkImage.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare = std::greater< _TVertex > >
+    class LabelledSeedsInterface
+      : public fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >
+    {
+    public:
+      typedef _TVertex      TVertex;
+      typedef _TInputValue  TInputValue;
+      typedef _TOutputValue TOutputValue;
+      typedef _TFrontId     TFrontId;
+      typedef _TCompare     TCompare;
+      typedef LabelledSeedsInterface Self;
+      typedef fpa::Base::SeedsInterface< TVertex, TInputValue, TOutputValue, TFrontId, TCompare > Superclass;
+
+      typedef typename Superclass::TNode        TNode;
+      typedef typename Superclass::TNodeCompare TNodeCompare;
+      typedef typename Superclass::TSeeds       TSeeds;
+
+      typedef itk::Image< TFrontId, TVertex::Dimension > TLabelImage;
+
+    public:
+      virtual void AddSeed( const TVertex& seed ) override;
+
+      const TLabelImage* GetLabels( ) const;
+      void SetLabels( const TLabelImage* image );
+
+    protected:
+      LabelledSeedsInterface( itk::ProcessObject* filter );
+      virtual ~LabelledSeedsInterface( );
+
+    protected:
+      typename TLabelImage::ConstPointer m_LabelImage;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/LabelledSeedsInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__LabelledSeedsInterface__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/LabelledSeedsInterface.hxx b/lib/fpa/Image/LabelledSeedsInterface.hxx
new file mode 100644 (file)
index 0000000..a9a73c9
--- /dev/null
@@ -0,0 +1,64 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__LabelledSeedsInterface__hxx__
+#define __fpa__Image__LabelledSeedsInterface__hxx__
+
+#include <sstream>
+#include <itkExceptionObject.h>
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+void
+fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+AddSeed( const TVertex& seed )
+{
+  std::ostringstream msg;
+  msg << "itk::ERROR: fpa::Image::LabelledSeedsInterface (" << this
+      << "): \"AddSeed( const TVertex& seed )\" is not valid for this class. "
+      << "Use \"SetLabels( TLabelImage* labels )\" instead.";
+  ::itk::ExceptionObject e(
+    __FILE__, __LINE__, msg.str( ).c_str( ), ITK_LOCATION
+    );
+  throw e;
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+const typename 
+fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+TLabelImage*
+fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+GetLabels( ) const
+{
+  return( this->m_LabelImage );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+void fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+SetLabels( const TLabelImage* image )
+{
+  this->m_LabelImage = image;
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+LabelledSeedsInterface( itk::ProcessObject* filter )
+  : Superclass( filter )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare >
+fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >::
+~LabelledSeedsInterface( )
+{
+}
+
+#endif // __fpa__Image__LabelledSeedsInterface__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/MinimumSpanningTree.h b/lib/fpa/Image/MinimumSpanningTree.h
new file mode 100644 (file)
index 0000000..a93157c
--- /dev/null
@@ -0,0 +1,71 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__MinimumSpanningTree__h__
+#define __fpa__Image__MinimumSpanningTree__h__
+
+#include <fpa/Base/MinimumSpanningTree.h>
+#include <itkImage.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< unsigned int _VDim >
+    class MinimumSpanningTree
+      : public fpa::Base::MinimumSpanningTree< itk::Index< _VDim >, itk::Image< itk::Offset< _VDim >, _VDim > >
+    {
+    public:
+      typedef itk::Index< _VDim > TVertex;
+      typedef itk::Image< itk::Offset< _VDim >, _VDim > TBaseImage;
+
+      typedef MinimumSpanningTree             Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+      typedef fpa::Base::MinimumSpanningTree< TVertex, TBaseImage > Superclass;
+
+      typedef typename Superclass::TCollision     TCollision;
+      typedef typename Superclass::TCollisionsRow TCollisionsRow;
+      typedef typename Superclass::TCollisions    TCollisions;
+      typedef typename Superclass::TVertices      TVertices;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro(
+        fpa::Image::MinimumSpanningTree,
+        fpa::Base::MinimumSpanningTree
+        );
+
+    public:
+      virtual TVertex GetParent( const TVertex& v ) const override
+        {
+          return( v + this->GetPixel( v ) );
+        }
+      virtual void SetParent( const TVertex& v, const TVertex& p ) override
+        {
+          this->SetPixel( v, p - v );
+        }
+
+    protected:
+      MinimumSpanningTree( )
+        : Superclass( )
+        { }
+      virtual ~MinimumSpanningTree( )
+        { }
+
+    private:
+      MinimumSpanningTree( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Image__MinimumSpanningTree__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/PathsToImageFilter.h b/lib/fpa/Image/PathsToImageFilter.h
new file mode 100644 (file)
index 0000000..dd467cd
--- /dev/null
@@ -0,0 +1,84 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__PathsToImageFilter__h__
+#define __fpa__Image__PathsToImageFilter__h__
+
+#include <itkRGBAPixel.h>
+#include <itkImageToImageFilter.h>
+#include <vector>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TMST, class _TOutputPixelValue >
+    class PathsToImageFilter
+      : public itk::ImageToImageFilter< _TMST, itk::Image< itk::RGBAPixel< _TOutputPixelValue >, _TMST::ImageDimension > >
+    {
+    public:
+      typedef _TMST TMST;
+      typedef _TOutputPixelValue TOutputPixelValue;
+      typedef itk::RGBAPixel< TOutputPixelValue > TOutputPixel;
+      typedef itk::Image< TOutputPixel, TMST::ImageDimension > TOutputImage;
+
+      typedef PathsToImageFilter              Self;
+      typedef itk::SmartPointer< Self >                     Pointer;
+      typedef itk::SmartPointer< const Self >               ConstPointer;
+      typedef itk::ImageToImageFilter< TMST, TOutputImage > Superclass;
+
+      typedef typename TMST::IndexType TIndex;
+      struct TPathData
+      {
+        TIndex Start;
+        TIndex End;
+        TOutputPixelValue Red;
+        TOutputPixelValue Green;
+        TOutputPixelValue Blue;
+      };
+      typedef std::vector< TPathData > TPaths;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro(
+        fpa::Image::PathsToImageFilter,
+        itk::ImageToImageFilter
+        );
+
+    public:
+      void AddPath(
+        const TIndex& start, const TIndex& end,
+        const TOutputPixelValue& r = TOutputPixelValue( 1 ),
+        const TOutputPixelValue& g = TOutputPixelValue( 0 ),
+        const TOutputPixelValue& b = TOutputPixelValue( 0 )
+        );
+
+    protected:
+      PathsToImageFilter( );
+      virtual ~PathsToImageFilter( );
+
+      virtual void GenerateData( ) override;
+
+    private:
+      PathsToImageFilter( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TPaths m_Paths;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/PathsToImageFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__PathsToImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/PathsToImageFilter.hxx b/lib/fpa/Image/PathsToImageFilter.hxx
new file mode 100644 (file)
index 0000000..487b9c8
--- /dev/null
@@ -0,0 +1,79 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__PathsToImageFilter__hxx__
+#define __fpa__Image__PathsToImageFilter__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TMST, class _TOutputPixelValue >
+void fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >::
+AddPath(
+  const TIndex& start, const TIndex& end,
+  const TOutputPixelValue& r,
+  const TOutputPixelValue& g,
+  const TOutputPixelValue& b
+  )
+{
+  if( start != end )
+  {
+    TPathData d;
+    d.Start = start;
+    d.End = end;
+    d.Red = r;
+    d.Green = g;
+    d.Blue = b;
+    this->m_Paths.push_back( d );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TMST, class _TOutputPixelValue >
+fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >::
+PathsToImageFilter( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TMST, class _TOutputPixelValue >
+fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >::
+~PathsToImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TMST, class _TOutputPixelValue >
+void fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >::
+GenerateData( )
+{
+  TOutputPixel color;
+  color.Fill( 0 );
+
+  const TMST* mst = this->GetInput( );
+  TOutputImage* output = this->GetOutput( );
+  output->SetBufferedRegion( mst->GetBufferedRegion( ) );
+  output->Allocate( );
+  output->FillBuffer( color );
+
+  typename TPaths::const_iterator d = this->m_Paths.begin( );
+  for( ; d != this->m_Paths.end( ); ++d )
+  {
+    typename TMST::TVertices path = mst->GetPath( d->Start, d->End );
+    color[ 0 ] = d->Red;
+    color[ 1 ] = d->Green;
+    color[ 2 ] = d->Blue;
+    color[ 3 ] = std::numeric_limits< TOutputPixelValue >::max( );
+    typename TMST::TVertices::const_iterator i = path.begin( );
+    for( ; i != path.end( ); ++i )
+      output->SetPixel( *i, color );
+
+  } // rof
+}
+
+#endif // __fpa__Image__PathsToImageFilter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/PolyLineParametricPath.h b/lib/fpa/Image/PolyLineParametricPath.h
new file mode 100644 (file)
index 0000000..7fd6489
--- /dev/null
@@ -0,0 +1,97 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__PolyLineParametricPath__h__
+#define __fpa__Image__PolyLineParametricPath__h__
+
+#include <itkPolyLineParametricPath.h>
+#include <itkImageBase.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< unsigned int _VDim >
+    class PolyLineParametricPath
+      : public itk::PolyLineParametricPath< _VDim >
+    {
+    public:
+      typedef PolyLineParametricPath               Self;
+      typedef itk::PolyLineParametricPath< _VDim > Superclass;
+      typedef itk::SmartPointer< Self >            Pointer;
+      typedef itk::SmartPointer< const Self >      ConstPointer;
+
+      typedef itk::ImageBase< _VDim >                  TImageBase;
+      typedef typename TImageBase::SpacingType         TSpacing;
+      typedef typename TImageBase::PointType           TPoint;
+      typedef typename TImageBase::DirectionType       TDirection;
+      typedef typename Superclass::ContinuousIndexType TContinuousIndex;
+      typedef typename TContinuousIndex::IndexType     TIndex;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( PolyLineParametricPath, itk::PolyLineParametricPath );
+
+      itkGetConstReferenceMacro( Spacing, TSpacing );
+      itkGetConstReferenceMacro( Origin, TPoint );
+      itkGetConstReferenceMacro( Direction, TDirection );
+      itkGetConstReferenceMacro( InverseDirection, TDirection );
+
+      itkSetMacro( Origin, TPoint );
+
+    public:
+      unsigned long GetSize( ) const;
+      TContinuousIndex GetContinuousVertex( unsigned long i ) const;
+      TIndex GetVertex( unsigned long i ) const;
+      TPoint GetPoint( unsigned long i ) const;
+
+      virtual void SetSpacing( const TSpacing& spac );
+      virtual void SetSpacing( const double spac[ _VDim ] );
+      virtual void SetSpacing( const float spac[ _VDim ] );
+      virtual void SetOrigin( const double ori[ _VDim ] );
+      virtual void SetOrigin( const float ori[ _VDim ] );
+      virtual void SetDirection( const TDirection& dir );
+
+      template< class _TRefImage >
+      inline void SetReferenceImage( const _TRefImage* image )
+        {
+          this->SetSpacing( image->GetSpacing( ) );
+          this->SetOrigin( image->GetOrigin( ) );
+          this->SetDirection( image->GetDirection( ) );
+        }
+
+    protected:
+      PolyLineParametricPath( );
+      virtual ~PolyLineParametricPath( );
+
+      virtual void _ComputeIndexToPhysicalPointMatrices( );
+
+    private:
+      // Purposely not implemented
+      PolyLineParametricPath( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TSpacing   m_Spacing;
+      TPoint     m_Origin;
+      TDirection m_Direction;
+      TDirection m_InverseDirection;
+      TDirection m_IndexToPhysicalPoint;
+      TDirection m_PhysicalPointToIndex;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/PolyLineParametricPath.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__PolyLineParametricPath__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/PolyLineParametricPath.hxx b/lib/fpa/Image/PolyLineParametricPath.hxx
new file mode 100644 (file)
index 0000000..4616dcf
--- /dev/null
@@ -0,0 +1,194 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__PolyLineParametricPath__hxx__
+#define __fpa__Image__PolyLineParametricPath__hxx__
+
+#include <itkMath.h>
+#include <itkNumericTraits.h>
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+unsigned long fpa::Image::PolyLineParametricPath< _VDim >::
+GetSize( ) const
+{
+  return( this->GetVertexList( )->Size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename fpa::Image::PolyLineParametricPath< _VDim >::
+TContinuousIndex
+fpa::Image::PolyLineParametricPath< _VDim >::
+GetContinuousVertex( unsigned long i ) const
+{
+  return( this->GetVertexList( )->GetElement( i ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename fpa::Image::PolyLineParametricPath< _VDim >::
+TIndex fpa::Image::PolyLineParametricPath< _VDim >::
+GetVertex( unsigned long i ) const
+{
+  TContinuousIndex cidx = this->GetContinuousVertex( i );
+  TIndex idx;
+  for( unsigned int d = 0; d < _VDim; ++d )
+    idx[ d ] = cidx[ d ];
+  return( idx );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename fpa::Image::PolyLineParametricPath< _VDim >::
+TPoint fpa::Image::PolyLineParametricPath< _VDim >::
+GetPoint( unsigned long i ) const
+{
+  typedef typename TPoint::CoordRepType _TCoordRep;
+  TPoint pnt;
+  TContinuousIndex idx = this->GetVertex( i );
+  for( unsigned int r = 0; r < _VDim; ++r )
+  {
+    _TCoordRep sum = itk::NumericTraits< _TCoordRep >::ZeroValue( );
+    for( unsigned int c = 0; c < _VDim; ++c )
+      sum += this->m_IndexToPhysicalPoint( r, c ) * idx[ c ];
+    pnt[ r ] = sum + this->m_Origin[ r ];
+
+  } // rof
+  return( pnt );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::PolyLineParametricPath< _VDim >::
+SetSpacing( const TSpacing& spac )
+{
+  if( this->m_Spacing != spac )
+  {
+    this->m_Spacing = spac;
+    this->_ComputeIndexToPhysicalPointMatrices( );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::PolyLineParametricPath< _VDim >::
+SetSpacing( const double spac[ _VDim ] )
+{
+  this->SetSpacing( TSpacing( spac ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::PolyLineParametricPath< _VDim >::
+SetSpacing( const float spac[ _VDim ] )
+{
+  TSpacing s;
+  for( unsigned int d = 0; d < _VDim; ++d )
+    s[ d ] = spac[ d ];
+  this->SetSpacing( s );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::PolyLineParametricPath< _VDim >::
+SetOrigin( const double ori[ _VDim ] )
+{
+  this->SetOrigin( TPoint( ori ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::PolyLineParametricPath< _VDim >::
+SetOrigin( const float ori[ _VDim ] )
+{
+  this->SetOrigin( TPoint( ori ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::PolyLineParametricPath< _VDim >::
+SetDirection( const TDirection& dir )
+{
+  bool modified = false;
+  for( unsigned int r = 0; r < _VDim; r++ )
+  {
+    for( unsigned int c = 0; c < _VDim; c++ )
+    {
+      if(
+        itk::Math::NotExactlyEquals(
+          this->m_Direction[ r ][ c ], dir[ r ][ c ]
+          )
+        )
+      {
+        this->m_Direction[ r ][ c ] = dir[ r ][ c ];
+        modified = true;
+      } // fi
+
+    } // rof
+
+  } // rof
+  if( modified )
+  {
+    this->_ComputeIndexToPhysicalPointMatrices( );
+    this->m_InverseDirection = this->m_Direction.GetInverse( );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+fpa::Image::PolyLineParametricPath< _VDim >::
+PolyLineParametricPath( )
+  : Superclass( )
+{
+  this->m_Spacing.Fill( 1.0 );
+  this->m_Origin.Fill( 0.0 );
+  this->m_Direction.SetIdentity( );
+  this->m_InverseDirection.SetIdentity( );
+  this->m_IndexToPhysicalPoint.SetIdentity( );
+  this->m_PhysicalPointToIndex.SetIdentity( );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+fpa::Image::PolyLineParametricPath< _VDim >::
+~PolyLineParametricPath( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::PolyLineParametricPath< _VDim >::
+_ComputeIndexToPhysicalPointMatrices( )
+{
+  TDirection scale;
+  scale.Fill( 0.0 );
+  for( unsigned int i = 0; i < _VDim; i++ )
+  {
+    if( this->m_Spacing[ i ] == 0.0 )
+      itkExceptionMacro(
+        "A spacing of 0 is not allowed: Spacing is " << this->m_Spacing
+        );
+    scale[ i ][ i ] = this->m_Spacing[ i ];
+
+  } // rof
+
+  if( vnl_determinant( this->m_Direction.GetVnlMatrix( ) ) == 0.0 )
+    itkExceptionMacro(
+      << "Bad direction, determinant is 0. Direction is "
+      << this->m_Direction
+      );
+  this->m_IndexToPhysicalPoint = this->m_Direction * scale;
+  this->m_PhysicalPointToIndex = this->m_IndexToPhysicalPoint.GetInverse( );
+  this->Modified( );
+}
+
+#endif // __fpa__Image__PolyLineParametricPath__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/RandomWalker.h b/lib/fpa/Image/RandomWalker.h
new file mode 100644 (file)
index 0000000..9e41147
--- /dev/null
@@ -0,0 +1,78 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__RandomWalker__h__
+#define __fpa__Image__RandomWalker__h__
+
+#include <itkImage.h>
+
+#include <fpa/Base/DijkstraBase.h>
+#include <fpa/Base/MarksInterface.h>
+#include <fpa/Image/Algorithm.h>
+#include <fpa/Image/LabelledSeedsInterface.h>
+#include <fpa/Image/Functors/Dijkstra/Function.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TInputImage, class _TLabelImage, class _TScalar >
+    class RandomWalker
+      : public fpa::Base::DijkstraBase< fpa::Image::Algorithm< _TInputImage, itk::Image< _TScalar, _TInputImage::ImageDimension >, fpa::Base::MarksInterface< typename _TInputImage::IndexType >, fpa::Image::LabelledSeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::PixelType, _TScalar, typename _TLabelImage::PixelType, typename _TInputImage::IndexType::LexicographicCompare > > >
+    {
+    public:
+      typedef _TInputImage TInputImage;
+      typedef _TLabelImage TLabelImage;
+      typedef _TScalar     TScalar;
+      typedef typename TInputImage::IndexType        TVertex;
+      typedef typename TVertex::LexicographicCompare TVertexCompare;
+      typedef typename TInputImage::PixelType        TInputValue;
+      typedef typename TLabelImage::PixelType        TFrontId;
+
+      typedef itk::Image< TScalar, _TInputImage::ImageDimension > TOutputImage;
+      typedef fpa::Base::MarksInterface< TVertex > TMarksInterface;
+      typedef fpa::Image::LabelledSeedsInterface< TVertex, TInputValue, _TScalar, TFrontId, TVertexCompare > TSeedsInterface;
+      typedef fpa::Image::Algorithm< _TInputImage, TOutputImage, TMarksInterface, TSeedsInterface > TAlgorithm;
+
+      typedef RandomWalker                          Self;
+      typedef fpa::Base::DijkstraBase< TAlgorithm > Superclass;
+      typedef itk::SmartPointer< Self >             Pointer;
+      typedef itk::SmartPointer< const Self >       ConstPointer;
+
+      typedef fpa::Image::Functors::Dijkstra::Function< TInputImage, TScalar > TWeightFunction;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( fpa::Image::RandomWalker, fpa::Base::RandomWalker );
+
+    public:
+      virtual itk::ModifiedTimeType GetMTime( ) const override;
+
+    protected:
+      RandomWalker( );
+      virtual ~RandomWalker( );
+
+      virtual void _BeforeGenerateData( ) override;
+      virtual void _QueueInit( ) override;
+
+    private:
+      // Purposely not implemented.
+      RandomWalker( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/RandomWalker.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__RandomWalker__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/RandomWalker.hxx b/lib/fpa/Image/RandomWalker.hxx
new file mode 100644 (file)
index 0000000..9016e97
--- /dev/null
@@ -0,0 +1,124 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__RandomWalker__hxx__
+#define __fpa__Image__RandomWalker__hxx__
+
+#include <sstream>
+
+#include <itkImageRegionConstIteratorWithIndex.h>
+#include <itkExceptionObject.h>
+
+#include <fpa/Image/Functors/Dijkstra/Gaussian.h>
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TScalar >
+itk::ModifiedTimeType
+fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >::
+GetMTime( ) const
+{
+  const TLabelImage* labels = this->GetLabels( );
+  itk::ModifiedTimeType t = this->Superclass::GetMTime( );
+  if( labels != NULL )
+  {
+    itk::ModifiedTimeType q = labels->GetMTime( );
+    t = ( q < t )? q: t;
+
+  } // fi
+  return( t );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TScalar >
+fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >::
+RandomWalker( )
+  : Superclass( )
+{
+  typedef fpa::Image::Functors::Dijkstra::Gaussian< TInputImage, TScalar > _TDefaultFunction;
+  this->SetWeightFunction( _TDefaultFunction::New( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TScalar >
+fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >::
+~RandomWalker( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TScalar >
+void fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >::
+_BeforeGenerateData( )
+{
+  this->Superclass::_BeforeGenerateData( );
+  TWeightFunction* wf =
+    dynamic_cast< TWeightFunction* >( this->GetWeightFunction( ) );
+  if( wf != NULL )
+    wf->SetImage( this->GetInput( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TScalar >
+void fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >::
+_QueueInit( )
+{
+  this->m_Seeds.clear( );
+  const TLabelImage* lbl = this->GetLabels( );
+  if( lbl == NULL )
+  {
+    std::ostringstream msg;
+    msg << "itk::ERROR: fpa::Image::RandomWalker (" << this
+        << "): Labelled image not defined.";
+    ::itk::ExceptionObject e(
+      __FILE__, __LINE__, msg.str( ).c_str( ), ITK_LOCATION
+      );
+    throw e;
+
+  } // fi
+
+  // Iterate over labels
+  typename TLabelImage::RegionType reg = lbl->GetRequestedRegion( );
+  itk::ImageRegionConstIteratorWithIndex< TLabelImage > lIt( lbl, reg );
+  for( lIt.GoToBegin( ); !lIt.IsAtEnd( ); ++lIt )
+  {
+    if( lIt.Get( ) > 0 )
+    {
+      bool is_seed = false;
+      for( unsigned int d = 0; d < TLabelImage::ImageDimension; ++d )
+      {
+        for( int s = -1; s <= 1; s += 2 )
+        {
+          TVertex neigh = lIt.GetIndex( );
+          neigh[ d ] += s;
+          is_seed |= ( lbl->GetPixel( neigh ) == 0 );
+
+        } // rof
+
+      } // rof
+
+      typename TSeedsInterface::TNode node;
+      node.Vertex = lIt.GetIndex( );
+      node.Parent = lIt.GetIndex( );
+      node.FrontId = lIt.Get( );
+      node.Value = TScalar( 0 );
+      if( !is_seed )
+      {
+        this->_Mark( lIt.GetIndex( ), lIt.Get( ) );
+        this->_UpdateOutputValue( node );
+      }
+      else
+        this->m_Seeds.insert( node );
+
+    } // fi
+
+  } // rof
+
+  // Ok, finish initialization
+  this->Superclass::_QueueInit( );
+}
+
+#endif // __fpa__Image__RandomWalker__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/RegionGrow.h b/lib/fpa/Image/RegionGrow.h
new file mode 100644 (file)
index 0000000..6a09487
--- /dev/null
@@ -0,0 +1,68 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__RegionGrow__h__
+#define __fpa__Image__RegionGrow__h__
+
+#include <fpa/Base/RegionGrow.h>
+#include <fpa/Base/MarksInterfaceWithCollisions.h>
+#include <fpa/Base/SeedsInterface.h>
+#include <fpa/Image/Algorithm.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TInputImage, class _TOutputImage, class _TFrontId = unsigned char >
+    class RegionGrow
+      : public fpa::Base::RegionGrow< fpa::Image::Algorithm< _TInputImage, _TOutputImage, fpa::Base::MarksInterfaceWithCollisions< typename _TInputImage::IndexType >, fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::PixelType, typename _TOutputImage::PixelType, _TFrontId, typename _TInputImage::IndexType::LexicographicCompare > > >
+    {
+    public:
+      typedef _TInputImage  TInputImage;
+      typedef _TOutputImage TOutputImage;
+      typedef _TFrontId     TFrontId;
+
+      typedef typename TInputImage::IndexType        TVertex;
+      typedef typename TVertex::LexicographicCompare TVertexCompare;
+      typedef typename TInputImage::PixelType        TInputValue;
+      typedef typename TOutputImage::PixelType       TOutputValue;
+
+      typedef fpa::Base::MarksInterfaceWithCollisions< TVertex > TMarksInterface;
+      typedef fpa::Base::SeedsInterface< TVertex, TInputValue, TOutputValue, TFrontId, TVertexCompare > TSeedsInterface;
+      typedef fpa::Image::Algorithm< TInputImage, TOutputImage, TMarksInterface, TSeedsInterface > TAlgorithm;
+
+      typedef RegionGrow                          Self;
+      typedef fpa::Base::RegionGrow< TAlgorithm > Superclass;
+      typedef itk::SmartPointer< Self >           Pointer;
+      typedef itk::SmartPointer< const Self >     ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( fpa::Image::RegionGrow, fpa::Base::RegionGrow );
+
+    protected:
+      RegionGrow( )
+        : Superclass( )
+        {
+        }
+      virtual ~RegionGrow( )
+        {
+        }
+
+    private:
+      // Purposely not implemented.
+      RegionGrow( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Image__RegionGrow__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Skeleton.h b/lib/fpa/Image/Skeleton.h
new file mode 100644 (file)
index 0000000..4942702
--- /dev/null
@@ -0,0 +1,67 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Skeleton__h__
+#define __fpa__Image__Skeleton__h__
+
+#include <vector>
+#include <fpa/Base/Graph.h>
+#include <fpa/Image/PolyLineParametricPath.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< unsigned int _VDim >
+    class Skeleton
+      : public fpa::Base::Graph< typename fpa::Image::PolyLineParametricPath< _VDim >::TIndex, typename fpa::Image::PolyLineParametricPath< _VDim >::Pointer, typename fpa::Image::PolyLineParametricPath< _VDim >::TIndex, typename fpa::Image::PolyLineParametricPath< _VDim >::TIndex::LexicographicCompare >
+    {
+    public:
+      typedef fpa::Image::PolyLineParametricPath< _VDim > TPath;
+      typedef typename TPath::TIndex                     TIndex;
+      typedef typename TIndex::LexicographicCompare      TIndexCompare;
+      typedef typename TPath::Pointer                    TPathPointer;
+
+      itkStaticConstMacro( Dimension, unsigned int, _VDim );
+
+      typedef fpa::Base::Graph< TIndex, TPathPointer, TIndex, TIndexCompare > Superclass;
+      typedef Skeleton                        Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Skeleton, fpa::Image::Graph );
+
+    public:
+      void AddBranch( TPath* path );
+      const TPath* GetBranch( const TIndex& a, const TIndex& b ) const;
+
+      std::vector< TIndex > GetEndPoints( ) const;
+      std::vector< TIndex > GetBifurcations( ) const;
+
+    protected:
+      Skeleton( );
+      virtual ~Skeleton( );
+
+    private:
+      // Purposely not implemented
+      Skeleton( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/Skeleton.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__Skeleton__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/Skeleton.hxx b/lib/fpa/Image/Skeleton.hxx
new file mode 100644 (file)
index 0000000..99424e9
--- /dev/null
@@ -0,0 +1,99 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Skeleton__hxx__
+#define __fpa__Image__Skeleton__hxx__
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::Skeleton< _VDim >::
+AddBranch( TPath* path )
+{
+  // Check inputs
+  if( path == NULL )
+    return;
+  unsigned long size = path->GetSize( );
+  if( size == 0 )
+    return;
+  TIndex a = path->GetVertex( 0 );
+  TIndex b = path->GetVertex( size - 1 );
+  if( this->HasEdge( a, b ) )
+    return;
+
+  // Add path
+  this->SetVertex( a, a );
+  this->SetVertex( b, b );
+  this->AddEdge( a, b, path );
+  this->AddEdge( b, a, path );
+  // TODO: this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+const typename fpa::Image::Skeleton< _VDim >::
+TPath* fpa::Image::Skeleton< _VDim >::
+GetBranch( const TIndex& a, const TIndex& b ) const
+{
+  static const TPath* null_path = NULL;
+  if( this->HasEdge( a, b ) )
+    return( this->GetEdges( a, b ).front( ) );
+  else
+    return( null_path );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+std::vector< typename fpa::Image::Skeleton< _VDim >::TIndex >
+fpa::Image::Skeleton< _VDim >::
+GetEndPoints( ) const
+{
+  std::vector< TIndex > res;
+  typename Superclass::TMatrix::const_iterator mIt = this->BeginEdgesRows( );
+  for( ; mIt != this->EndEdgesRows( ); ++mIt )
+  {
+    unsigned long count = mIt->second.size( );
+    if( count == 1 )
+      res.push_back( mIt->first );
+
+  } // rof
+  return( res );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+std::vector< typename fpa::Image::Skeleton< _VDim >::TIndex >
+fpa::Image::Skeleton< _VDim >::
+GetBifurcations( ) const
+{
+  std::vector< TIndex > res;
+  typename Superclass::TMatrix::const_iterator mIt = this->BeginEdgesRows( );
+  for( ; mIt != this->EndEdgesRows( ); ++mIt )
+  {
+    unsigned long count = mIt->second.size( );
+    if( count > 1 )
+      res.push_back( mIt->first );
+
+  } // rof
+  return( res );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+fpa::Image::Skeleton< _VDim >::
+Skeleton( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+fpa::Image::Skeleton< _VDim >::
+~Skeleton( )
+{
+}
+
+#endif // __fpa__Image__Skeleton__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/SkeletonFilter.h b/lib/fpa/Image/SkeletonFilter.h
new file mode 100644 (file)
index 0000000..296ac87
--- /dev/null
@@ -0,0 +1,160 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__SkeletonFilter__h__
+#define __fpa__Image__SkeletonFilter__h__
+
+#include <itkProcessObject.h>
+#include <itkSignedMaurerDistanceMapImageFilter.h>
+#include <fpa/Image/Dijkstra.h>
+#include <fpa/Image/Skeleton.h>
+
+/*
+  #include <functional>
+  #include <map>
+
+
+  #include <fpa/Image/MinimumSpanningTree.h>
+
+  #include <itkMinimumMaximumImageCalculator.h>
+  #include <fpa/Image/Functors/Dijkstra/Invert.h>
+*/
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TInputImage, class _TDistanceMap = itk::SignedMaurerDistanceMapImageFilter< _TInputImage, itk::Image< double, _TInputImage::ImageDimension > > >
+    class SkeletonFilter
+      : public itk::ProcessObject
+    {
+    public:
+      typedef SkeletonFilter                  Self;
+      typedef itk::ProcessObject              Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TInputImage  TInputImage;
+      typedef _TDistanceMap TDistanceMap;
+      itkStaticConstMacro(
+        Dimension,
+        unsigned int,
+        TInputImage::ImageDimension
+        );
+
+      typedef typename TDistanceMap::OutputImageType TOutputImage;
+      typedef typename TInputImage::IndexType        TIndex;
+      typedef typename TOutputImage::PixelType       TScalar;
+
+      typedef fpa::Image::Skeleton< Self::Dimension > TSkeleton;
+
+    protected:
+      typedef std::multimap< TScalar, TIndex > _TSkeletonQueue;
+
+      /**
+       */
+      class _TDijkstra
+        : public fpa::Image::Dijkstra< TOutputImage, TOutputImage >
+      {
+      public:
+        typedef _TDijkstra                                         Self;
+        typedef fpa::Image::Dijkstra< TOutputImage, TOutputImage > Superclass;
+        typedef itk::SmartPointer< Self >                          Pointer;
+        typedef itk::SmartPointer< const Self >                    ConstPointer;
+
+        typedef typename Superclass::TNode TNode;
+        typedef typename Superclass::TMST  TMST;
+
+      public:
+        itkNewMacro( Self );
+        itkTypeMacro( _TDijkstra, fpa::Image::Dijkstra );
+
+        itkGetConstReferenceMacro( SkeletonQueue, _TSkeletonQueue );
+
+      protected:
+        _TDijkstra( );
+        virtual ~_TDijkstra( );
+
+        virtual void _BeforeGenerateData( ) override;
+        virtual void _UpdateOutputValue( const TNode& n ) override;
+
+      private:
+        // Purposely not implemented
+        _TDijkstra( const Self& other );
+        Self& operator=( const Self& other );
+
+      protected:
+        _TSkeletonQueue m_SkeletonQueue;
+      };
+      typedef typename _TDijkstra::TMST _TMST;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( fpa::Image::SkeletonFilter, fpa::Image::Dijkstra );
+
+      itkBooleanMacro( SeedFromMaximumDistance );
+      itkGetConstMacro( SeedFromMaximumDistance, bool );
+      itkSetMacro( SeedFromMaximumDistance, bool );
+
+      itkGetConstObjectMacro( DistanceMap, TDistanceMap );
+      itkGetObjectMacro( DistanceMap, TDistanceMap );
+
+      itkGetConstMacro( Seed, TIndex );
+      itkSetMacro( Seed, TIndex );
+
+    public:
+      virtual itk::ModifiedTimeType GetMTime( ) const override;
+
+      void SetInput( TInputImage* input );
+      TInputImage* GetInput( );
+      const TInputImage* GetInput( ) const;
+
+      TSkeleton* GetOutput( );
+      const TSkeleton* GetOutput( ) const;
+
+    protected:
+      SkeletonFilter( );
+      virtual ~SkeletonFilter( );
+
+      virtual void GenerateData( ) override;
+
+      template< class _TMarksPointer >
+      void _MarkSphere(
+        _TMarksPointer& marks,
+        const TOutputImage* dmap,
+        const TIndex& center
+        );
+
+      void _EndPoints(
+        std::vector< TIndex >& end_points,
+        const TOutputImage* dmap,
+        const _TMST* mst,
+        const _TSkeletonQueue& queue
+        );
+
+    private:
+      // Purposely not implemented.
+      SkeletonFilter( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TDistanceMap::Pointer m_DistanceMap;
+      bool   m_SeedFromMaximumDistance;
+      TIndex m_Seed;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/SkeletonFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__SkeletonFilter__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/SkeletonFilter.hxx b/lib/fpa/Image/SkeletonFilter.hxx
new file mode 100644 (file)
index 0000000..0f33388
--- /dev/null
@@ -0,0 +1,359 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__SkeletonFilter__hxx__
+#define __fpa__Image__SkeletonFilter__hxx__
+
+#include <itkImage.h>
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkMinimumMaximumImageCalculator.h>
+#include <fpa/Image/Functors/Dijkstra/Invert.h>
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra::
+_TDijkstra( )
+  : Superclass( )
+{
+  // Prepare weight function
+  typedef fpa::Image::Functors::Dijkstra::Invert< TOutputImage, TScalar > _TWeight;
+  typename _TWeight::Pointer weight = _TWeight::New( );
+  weight->SetAlpha( 1 );
+  weight->SetBeta( 1 );
+  this->SetWeightFunction( weight );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra::
+~_TDijkstra( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra::
+_BeforeGenerateData( )
+{
+  this->Superclass::_BeforeGenerateData( );
+  this->m_SkeletonQueue.clear( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra::
+_UpdateOutputValue( const TNode& n )
+{
+  typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue;
+
+  this->Superclass::_UpdateOutputValue( n );
+  double d = double( this->GetInput( )->GetPixel( n.Vertex ) );
+  if( d >= double( 0 ) )
+  {
+    // Update skeleton candidates
+    d += double( 1e-5 );
+    double v = double( n.Value ) / ( d * d );
+    this->m_SkeletonQueue.insert( _TSkeletonQueueValue( v, n.Vertex ) );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+itk::ModifiedTimeType
+fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+GetMTime( ) const
+{
+  itk::ModifiedTimeType t = this->Superclass::GetMTime( );
+  itk::ModifiedTimeType q = this->m_DistanceMap->GetMTime( );
+  return( ( q < t )? q: t );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+SetInput( TInputImage* input )
+{
+  this->Superclass::SetNthInput( 0, input );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+TInputImage* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+GetInput( )
+{
+  return( dynamic_cast< TInputImage* >( this->Superclass::GetInput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+const typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+TInputImage* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+GetInput( ) const
+{
+  return(
+    dynamic_cast< const TInputImage* >( this->Superclass::GetInput( 0 ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+TSkeleton* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+GetOutput( )
+{
+  return( dynamic_cast< TSkeleton* >( this->Superclass::GetOutput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+const typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+TSkeleton* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+GetOutput( ) const
+{
+  return(
+    dynamic_cast< const TSkeleton* >( this->Superclass::GetOutput( 0 ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+SkeletonFilter( )
+  : Superclass( ),
+    m_SeedFromMaximumDistance( false )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+  this->SetNumberOfRequiredOutputs( 1 );
+  this->SetNthOutput( 0, TSkeleton::New( ) );
+
+  this->m_DistanceMap = TDistanceMap::New( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+~SkeletonFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+GenerateData( )
+{
+  // Update distance map
+  this->m_DistanceMap->SetInput( this->GetInput( ) );
+  this->m_DistanceMap->Update( );
+
+  // Correct seed
+  if( this->m_SeedFromMaximumDistance )
+  {
+    typedef itk::MinimumMaximumImageCalculator< TOutputImage > _TMinMax;
+    typename _TMinMax::Pointer minmax = _TMinMax::New( );
+    minmax->SetImage( this->m_DistanceMap->GetOutput( ) );
+    minmax->Compute( );
+    this->m_Seed = minmax->GetIndexOfMaximum( );
+
+  } // fi
+
+  // Compute MST
+  typename _TDijkstra::Pointer dijkstra = _TDijkstra::New( );
+  dijkstra->SetInput( this->m_DistanceMap->GetOutput( ) );
+  dijkstra->AddSeed( this->m_Seed );
+  dijkstra->Update( );
+
+  // Compute end-points
+  std::vector< TIndex > end_points;
+  this->_EndPoints(
+    end_points,
+    this->m_DistanceMap->GetOutput( ),
+    dijkstra->GetMinimumSpanningTree( ),
+    dijkstra->GetSkeletonQueue( )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+template< class _TMarksPointer >
+void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+_MarkSphere(
+  _TMarksPointer& marks, const TOutputImage* dmap, const TIndex& center
+  )
+{
+  typedef typename _TMarksPointer::ObjectType          _TMarks;
+  typedef itk::ImageRegionIteratorWithIndex< _TMarks > _TMarksIt;
+
+  static const double _eps = std::sqrt( double( Self::Dimension + 1 ) );
+  typename _TMarks::SpacingType spac = dmap->GetSpacing( );
+  typename _TMarks::RegionType region = dmap->GetRequestedRegion( );
+
+  typename _TMarks::PointType cnt;
+  dmap->TransformIndexToPhysicalPoint( center, cnt );
+  double r = double( dmap->GetPixel( center ) ) * _eps;
+
+  TIndex i0, i1;
+  for( unsigned int d = 0; d < Self::Dimension; ++d )
+  {
+    long off = long( std::ceil( r / double( spac[ d ] ) ) );
+    if( off < 3 )
+      off = 3;
+    i0[ d ] = center[ d ] - off;
+    i1[ d ] = center[ d ] + off;
+
+    if( i0[ d ] < region.GetIndex( )[ d ] )
+      i0[ d ] = region.GetIndex( )[ d ];
+
+    if( i1[ d ] >= region.GetIndex( )[ d ] + region.GetSize( )[ d ] )
+      i1[ d ] = region.GetIndex( )[ d ] + region.GetSize( )[ d ] - 1;
+
+  } // rof
+
+  typename _TMarks::SizeType size;
+  for( unsigned int d = 0; d < Self::Dimension; ++d )
+    size[ d ] = i1[ d ] - i0[ d ] + 1;
+
+  typename _TMarks::RegionType neighRegion;
+  neighRegion.SetIndex( i0 );
+  neighRegion.SetSize( size );
+
+  _TMarksIt mIt( marks, neighRegion );
+  for( mIt.GoToBegin( ); !mIt.IsAtEnd( ); ++mIt )
+    mIt.Set( true );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::
+_EndPoints(
+  std::vector< TIndex >& end_points,
+  const TOutputImage* dmap,
+  const _TMST* mst,
+  const _TSkeletonQueue& queue
+  )
+{
+  typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue;
+
+  // Some values
+  typedef itk::Image< bool, Self::Dimension > _TMarks;
+  typename _TMarks::Pointer marks = _TMarks::New( );
+  marks->SetLargestPossibleRegion( mst->GetLargestPossibleRegion( ) );
+  marks->SetRequestedRegion( mst->GetRequestedRegion( ) );
+  marks->SetBufferedRegion( mst->GetBufferedRegion( ) );
+  marks->SetSpacing( mst->GetSpacing( ) );
+  marks->SetOrigin( mst->GetOrigin( ) );
+  marks->SetDirection( mst->GetDirection( ) );
+  marks->Allocate( );
+  marks->FillBuffer( false );
+
+  // Get candidates in maximum to minimum iteration
+  typename _TSkeletonQueue::const_reverse_iterator nIt = queue.rbegin( );
+  for( ; nIt != queue.rend( ); ++nIt )
+  {
+    // Mark it and update end-points
+    if( !( marks->GetPixel( nIt->second ) ) )
+    {
+      marks->SetPixel( nIt->second, true );
+      end_points.push_back( nIt->second );
+
+      // Mark path
+      TIndex it = nIt->second;
+      TIndex p = mst->GetParent( it );
+      while( it != p )
+      {
+        this->_MarkSphere( marks, dmap, it );
+        it = p;
+        p = mst->GetParent( it );
+
+      } // elihw
+      this->_MarkSphere( marks, dmap, it );
+
+    } // fi
+
+  } // rof
+}
+
+
+
+/* TODO
+   this->m_DistanceMap = TDistanceMap::New( );
+   this->m_DistanceMap->InsideIsPositiveOn( );
+   this->m_DistanceMap->SquaredDistanceOff( );
+   this->m_DistanceMap->UseImageSpacingOn( );
+
+   template< class _TImage, class _TScalar >
+   void fpa::Image::SkeletonFilter< _TImage, _TScalar >::
+   _Skeleton( const std::vector< TVertex >& end_points, _TAdjacencies& A )
+   {
+   typedef typename TSkeleton::TPath _TPath;
+   typedef itk::Image< unsigned long, TImage::ImageDimension > _TTagsImage;
+
+   TMST* mst = this->GetMinimumSpanningTree( );
+   TSkeleton* skeleton = this->GetSkeleton( );
+
+   // Tag branches
+   typename _TTagsImage::Pointer tags = _TTagsImage::New( );
+   tags->SetLargestPossibleRegion( mst->GetLargestPossibleRegion( ) );
+   tags->SetRequestedRegion( mst->GetRequestedRegion( ) );
+   tags->SetBufferedRegion( mst->GetBufferedRegion( ) );
+   tags->Allocate( );
+   tags->FillBuffer( 0 );
+   typename std::vector< TVertex >::const_iterator eIt = end_points.begin( );
+   for( ; eIt != end_points.end( ); ++eIt )
+   {
+   TVertex it = *eIt;
+   TVertex p = mst->GetParent( it );
+   while( it != p )
+   {
+   tags->SetPixel( it, tags->GetPixel( it ) + 1 );
+   it = p;
+   p = mst->GetParent( it );
+   
+   } // elihw
+   tags->SetPixel( it, tags->GetPixel( it ) + 1 );
+
+   } // rof
+
+   // Build paths (branches)
+   eIt = end_points.begin( );
+   for( ; eIt != end_points.end( ); ++eIt )
+   {
+   TVertex it = *eIt;
+   TVertex p = mst->GetParent( it );
+   TVertex sIdx = it;
+   typename _TPath::Pointer path = _TPath::New( );
+   path->SetReferenceImage( mst );
+   while( it != p )
+   {
+   if( tags->GetPixel( sIdx ) != tags->GetPixel( it ) )
+   {
+   // Ok, a new branch has been added
+   path->AddVertex( it );
+   skeleton->AddBranch( path );
+   
+   // Update a new starting index
+   path = _TPath::New( );
+   path->SetReferenceImage( mst );
+   sIdx = it;
+   }
+   else
+   path->AddVertex( it );
+   it = p;
+   p = mst->GetParent( it );
+
+   } // elihw
+   
+   // Finally, add last branch
+   path->AddVertex( it );
+   skeleton->AddBranch( path );
+   
+   } // rof
+   }
+*/
+
+#endif // __fpa__Image__SkeletonFilter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/VisualDebugger.h b/lib/fpa/Image/VisualDebugger.h
new file mode 100644 (file)
index 0000000..90e94e1
--- /dev/null
@@ -0,0 +1,98 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__VisualDebugger__h__
+#define __fpa__Image__VisualDebugger__h__
+
+#include <fpa/Config.h>
+
+#include <vector>
+
+#include <itkCommand.h>
+#include <itkImage.h>
+#include <itkRGBAPixel.h>
+
+#ifdef USE_ivq
+#include <itkImageToVTKImageFilter.h>
+#endif // USE_ivq
+
+class vtkRenderer;
+class vtkRenderWindowInteractor;
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TFilter >
+    class VisualDebugger
+      : public itk::Command
+    {
+    public:
+      typedef VisualDebugger                  Self;
+      typedef itk::Command                    Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TFilter                      TFilter;
+      typedef typename TFilter::TInputImage TImage;
+
+      typedef itk::RGBAPixel< unsigned char > TLabel;
+      typedef itk::Image< TLabel, TImage::ImageDimension > TLabels;
+#ifdef USE_ivq
+      typedef itk::ImageToVTKImageFilter< TLabels > TVTKLabels;
+#endif // USE_ivq
+
+    public:
+      itkTypeMacro( fpa::Image::VisualDebugger, itk::Command );
+
+      itkGetConstObjectMacro( Labels, TLabels );
+
+    public:
+      void SetVisualization(
+        vtkRenderer* renderer, vtkRenderWindowInteractor* iren
+        );
+      virtual void Execute(
+        itk::Object* caller, const itk::EventObject& event
+        ) override;
+      virtual void Execute(
+        const itk::Object* caller, const itk::EventObject& event
+        ) override;
+
+      virtual void Render( ) = 0;
+      virtual void StartVisualization( ) = 0;
+      virtual void EndVisualization( ) = 0;
+
+    protected:
+      VisualDebugger( );
+      virtual ~VisualDebugger( );
+
+    private:
+      // Purposely not implemented.
+      VisualDebugger( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      std::vector< TLabel >     m_Colors;
+      typename TLabels::Pointer m_Labels;
+#ifdef USE_ivq
+      vtkRenderer*                 m_Renderer;
+      vtkRenderWindowInteractor*   m_Interactor;
+      typename TVTKLabels::Pointer m_VTKLabels;
+#endif // USE_ivq
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/VisualDebugger.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__VisualDebugger__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/VisualDebugger.hxx b/lib/fpa/Image/VisualDebugger.hxx
new file mode 100644 (file)
index 0000000..d45a803
--- /dev/null
@@ -0,0 +1,134 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__VisualDebugger__hxx__
+#define __fpa__Image__VisualDebugger__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+void fpa::Image::VisualDebugger< _TFilter >::
+SetVisualization( vtkRenderer* renderer, vtkRenderWindowInteractor* iren )
+{
+#ifdef USE_ivq
+  this->m_Renderer = renderer;
+  this->m_Interactor = iren;
+  this->Modified( );
+#endif // USE_ivq
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+void fpa::Image::VisualDebugger< _TFilter >::
+Execute( itk::Object* caller, const itk::EventObject& event )
+{
+  this->Execute( const_cast< const itk::Object* >( caller ), event );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+void fpa::Image::VisualDebugger< _TFilter >::
+Execute( const itk::Object* caller, const itk::EventObject& event )
+{
+  typedef itk::StartEvent           _TStart;
+  typedef itk::EndEvent             _TEnd;
+  typedef typename _TFilter::TEvent _TEvent;
+
+  // Check validity
+  const TFilter* filter = dynamic_cast< const TFilter* >( caller );
+  if( filter == NULL )
+    return;
+
+  // Get correct event type
+  const _TEvent* ev_fpa = dynamic_cast< const _TEvent* >( &event );
+  const _TStart* ev_start = dynamic_cast< const _TStart* >( &event );
+  const _TEnd* ev_end = dynamic_cast< const _TEnd* >( &event );
+  if( ev_fpa != NULL )
+  {
+    if( this->m_Labels.IsNotNull( ) )
+    {
+      TLabel new_color;
+      if( ev_fpa->IntoQueue )
+        new_color = this->m_Colors[ this->m_Colors.size( ) - 2 ];
+      else
+        new_color =
+          this->m_Colors[
+            ( ev_fpa->FrontId - 1 ) % ( this->m_Colors.size( ) - 2 )
+            ];
+      TLabel old_color = this->m_Labels->GetPixel( ev_fpa->Vertex );
+      if( !( new_color == old_color ) )
+      {
+        this->m_Labels->SetPixel( ev_fpa->Vertex, new_color );
+        this->m_VTKLabels->Modified( );
+        this->Render( );
+
+      } // fi
+
+    } // fi
+  }
+  else if( ev_start != NULL )
+  {
+    const TImage* image = filter->GetInput( );
+    this->m_Labels = TLabels::New( );
+    this->m_Labels->
+      SetLargestPossibleRegion( image->GetLargestPossibleRegion( ) );
+    this->m_Labels->SetRequestedRegion( image->GetRequestedRegion( ) );
+    this->m_Labels->SetBufferedRegion( image->GetBufferedRegion( ) );
+    this->m_Labels->SetOrigin( image->GetOrigin( ) );
+    this->m_Labels->SetSpacing( image->GetSpacing( ) );
+    this->m_Labels->SetDirection( image->GetDirection( ) );
+    this->m_Labels->Allocate( );
+    this->m_Labels->FillBuffer( this->m_Colors.back( ) );
+#ifdef USE_ivq
+    this->m_VTKLabels = TVTKLabels::New( );
+    this->m_VTKLabels->SetInput( this->m_Labels );
+    this->m_VTKLabels->Update( );
+    this->StartVisualization( );
+#endif // USE_ivq
+  }
+  else if( ev_end != NULL )
+  {
+    this->EndVisualization( );
+    this->m_Labels = NULL;
+    this->m_VTKLabels = NULL;
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+fpa::Image::VisualDebugger< _TFilter >::
+VisualDebugger( )
+  : Superclass( )
+{
+  unsigned char colors[ 8 ][ 4 ] =
+  {
+    { 255,   0,   0, 128 },
+    {   0, 255,   0, 128 },
+    {   0,   0, 255, 128 },
+    {   0, 255, 255, 128 },
+    { 255,   0, 255, 128 },
+    { 255, 255,   0, 128 },
+    { 255, 128,  64, 255 },
+    {   0,   0,   0,   0 }
+  };
+  for( unsigned int i = 0; i < 8; ++i )
+    this->m_Colors.push_back( TLabel( colors[ i ] ) );
+
+#ifdef USE_ivq
+  this->m_Renderer = NULL;
+  this->m_Interactor = NULL;
+#endif // USE_ivq
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+fpa::Image::VisualDebugger< _TFilter >::
+~VisualDebugger( )
+{
+}
+
+#endif // __fpa__Image__VisualDebugger__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/VisualDebugger2D.h b/lib/fpa/Image/VisualDebugger2D.h
new file mode 100644 (file)
index 0000000..21346d9
--- /dev/null
@@ -0,0 +1,76 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__VisualDebugger2D__h__
+#define __fpa__Image__VisualDebugger2D__h__
+
+#include <fpa/Image/VisualDebugger.h>
+#ifdef USE_ivq
+#include <vtkSmartPointer.h>
+#include <ivq/VTK/ImageActor.h>
+#endif // USE_ivq
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TFilter >
+    class VisualDebugger2D
+      : public fpa::Image::VisualDebugger< _TFilter >
+    {
+    public:
+      typedef VisualDebugger2D                       Self;
+      typedef fpa::Image::VisualDebugger< _TFilter > Superclass;
+      typedef itk::SmartPointer< Self >              Pointer;
+      typedef itk::SmartPointer< const Self >        ConstPointer;
+
+      typedef typename Superclass::TFilter TFilter;
+      typedef typename Superclass::TImage  TImage;
+      typedef typename Superclass::TLabel  TLabel;
+      typedef typename Superclass::TLabels TLabels;
+#ifdef USE_ivq
+      typedef typename Superclass::TVTKLabels TVTKLabels;
+      typedef ivq::VTK::ImageActor TImageActor;
+#endif // USE_ivq
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( fpa::Image::VisualDebugger2D, fpa::Image::VisualDebugger );
+
+    public:
+      virtual void Render( ) override;
+      virtual void StartVisualization( ) override;
+      virtual void EndVisualization( ) override;
+
+    protected:
+      VisualDebugger2D( );
+      virtual ~VisualDebugger2D( );
+
+    private:
+      // Purposely not implemented.
+      VisualDebugger2D( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+#ifdef USE_ivq
+      vtkSmartPointer< TImageActor > m_Actor;
+      unsigned long m_NumberOfPixels;
+      unsigned long m_RenderCount;
+#endif // USE_ivq
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/VisualDebugger2D.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__VisualDebugger2D__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Image/VisualDebugger2D.hxx b/lib/fpa/Image/VisualDebugger2D.hxx
new file mode 100644 (file)
index 0000000..91eff97
--- /dev/null
@@ -0,0 +1,74 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__VisualDebugger2D__hxx__
+#define __fpa__Image__VisualDebugger2D__hxx__
+
+#include <vtkRenderer.h>
+#include <vtkRenderWindowInteractor.h>
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+void fpa::Image::VisualDebugger2D< _TFilter >::
+Render( )
+{
+#ifdef USE_ivq
+  if( this->m_Renderer == NULL || this->m_Interactor == NULL )
+    return;
+  this->m_Actor->Modified( );
+  this->m_RenderCount = ( this->m_RenderCount + 1 ) % this->m_NumberOfPixels;
+  if( this->m_RenderCount == 0 )
+    this->m_Interactor->Render( );
+#endif // USE_ivq
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+void fpa::Image::VisualDebugger2D< _TFilter >::
+StartVisualization( )
+{
+#ifdef USE_ivq
+  if( this->m_Renderer == NULL || this->m_Interactor == NULL )
+    return;
+  this->m_Actor = vtkSmartPointer< TImageActor >::New( );
+  this->m_Actor->SetInputData( this->m_VTKLabels->GetOutput( ) );
+  this->m_Actor->Update( );
+  this->m_Renderer->AddViewProp( this->m_Actor );
+
+  this->m_NumberOfPixels =
+    double(
+      this->m_VTKLabels->GetInput( )->
+      GetRequestedRegion( ).GetNumberOfPixels( )
+      ) * 0.005;
+  this->m_RenderCount = 0;
+
+#endif // USE_ivq
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+void fpa::Image::VisualDebugger2D< _TFilter >::
+EndVisualization( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+fpa::Image::VisualDebugger2D< _TFilter >::
+VisualDebugger2D( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+fpa::Image::VisualDebugger2D< _TFilter >::
+~VisualDebugger2D( )
+{
+}
+
+#endif // __fpa__Image__VisualDebugger2D__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Version.cxx.in b/lib/fpa/Version.cxx.in
new file mode 100644 (file)
index 0000000..1bac65e
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include <fpa/fpa_export.h>
+#include <string>
+
+std::string FPA_EXPORT version( ) { return( "@prj_VERSION@" ); }
+
+// eof - $RCSfile$
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..dc97055
--- /dev/null
@@ -0,0 +1,10 @@
+option(BUILD_TESTS "Build command line tests." OFF)
+if(BUILD_TESTS)
+  include_directories(
+    ${PROJECT_SOURCE_DIR}/lib
+    ${PROJECT_BINARY_DIR}/lib
+    )
+  subdirs(image)
+endif(BUILD_TESTS)
+
+## eof - $RCSfile$
diff --git a/tests/image/BaseFunctions.h b/tests/image/BaseFunctions.h
new file mode 100644 (file)
index 0000000..21200d0
--- /dev/null
@@ -0,0 +1,315 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__tests__image__BaseFunctions__h__
+#define __fpa__tests__image__BaseFunctions__h__
+
+#include <cstdarg>
+#include <string>
+
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+
+#include <fpa/Config.h>
+#ifdef USE_ivq
+#  include <itkImageToVTKImageFilter.h>
+#  include <itkVTKImageToImageFilter.h>
+#  include <vtkSmartPointer.h>
+#  include <vtkRenderWindow.h>
+#  include <ivq/VTK/ImageViewer.h>
+#  include <ivq/VTK/BrushWidget.h>
+#  include <ivq/VTK/SeedWidgetOverImageActor.h>
+#  include <fpa/Image/VisualDebugger2D.h>
+#endif // USE_ivq
+
+namespace fpa
+{
+  namespace tests
+  {
+    namespace image
+    {
+      // -------------------------------------------------------------------
+      template< class _TPointer >
+      void CreateImage(
+        _TPointer& img,
+        const typename _TPointer::ObjectType::PixelType& zero,
+        ...
+        )
+      {
+        typedef typename _TPointer::ObjectType _TImage;
+
+        va_list vl;
+        va_start( vl, zero );
+
+        typename _TImage::SizeType size;
+        for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+          size[ d ] = va_arg( vl, int );
+
+        typename _TImage::SpacingType spac;
+        for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+          spac[ d ] = va_arg( vl, double );
+
+        img = _TImage::New( );
+        img->SetRegions( size );
+        img->SetSpacing( spac );
+        img->Allocate( );
+        img->FillBuffer( zero );
+
+        va_end( vl );
+      }
+
+      // -------------------------------------------------------------------
+      template< class _TPointer >
+      std::string Read( _TPointer& img, const std::string& fname )
+      {
+        typedef typename _TPointer::ObjectType _TImage;
+        typedef itk::ImageFileReader< _TImage > _TReader;
+
+        typename _TReader::Pointer reader = _TReader::New( );
+        reader->SetFileName( fname );
+        try
+        {
+          reader->Update( );
+        }
+        catch( std::exception& err )
+        {
+          return( err.what( ) );
+
+        } // ytr
+        img = reader->GetOutput( );
+        img->DisconnectPipeline( );
+        return( "" );
+      }
+
+      // -------------------------------------------------------------------
+      template< class _TImage >
+      std::string Write( const _TImage* img, const std::string& fname )
+      {
+        typedef itk::ImageFileWriter< _TImage > _TWriter;
+
+        typename _TWriter::Pointer writer = _TWriter::New( );
+        writer->SetInput( img );
+        writer->SetFileName( fname );
+        try
+        {
+          writer->Update( );
+        }
+        catch( std::exception& err )
+        {
+          return( err.what( ) );
+
+        } // ytr
+        return( "" );
+      }
+
+      // -------------------------------------------------------------------
+      template< class _TFilter >
+      class Viewer
+      {
+      public:
+        typedef _TFilter TFilter;
+        typedef typename _TFilter::TInputImage TInputImage;
+
+      public:
+        Viewer( const TInputImage* image )
+          {
+#ifdef USE_ivq
+            this->m_VTKInputImage = TVTKInputImage::New( );
+            this->m_VTKInputImage->SetInput( image );
+            this->m_VTKInputImage->Update( );
+
+            this->m_Viewer = vtkSmartPointer< ivq::VTK::ImageViewer >::New( );
+            this->m_Viewer->SetInputData( this->m_VTKInputImage->GetOutput( ) );
+#endif // USE_ivq
+          }
+
+        virtual ~Viewer( )
+          {
+          }
+
+        void ActivateSeedWidget( )
+          {
+#ifdef USE_ivq
+            this->m_SeedWidget =
+              vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( );
+            this->m_SeedWidget->SetActor( this->m_Viewer->GetImageActor( ) );
+            this->m_SeedWidget->SetInteractor(
+              this->m_Viewer->GetRenderWindow( )->GetInteractor( )
+              );
+#endif // USE_ivq
+          }
+
+        void ActivateBrushWidget( )
+          {
+#ifdef USE_ivq
+            this->m_BrushWidget =
+              vtkSmartPointer< ivq::VTK::BrushWidget >::New( );
+            this->m_BrushWidget->SetImageActor( this->m_Viewer->GetImageActor( ) );
+            this->m_BrushWidget->SetInteractor(
+              this->m_Viewer->GetRenderWindow( )->GetInteractor( )
+              );
+#endif // USE_ivq
+          }
+
+        void Show( )
+          {
+#ifdef USE_ivq
+            this->m_Viewer->Render( );
+            this->m_Viewer->ResetCamera( );
+            this->m_Viewer->Initialize( );
+            this->m_Viewer->Render( );
+            if( this->m_SeedWidget.GetPointer( ) != NULL )
+              this->m_SeedWidget->EnabledOn( );
+            if( this->m_BrushWidget.GetPointer( ) != NULL )
+              this->m_BrushWidget->EnabledOn( );
+            this->m_Viewer->Start( );
+            if( this->m_SeedWidget.GetPointer( ) != NULL )
+              this->m_SeedWidget->EnabledOff( );
+            if( this->m_BrushWidget.GetPointer( ) != NULL )
+              this->m_BrushWidget->EnabledOff( );
+#endif // USE_ivq
+          }
+
+        void AssociateSeedsTo( TFilter* filter )
+          {
+#ifdef USE_ivq
+            if( this->m_SeedWidget.GetPointer( ) != NULL )
+            {
+              const ivq::VTK::SeedWidgetOverImageActor::TSeeds& wdg_seeds =
+                this->m_SeedWidget->GetSeeds( );
+              ivq::VTK::SeedWidgetOverImageActor::TSeeds::const_iterator wsIt;
+              for( wsIt = wdg_seeds.begin( ); wsIt != wdg_seeds.end( ); ++wsIt )
+              {
+                typename TInputImage::PointType pnt;
+                for( unsigned int i = 0; i < wsIt->second.size( ); i += 3 )
+                {
+                  pnt[ 0 ] = wsIt->second[ i ];
+                  pnt[ 1 ] = wsIt->second[ i + 1 ];
+
+                  typename TInputImage::IndexType idx;
+                  filter->GetInput( )->TransformPhysicalPointToIndex( pnt, idx );
+                  filter->AddSeed( idx );
+
+                } // rof
+
+              } // rof
+
+            } // fi
+#endif // USE_ivq
+          }
+
+        void AssociateLabelsTo( TFilter* filter )
+          {
+#ifdef USE_ivq
+            if( this->m_BrushWidget.GetPointer( ) != NULL )
+            {
+              typedef typename TFilter::TLabelImage _TLabelImage;
+              typedef itk::VTKImageToImageFilter< _TLabelImage > TITKImage;
+              typename TITKImage::Pointer itk_image = TITKImage::New( );
+              itk_image->SetInput( this->m_BrushWidget->GetCanvas( ) );
+              itk_image->Update( );
+              filter->SetLabels( itk_image->GetOutput( ) );
+
+            } // fi
+#endif // USE_ivq
+          }
+
+        void ObserveFilter( TFilter* filter )
+          {
+#ifdef USE_ivq
+            typedef fpa::Image::VisualDebugger2D< TFilter > _TDeb;
+            typedef typename TFilter::TEvent                _TEvent;
+            typename _TDeb::Pointer deb = _TDeb::New( );
+            deb->SetVisualization(
+              this->m_Viewer->GetRenderer( ),
+              this->m_Viewer->GetRenderWindow( )->GetInteractor( )
+              );
+            this->m_Observer1 = filter->AddObserver( itk::StartEvent( ), deb );
+            this->m_Observer2 = filter->AddObserver( itk::EndEvent( ), deb );
+            this->m_Observer3 = filter->AddObserver( _TEvent( ), deb );
+            filter->VisualDebugOn( );
+#endif // USE_ivq
+          }
+
+      protected:
+#ifdef USE_ivq
+        typedef itk::ImageToVTKImageFilter< TInputImage > TVTKInputImage;
+        typename TVTKInputImage::Pointer                      m_VTKInputImage;
+        vtkSmartPointer< ivq::VTK::ImageViewer >              m_Viewer;
+        vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor > m_SeedWidget;
+        vtkSmartPointer< ivq::VTK::BrushWidget >              m_BrushWidget;
+        unsigned long m_Observer1;
+        unsigned long m_Observer2;
+        unsigned long m_Observer3;
+#endif // USE_ivq
+
+
+        /* TODO
+           #ifdef USE_ivq
+           // VTK image
+           typedef itk::ImageToVTKImageFilter< TImage > TVTKImage;
+           TVTKImage::Pointer vtk_input;
+           vtkSmartPointer< ivq::VTK::ImageViewer > view;
+           vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor > widget;
+
+           if( visual_debug )
+           {
+           vtk_input = TVTKImage::New( );
+           vtk_input->SetInput( input );
+           vtk_input->Update( );
+
+           // Viewer
+           view = vtkSmartPointer< ivq::VTK::ImageViewer >::New( );
+           view->SetInputData( vtk_input->GetOutput( ) );
+           view->SetSlice( 0 );
+
+           // Widget
+           widget = vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( );
+           widget->SetActor( view->GetImageActor( ) );
+           widget->SetInteractor( view->GetRenderWindow( )->GetInteractor( ) );
+
+           // Visualize
+           view->Render( );
+           view->ResetCamera( );
+           view->Initialize( );
+           view->Render( );
+           widget->EnabledOn( );
+           view->Start( );
+           widget->EnabledOff( );
+
+           const ivq::VTK::SeedWidgetOverImageActor::TSeeds& wdg_seeds =
+           widget->GetSeeds( );
+           ivq::VTK::SeedWidgetOverImageActor::TSeeds::const_iterator wsIt;
+           for( wsIt = wdg_seeds.begin( ); wsIt != wdg_seeds.end( ); ++wsIt )
+           {
+           TImage::PointType pnt;
+           for( unsigned int i = 0; i < wsIt->second.size( ); i += 3 )
+           {
+           pnt[ 0 ] = wsIt->second[ i ];
+           pnt[ 1 ] = wsIt->second[ i + 1 ];
+
+           TImage::IndexType idx;
+           input->TransformPhysicalPointToIndex( pnt, idx );
+           seeds.push_back( idx );
+
+           } // rof
+
+           } // rof
+
+           } // fi
+           #endif // USE_ivq
+        */
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+
+#endif // __fpa__tests__image__BaseFunctions__h__
+
+// eof - $RCSfile$
diff --git a/tests/image/CMakeLists.txt b/tests/image/CMakeLists.txt
new file mode 100644 (file)
index 0000000..00facdf
--- /dev/null
@@ -0,0 +1,19 @@
+set(_pfx test_fpa_image_)
+set(
+  _examples
+  RegionGrow_Tautology
+  Dijkstra_Identity
+  Dijkstra_Gaussian
+  RandomWalker
+  SkeletonFilter
+  )
+foreach(_e ${_examples})
+  add_executable(${_pfx}${_e} ${_e}.cxx)
+  if(ivq_FOUND)
+    target_link_libraries(${_pfx}${_e} fpa ivq::ivq)
+  else(ivq_FOUND)
+    target_link_libraries(${_pfx}${_e} fpa)
+  endif(ivq_FOUND)
+endforeach(_e)
+
+## eof - $RCSfile$
diff --git a/tests/image/Dijkstra_Gaussian.cxx b/tests/image/Dijkstra_Gaussian.cxx
new file mode 100644 (file)
index 0000000..d0461ff
--- /dev/null
@@ -0,0 +1,99 @@
+#include "BaseFunctions.h"
+#include <itkImage.h>
+#include <fpa/Image/Dijkstra.h>
+#include <fpa/Image/Functors/Dijkstra/Gaussian.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 2;
+typedef unsigned char TPixel;
+typedef float         TScalar;
+
+typedef itk::Image< TPixel, Dim >                                    TInputImage;
+typedef itk::Image< TScalar, Dim >                                  TScalarImage;
+typedef fpa::Image::Dijkstra< TInputImage, TScalarImage >                TFilter;
+typedef fpa::Image::Functors::Dijkstra::Gaussian< TInputImage, TScalar > TWeight;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get arguments
+  if( argc < 8 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " input_image output_image output_marks alpha beta"
+      << " stop_at_one_front visual_debug ..."
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string input_image_filename = argv[ 1 ];
+  std::string output_image_filename = argv[ 2 ];
+  std::string output_marks_filename = argv[ 3 ];
+  double alpha = std::atoi( argv[ 4 ] );
+  double beta = std::atoi( argv[ 5 ] );
+  bool stop_at_one_front = ( argv[ 6 ][ 0 ] == '1' );
+  bool visual_debug = ( argv[ 7 ][ 0 ] == '1' );
+
+  // Create image
+  TInputImage::Pointer image;
+  std::string err0 = fpa::tests::image::Read( image, input_image_filename );
+  if( err0 != "" )
+  {
+    std::cerr << "Error caught: " << err0 << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Interact with image
+  fpa::tests::image::Viewer< TFilter > viewer( image );
+  if( visual_debug )
+  {
+    viewer.ActivateSeedWidget( );
+    viewer.Show( );
+
+  } // fi
+
+  // Prepare weight
+  TWeight::Pointer weight = TWeight::New( );
+  weight->SetAlpha( alpha );
+  weight->SetBeta( beta );
+
+  // Prepare filter
+  TFilter::Pointer filter = TFilter::New( );
+  filter->SetInput( image );
+  filter->SetWeightFunction( weight );
+  filter->SetStopAtOneFront( stop_at_one_front );
+
+  // Get all seeds
+  for( int i = 8; i < argc; i += 2 )
+  {
+    if( i + 1 < argc )
+    {
+      TInputImage::IndexType seed;
+      seed[ 0 ] = std::atoi( argv[ i ] );
+      seed[ 1 ] = std::atoi( argv[ i + 1 ] );
+      filter->AddSeed( seed );
+
+    } // fi
+
+  } // rof
+  viewer.AssociateSeedsTo( filter );
+
+  // Prepare visual debug and update
+  if( visual_debug )
+    viewer.ObserveFilter( filter );
+  filter->Update( );
+
+  // Save results
+  std::string err1 =
+    fpa::tests::image::Write( filter->GetOutput( ), output_image_filename );
+  std::string err2 =
+    fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename );
+  if( err1 != "" ) std::cerr << "Error caught: " << err1 << std::endl;
+  if( err2 != "" ) std::cerr << "Error caught: " << err2 << std::endl;
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tests/image/Dijkstra_Identity.cxx b/tests/image/Dijkstra_Identity.cxx
new file mode 100644 (file)
index 0000000..57f3593
--- /dev/null
@@ -0,0 +1,87 @@
+#include "BaseFunctions.h"
+#include <itkImage.h>
+#include <fpa/Image/Dijkstra.h>
+#include <fpa/Image/Functors/Dijkstra/Identity.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 2;
+typedef unsigned char TPixel;
+typedef float         TScalar;
+
+typedef itk::Image< TPixel, Dim >                                    TInputImage;
+typedef itk::Image< TScalar, Dim >                                  TScalarImage;
+typedef fpa::Image::Dijkstra< TInputImage, TScalarImage >                TFilter;
+typedef fpa::Image::Functors::Dijkstra::Identity< TInputImage, TScalar > TWeight;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get arguments
+  if( argc < 6 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " output_image output_marks width height visual_debug ..."
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string output_image_filename = argv[ 1 ];
+  std::string output_marks_filename = argv[ 2 ];
+  int width = std::atoi( argv[ 3 ] );
+  int height = std::atoi( argv[ 4 ] );
+  bool visual_debug = ( argv[ 5 ][ 0 ] == '1' );
+
+  // Create image
+  TInputImage::Pointer image;
+  fpa::tests::image::CreateImage( image, 1, width, height, 1.0, 1.0 );
+
+  // Interact with image
+  fpa::tests::image::Viewer< TFilter > viewer( image );
+  if( visual_debug )
+  {
+    viewer.ActivateSeedWidget( );
+    viewer.Show( );
+
+  } // fi
+
+  // Prepare weight
+  TWeight::Pointer weight = TWeight::New( );
+
+  // Prepare filter
+  TFilter::Pointer filter = TFilter::New( );
+  filter->SetInput( image );
+  filter->SetWeightFunction( weight );
+
+  // Get all seeds
+  for( int i = 6; i < argc; i += 2 )
+  {
+    if( i + 1 < argc )
+    {
+      TInputImage::IndexType seed;
+      seed[ 0 ] = std::atoi( argv[ i ] );
+      seed[ 1 ] = std::atoi( argv[ i + 1 ] );
+      filter->AddSeed( seed );
+
+    } // fi
+
+  } // rof
+  viewer.AssociateSeedsTo( filter );
+
+  // Prepare visual debug and update
+  if( visual_debug )
+    viewer.ObserveFilter( filter );
+  filter->Update( );
+
+  // Save results
+  std::string err1 =
+    fpa::tests::image::Write( filter->GetOutput( ), output_image_filename );
+  std::string err2 =
+    fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename );
+  if( err1 != "" ) std::cerr << err1 << std::endl;
+  if( err2 != "" ) std::cerr << err2 << std::endl;
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tests/image/RandomWalker.cxx b/tests/image/RandomWalker.cxx
new file mode 100644 (file)
index 0000000..59c9105
--- /dev/null
@@ -0,0 +1,113 @@
+#include "BaseFunctions.h"
+#include <itkImage.h>
+#include <fpa/Image/RandomWalker.h>
+#include <fpa/Image/Functors/Dijkstra/Gaussian.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 2;
+typedef short         TPixel;
+typedef unsigned char TLabel;
+typedef float         TScalar;
+
+typedef itk::Image< TPixel, Dim >                                    TInputImage;
+typedef itk::Image< TLabel, Dim >                                    TLabelImage;
+typedef fpa::Image::RandomWalker< TInputImage, TLabelImage, TScalar >    TFilter;
+typedef fpa::Image::Functors::Dijkstra::Gaussian< TInputImage, TScalar > TWeight;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get arguments
+  if( argc < 7 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " input_image [labels_image] output_image output_costs"
+      << " alpha beta visual_debug"
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  int idx = ( argc == 7 )? 2: 3;
+  std::string input_image_filename = argv[ 1 ];
+  std::string labels_image_filename = ( argc == 8 )? argv[ 2 ]: "";
+  std::string output_image_filename = argv[ idx ];
+  std::string output_costs_filename = argv[ idx + 1 ];
+  double alpha = std::atof( argv[ idx + 2 ] );
+  double beta = std::atof( argv[ idx + 3 ] );
+  bool visual_debug = ( argv[ idx + 4 ][ 0 ] == '1' );
+
+  // Read image
+  TInputImage::Pointer image;
+  std::string err0 = fpa::tests::image::Read( image, input_image_filename );
+  if( err0 != "" )
+  {
+    std::cerr << "Error caught: " << err0 << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Read label
+  TLabelImage::Pointer labels;
+  if( labels_image_filename != "" )
+  {
+    std::string err1 = fpa::tests::image::Read( labels, labels_image_filename );
+    if( err1 != "" )
+    {
+      std::cerr << "Error caught: " << err1 << std::endl;
+      return( 1 );
+
+    } // fi
+
+  } // fi
+
+  // Interact with image
+  fpa::tests::image::Viewer< TFilter > viewer( image );
+  if( visual_debug )
+  {
+    if( labels.IsNull( ) )
+      viewer.ActivateBrushWidget( );
+    viewer.Show( );
+
+  } // fi
+
+  // Prepare weight
+  TWeight::Pointer weight = TWeight::New( );
+  weight->SetAlpha( alpha );
+  weight->SetBeta( beta );
+
+  // Prepare filter
+  TFilter::Pointer filter = TFilter::New( );
+  filter->SetInput( image );
+  filter->SetWeightFunction( weight );
+  if( labels.IsNull( ) )
+    viewer.AssociateLabelsTo( filter );
+  else
+    filter->SetLabels( labels );
+
+  // Prepare visual debug and update
+  if( visual_debug )
+    viewer.ObserveFilter( filter );
+  try
+  {
+    filter->Update( );
+  }
+  catch( std::exception& err )
+  {
+    std::cerr << "Error caught: " << err.what( ) << std::endl;
+    return( 1 );
+
+  } // yrt
+
+  // Save results
+  std::string err1 =
+    fpa::tests::image::Write( filter->GetMarks( ), output_image_filename );
+  std::string err2 =
+    fpa::tests::image::Write( filter->GetOutput( ), output_costs_filename );
+  if( err1 != "" ) std::cerr << "Error caught: " << err1 << std::endl;
+  if( err2 != "" ) std::cerr << "Error caught: " << err2 << std::endl;
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tests/image/RegionGrow_Tautology.cxx b/tests/image/RegionGrow_Tautology.cxx
new file mode 100644 (file)
index 0000000..7cdffa5
--- /dev/null
@@ -0,0 +1,87 @@
+#include "BaseFunctions.h"
+#include <itkImage.h>
+#include <fpa/Image/RegionGrow.h>
+#include <fpa/Base/Functors/RegionGrow/Tautology.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 2;
+typedef unsigned char TPixel;
+
+typedef itk::Image< TPixel, Dim >                            TImage;
+typedef fpa::Image::RegionGrow< TImage, TImage >             TFilter;
+typedef fpa::Base::Functors::RegionGrow::Tautology< TPixel > TPredicate;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get arguments
+  if( argc < 6 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " output_image output_marks width height visual_debug ..."
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string output_image_filename = argv[ 1 ];
+  std::string output_marks_filename = argv[ 2 ];
+  int width = std::atoi( argv[ 3 ] );
+  int height = std::atoi( argv[ 4 ] );
+  bool visual_debug = ( argv[ 5 ][ 0 ] == '1' );
+
+  // Create image
+  TImage::Pointer image;
+  fpa::tests::image::CreateImage( image, 0, width, height, 1.0, 1.0 );
+
+  // Interact with image
+  fpa::tests::image::Viewer< TFilter > viewer( image );
+  if( visual_debug )
+  {
+    viewer.ActivateSeedWidget( );
+    viewer.Show( );
+
+  } // fi
+
+  // Prepare predicate
+  TPredicate::Pointer predicate = TPredicate::New( );
+
+  // Prepare filter
+  TFilter::Pointer filter = TFilter::New( );
+  filter->SetInput( image );
+  filter->SetPredicate( predicate );
+  filter->SetInsideValue( 255 );
+  filter->SetOutsideValue( 0 );
+
+  // Get all seeds
+  for( int i = 6; i < argc; i += 2 )
+  {
+    if( i + 1 < argc )
+    {
+      TImage::IndexType seed;
+      seed[ 0 ] = std::atoi( argv[ i ] );
+      seed[ 1 ] = std::atoi( argv[ i + 1 ] );
+      filter->AddSeed( seed );
+
+    } // fi
+
+  } // rof
+  viewer.AssociateSeedsTo( filter );
+
+  // Prepare visual debug and update
+  if( visual_debug )
+    viewer.ObserveFilter( filter );
+  filter->Update( );
+
+  // Save results
+  std::string err1 =
+    fpa::tests::image::Write( filter->GetOutput( ), output_image_filename );
+  std::string err2 =
+    fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename );
+  if( err1 != "" ) std::cerr << err1 << std::endl;
+  if( err2 != "" ) std::cerr << err2 << std::endl;
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tests/image/SkeletonFilter.cxx b/tests/image/SkeletonFilter.cxx
new file mode 100644 (file)
index 0000000..ec0aa74
--- /dev/null
@@ -0,0 +1,74 @@
+#include "BaseFunctions.h"
+#include <itkImage.h>
+#include <fpa/Image/SkeletonFilter.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 3;
+typedef short TPixel;
+
+typedef itk::Image< TPixel, Dim >                 TInputImage;
+typedef fpa::Image::SkeletonFilter< TInputImage > TFilter;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get arguments
+  if( argc < 3 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " input_image output_skeleton ..."
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string input_image_filename = argv[ 1 ];
+  std::string output_skeleton_filename = argv[ 2 ];
+
+  // Read image
+  TInputImage::Pointer image;
+  std::string err1 = fpa::tests::image::Read( image, input_image_filename );
+  if( err1 != "" )
+  {
+    std::cerr << "Error caught: " << err1 << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Prepare filter
+  TFilter::Pointer filter = TFilter::New( );
+  filter->SetInput( image );
+
+  // Configure seed
+  if( argc == 6 )
+  {
+    TInputImage::PointType pnt;
+    pnt[ 0 ] = std::atof( argv[ 3 ] );
+    pnt[ 1 ] = std::atof( argv[ 4 ] );
+    pnt[ 2 ] = std::atof( argv[ 5 ] );
+
+    TInputImage::IndexType seed;
+    image->TransformPhysicalPointToIndex( pnt, seed );
+
+    filter->SeedFromMaximumDistanceOff( );
+    filter->SetSeed( seed );
+  }
+  else
+    filter->SeedFromMaximumDistanceOn( );
+
+  // Update
+  filter->Update( );
+
+  // Save results
+  /* TODO
+     std::string err1 =
+     fpa::tests::image::Write( filter->GetOutput( ), output_image_filename );
+     std::string err2 =
+     fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename );
+     if( err1 != "" ) std::cerr << err1 << std::endl;
+     if( err2 != "" ) std::cerr << err2 << std::endl;
+  */
+  return( 0 );
+}
+
+// eof - $RCSfile$