You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
512 lines
17 KiB
C++
512 lines
17 KiB
C++
/*=========================================================================
|
|
|
|
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 A data object structured as a tree.
|
|
*
|
|
* An hypertree grid is a dataobject containing a rectilinear grid of
|
|
* elements that can be either null or a hypertree.
|
|
* An hypertree is a dataobject describing a decomposition tree.
|
|
* A VERTICE is an element of this tree.
|
|
* A NODE, also called COARSE cell, is a specific vertice which is
|
|
* refined and than has either exactly f^d children, where f in {2,3}
|
|
* is the branching factor, the same value for all trees in this
|
|
* hypertree grid, and d in {1,2,3} is the spatial dimension. It is
|
|
* called coarse because there are smaller child cells.
|
|
* A LEAF, also called FINE cell, is a vertice without children, not
|
|
* refined. It is called fine because in the same space there are no
|
|
* finer cells.
|
|
* In a tree, we can find coarse cells smaller than fine cell but not
|
|
* in the same space.
|
|
*
|
|
* Such trees have particular names for f=2:
|
|
* - bintree (d=1),
|
|
* - quadtree (d=2),
|
|
* - octree (d=3).
|
|
*
|
|
* 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
|
|
*
|
|
* Attributes are associated with (all) cells, not with points. The
|
|
* attributes that are associated with coarses, it's used for LoD
|
|
* (Level-of-Detail). The attributes on coarse cells can be given by the
|
|
* code or/and computed by the use of a specifc filter exploiting the
|
|
* values from its children (which can be leaves or not).
|
|
*
|
|
* The geometry is implicitly given by the size of the root node on each
|
|
* axis and position of the origin. In fact, in 3D, the geometry is then
|
|
* not limited to a cube but can have a rectangular shape.
|
|
*
|
|
* By construction, an hypertree is efficient in memory usage. The LoD
|
|
* feature allows for quick culling of part of the dataobject.
|
|
*
|
|
* This is an abstract class used as a superclass by a custom templated
|
|
* compact class. Other versions of this code could be made available
|
|
* to meet other needs without questioning cursors and filters.
|
|
* All methods are pure virtual. This is done to hide templates.
|
|
*
|
|
* @par Case octree with f=2, d=3:
|
|
* For each node (coarse cell), 8 children are encoded in a child index
|
|
* (from 0 to 7) in the following orientation described in hypertree grid.
|
|
* It is easy to access each child as a cell of a grid.
|
|
* Note also that the binary representation is relevant, each bit codes
|
|
* 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 (1)
|
|
* -z side is first, in counter-clockwise order:
|
|
* 0: -y -x sides
|
|
* 1: -y +x sides
|
|
* 2: +y -x sides
|
|
* 3: +y +x sides
|
|
* +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
|
|
* +-+-+ ^
|
|
* |2|3| |
|
|
* +-+-+ O +z +-> +x
|
|
* |0|1|
|
|
* +-+-+
|
|
* +y
|
|
* +-+-+ ^
|
|
* |6|7| |
|
|
* +-+-+ 1 +z +-> +x
|
|
* |4|5|
|
|
* +-+-+
|
|
* \endverbatim
|
|
*
|
|
* @par Case quadtree with f=2, d=2:
|
|
* Just use 2 bits.
|
|
* \verbatim
|
|
* +y
|
|
* +-+-+ ^
|
|
* |2|3| |
|
|
* +-+-+ +-> +x
|
|
* |0|1|
|
|
* +-+-+
|
|
* \endverbatim
|
|
*
|
|
* @par Case bintree with f=2, d=1:
|
|
* Just use 1 bits.
|
|
* \verbatim
|
|
* O+-> +x
|
|
* \endverbatim
|
|
*
|
|
* It's more difficult with f=3.
|
|
*
|
|
* @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
|
|
* Among others, this class was simplified, optimized (memory), documented and
|
|
* completed for to improve IO XML by Jacques-Bernard Lekien 2018-19
|
|
* This work was supported by Commissariat a l'Energie Atomique
|
|
* CEA, DAM, DIF, F-91297 Arpajon, France.
|
|
*/
|
|
|
|
#ifndef vtkHyperTree_h
|
|
#define vtkHyperTree_h
|
|
|
|
#include "vtkCommonDataModelModule.h" // For export macro
|
|
#include "vtkObject.h"
|
|
|
|
#include <cassert> // Used internally
|
|
#include <memory> // std::shared_ptr
|
|
|
|
class vtkBitArray;
|
|
class vtkUnsignedLongArray;
|
|
|
|
class vtkIdList;
|
|
|
|
class vtkHyperTreeGridScales;
|
|
|
|
//=============================================================================
|
|
struct vtkHyperTreeData
|
|
{
|
|
// Index of this tree in the hypertree grid
|
|
vtkIdType TreeIndex;
|
|
|
|
// Number of levels in the tree
|
|
unsigned int NumberOfLevels;
|
|
|
|
// Number of vertices in this tree (coarse and leaves)
|
|
vtkIdType NumberOfVertices;
|
|
|
|
// Number of nodes (non-leaf vertices) in the tree
|
|
vtkIdType NumberOfNodes;
|
|
|
|
// Offset start for the implicit global index mapping fixed by
|
|
// SetGlobalIndexStart after create a tree.
|
|
// If you don't choose implicit global index mapping then this
|
|
// value is -1. Then, you must to describ explicit global index
|
|
// mapping by using then SetGlobalIndexFromLocal for each cell
|
|
// in tree.
|
|
// The extra cost is equivalent to the cost of a field of values
|
|
// of cells.
|
|
vtkIdType GlobalIndexStart;
|
|
};
|
|
|
|
//=============================================================================
|
|
class VTKCOMMONDATAMODEL_EXPORT vtkHyperTree : public vtkObject
|
|
{
|
|
public:
|
|
vtkTypeMacro(vtkHyperTree, vtkObject);
|
|
|
|
void PrintSelf(ostream&, vtkIndent) override;
|
|
|
|
/**
|
|
* Restore the initial state: only one vertice is then a leaf:
|
|
* the root cell for the hypertree.
|
|
* @param branchFactor
|
|
* @param dimension
|
|
* @param numberOfChildren
|
|
*/
|
|
void Initialize(unsigned char, unsigned char, unsigned char);
|
|
|
|
/**
|
|
* Restore a state from read data, without using a cursor
|
|
* Call after create hypertree with initialize.
|
|
*
|
|
* @param numberOfLevels: the maximum number of levels.
|
|
* @param nbVertices: the number of vertices of the future tree
|
|
* (coarse and leaves), fixed either the information loading
|
|
* (for load reduction) or defined by the fixed level of reader.
|
|
* @param nbVerticesOfLastLevel: the number of vertices of last
|
|
* valid level.
|
|
* @param isParent: a binary decomposition tree by level with
|
|
* constraint all describe children. It is useless to declare
|
|
* all the lastest values to False, especially the last level
|
|
* may not be defined.
|
|
* @param isMasked: a binary mask corresponding. It is useless
|
|
* to declare all the latest values to False.
|
|
* @param outIsMasked: the mask of hypertree grid including
|
|
* this hypertree which is a vtkBitArray.
|
|
*/
|
|
virtual void InitializeForReader(vtkIdType numberOfLevels, vtkIdType nbVertices,
|
|
vtkIdType nbVerticesOfLastLevel, vtkBitArray* isParent, vtkBitArray* isMasked,
|
|
vtkBitArray* outIsMasked) = 0;
|
|
|
|
/**
|
|
* Initialize a state from write data.
|
|
* Call after create the hypertree grid.
|
|
*
|
|
* @param inIsMasked: the mask of hypertree grid including
|
|
* this hypertree which is a vtkBitArray.
|
|
* @param nbVerticesbyLevel: the number of vertices in tree
|
|
* (coarse and leaves) by each level.
|
|
* @param isParent: modify the vtkBitArray, a binary decomposition
|
|
* tree by level with constraint all describe children. It is
|
|
* useless to declare all the lastest values to False, especially
|
|
* the last level may not be defined.
|
|
* @param isMasked: modify the vtkBitArray, a binary mask
|
|
* corresponding. It is useless to declare all the latest values
|
|
* to False.
|
|
*/
|
|
virtual void GetByLevelForWriter(vtkBitArray* inIsMasked, vtkUnsignedLongArray* nbVerticesbyLevel,
|
|
vtkBitArray* isParent, vtkBitArray* isMasked, vtkIdList* ids) = 0;
|
|
|
|
/**
|
|
* Copy the structure by sharing the decomposition description
|
|
* of the tree.
|
|
* \pre ht_exist: ht!=nullptr
|
|
*/
|
|
void CopyStructure(vtkHyperTree* ht);
|
|
|
|
/**
|
|
* Return a freeze instance (a priori compact but potentially
|
|
* unmodifiable).
|
|
* This method is calling by the Squeeze method of hypertree grid.
|
|
* The mode parameter will allow to propose different instances.
|
|
* Today, there is none, the freeze call does not do anything.
|
|
*/
|
|
virtual vtkHyperTree* Freeze(const char* mode) = 0;
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get tree index in hypertree grid.
|
|
* Services for internal use between hypertree grid and hypertree.
|
|
*/
|
|
void SetTreeIndex(vtkIdType treeIndex) { this->Datas->TreeIndex = treeIndex; }
|
|
vtkIdType GetTreeIndex() const { return this->Datas->TreeIndex; }
|
|
//@}
|
|
|
|
/**
|
|
* Return the number of levels.
|
|
*/
|
|
unsigned int GetNumberOfLevels() const
|
|
{
|
|
assert("post: result_greater_or_equal_to_one" && this->Datas->NumberOfLevels >= 1);
|
|
return this->Datas->NumberOfLevels;
|
|
}
|
|
|
|
/**
|
|
* Return the number of all vertices (coarse and fine) in the tree.
|
|
*/
|
|
vtkIdType GetNumberOfVertices() const { return this->Datas->NumberOfVertices; }
|
|
|
|
/**
|
|
* Return the number of nodes (coarse) in the tree.
|
|
*/
|
|
vtkIdType GetNumberOfNodes() const { return this->Datas->NumberOfNodes; }
|
|
|
|
/**
|
|
* Return the number of leaf (fine) in the tree.
|
|
*/
|
|
vtkIdType GetNumberOfLeaves() const
|
|
{
|
|
return this->Datas->NumberOfVertices - this->Datas->NumberOfNodes;
|
|
}
|
|
|
|
/**
|
|
* Return the branch factor of the tree.
|
|
*/
|
|
int GetBranchFactor() const { return this->BranchFactor; }
|
|
|
|
/**
|
|
* Return the spatial dimension of the tree.
|
|
*/
|
|
int GetDimension() const { return this->Dimension; }
|
|
|
|
/**
|
|
* Return the number of children per node of the tree.
|
|
* This value is branchfactoring scale spatial dimenion (f^d).
|
|
*/
|
|
vtkIdType GetNumberOfChildren() const { return this->NumberOfChildren; }
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get scale of the tree in each direction for the ground
|
|
* level (0).
|
|
*/
|
|
void GetScale(double s[3]) const;
|
|
|
|
double GetScale(unsigned int d) const;
|
|
//@}
|
|
|
|
/**
|
|
* In an hypertree, all cells are the same size by level. This
|
|
* fonction initialize this cache system is particular used by
|
|
* the symetric filter.
|
|
*/
|
|
std::shared_ptr<vtkHyperTreeGridScales> InitializeScales(
|
|
const double* scales, bool reinitialize = false) const;
|
|
|
|
/**
|
|
* Return an instance of an implementation of a hypertree for
|
|
* given branch factor and dimension.
|
|
* Other versions of this code could be made available to meet
|
|
* other needs without questioning cursors and filters.
|
|
* Since an instance, an other instance can be creating by call
|
|
* the method Freeze (by default, nothing more, instance currently
|
|
* is returning).
|
|
*/
|
|
VTK_NEWINSTANCE
|
|
static vtkHyperTree* CreateInstance(unsigned char branchFactor, unsigned char dimension);
|
|
/**
|
|
* Return memory used in bytes.
|
|
* NB: Ignore the attribute array because its size is added by the data set.
|
|
*/
|
|
virtual unsigned long GetActualMemorySizeBytes() = 0;
|
|
|
|
/**
|
|
* Return memory used in kibibytes (1024 bytes).
|
|
* NB: Ignore the attribute array because its size is added by the data set.
|
|
*/
|
|
unsigned int GetActualMemorySize()
|
|
{
|
|
// in kilibytes
|
|
return static_cast<unsigned int>(this->GetActualMemorySizeBytes() / 1024);
|
|
}
|
|
|
|
/**
|
|
* Return if implicit global index maping has been used.
|
|
* If true, the initialize has been done by SetGlobalIndexStart (one call
|
|
* by hypertree).
|
|
* If false, the initialize has been done by SetGlobalIndexFromLocal (one
|
|
* call by cell of hypertree).
|
|
* GetGlobalIndexFromLocel get the good value of global index mapping for
|
|
* one cell what ever the initialize metho used.
|
|
*/
|
|
virtual bool IsGlobalIndexImplicit() = 0;
|
|
|
|
/**
|
|
* Set the start implicit global index mapping for the first cell in the
|
|
* current tree.
|
|
* The implicit global index mapping of a node will be computed by
|
|
* this start index + the node index (local offset in tree).
|
|
* The node index begin by 0, the origin cell in tree. The follow values
|
|
* are organizing by fatrie as i to i+NumberOfChildren, for all children
|
|
* of one coarse cell, i is 1+8*s with s in integer. The order of fatrie
|
|
* depend of order to call SubdivideLeaf.
|
|
* This global index mapping permits to access a value of
|
|
* field for a cell, in implicit, the order values depends of implicit
|
|
* order linking with the order build of this tree.
|
|
* WARNING: See of hypertree grid, for to use a implicit global index
|
|
* mapping, you have to build hypertree by hypertree without to recome
|
|
* in hypertree also build.
|
|
* For this tree, in debug, assert is calling if tried call
|
|
* SetGlobalIndexFromLocal.
|
|
* \pre not_global_index_start_if_use_global_index_from_local
|
|
*/
|
|
virtual void SetGlobalIndexStart(vtkIdType start) = 0;
|
|
|
|
/**
|
|
* Get the start global index for the current tree for implicit global
|
|
* index mapping.
|
|
*/
|
|
vtkIdType GetGlobalIndexStart() const { return this->Datas->GlobalIndexStart; }
|
|
|
|
/**
|
|
* Set the mapping between a node index in tree and a explicit global
|
|
* index mapping.
|
|
* This global index mapping permits to access a value of
|
|
* field for a cell, in explicit, the index depend of order values.
|
|
* For this tree, in debug, assert is calling if tried call
|
|
* SetGlobalIndexStart.
|
|
* \pre not_global_index_from_local_if_use_global_index_start
|
|
*/
|
|
virtual void SetGlobalIndexFromLocal(vtkIdType index, vtkIdType global) = 0;
|
|
|
|
/**
|
|
* Get the global id of a local node identified by index.
|
|
* Use the explicit mapping function if available or the implicit
|
|
* mapping build with start global index.
|
|
* \pre not_valid_index
|
|
* \pre not_positive_start_index (case implicit global index mapping)
|
|
* \pre not_positive_global_index (case explicit global index mapping)
|
|
*/
|
|
virtual vtkIdType GetGlobalIndexFromLocal(vtkIdType index) const = 0;
|
|
|
|
/**
|
|
* Return the maximum value reached by global index mapping
|
|
* (implicit or explicit).
|
|
*/
|
|
virtual vtkIdType GetGlobalNodeIndexMax() const = 0;
|
|
|
|
/**
|
|
* Return if a vertice identified by index in tree as being leaf.
|
|
* \pre not_valid_index
|
|
*/
|
|
virtual bool IsLeaf(vtkIdType index) const = 0;
|
|
|
|
/**
|
|
* Subdivide a vertice, only if its a leaf.
|
|
* \pre not_valide_index
|
|
* \pre not_leaf
|
|
*/
|
|
virtual void SubdivideLeaf(vtkIdType index, unsigned int level) = 0;
|
|
|
|
/**
|
|
* Return if a vertice identified by index in tree as a terminal node.
|
|
* For this, all childrens mus be all leaves.
|
|
* \pre not_valid_index
|
|
* \pre not_valid_child_index
|
|
*/
|
|
virtual bool IsTerminalNode(vtkIdType index) const = 0;
|
|
|
|
/**
|
|
* Return the elder child index, local index node of first child, of
|
|
* node, coarse cell, identified by index_parent.
|
|
* \pre not_valid_index_parent
|
|
* Public only for entry: vtkHyperTreeGridEntry,
|
|
* vtkHyperTreeGridGeometryEntry, vtkHyperTreeGridGeometryLevelEntry
|
|
*/
|
|
virtual vtkIdType GetElderChildIndex(unsigned int index_parent) const = 0;
|
|
|
|
//@{
|
|
/**
|
|
* In an hypertree, all cells are the same size by level. This
|
|
* fonction initializes this cache system is particulary used by
|
|
* the symetric filter.
|
|
* Here, you set a scales since extern description (sharing).
|
|
*/
|
|
void SetScales(std::shared_ptr<vtkHyperTreeGridScales> scales) const { this->Scales = scales; }
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Return the existence scales.
|
|
*/
|
|
bool HasScales() const { return (this->Scales != nullptr); }
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Return all scales.
|
|
*/
|
|
std::shared_ptr<vtkHyperTreeGridScales> GetScales() const
|
|
{
|
|
assert(this->Scales != nullptr);
|
|
return this->Scales;
|
|
}
|
|
//@}
|
|
|
|
protected:
|
|
vtkHyperTree()
|
|
: BranchFactor(2)
|
|
, Dimension(3)
|
|
, NumberOfChildren(8)
|
|
{
|
|
}
|
|
|
|
virtual ~vtkHyperTree() override {}
|
|
|
|
virtual void InitializePrivate() = 0;
|
|
virtual void PrintSelfPrivate(ostream& os, vtkIndent indent) = 0;
|
|
virtual void CopyStructurePrivate(vtkHyperTree* ht) = 0;
|
|
|
|
//-- Global information
|
|
|
|
// Branching factor of tree (2 or 3)
|
|
unsigned char BranchFactor;
|
|
|
|
// Dimension of tree (1, 2, or 3)
|
|
unsigned char Dimension;
|
|
|
|
// Number of children for coarse cell
|
|
unsigned char NumberOfChildren;
|
|
|
|
//-- Local information
|
|
std::shared_ptr<vtkHyperTreeData> Datas;
|
|
|
|
// Storage of pre-computed per-level cell scales
|
|
// In hypertree grid, one description by hypertree.
|
|
// In Uniform hypertree grid, one description by hypertree grid
|
|
// (all cells, differents hypertree, are identicals by level).
|
|
mutable std::shared_ptr<vtkHyperTreeGridScales> Scales;
|
|
|
|
private:
|
|
vtkHyperTree(const vtkHyperTree&) = delete;
|
|
void operator=(const vtkHyperTree&) = delete;
|
|
};
|
|
|
|
#endif
|