/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkOctreeNode.h,v $
  Language:  C++
  Date:      $Date: 2009-02-06 20:53:15 $
  Version:   $Revision: 1.6 $

  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 __itkOctreeNode_h
#define __itkOctreeNode_h
#include "itkMacro.h"
namespace itk {

enum LeafIdentifier { ZERO=0,ONE=1,TWO=2,THREE=3,FOUR=4,FIVE=5,SIX=6,SEVEN=7 };


//A forward-declaration
class OctreeNodeBranch;
class OctreeBase;
  
/**
 * \class OctreeNode
 * OctreeNode data structure,  OctreeNodes have two states: 1) They are a Colored node and the 
 * m_Branch is a sentinal value indicating the color, or 2) they are a branch node, and m_Branch
 * is a dynamically allocated array of 8 pointers to OctreeNodes.  In the second state, the 8 child
 * OctreeNodes are instantiated by the parent node.
 * \author Hans J. Johnson
 * This class is the basic building block of an octree.  It is rarely used by itself, and commonly
 * used by the Octree class.
 */
class ITKCommon_EXPORT OctreeNode
{
public:
  /**
   * Default constructor
   * \author Hans J. Johnson
   * \post After construction, it is assumed all children of this node are colored
   * with values of 0.
   */
  OctreeNode(void);
  /**
   * Default destructor
   * \author Hans J. Johnson
   */
  virtual ~OctreeNode(void);

  /**
   * Returns the value of the specified Child for for this OctreeNode
   * \author Hans J. Johnson
   * \param ChildID The numerical identifier of the desired child.
   * \return A pointer to the Disired child. NOTE: This is always an
   * instance of an OctreeNode.
   * @{
   */
  OctreeNode & GetChild(const enum LeafIdentifier ChildID) const;
  OctreeNode & GetChild(const enum LeafIdentifier ChildID);
  /** @} */
  /**
   * Determines the color value of the specified Child for for this OctreeNode
   * \author Hans J. Johnson
   * \param ChildID The numerical identifier of the desired child.
   * \return A value between 0 and 255 to indicate the color of the Disired child.
   * \pre Must determine that the specified node is colored (Use IsNodeColored() 
   * member function.  Behavior is undefined when the child is another Octree.
   */
  int GetColor(void) const;
  /**
   * Sets the color value of the specified Child for for this OctreeNode
   * \author Hans J. Johnson
   * \param ChildID The numerical identifier of the desired child.
   * \param NodeColor The disired color of this node.
   * \post All children of the specified child are removed, and the child is set to
   * the desired value.
   */
  void SetColor( int NodeColor);
  /**
   * Sets the color value of the specified Child for for this OctreeNode
   * \author Hans J. Johnson
   * \param ChildID The numerical identifier of the desired child.
   * \param NodeColor The disired color of this node.
   * \post All children of the specified child are removed, and the child is set to
   * the desired value.
   */
  void SetBranch(OctreeNodeBranch * NewBranch);
  /**
   * Determines if the child is a leaf node (colored), or a branch node (uncolored)
   * \author Hans J. Johnson
   * \param ChildID The numerical identifier of the desired child.
   * \return true if it is colored, false if it is not
   */
  bool IsNodeColored(void) const;
  inline void SetParentOctree(OctreeBase *parent)
    {
    m_Parent = parent;
    }
protected:
private:
  /**
   * Removes all children from this node down, and sets the value 
   * value of the children to background.
   * \author Hans J. Johnson
   */
  void RemoveChildren(void);

  /**
   * Each element holds COLOR or pointer to another octree node 
   */
  OctreeNodeBranch * m_Branch; 
  OctreeBase       * m_Parent;
};

class OctreeNodeBranch
{
public:
  OctreeNodeBranch(OctreeBase *parent)
    {
    for(int i = 0; i < 8; i++)
      {
      m_Leaves[i].SetParentOctree(parent);
      }
    }
  inline OctreeNode *GetLeaf(enum LeafIdentifier LeafID)
    {
    return &m_Leaves[LeafID];
    }
private:
  OctreeNode m_Leaves[8];
};
} //End of itk Namespace
#endif                          /* __itkOctreeNode_h */
