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

  Program:   Visualization Toolkit
  Module:    vtkHyperTree.h

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/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 notice for more information.

=========================================================================*/
/**
 * @class   vtkHyperTree
 * @brief   An object structured as a tree where each node has
 * exactly either 2^d or 3^d children.
 *
 *
 * An hypertree is a dataset where each node has either exactly f^d
 * children or no child at all if the node is a leaf, where f in {2,3}
 * is the branching factor of the tree and d in {1,2,3} is the
 * dimension of the dataset.
 * Such trees have particular names when f=2: bintree (d=1), quadtree
 * (d=2), and octree (d=2). When f=3, we respectively call them
 * 3-tree, 9-tree, and 27-tree.
 *
 * The original octree class name came from the following paper:
 * \verbatim
 * @ARTICLE{yau-srihari-1983,
 *  author={Mann-May Yau and Sargur N. Srihari},
 *  title={A Hierarchical Data Structure for Multidimensional Digital Images},
 *  journal={Communications of the ACM},
 *  month={July},
 *  year={1983},
 *  volume={26},
 *  number={7},
 *  pages={504--515}
 *  }
 * \endverbatim
 *
 * Each node is a cell. Attributes are associated with cells, not with points.
 * The geometry is implicitly given by the size of the root node on each axis
 * and position of the center and the orientation. (TODO: review center
 * position and orientation). The geometry is then not limited to an hybercube
 * but can have a rectangular shape.
 * Attributes are associated with leaves. For LOD (Level-Of-Detail) purpose,
 * attributes can be computed on none-leaf nodes by computing the average
 * values from its children (which can be leaves or not).
 *
 * By construction, an hypertree is efficient in memory usage when the
 * geometry is sparse. The LOD feature allows for quick culling of part of the
 * dataset.
 *
 * This is an abstract class used as a superclass by a templated compact class.
 * All methods are pure virtual. This is done to hide templates.
 *
 * @par Case with f=2:
 * * d=3 case (octree)
 * for each node, each child index (from 0 to 7) is encoded in the
 * following orientation.
 * It is easy to access each child as a cell of a grid.
 * Note also that the binary representation is relevant, each bit code
 * a side:
 * bit 0 encodes -x side (0) or +x side (1)
 * bit 1 encodes -y side (0) or +y side (1)
 * bit 2 encodes -z side (0) or +z side (2)
 * -z side is first, in counter-clockwise order:
 *  0: -y -x sides
 *  1: -y +x sides
 *  2: +y -x sides
 *  3: +y +x sides
 * \verbatim
 *              +y
 * +-+-+        ^
 * |2|3|        |
 * +-+-+  O +z  +-> +x
 * |0|1|
 * +-+-+
 * \endverbatim
 *
 * @par Case with f=2:
 * +z side is last, in counter-clockwise order:
 *  4: -y -x sides
 *  5: -y +x sides
 *  6: +y -x sides
 *  7: +y +x sides
 * \verbatim
 *              +y
 * +-+-+        ^
 * |6|7|        |
 * +-+-+  O +z  +-> +x
 * |4|5|
 * +-+-+
 * \endverbatim
 *
 * @par Case with f=2:
 * The cases with fewer dimensions are consistent with the octree case:
 *
 * @par Case with f=2:
 * * d=2 case (quadtree):
 * in counter-clockwise order:
 *  0: -y -x edges
 *  1: -y +x edges
 *  2: +y -x edges
 *  3: +y +x edges
 * \verbatim
 *         +y
 * +-+-+   ^
 * |2|3|   |
 * +-+-+  O+-> +x
 * |0|1|
 * +-+-+
 * \endverbatim
 *
 * @par Case with f=2:
 * * d=1 case (bintree):
 * \verbatim
 * +0+1+  O+-> +x
 * \endverbatim
 *
 * @warning
 * It is not a spatial search object. If you are looking for this kind of
 * octree see vtkCellLocator instead.
 *
 * @par Thanks:
 * This class was written by Philippe Pebay, Joachim Pouderoux, and Charles Law, Kitware 2013
 * This class was modified by Guenole Harel and  Jacques-Bernard Lekien 2014
 * This class was modified by Philippe Pebay, 2016
 * This work was supported by Commissariat a l'Energie Atomique (CEA/DIF)
*/

#ifndef vtkHyperTree_h
#define vtkHyperTree_h

#include "vtkCommonDataModelModule.h" // For export macro
#include "vtkObject.h"

class vtkHyperTreeCursor;

class VTKCOMMONDATAMODEL_EXPORT vtkHyperTree : public vtkObject
{
public:
  vtkTypeMacro(vtkHyperTree, vtkObject);
  void PrintSelf( ostream&, vtkIndent ) override;

  /**
   * Restore the initial state: only one node and one leaf: the root.
   */
  virtual void Initialize() = 0;

  /**
   * Return the number of levels.
   */
  virtual vtkIdType GetNumberOfLevels() = 0;

  /**
   * Return the number of vertices in the tree.
   */
  virtual vtkIdType GetNumberOfVertices() = 0;

  /**
   * Return the number of nodes (non-leaf vertices) in the tree.
   */
  virtual vtkIdType GetNumberOfNodes() = 0;

  /**
   * Return the number of leaf vertices in the tree.
   */
  virtual vtkIdType GetNumberOfLeaves() = 0;

  /**
   * Return the branch factor of the tree.
   */
  virtual int GetBranchFactor() = 0;

  /**
   * Return the dimension of the tree.
   */
  virtual int GetDimension() = 0;

  /**
   * Return the number of children per node of the tree.
   */
  virtual vtkIdType GetNumberOfChildren() = 0;

  //@{
  /**
   * Set/Get scale of the tree in each direction.
   */
  virtual void SetScale( double[3] ) = 0;
  virtual void GetScale( double[3] ) = 0;
  virtual double GetScale( unsigned int ) = 0;
  //@}

  /**
   * Return an instance of a templated hypertree for given branch
   * factor and dimension.
   * This is done to hide templates.
   */
  VTK_NEWINSTANCE
  static vtkHyperTree* CreateInstance( unsigned int branchFactor,
                                       unsigned int dimension );

  /**
   * Find the Index of the parent of a vertex in the hypertree.
   * This is done to hide templates.
   */
  virtual void FindParentIndex( vtkIdType& );

  /**
   * Find the Index, Parent Index and IsLeaf() parameters of the child
   * of a node in the hypertree.
   * This is done to hide templates.
   */
  virtual void FindChildParameters( int, vtkIdType&, bool& );

  /**
   * Return pointer to new instance of hyper tree cursor
   */
  virtual vtkHyperTreeCursor* NewCursor() = 0;

  /**
   * Subdivide node pointed by cursor, only if its a leaf.
   * At the end, cursor points on the node that used to be leaf.
   * \pre leaf_exists: leaf!=0
   * \pre is_a_leaf: leaf->CurrentIsLeaf()
   */
  virtual void SubdivideLeaf( vtkHyperTreeCursor* leaf ) = 0;

  /**
   * Return memory used in kibibytes (1024 bytes).
   * NB: Ignore the attribute array because its size is added by the data set.
   */
  virtual unsigned int GetActualMemorySize() = 0;

  /**
   * Set the start global index for the current tree.
   * The global index of a node will be this index + the node index.
   */
  virtual void SetGlobalIndexStart( vtkIdType ) = 0;

  /**
   * Set the mapping between local & global Ids used by HyperTreeGrids.
   */
  virtual void SetGlobalIndexFromLocal( vtkIdType local, vtkIdType global ) = 0;

  /**
   * Get the global id of a local node.
   * Use the mapping function if available or the start global index.
   */
  virtual vtkIdType GetGlobalIndexFromLocal( vtkIdType local ) = 0;

protected:
  vtkHyperTree()
  {
  }

private:
  vtkHyperTree(const vtkHyperTree&) = delete;
  void operator=(const vtkHyperTree&) = delete;
};

#endif
