text: /*=========================================================================
   *
   *  Copyright Insight Software Consortium
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *         http://www.apache.org/licenses/LICENSE-2.0.txt
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   *=========================================================================*/
  #ifndef __itkShapedFloodFilledFunctionConditionalConstIterator_h
  #define __itkShapedFloodFilledFunctionConditionalConstIterator_h
  
  #include <queue>
  #include <vector>
  
  #include "itkSize.h"
  #include "itkConditionalConstIterator.h"
  #include "itkConnectedComponentAlgorithm.h"
  
  namespace itk
  {
  /**
   * \class ShapedFloodFilledFunctionConditionalConstIterator
   * \brief Iterates over a flood-filled spatial function.
   *
   * Contributed as a paper to the Insight Journal:
   *  http://hdl.handle.net/1926/1320
   *
   * \ingroup ImageIterators
   *
   * \ingroup ITK-Common
   */
  template< class TImage, class TFunction >
  class ITK_EXPORT ShapedFloodFilledFunctionConditionalConstIterator:
    public ConditionalConstIterator< TImage >
  {
  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;
  
    /** Index Container Type */
    typedef typename std::vector< IndexType > SeedsContainerType;
  
    /** 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 itk::ShapedNeighborhoodIterator< ImageType > 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< IndexType > & 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_Seeds.push_back (seed);
    }
  
    /** Clear all the seeds */
    void ClearSeeds()
    {
      m_Seeds.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< ITK_TYPENAME TTempImage::PixelType >::Zero
        );
  
      for ( unsigned int i = 0; i < m_Seeds.size(); i++ )
        {
        if ( this->m_Image->GetBufferedRegion().IsInside (m_Seeds[i])
             && this->IsPixelIncluded(m_Seeds[i]) )
          {
          // Push the seed onto the queue
          m_IndexStack.push(m_Seeds[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_Seeds[i], 2);
          }
        }
    }
  
    /** Walk forward one index */
    void operator++()
    { this->DoFloodStep(); }
  
    void DoFloodStep();
  
    virtual SmartPointer< FunctionType > 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);
  
    virtual const SeedsContainerType &GetSeeds() const
    {
      return m_Seeds;
    }
  protected: //made protected so other iterators can access
    /** Smart pointer to the function we're evaluating */
    SmartPointer< FunctionType > 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< unsigned char, itkGetStaticConstMacro(NDimensions) > TTempImage;
  
    typename TTempImage::Pointer m_TempPtr;
  
    /** A list of locations to start the recursive fill */
    SeedsContainerType m_Seeds;
  
    /** 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< IndexType > 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
  