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.
989 lines
29 KiB
C++
989 lines
29 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkHyperTreeGrid.cxx
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
#include "vtkHyperTree.h"
|
|
|
|
#include "vtkHyperTreeCursor.h"
|
|
#include "vtkObjectFactory.h"
|
|
|
|
#include <deque>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
#include <cassert>
|
|
|
|
// Description:
|
|
// The template value N describes the number of children to binary and
|
|
// ternary trees.
|
|
template<int N> class vtkCompactHyperTree;
|
|
template<int N> class vtkCompactHyperTreeNode;
|
|
|
|
template<int N> class vtkCompactHyperTreeCursor : public vtkHyperTreeCursor
|
|
{
|
|
public:
|
|
//---------------------------------------------------------------------------
|
|
vtkTypeMacro(vtkCompactHyperTreeCursor<N>, vtkHyperTreeCursor);
|
|
|
|
static vtkCompactHyperTreeCursor<N>* New()
|
|
{
|
|
vtkCompactHyperTreeCursor<N> *ret = new vtkCompactHyperTreeCursor<N>;
|
|
ret->InitializeObjectBase();
|
|
return ret;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Initialization
|
|
virtual void SetTree( vtkCompactHyperTree<N>* tree )
|
|
{
|
|
this->Tree = tree;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Initialization
|
|
vtkHyperTree* GetTree() VTK_OVERRIDE
|
|
{
|
|
return this->Tree;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkIdType GetLeafId() VTK_OVERRIDE
|
|
{
|
|
assert( "pre: is_leaf" && IsLeaf() );
|
|
return this->Index;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkIdType GetNodeId() VTK_OVERRIDE
|
|
{
|
|
return this->Index;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
bool IsLeaf() VTK_OVERRIDE
|
|
{
|
|
return this->Leaf;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
bool IsTerminalNode() VTK_OVERRIDE
|
|
{
|
|
bool result = ! this->Leaf;
|
|
if( result )
|
|
{
|
|
vtkCompactHyperTreeNode<N>* node = this->Tree->GetNode( this->Index );
|
|
result = node->IsTerminalNode();
|
|
}
|
|
// A=>B: notA or B
|
|
assert( "post: compatible" && ( ! result || ! this->Leaf) );
|
|
return result;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
bool IsRoot() VTK_OVERRIDE
|
|
{
|
|
return ( ! this->Leaf && this->Index == 0 )
|
|
|| ( this->Leaf && ! this->Index && this->Tree->GetLeafParentSize() == 1 );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int GetCurrentLevel() VTK_OVERRIDE
|
|
{
|
|
int result = this->GetChildHistorySize();
|
|
assert( "post: positive_result" && result >= 0 );
|
|
return result;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return the child number of the current node relative to its parent.
|
|
// \pre not_root: !IsRoot().
|
|
// \post valid_range: result >= 0 && result<GetNumberOfChildren()
|
|
int GetChildIndex() VTK_OVERRIDE
|
|
{
|
|
assert( "post: valid_range" && this->ChildIndex >= 0 &&
|
|
this->ChildIndex < GetNumberOfChildren() );
|
|
return this->ChildIndex;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Cursor movement.
|
|
// \pre can be root
|
|
// \post is_root: IsRoot()
|
|
void ToRoot() VTK_OVERRIDE
|
|
{
|
|
this->ChildHistory.clear();
|
|
this->Leaf = ( this->Tree->GetLeafParentSize() == 1 );
|
|
this->Index = this->Leaf ? 0 : 1;
|
|
this->ChildIndex = 0;
|
|
memset( this->Indices, 0, 3 * sizeof(int) );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// \pre not_root: !IsRoot()
|
|
void ToParent() VTK_OVERRIDE
|
|
{
|
|
assert( "pre: not_root" && !IsRoot() );
|
|
this->Index = this->Leaf ?
|
|
this->Tree->GetLeafParent( this->Index ) :
|
|
this->Tree->GetNode( this->Index )->GetParent();
|
|
|
|
this->Leaf = false;
|
|
this->ChildIndex = this->ChildHistory.back(); // top()
|
|
this->ChildHistory.pop_back();
|
|
|
|
for ( unsigned int i = 0; i < this->Dimension; ++ i )
|
|
{
|
|
this->Indices[i] = this->Indices[i] / this->Tree->GetBranchFactor();
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// \pre not_leaf: !IsLeaf()
|
|
// \pre valid_child: child >= 0 && child<this->GetNumberOfChildren()
|
|
void ToChild( int child ) VTK_OVERRIDE
|
|
{
|
|
assert( "pre: not_leaf" && !IsLeaf() );
|
|
assert( "pre: valid_child" && child >= 0
|
|
&& child < this->GetNumberOfChildren() );
|
|
|
|
vtkCompactHyperTreeNode<N>* node = this->Tree->GetNode( this->Index );
|
|
this->ChildHistory.push_back( this->ChildIndex );
|
|
this->ChildIndex = child;
|
|
this->Index = node->GetChild( child );
|
|
this->Leaf = node->IsChildLeaf( child );
|
|
|
|
int tmpChild = child;
|
|
int branchFactor = this->Tree->GetBranchFactor();
|
|
for ( unsigned int i = 0; i < this->Dimension; ++ i )
|
|
{
|
|
// Effectively convert child to base 2/3 (branch factor)
|
|
int tmp = tmpChild;
|
|
tmpChild /= branchFactor;
|
|
int index = tmp - ( branchFactor * tmpChild ); // Remainder (mod)
|
|
assert( "check: mod 3 value" && index >= 0 && index<branchFactor);
|
|
this->Indices[i] = ( this->Indices[i] * branchFactor ) + index;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Move the cursor to the same node pointed by `other'.
|
|
// \pre other_exists: other != 0
|
|
// \pre same_hyperTree: this->SameTree( other )
|
|
// \post equal: this->IsEqual( other )
|
|
void ToSameNode( vtkHyperTreeCursor* other ) VTK_OVERRIDE
|
|
{
|
|
assert( "pre: other_exists" && other != 0 );
|
|
assert( "pre: same_hyperTree" && this->SameTree( other ) );
|
|
|
|
vtkCompactHyperTreeCursor<N> *o =
|
|
static_cast<vtkCompactHyperTreeCursor<N> *>( other );
|
|
|
|
this->Index = o->Index;
|
|
this->ChildIndex = o->ChildIndex;
|
|
this->Leaf = o->Leaf;
|
|
this->ChildHistory = o->ChildHistory; // use assignment operator
|
|
memcpy( this->Indices, o->Indices, 3 * sizeof(int) );
|
|
|
|
assert( "post: equal" && this->IsEqual(other) );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Description:
|
|
// Is `this' equal to `other'?
|
|
// \pre other_exists: other != 0
|
|
// \pre same_hyperTree: this->SameTree(other);
|
|
bool IsEqual( vtkHyperTreeCursor* other ) VTK_OVERRIDE
|
|
{
|
|
assert( "pre: other_exists" && other != 0 );
|
|
assert( "pre: same_hyperTree" && this->SameTree(other) );
|
|
|
|
vtkCompactHyperTreeCursor<N>* o =
|
|
static_cast<vtkCompactHyperTreeCursor<N> *>( other );
|
|
|
|
bool result = this->Index == o->Index
|
|
&& this->ChildIndex == o->ChildIndex
|
|
&& this->Leaf == o->Leaf
|
|
&& this->ChildHistory == o->ChildHistory;
|
|
|
|
for ( unsigned int i = 0; result && i < this->Dimension; ++ i )
|
|
{
|
|
result = ( this->Indices[i] == o->Indices[i] );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
vtkHyperTreeCursor* Clone() VTK_OVERRIDE
|
|
{
|
|
vtkCompactHyperTreeCursor<N>* result = this->NewInstance();
|
|
assert( "post: results_exists" && result != 0 );
|
|
result->Tree = this->Tree;
|
|
assert( "post: same_tree" && result->SameTree( this ) );
|
|
return result;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int SameTree( vtkHyperTreeCursor* other ) VTK_OVERRIDE
|
|
{
|
|
assert( "pre: other_exists" && other != 0 );
|
|
vtkCompactHyperTreeCursor<N> *o =
|
|
vtkCompactHyperTreeCursor<N>::SafeDownCast( other );
|
|
return o != 0 && this->Tree == o->Tree;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return the index in dimension `d', as if the node was a cell of a
|
|
// uniform grid of 1<<GetCurrentLevel() cells in each dimension.
|
|
// \pre valid_range: d >= 0 && d<GetDimension()
|
|
// \post valid_result: result >= 0 && result<(1<<GetCurrentLevel() )
|
|
int GetIndex(int d) VTK_OVERRIDE
|
|
{
|
|
assert( "pre: valid_range" && d >= 0 && d < this->Dimension );
|
|
return this->Indices[d];
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return the number of children for each node of the tree.
|
|
// \post positive_number: result>0
|
|
int GetNumberOfChildren() VTK_OVERRIDE
|
|
{
|
|
return N;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return the dimension of the tree.
|
|
// \post positive_result: result >= 0
|
|
int GetDimension() VTK_OVERRIDE
|
|
{
|
|
assert( "post: positive_result " && this->Dimension > 0 );
|
|
assert( "post: up_to_3 " && this->Dimension <= 3 ); // and then
|
|
return this->Dimension;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Move to the node described by its indices in each dimension and
|
|
// at a given level. If there is actually a node or a leaf at this
|
|
// location, Found() returns true. Otherwise, Found() returns false and the
|
|
// cursor moves to the closest parent of the query. It can be the root in the
|
|
// worst case.
|
|
// \pre indices_exists: indices != 0
|
|
// \pre valid_size: sizeof(indices)==GetDimension()
|
|
// \pre valid_level: level >= 0
|
|
void MoveToNode(int* indices,
|
|
int level) VTK_OVERRIDE
|
|
{
|
|
assert( "pre: indices_exists" && indices != 0 );
|
|
assert( "pre: valid_level" && level >= 0 );
|
|
|
|
this->ToRoot();
|
|
|
|
int tmpIndices[3];
|
|
memcpy( tmpIndices, indices, this->Dimension * sizeof(int) );
|
|
// Convert to base 2 / 3 starting with most significant digit.
|
|
|
|
int i = 0;
|
|
int mask = 1;
|
|
while ( ++ i < level )
|
|
{
|
|
mask *= this->Tree->GetBranchFactor();
|
|
}
|
|
|
|
int currentLevel = 0;
|
|
while( !this->IsLeaf() && currentLevel < level )
|
|
{
|
|
// Compute the child index
|
|
i = this->Dimension - 1;
|
|
int child = 0;
|
|
while ( i >= 0 )
|
|
{
|
|
int digit = tmpIndices[i] / mask;
|
|
tmpIndices[i] -= digit*mask;
|
|
child *= child * this->Tree->GetBranchFactor() + digit;
|
|
-- i;
|
|
}
|
|
this->ToChild( child );
|
|
++ currentLevel;
|
|
mask /= this->Tree->GetBranchFactor();
|
|
}
|
|
this->IsFound = ( currentLevel == level );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
bool Found() VTK_OVERRIDE
|
|
{
|
|
return this->IsFound;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// NB: Public only for the vtkCompactHyperTreeCursor.
|
|
void SetIsLeaf( bool value )
|
|
{
|
|
this->Leaf = value;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void SetChildIndex(int childIndex )
|
|
{
|
|
assert( "pre: valid_range" && childIndex >= 0
|
|
&& childIndex<GetNumberOfChildren() );
|
|
this->ChildIndex = childIndex;
|
|
assert( "post: is_set" && childIndex==GetChildIndex() );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Public only for vtkCompactHyperTree.
|
|
void SetIndex( vtkIdType index )
|
|
{
|
|
assert( "pre: positive_index" && index >= 0 );
|
|
this->Index = index;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Public only for vtkCompactHyperTree.
|
|
vtkIdType GetChildHistorySize()
|
|
{
|
|
return static_cast<vtkIdType>( this->ChildHistory.size() );
|
|
}
|
|
|
|
protected:
|
|
//---------------------------------------------------------------------------
|
|
vtkCompactHyperTreeCursor()
|
|
{
|
|
switch ( N )
|
|
{
|
|
case 2:
|
|
case 3:
|
|
this->Dimension = 1;
|
|
break;
|
|
case 4:
|
|
case 9:
|
|
this->Dimension = 2;
|
|
break;
|
|
case 8:
|
|
case 27:
|
|
this->Dimension = 3;
|
|
break;
|
|
default:
|
|
this->Dimension = 0;
|
|
assert( "Bad number of children" && this->Dimension == 0 );
|
|
}
|
|
this->Tree = 0;
|
|
this->Index = 0;
|
|
this->Leaf = false;
|
|
this->ChildIndex = 0;
|
|
memset( this->Indices, 0, 3 * sizeof(int) );
|
|
}
|
|
|
|
vtkCompactHyperTree<N> *Tree;
|
|
unsigned char Dimension;
|
|
|
|
// Index either in the Nodes or Parents (if leaf)
|
|
vtkIdType Index;
|
|
|
|
// Number of current node as a child
|
|
int ChildIndex;
|
|
|
|
bool IsFound;
|
|
bool Leaf;
|
|
|
|
// A stack, but stack does not have clear()
|
|
std::deque<int> ChildHistory;
|
|
|
|
// Index in each dimension of the current node, as if the tree at the current
|
|
// level were a uniform grid. Default to 3 dimensions, use only those needed
|
|
int Indices[3];
|
|
|
|
private:
|
|
vtkCompactHyperTreeCursor(const vtkCompactHyperTreeCursor<N> &) VTK_DELETE_FUNCTION;
|
|
void operator=(const vtkCompactHyperTreeCursor<N> &) VTK_DELETE_FUNCTION;
|
|
};
|
|
|
|
// We could use a 4 byte int, but the internals are completely hidden.
|
|
class vtkHyperTreeLeafFlags
|
|
{
|
|
public:
|
|
vtkHyperTreeLeafFlags()
|
|
{ // Unused bits are set to 1.
|
|
for ( int i = 0; i < 4; ++ i )
|
|
{
|
|
this->Flags[i] = 0xFF;
|
|
}
|
|
}
|
|
|
|
// True if all chilren are leaves.
|
|
bool IsTerminal()
|
|
{
|
|
// Unused bits are set to 1.
|
|
return this->Flags[0] == 0xFF
|
|
&& this->Flags[1] == 0xFF
|
|
&& this->Flags[2] == 0xFF;
|
|
}
|
|
|
|
void SetLeafFlag(int idx, bool val)
|
|
{
|
|
assert( "Valid child idx" && idx >= 0 && idx < 32);
|
|
int i = 0;
|
|
while ( idx >= 8 )
|
|
{
|
|
++ i;
|
|
idx -= 8;
|
|
}
|
|
unsigned char mask = 1 << idx;
|
|
this->Flags[i] = val ?
|
|
( this->Flags[i] | mask ) : ( this->Flags[i] & (mask ^ 0xFF) );
|
|
}
|
|
|
|
bool GetLeafFlag(int idx)
|
|
{
|
|
assert( "Valid child idx" && idx >= 0 && idx < 32);
|
|
int i = 0;
|
|
while ( idx >= 8 )
|
|
{
|
|
++ i;
|
|
idx -= 8;
|
|
}
|
|
unsigned char mask = 1 << idx;
|
|
return ( mask & this->Flags[i] ) == mask;
|
|
}
|
|
|
|
void PrintSelf(ostream& os, int numChildren)
|
|
{
|
|
assert( "Number of children" && numChildren >= 0 && numChildren < 32);
|
|
int childIdx = 0;
|
|
int byteIdx = 0;
|
|
unsigned char mask = 1;
|
|
while ( childIdx < numChildren )
|
|
{
|
|
os << ( ( this->Flags[byteIdx] & mask ) == mask );
|
|
++childIdx;
|
|
if ( mask == 128 )
|
|
{
|
|
mask = 1;
|
|
++byteIdx;
|
|
}
|
|
else
|
|
{
|
|
mask <<= 1;
|
|
}
|
|
}
|
|
os << endl;
|
|
}
|
|
|
|
private:
|
|
unsigned char Flags[4];
|
|
};
|
|
|
|
// Description:
|
|
// A node of the Tree which is not a leaf.
|
|
// Expected template values: 4, 8, 9, 27.
|
|
template<int N> class vtkCompactHyperTreeNode
|
|
{
|
|
public:
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// See GetParent().
|
|
void SetParent(vtkIdType parent)
|
|
{
|
|
assert( "pre: positive_parent" && parent >= 0 );
|
|
this->Parent = parent;
|
|
assert( "post: is_set" && parent == this->GetParent() );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return the index of the parent node of the current node in the
|
|
// nodes array of the hyperTree.
|
|
int GetParent()
|
|
{
|
|
assert( "post: positive_result" && this->Parent >= 0 );
|
|
return this->Parent;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// See GetLeafFlags()
|
|
void SetLeafFlag( vtkIdType childIdx, bool flag )
|
|
{
|
|
this->LeafFlags.SetLeafFlag( childIdx, flag );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description
|
|
// Are children all leaves?
|
|
bool IsTerminalNode()
|
|
{
|
|
return this->LeafFlags.IsTerminal();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Is the `i'-th child of the node a leaf ?
|
|
bool IsChildLeaf( int i )
|
|
{
|
|
assert( "pre: valid_range" && i >= 0 && i < N );
|
|
return this->LeafFlags.GetLeafFlag( i );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// See GetChild().
|
|
void SetChild( int i, int child )
|
|
{
|
|
assert( "pre: valid_range" && i >= 0 && i < N);
|
|
assert( "pre: positive_child" && child >= 0 );
|
|
this->Children[i] = child;
|
|
assert( "post: is_set" && child == this->GetChild( i ) );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return the index of of the 'i'-th child. If the result of
|
|
// IsChildLeaf( i ) is true, the index points to an element in the LeafParent
|
|
// and Attribute arrays of the hyperTree class. If not, the index points to
|
|
// an element in the Nodes array of the hyperTree class.
|
|
int GetChild( int i )
|
|
{
|
|
assert( "pre: valid_range" && i >= 0 && i < N);
|
|
assert( "post: positive_result" && this->Children[i] >= 0 );
|
|
return this->Children[i];
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void PrintSelf( ostream& os, vtkIndent indent )
|
|
{
|
|
os << indent << "Parent=" << this->Parent << endl;
|
|
os << indent << "LeafFlags= ";
|
|
this->LeafFlags.PrintSelf( os, N );
|
|
|
|
for( int i = 0; i < N; ++ i )
|
|
{
|
|
os << indent << this->Children[i] << endl;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
//---------------------------------------------------------------------------
|
|
int Parent; // index
|
|
vtkHyperTreeLeafFlags LeafFlags;
|
|
int Children[N];
|
|
};
|
|
|
|
template<int N> class vtkCompactHyperTree : public vtkHyperTree
|
|
{
|
|
public:
|
|
vtkTypeMacro(vtkCompactHyperTree<N>,vtkHyperTree);
|
|
|
|
//---------------------------------------------------------------------------
|
|
static vtkCompactHyperTree<N>* New()
|
|
{
|
|
vtkCompactHyperTree<N> *ret = new vtkCompactHyperTree<N>;
|
|
ret->InitializeObjectBase();
|
|
return ret;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Restore the initial state: only one node and one leaf: the root.
|
|
void Initialize() VTK_OVERRIDE
|
|
{
|
|
this->Nodes.resize( 1 );
|
|
this->Nodes[0].SetParent( 0 );
|
|
for ( int i = 0; i < N; ++ i )
|
|
{
|
|
// It is assumed that the root is a special node with only one child.
|
|
// The other children flags are irrelevant, but set them as nodes for
|
|
// no good reason.
|
|
this->Nodes[0].SetLeafFlag( i, i == 0 ); // First child is a leaf
|
|
this->Nodes[0].SetChild( i, 0 );
|
|
}
|
|
this->LeafParent.resize( 1 );
|
|
this->LeafParent[0] = 0;
|
|
this->NumberOfLevels = 1;
|
|
this->NumberOfNodes = 1;
|
|
this->GlobalIndexTable.clear();
|
|
this->GlobalIndexStart = 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkHyperTreeCursor* NewCursor() VTK_OVERRIDE
|
|
{
|
|
vtkCompactHyperTreeCursor<N>* result = vtkCompactHyperTreeCursor<N>::New();
|
|
result->SetTree( this );
|
|
return result;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
~vtkCompactHyperTree() VTK_OVERRIDE
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkIdType GetNumberOfLeaves() VTK_OVERRIDE
|
|
{
|
|
return this->NumberOfNodes;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkIdType GetNumberOfIndex() VTK_OVERRIDE
|
|
{
|
|
return static_cast<vtkIdType>( this->LeafParent.size() );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void SetGlobalIndexStart( vtkIdType start ) VTK_OVERRIDE
|
|
{
|
|
this->GlobalIndexStart = start;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void SetGlobalIndexFromLocal( vtkIdType local, vtkIdType global ) VTK_OVERRIDE
|
|
{
|
|
if ( static_cast<vtkIdType>( this->GlobalIndexTable.size() ) <= local )
|
|
{
|
|
this->GlobalIndexTable.resize( local + 1 );
|
|
}
|
|
this->GlobalIndexTable[ local ] = global;
|
|
if ( local == 0 && this->LeafParent.size() == 1 )
|
|
{
|
|
SetGlobalIndexFromLocal( 1, global );
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
vtkIdType GetGlobalIndexFromLocal( vtkIdType local ) VTK_OVERRIDE
|
|
{
|
|
return ( local < static_cast<vtkIdType>( this->GlobalIndexTable.size() ) ) ?
|
|
this->GlobalIndexTable[ local ] : ( this->GlobalIndexStart + local );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return the erenumber of levels.
|
|
// \post result_greater_or_equal_to_one: result>=1
|
|
vtkIdType GetNumberOfLevels() VTK_OVERRIDE
|
|
{
|
|
assert( "post: result_greater_or_equal_to_one"
|
|
&& this->NumberOfLevels >= 1 );
|
|
return this->NumberOfLevels;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Public only for the vtkCompactHyperTreeCursor.
|
|
vtkCompactHyperTreeNode<N>* GetNode( int nodeIdx )
|
|
{
|
|
assert( "pre: valid_range" && nodeIdx >= 0
|
|
&& nodeIdx < this->GetNumberOfNodes() );
|
|
return &this->Nodes[nodeIdx];
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Public only for the vtkCompactHyperTreeCursor.
|
|
// NB: Cursor (index ) appears to be different between nodes and leaves.
|
|
// Different arrays => overlapping indexes.
|
|
// I am changing the name for clarity.
|
|
// This really returns the nodeIdx of the leafs parent.
|
|
int GetLeafParent( int leafIdx )
|
|
{
|
|
assert( "pre: valid_range" && leafIdx >= 0
|
|
&& leafIdx < this->GetNumberOfIndex() );
|
|
assert( "post: valid_result" && this->LeafParent[leafIdx] >= 0
|
|
&& this->LeafParent[leafIdx] < this->GetNumberOfNodes() );
|
|
return this->LeafParent[leafIdx];
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// NB: Public only for the vtkCompactHyperTreeCursor.
|
|
vtkIdType GetNumberOfNodes() VTK_OVERRIDE
|
|
{
|
|
assert( "post: not_empty" && this->Nodes.size() > 0 );
|
|
return static_cast<vtkIdType>( this->Nodes.size() );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void SubdivideLeaf( vtkHyperTreeCursor* leafCursor ) VTK_OVERRIDE
|
|
{
|
|
assert( "pre: leaf_exists" && leafCursor != 0 );
|
|
assert( "pre: is_a_leaf" && leafCursor->IsLeaf() );
|
|
|
|
// We are using a vtkCompactHyperTreeCursor.
|
|
vtkCompactHyperTreeCursor<N>* cursor =
|
|
static_cast<vtkCompactHyperTreeCursor<N> *>(leafCursor);
|
|
|
|
// The leaf becomes a node and is not anymore a leaf
|
|
cursor->SetIsLeaf( false ); // let the cursor know about that change.
|
|
vtkIdType nodeIndex = cursor->GetNodeId();
|
|
|
|
// Nodes get constructed with leaf flags set to 1.
|
|
if ( this->GetNumberOfNodes() <= nodeIndex )
|
|
{
|
|
this->Nodes.resize( nodeIndex + 1 );
|
|
}
|
|
vtkIdType parentNodeIdx = this->LeafParent[nodeIndex];
|
|
this->Nodes[nodeIndex].SetParent( parentNodeIdx );
|
|
|
|
// Change the parent: it has one less child as a leaf
|
|
vtkCompactHyperTreeNode<N>& parent = this->Nodes[parentNodeIdx];
|
|
|
|
// New nodes index in parents children array.
|
|
int idx = cursor->GetChildIndex();
|
|
parent.SetLeafFlag( idx, false );
|
|
parent.SetChild( idx, static_cast<int>( nodeIndex ) );
|
|
|
|
// The first new child
|
|
// Recycle the leaf index we are deleting because it became a node.
|
|
// This avoids messy leaf parent array issues.
|
|
this->NumberOfNodes += N;
|
|
// The other (N) new children.
|
|
size_t nextLeaf = this->LeafParent.size();
|
|
this->LeafParent.resize( nextLeaf + N );
|
|
for ( int i = 0; i < N; ++ i, ++ nextLeaf )
|
|
{
|
|
this->Nodes[nodeIndex].SetChild( i, static_cast<int>( nextLeaf ) );
|
|
this->LeafParent[nextLeaf] = nodeIndex;
|
|
this->Nodes[nodeIndex].SetLeafFlag( i, true );
|
|
}
|
|
|
|
// Update the number of leaves per level.
|
|
vtkIdType level = cursor->GetChildHistorySize();
|
|
|
|
// Add the new leaves to the number of leaves at the next level.
|
|
if ( level + 1 == this->NumberOfLevels ) // >=
|
|
{
|
|
// We have a new level.
|
|
++ this->NumberOfLevels;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// NB: Bad interface: This is really GetNumberOfLeaves.
|
|
vtkIdType GetLeafParentSize()
|
|
{
|
|
return static_cast<int>( this->LeafParent.size() );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void PrintSelf( ostream& os, vtkIndent indent ) VTK_OVERRIDE
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "Dimension=" << this->Dimension << endl;
|
|
os << indent << "BranchFactor=" << this->BranchFactor << endl;
|
|
|
|
os << indent << "Nodes=" << this->Nodes.size() << endl;
|
|
for ( unsigned int i = 0; i < this->Nodes.size(); ++ i )
|
|
{
|
|
this->Nodes[i].PrintSelf( os, indent );
|
|
}
|
|
os << endl;
|
|
|
|
os << indent << "LeafParent="<<this->LeafParent.size() << endl;
|
|
for ( unsigned int i = 0; i < this->LeafParent.size(); ++ i )
|
|
{
|
|
os << this->LeafParent[i] << " ";
|
|
}
|
|
os << endl;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Return memory used in kibibytes (1024 bytes).
|
|
// Ignore the attribute array because its size is added by the data set.
|
|
unsigned int GetActualMemorySize() VTK_OVERRIDE
|
|
{
|
|
size_t size = sizeof(vtkIdType) * this->LeafParent.size() +
|
|
sizeof(vtkCompactHyperTreeNode<N>) * this->Nodes.size() +
|
|
sizeof(vtkIdType) * this->GlobalIndexTable.size();
|
|
return static_cast<unsigned int>( size / 1024 );
|
|
}
|
|
|
|
int GetBranchFactor() VTK_OVERRIDE
|
|
{
|
|
return this->BranchFactor;
|
|
}
|
|
|
|
int GetDimension() VTK_OVERRIDE
|
|
{
|
|
return this->Dimension;
|
|
}
|
|
|
|
void SetScale( double s[3] ) VTK_OVERRIDE
|
|
{
|
|
memcpy( this->Scale, s, 3 * sizeof( double ) );
|
|
}
|
|
void GetScale( double s[3] ) VTK_OVERRIDE
|
|
{
|
|
memcpy( s, this->Scale, 3 * sizeof( double ) );
|
|
}
|
|
double GetScale( unsigned int d ) VTK_OVERRIDE
|
|
{
|
|
return this->Scale[d];
|
|
}
|
|
|
|
protected:
|
|
//---------------------------------------------------------------------------
|
|
// Description:
|
|
// Default constructor.
|
|
// The tree as only one node and one leaf: the root.
|
|
vtkCompactHyperTree()
|
|
{
|
|
// Set tree parameters depending on template parameter value
|
|
switch ( N )
|
|
{
|
|
case 2:
|
|
this->BranchFactor = 2;
|
|
this->Dimension = 1;
|
|
break;
|
|
case 3:
|
|
this->BranchFactor = 3;
|
|
this->Dimension = 1;
|
|
break;
|
|
case 4:
|
|
this->BranchFactor = 2;
|
|
this->Dimension = 2;
|
|
break;
|
|
case 8:
|
|
this->BranchFactor = 2;
|
|
this->Dimension = 3;
|
|
break;
|
|
case 9:
|
|
this->BranchFactor = 3;
|
|
this->Dimension = 2;
|
|
break;
|
|
case 27:
|
|
this->BranchFactor = 3;
|
|
this->Dimension = 3;
|
|
break;
|
|
} // switch ( N )
|
|
|
|
// Set default scale
|
|
for ( int i = 0; i < 3; ++ i )
|
|
{
|
|
this->Scale[i] = 1.;
|
|
}
|
|
|
|
this->Initialize();
|
|
}
|
|
|
|
int BranchFactor;
|
|
int Dimension;
|
|
double Scale[3];
|
|
vtkIdType NumberOfLevels;
|
|
vtkIdType NumberOfNodes;
|
|
|
|
vtkIdType GlobalIndexStart;
|
|
|
|
// Storage for non-leaf tree nodes
|
|
std::vector<vtkCompactHyperTreeNode<N> > Nodes;
|
|
|
|
// Storage to record the parent of each leaf
|
|
std::vector<vtkIdType> LeafParent;
|
|
|
|
// Storage to record the local to global id mapping
|
|
std::vector<vtkIdType> GlobalIndexTable;
|
|
|
|
private:
|
|
vtkCompactHyperTree(const vtkCompactHyperTree<N> &) VTK_DELETE_FUNCTION;
|
|
void operator=(const vtkCompactHyperTree<N> &) VTK_DELETE_FUNCTION;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkHyperTree* vtkHyperTree::CreateInstance( unsigned int factor,
|
|
unsigned int dimension )
|
|
{
|
|
switch ( factor )
|
|
{
|
|
case 2:
|
|
switch ( dimension )
|
|
{
|
|
case 3:
|
|
return vtkCompactHyperTree<8>::New();
|
|
case 2:
|
|
return vtkCompactHyperTree<4>::New();
|
|
case 1:
|
|
return vtkCompactHyperTree<2>::New();
|
|
default:
|
|
vtkGenericWarningMacro( "Bad dimension " << dimension );
|
|
}
|
|
break;
|
|
case 3:
|
|
switch ( dimension )
|
|
{
|
|
case 3:
|
|
return vtkCompactHyperTree<27>::New();
|
|
case 2:
|
|
return vtkCompactHyperTree<9>::New();
|
|
case 1:
|
|
return vtkCompactHyperTree<3>::New();
|
|
default:
|
|
vtkGenericWarningMacro( "Bad dimension " << dimension );
|
|
}
|
|
break;
|
|
default:
|
|
vtkGenericWarningMacro( "Bad branching factor " << factor );
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkHyperTree::FindChildParameters( int child, vtkIdType& index, bool& isLeaf )
|
|
{
|
|
#define GetNodeParametersMacro( _N_ ) \
|
|
{ \
|
|
vtkCompactHyperTree<_N_>* tree = static_cast<vtkCompactHyperTree<_N_>*>( this ); \
|
|
vtkCompactHyperTreeNode<_N_>* node = tree->GetNode( static_cast<int>(index) ); \
|
|
index = static_cast<vtkIdType>(node->GetChild( child )); \
|
|
isLeaf = node->IsChildLeaf( child ); \
|
|
return; \
|
|
}
|
|
|
|
switch ( this->GetDimension() )
|
|
{
|
|
case 3:
|
|
switch ( this->GetBranchFactor() )
|
|
{
|
|
case 2: GetNodeParametersMacro( 8 );
|
|
case 3: GetNodeParametersMacro( 27 );
|
|
} // case 3
|
|
break;
|
|
case 2:
|
|
switch ( this->GetBranchFactor() )
|
|
{
|
|
case 2: GetNodeParametersMacro( 4 );
|
|
case 3: GetNodeParametersMacro( 9 );
|
|
} // case 2
|
|
break;
|
|
case 1:
|
|
switch ( this->GetBranchFactor() )
|
|
{
|
|
case 2: GetNodeParametersMacro( 2 );
|
|
case 3: GetNodeParametersMacro( 3 );
|
|
} // case 1
|
|
break;
|
|
}
|
|
|
|
#undef GetNodeParametersMacro
|
|
|
|
vtkGenericWarningMacro( "Bad branching factor " << this->GetBranchFactor() );
|
|
}
|