From: Leonardo Florez-Valencia Date: Fri, 10 Apr 2015 02:40:15 +0000 (-0500) Subject: Skeletonization ready to use X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=dba0f8d24a98fabeb461b337ed78efaf06cb057c;p=FrontAlgorithms.git Skeletonization ready to use --- diff --git a/appli/examples/CMakeLists.txt b/appli/examples/CMakeLists.txt index fd255c1..3e000b8 100644 --- a/appli/examples/CMakeLists.txt +++ b/appli/examples/CMakeLists.txt @@ -18,6 +18,7 @@ IF(USE_VTK) example_Image_Dijkstra_DanielssonCost example_Image_Dijkstra_DanielssonCost_TwoSeedsPath example_Image_Dijkstra_EndPointDetection + example_ShowSkeleton ) FOREACH(EX ${SIMPLE_VTK_EXAMPLES}) ADD_EXECUTABLE(${EX} ${EX}.cxx) diff --git a/appli/examples/example_ShowSkeleton.cxx b/appli/examples/example_ShowSkeleton.cxx new file mode 100644 index 0000000..b4d03b4 --- /dev/null +++ b/appli/examples/example_ShowSkeleton.cxx @@ -0,0 +1,254 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 3; +typedef unsigned char TPixel; + +typedef itk::Image< TPixel, Dim > TImage; +typedef itk::ImageToVTKImageFilter< TImage > TVTKInputImage; + +typedef fpa::Image::DijkstraWithEndPointDetection< TImage, TImage > TFilter; +typedef TFilter::TMinimumSpanningTree TMinimumSpanningTree; +typedef TFilter::TUniqueVertices TUniqueVertices; +typedef TFilter::TBranches TBranches; +typedef TFilter::TVertices TVertices; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 6 ) + { + std::cerr + << "Usage: " << argv[ 0 ] << std::endl + << " input_image" << std::endl + << " input_minimum_spanning_tree" << std::endl + << " input_endpoints" << std::endl + << " input_bifurcations" << std::endl + << " input_branches" << std::endl + << std::endl; + return( 1 ); + + } // fi + std::string input_image_fn = argv[ 1 ]; + std::string mst_input_fn = argv[ 2 ]; + std::string endpoints_input_fn = argv[ 3 ]; + std::string bifurcations_input_fn = argv[ 4 ]; + std::string branches_input_fn = argv[ 5 ]; + + // Read image + typename itk::ImageFileReader< TImage >::Pointer input_image_reader = + itk::ImageFileReader< TImage >::New( ); + input_image_reader->SetFileName( input_image_fn ); + input_image_reader->Update( ); + TImage::ConstPointer input_image = input_image_reader->GetOutput( ); + + TVTKInputImage::Pointer vtk_input_image = TVTKInputImage::New( ); + vtk_input_image->SetInput( input_image ); + vtk_input_image->Update( ); + + // Read minimum spanning tree + fpa::IO::MinimumSpanningTreeReader< TMinimumSpanningTree >::Pointer + mst_input_reader = + fpa::IO::MinimumSpanningTreeReader< TMinimumSpanningTree >::New( ); + mst_input_reader->SetFileName( mst_input_fn ); + mst_input_reader->Update( ); + TMinimumSpanningTree::ConstPointer mst_input = mst_input_reader->GetOutput( ); + + fpa::IO::UniqueValuesContainerReader< TUniqueVertices >::Pointer + endpoints_input_reader = + fpa::IO::UniqueValuesContainerReader< TUniqueVertices >::New( ); + endpoints_input_reader->SetFileName( endpoints_input_fn ); + endpoints_input_reader->Update( ); + TUniqueVertices::ConstPointer endpoints_input = endpoints_input_reader->GetOutput( ); + + fpa::IO::UniqueValuesContainerReader< TUniqueVertices >::Pointer + bifurcations_input_reader = + fpa::IO::UniqueValuesContainerReader< TUniqueVertices >::New( ); + bifurcations_input_reader->SetFileName( bifurcations_input_fn ); + bifurcations_input_reader->Update( ); + TUniqueVertices::ConstPointer bifurcations_input = + bifurcations_input_reader->GetOutput( ); + + fpa::IO::MatrixValuesContainerReader< TBranches >::Pointer + branches_input_reader = + fpa::IO::MatrixValuesContainerReader< TBranches >::New( ); + branches_input_reader->SetFileName( branches_input_fn ); + branches_input_reader->Update( ); + TBranches::ConstPointer branches_input = branches_input_reader->GetOutput( ); + unsigned int nBranches = branches_input_reader->GetNumberOfLabels( ); + + // Show input image and let some interaction + fpa::VTK::ImageMPR view; + view.SetBackground( 0.3, 0.2, 0.8 ); + view.SetSize( 800, 800 ); + view.SetImage( vtk_input_image->GetOutput( ) ); + + vtkSmartPointer< vtkImageMarchingCubes > mc = + vtkSmartPointer< vtkImageMarchingCubes >::New( ); + mc->SetInputData( vtk_input_image->GetOutput( ) ); + mc->SetValue( 0, 1e-1 ); + mc->Update( ); + view.AddPolyData( mc->GetOutput( ), 1, 1, 1, 0.4 ); + + // Show endpoints + vtkSmartPointer< vtkPoints > endpoints_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > endpoints_cells = + vtkSmartPointer< vtkCellArray >::New( ); + for( + TUniqueVertices::ConstIterator epIt = endpoints_input->Begin( ); + epIt != endpoints_input->End( ); + ++epIt + ) + { + TImage::PointType pnt; + input_image->TransformIndexToPhysicalPoint( *epIt, pnt ); + endpoints_points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + endpoints_cells->InsertNextCell( 1 ); + endpoints_cells-> + InsertCellPoint( endpoints_points->GetNumberOfPoints( ) - 1 ); + + } // rof + vtkSmartPointer< vtkPolyData > endpoints_polydata = + vtkSmartPointer< vtkPolyData >::New( ); + endpoints_polydata->SetPoints( endpoints_points ); + endpoints_polydata->SetVerts( endpoints_cells ); + view.AddPolyData( endpoints_polydata, 0, 0, 1, 1 ); + + // Show bifurcations + vtkSmartPointer< vtkPoints > bifurcations_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > bifurcations_cells = + vtkSmartPointer< vtkCellArray >::New( ); + for( + TUniqueVertices::ConstIterator bfIt = bifurcations_input->Begin( ); + bfIt != bifurcations_input->End( ); + ++bfIt + ) + { + TImage::PointType pnt; + input_image->TransformIndexToPhysicalPoint( *bfIt, pnt ); + bifurcations_points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + bifurcations_cells->InsertNextCell( 1 ); + bifurcations_cells-> + InsertCellPoint( bifurcations_points->GetNumberOfPoints( ) - 1 ); + + } // rof + vtkSmartPointer< vtkPolyData > bifurcations_polydata = + vtkSmartPointer< vtkPolyData >::New( ); + bifurcations_polydata->SetPoints( bifurcations_points ); + bifurcations_polydata->SetVerts( bifurcations_cells ); + view.AddPolyData( bifurcations_polydata, 0, 1, 0, 1 ); + + // Show branches (simple and detailed) + vtkSmartPointer< vtkPoints > simple_branches_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > simple_branches_cells = + vtkSmartPointer< vtkCellArray >::New( ); + + vtkSmartPointer< vtkPoints > detailed_branches_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > detailed_branches_cells = + vtkSmartPointer< vtkCellArray >::New( ); + vtkSmartPointer< vtkFloatArray > detailed_branches_scalars = + vtkSmartPointer< vtkFloatArray >::New( ); + + TBranches::ConstIterator brIt = branches_input->Begin( ); + for( ; brIt != branches_input->End( ); ++brIt ) + { + // Branch's first point + TImage::PointType first_point; + input_image->TransformIndexToPhysicalPoint( brIt->first, first_point ); + unsigned long first_id = simple_branches_points->GetNumberOfPoints( ); + simple_branches_points->InsertNextPoint( + first_point[ 0 ], first_point[ 1 ], first_point[ 2 ] + ); + + TBranches::ConstRowIterator brRowIt = branches_input->Begin( brIt ); + for( ; brRowIt != branches_input->End( brIt ); ++brRowIt ) + { + // Branch's second point + TImage::PointType second_point; + input_image-> + TransformIndexToPhysicalPoint( brRowIt->first, second_point ); + unsigned long second_id = simple_branches_points->GetNumberOfPoints( ); + simple_branches_points->InsertNextPoint( + second_point[ 0 ], second_point[ 1 ], second_point[ 2 ] + ); + simple_branches_cells->InsertNextCell( 2 ); + simple_branches_cells->InsertCellPoint( first_id ); + simple_branches_cells->InsertCellPoint( second_id ); + + // Detailed path + double pathId = double( brRowIt->second - 1 ) / double( nBranches - 1 ); + TVertices path; + mst_input->GetPath( path, brIt->first, brRowIt->first ); + TVertices::const_iterator pIt = path.begin( ); + for( ; pIt != path.end( ); ++pIt ) + { + TImage::PointType path_point; + input_image->TransformIndexToPhysicalPoint( *pIt, path_point ); + detailed_branches_points->InsertNextPoint( + path_point[ 0 ], path_point[ 1 ], path_point[ 2 ] + ); + detailed_branches_scalars->InsertNextTuple1( pathId ); + if( pIt != path.begin( ) ) + { + unsigned long nPoints = + detailed_branches_points->GetNumberOfPoints( ); + detailed_branches_cells->InsertNextCell( 2 ); + detailed_branches_cells->InsertCellPoint( nPoints - 2 ); + detailed_branches_cells->InsertCellPoint( nPoints - 1 ); + + } // fi + + } // rof + + } // rof + + } // rof + vtkSmartPointer< vtkPolyData > simple_branches_polydata = + vtkSmartPointer< vtkPolyData >::New( ); + simple_branches_polydata->SetPoints( simple_branches_points ); + simple_branches_polydata->SetLines( simple_branches_cells ); + view.AddPolyData( simple_branches_polydata, 1, 0, 1, 1 ); + + vtkSmartPointer< vtkPolyData > detailed_branches_polydata = + vtkSmartPointer< vtkPolyData >::New( ); + detailed_branches_polydata->SetPoints( detailed_branches_points ); + detailed_branches_polydata->SetLines( detailed_branches_cells ); + detailed_branches_polydata-> + GetPointData( )->SetScalars( detailed_branches_scalars ); + view.AddPolyData( detailed_branches_polydata, 1 ); + + // Allow some interaction + view.Render( ); + view.Start( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MinimumSpanningTree.h b/lib/fpa/Base/MinimumSpanningTree.h index be6dae4..a020d47 100644 --- a/lib/fpa/Base/MinimumSpanningTree.h +++ b/lib/fpa/Base/MinimumSpanningTree.h @@ -46,7 +46,12 @@ namespace fpa this->Get( )[ v ] = TNodeInfo( p, fid ); this->Modified( ); } - + void Clear( ) + { + this->Get( ).clear( ); + this->m_Collisions.clear( ); + this->m_FrontPaths.clear( ); + } virtual void GetPath( std::vector< V >& path, const V& a, const V& b ) const; diff --git a/lib/fpa/IO/MatrixValuesContainerReader.h b/lib/fpa/IO/MatrixValuesContainerReader.h new file mode 100644 index 0000000..8d65074 --- /dev/null +++ b/lib/fpa/IO/MatrixValuesContainerReader.h @@ -0,0 +1,63 @@ +#ifndef __FPA__IO__MATRIXVALUESCONTAINERREADER__H__ +#define __FPA__IO__MATRIXVALUESCONTAINERREADER__H__ + +#include +#include + +namespace fpa +{ + namespace IO + { + /** + */ + template< class T > + class MatrixValuesContainerReader + : public itk::ProcessObject + { + public: + typedef MatrixValuesContainerReader Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef T TTree; + + public: + itkNewMacro( Self ); + itkTypeMacro( MatrixValuesContainerReader, itkProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkGetConstMacro( NumberOfLabels, unsigned int ); + + itkSetMacro( FileName, std::string ); + + public: + T* GetOutput( ); + + virtual void Update( ); + + protected: + MatrixValuesContainerReader( ); + virtual ~MatrixValuesContainerReader( ); + + virtual void GenerateData( ); + + private: + // Purposely not implemented + MatrixValuesContainerReader( const Self& other ); + Self& operator=( const Self& other ); + + protected: + std::string m_FileName; + unsigned int m_NumberOfLabels; + }; + + } // ecapseman + +} // ecapseman + +#include + +#endif // __FPA__IO__MATRIXVALUESCONTAINERREADER__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/IO/MatrixValuesContainerReader.hxx b/lib/fpa/IO/MatrixValuesContainerReader.hxx new file mode 100644 index 0000000..902462b --- /dev/null +++ b/lib/fpa/IO/MatrixValuesContainerReader.hxx @@ -0,0 +1,103 @@ +#ifndef __FPA__IO__MATRIXVALUESCONTAINERREADER__HXX__ +#define __FPA__IO__MATRIXVALUESCONTAINERREADER__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class T > +T* fpa::IO::MatrixValuesContainerReader< T >:: +GetOutput( ) +{ + return( itkDynamicCastInDebugMode< T* >( this->GetPrimaryOutput( ) ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +void fpa::IO::MatrixValuesContainerReader< T >:: +Update( ) +{ + this->GenerateData( ); +} + +// ------------------------------------------------------------------------- +template< class T > +fpa::IO::MatrixValuesContainerReader< T >:: +MatrixValuesContainerReader( ) + : Superclass( ), + m_FileName( "" ) +{ + this->itk::ProcessObject::SetNumberOfRequiredOutputs( 1 ); + this->itk::ProcessObject::SetNthOutput( 0, T::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +fpa::IO::MatrixValuesContainerReader< T >:: +~MatrixValuesContainerReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< class T > +void fpa::IO::MatrixValuesContainerReader< T >:: +GenerateData( ) +{ + T* output = this->GetOutput( ); + output->Clear( ); + + std::ifstream in( this->m_FileName.c_str( ) ); + if( !in ) + { + itkExceptionMacro( + << "Error opening file to read a minimum spanning tree: \"" + << this->m_FileName + << "\"" + ); + return; + + } // fi + + unsigned int dim; + unsigned long nTuples; + in >> dim >> nTuples; + this->m_NumberOfLabels = 0; + for( unsigned long tId = 0; tId < nTuples; ++tId ) + { + unsigned long nCouples; + in >> nCouples; + typename T::TIndex v0; + for( unsigned int d = 0; d < dim; ++d ) + { + long val; + in >> val; + if( d < T::TIndex::Dimension ) + v0[ d ] = val; + + } // rof + + for( unsigned long cId = 0; cId < nCouples; ++cId ) + { + typename T::TIndex v1; + for( unsigned int d = 0; d < dim; ++d ) + { + long val; + in >> val; + if( d < T::TIndex::Dimension ) + v1[ d ] = val; + + } // rof + typename T::TValue val; + in >> val; + output->SetValue( v0, v1, val ); + if( val > this->m_NumberOfLabels ) + this->m_NumberOfLabels = val; + + } // rof + + } // rof + in.close( ); +} + +#endif // __FPA__IO__MATRIXVALUESCONTAINERREADER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/IO/MinimumSpanningTreeReader.h b/lib/fpa/IO/MinimumSpanningTreeReader.h new file mode 100644 index 0000000..40bf102 --- /dev/null +++ b/lib/fpa/IO/MinimumSpanningTreeReader.h @@ -0,0 +1,60 @@ +#ifndef __FPA__IO__MINIMUMSPANNINGTREEREADER__H__ +#define __FPA__IO__MINIMUMSPANNINGTREEREADER__H__ + +#include +#include + +namespace fpa +{ + namespace IO + { + /** + */ + template< class T > + class MinimumSpanningTreeReader + : public itk::ProcessObject + { + public: + typedef MinimumSpanningTreeReader Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef T TTree; + + public: + itkNewMacro( Self ); + itkTypeMacro( MinimumSpanningTreeReader, itkProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + T* GetOutput( ); + + virtual void Update( ); + + protected: + MinimumSpanningTreeReader( ); + virtual ~MinimumSpanningTreeReader( ); + + virtual void GenerateData( ); + + private: + // Purposely not implemented + MinimumSpanningTreeReader( const Self& other ); + Self& operator=( const Self& other ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + +} // ecapseman + +#include + +#endif // __FPA__IO__MINIMUMSPANNINGTREEREADER__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/IO/MinimumSpanningTreeReader.hxx b/lib/fpa/IO/MinimumSpanningTreeReader.hxx new file mode 100644 index 0000000..9a41db5 --- /dev/null +++ b/lib/fpa/IO/MinimumSpanningTreeReader.hxx @@ -0,0 +1,114 @@ +#ifndef __FPA__IO__MINIMUMSPANNINGTREEREADER__HXX__ +#define __FPA__IO__MINIMUMSPANNINGTREEREADER__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class T > +T* fpa::IO::MinimumSpanningTreeReader< T >:: +GetOutput( ) +{ + return( itkDynamicCastInDebugMode< T* >( this->GetPrimaryOutput( ) ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +void fpa::IO::MinimumSpanningTreeReader< T >:: +Update( ) +{ + this->GenerateData( ); +} + +// ------------------------------------------------------------------------- +template< class T > +fpa::IO::MinimumSpanningTreeReader< T >:: +MinimumSpanningTreeReader( ) + : Superclass( ), + m_FileName( "" ) +{ + this->itk::ProcessObject::SetNumberOfRequiredOutputs( 1 ); + this->itk::ProcessObject::SetNthOutput( 0, T::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +fpa::IO::MinimumSpanningTreeReader< T >:: +~MinimumSpanningTreeReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< class T > +void fpa::IO::MinimumSpanningTreeReader< T >:: +GenerateData( ) +{ + T* output = this->GetOutput( ); + output->Clear( ); + + std::ifstream in( this->m_FileName.c_str( ) ); + if( !in ) + { + itkExceptionMacro( + << "Error opening file to read a minimum spanning tree: \"" + << this->m_FileName + << "\"" + ); + return; + + } // fi + + unsigned int dim; + unsigned long nSeeds, nVertices; + in >> dim >> nSeeds; + + typedef typename T::TCollisions _TCollisions; + typedef typename _TCollisions::value_type _TCollisionsRow; + typedef typename _TCollisionsRow::value_type _TCollision; + typedef typename T::TVertex _TVertex; + + _TCollisions + collisions( nSeeds, _TCollisionsRow( nSeeds, _TCollision( _TVertex( ), false ) ) ); + for( unsigned long i = 0; i < nSeeds; ++i ) + { + for( unsigned long j = 0; j < nSeeds; ++j ) + { + int val; + in >> val; + collisions[ i ][ j ].second = ( val == 1 ); + + } // rof + + } // rof + + in >> nVertices; + for( unsigned long vId = 0; vId < nVertices; ++vId ) + { + typename T::TVertex v0, v1; + for( unsigned int d = 0; d < dim; ++d ) + { + long val; + in >> val; + if( d < T::TVertex::Dimension ) + v0[ d ] = val; + + } // rof + for( unsigned int d = 0; d < dim; ++d ) + { + long val; + in >> val; + if( d < T::TVertex::Dimension ) + v1[ d ] = val; + + } // rof + short fId; + in >> fId; + output->SetParent( v0, v1, fId ); + + } // rof + output->SetCollisions( collisions ); + in.close( ); +} + +#endif // __FPA__IO__MINIMUMSPANNINGTREEREADER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/IO/UniqueValuesContainerReader.h b/lib/fpa/IO/UniqueValuesContainerReader.h new file mode 100644 index 0000000..5dc895b --- /dev/null +++ b/lib/fpa/IO/UniqueValuesContainerReader.h @@ -0,0 +1,60 @@ +#ifndef __FPA__IO__UNIQUEVALUESCONTAINERREADER__H__ +#define __FPA__IO__UNIQUEVALUESCONTAINERREADER__H__ + +#include +#include + +namespace fpa +{ + namespace IO + { + /** + */ + template< class T > + class UniqueValuesContainerReader + : public itk::ProcessObject + { + public: + typedef UniqueValuesContainerReader Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef T TTree; + + public: + itkNewMacro( Self ); + itkTypeMacro( UniqueValuesContainerReader, itkProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + T* GetOutput( ); + + virtual void Update( ); + + protected: + UniqueValuesContainerReader( ); + virtual ~UniqueValuesContainerReader( ); + + virtual void GenerateData( ); + + private: + // Purposely not implemented + UniqueValuesContainerReader( const Self& other ); + Self& operator=( const Self& other ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + +} // ecapseman + +#include + +#endif // __FPA__IO__UNIQUEVALUESCONTAINERREADER__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/IO/UniqueValuesContainerReader.hxx b/lib/fpa/IO/UniqueValuesContainerReader.hxx new file mode 100644 index 0000000..16719f2 --- /dev/null +++ b/lib/fpa/IO/UniqueValuesContainerReader.hxx @@ -0,0 +1,82 @@ +#ifndef __FPA__IO__UNIQUEVALUESCONTAINERREADER__HXX__ +#define __FPA__IO__UNIQUEVALUESCONTAINERREADER__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class T > +T* fpa::IO::UniqueValuesContainerReader< T >:: +GetOutput( ) +{ + return( itkDynamicCastInDebugMode< T* >( this->GetPrimaryOutput( ) ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +void fpa::IO::UniqueValuesContainerReader< T >:: +Update( ) +{ + this->GenerateData( ); +} + +// ------------------------------------------------------------------------- +template< class T > +fpa::IO::UniqueValuesContainerReader< T >:: +UniqueValuesContainerReader( ) + : Superclass( ), + m_FileName( "" ) +{ + this->itk::ProcessObject::SetNumberOfRequiredOutputs( 1 ); + this->itk::ProcessObject::SetNthOutput( 0, T::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +fpa::IO::UniqueValuesContainerReader< T >:: +~UniqueValuesContainerReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< class T > +void fpa::IO::UniqueValuesContainerReader< T >:: +GenerateData( ) +{ + T* output = this->GetOutput( ); + output->Clear( ); + + std::ifstream in( this->m_FileName.c_str( ) ); + if( !in ) + { + itkExceptionMacro( + << "Error opening file to read a minimum spanning tree: \"" + << this->m_FileName + << "\"" + ); + return; + + } // fi + + unsigned int dim; + unsigned long nVertices; + in >> dim >> nVertices; + for( unsigned long vId = 0; vId < nVertices; ++vId ) + { + typename T::TValue v; + for( unsigned int d = 0; d < dim; ++d ) + { + long val; + in >> val; + if( d < T::TValue::Dimension ) + v[ d ] = val; + + } // rof + output->Insert( v ); + + } // rof + in.close( ); +} + +#endif // __FPA__IO__UNIQUEVALUESCONTAINERREADER__HXX__ + +// eof - $RCSfile$