/*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkShapedFloodFilledFunctionConditionalConstIterator.h,v $ Language: C++ Date: $Date: 2007/02/05 13:35:52 $ Version: $Revision: 1.18 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef __itkShapedFloodFilledFunctionConditionalConstIterator_h #define __itkShapedFloodFilledFunctionConditionalConstIterator_h #include #include #include "itkIndex.h" #include "itkSize.h" #include "itkConditionalConstIterator.h" #include "itkShapedNeighborhoodIterator.h" #include "itkConnectedComponentAlgorithm.h" #include "itkImage.h" namespace itk { /** * \class ShapedFloodFilledFunctionConditionalConstIterator * \brief Iterates over a flood-filled spatial function. * * \ingroup ImageIterators * */ template class ITK_EXPORT ShapedFloodFilledFunctionConditionalConstIterator: public ConditionalConstIterator { public: /** Standard class typedefs. */ typedef ShapedFloodFilledFunctionConditionalConstIterator Self; /** Type of function */ typedef TFunction FunctionType; /** Type of vector used to store location info in the spatial function */ typedef typename TFunction::InputType FunctionInputType; /** Index typedef support. */ typedef typename TImage::IndexType IndexType; /** Offset typedef support. */ typedef typename TImage::OffsetType OffsetType; /** Size typedef support. */ typedef typename TImage::SizeType SizeType; /** Region typedef support */ typedef typename TImage::RegionType RegionType; /** Image typedef support. */ typedef TImage ImageType; /** Internal Pixel Type */ typedef typename TImage::InternalPixelType InternalPixelType; /** External Pixel Type */ typedef typename TImage::PixelType PixelType; /** Internal Neighborhood Iterator Type */ typedef typename ShapedNeighborhoodIterator NeighborhoodIteratorType; /** Dimension of the image the iterator walks. This constant is needed so * that functions that are templated over image iterator type (as opposed to * being templated over pixel type and dimension) can have compile time * access to the dimension of the image that the iterator walks. */ itkStaticConstMacro(NDimensions, unsigned int, TImage::ImageDimension); /** Constructor establishes an iterator to walk a particular image and a * particular region of that image. This version of the constructor uses * an explicit seed pixel for the flood fill, the "startIndex" */ ShapedFloodFilledFunctionConditionalConstIterator(const ImageType *imagePtr, FunctionType *fnPtr, IndexType startIndex); /** Constructor establishes an iterator to walk a particular image and a * particular region of that image. This version of the constructor uses * a list of seed pixels for the flood fill */ ShapedFloodFilledFunctionConditionalConstIterator(const ImageType *imagePtr, FunctionType *fnPtr, std::vector & startIndices); /** Constructor establishes an iterator to walk a particular image and a * particular region of that image. This version of the constructor * should be used when the seed pixel is unknown */ ShapedFloodFilledFunctionConditionalConstIterator(const ImageType *imagePtr, FunctionType *fnPtr); /** Automatically find a seed pixel and set m_StartIndex. Does nothing * if a seed pixel isn't found. A seed pixel is determined by * traversing the input image's LargestPossibleRegion and * applying the IsPixelIncluded() test.*/ void FindSeedPixel(); /** Automatically find all seed pixels. */ void FindSeedPixels(); /** Initializes the iterator, called from constructor */ void InitializeIterator(); /** Default Destructor. */ virtual ~ShapedFloodFilledFunctionConditionalConstIterator() {}; /** Compute whether the index of interest should be included in the flood */ virtual bool IsPixelIncluded(const IndexType & index) const = 0; /** operator= is provided to make sure the handle to the image is properly * reference counted. */ Self &operator=(const Self& it) { this->m_Image = it.m_Image; // copy the smart pointer this->m_Region = it.m_Region; return *this; } /** Get the dimension (size) of the index. */ static unsigned int GetIteratorDimension() {return TImage::ImageDimension;} /** Get the index. This provides a read only reference to the index. * This causes the index to be calculated from pointer arithmetic and is * therefore an expensive operation. * \sa SetIndex */ const IndexType GetIndex() { return m_IndexStack.front();} /** Get the pixel value */ const PixelType & Get(void) const { return this->m_Image->GetPixel(m_IndexStack.front() ); } /** Is the iterator at the end of the region? */ bool IsAtEnd() { return this->m_IsAtEnd; } /** Put more seeds on the list */ void AddSeed ( const IndexType seed ) { m_StartIndices.push_back ( seed ); } /** Clear all the seeds */ void ClearSeeds () { m_StartIndices.clear(); } /** Move an iterator to the beginning of the region. "Begin" is * defined as the first pixel in the region. */ void GoToBegin() { // Clear the queue while (!m_IndexStack.empty()) { m_IndexStack.pop(); } this->m_IsAtEnd = true; // Initialize the temporary image m_TempPtr->FillBuffer( NumericTraits::Zero ); for ( unsigned int i = 0; i < m_StartIndices.size(); i++ ) { if( this->m_Image->GetBufferedRegion().IsInside ( m_StartIndices[i] ) && this->IsPixelIncluded(m_StartIndices[i]) ) { // Push the seed onto the queue m_IndexStack.push(m_StartIndices[i]); // Obviously, we're at the beginning this->m_IsAtEnd = false; // Mark the start index in the temp image as inside the // function, neighbor check incomplete m_TempPtr->SetPixel(m_StartIndices[i], 2); } } } /** Walk forward one index */ void operator++() { this->DoFloodStep(); } void DoFloodStep(); virtual SmartPointer GetFunction() const { return m_Function; } /** When m_FullyConnected is set to true, the neighborhood * iterator will inspect an 8 respectively 26 neighborhood. * When the value is set to false, the neighborhood will be * 4 in 2D and 6 in 3D. */ void SetFullyConnected(const bool _arg); bool GetFullyConnected() const; itkBooleanMacro(FullyConnected); protected: //made protected so other iterators can access /** Smart pointer to the function we're evaluating */ SmartPointer m_Function; /** A temporary image used for storing info about indices * 0 = pixel has not yet been processed * 1 = pixel is not inside the function * 2 = pixel is inside the function, neighbor check incomplete * 3 = pixel is inside the function, neighbor check complete */ typedef Image TTempImage; typename TTempImage::Pointer m_TempPtr; /** A list of locations to start the recursive fill */ std::vector m_StartIndices; /** The origin of the source image */ typename ImageType::PointType m_ImageOrigin; /** The spacing of the source image */ typename ImageType::SpacingType m_ImageSpacing; /** The neighborhood iterator */ NeighborhoodIteratorType m_NeighborhoodIterator; /** Region of the source image */ RegionType m_ImageRegion; /** Stack used to hold the path of the iterator through the image */ std::queue m_IndexStack; /** Location vector used in the flood algorithm */ FunctionInputType m_LocationVector; /** Indicates whether or not we've found a neighbor that needs to be * checked. */ bool m_FoundUncheckedNeighbor; /** Indicates whether or not an index is valid (inside an image)/ */ bool m_IsValidIndex; /** Defines the connectivity of the neighborhood iterator. * In case of 2D the default connectivity is 4 (6 in 3D) and * when m_FullyConnected is set to true the connectivity is * 8 (26 in 3D). */ bool m_FullyConnected; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkShapedFloodFilledFunctionConditionalConstIterator.txx" #endif #endif