Commit 3218f2cc authored by Joachim Pouderoux's avatar Joachim Pouderoux
Browse files

HTG modification to support only defined (has mat) level 0 cells.

Change the HyperTreeGrid mechanisms to provide efficient storage of very
large level 0 grids with only few cells defined. Instead of creating a
full grid array, only defined cells (through MaterialMaskIndex array)
are stored and processed.
The source has been updated to take advantage of this new feature.

Some optimizations and code simplification are also provided.

Provide a new test TestHyperTreeGridTernary3DGeometryLargeMaterialBits
to test the large grids management.

Set 3: Fix tests, mainly fix CopyStructure.

Change-Id: Iaab0afd7d13e66d9ab105c554a4d873ab59f1d35
parent c0b9e934
......@@ -55,7 +55,7 @@ public:
}
//---------------------------------------------------------------------------
int GetLeafId()
vtkIdType GetLeafId()
{
assert( "pre: is_leaf" && IsLeaf() );
return this->Index;
......@@ -314,7 +314,7 @@ public:
}
//---------------------------------------------------------------------------
virtual int Found()
virtual bool Found()
{
return this->IsFound;
}
......@@ -337,7 +337,7 @@ public:
//---------------------------------------------------------------------------
// Description:
// Public only for vtkCompactHyperTree.
void SetIndex( int index )
void SetIndex( vtkIdType index )
{
assert( "pre: positive_index" && index >= 0 );
this->Index = index;
......@@ -384,12 +384,12 @@ protected:
unsigned char Dimension;
// Index either in the Nodes or Parents (if leaf)
int Index;
vtkIdType Index;
// Number of current node as a child
int ChildIndex;
int IsFound;
bool IsFound;
bool Leaf;
// A stack, but stack does not have clear()
......@@ -429,15 +429,8 @@ public:
++ i;
idx -= 8;
}
unsigned char mask = 1<<idx;
if ( val )
{
this->Flags[i] = this->Flags[i] | mask;
}
else
{
this->Flags[i] = this->Flags[i] & (mask^255);
}
unsigned char mask = 1 << idx;
this->Flags[i] = val ? ( this->Flags[i] | mask ) : ( this->Flags[i] & (mask ^ 255) );
}
bool GetLeafFlag(int idx)
......@@ -450,7 +443,7 @@ public:
idx -= 8;
}
unsigned char mask = 1 << idx;
return (mask & this->Flags[i]) == mask;
return ( mask & this->Flags[i] ) == mask;
}
void PrintSelf(ostream& os, int numChildren)
......@@ -461,7 +454,7 @@ public:
unsigned char mask = 1;
while ( childIdx < numChildren )
{
os << ((( this->Flags[byteIdx])&mask)==mask);
os << ( ( this->Flags[byteIdx] & mask ) == mask );
++childIdx;
if (mask == 128)
{
......@@ -489,11 +482,11 @@ public:
//---------------------------------------------------------------------------
// Description:
// See GetParent().
void SetParent(int parent)
void SetParent(vtkIdType parent)
{
assert( "pre: positive_parent" && parent >= 0 );
this->Parent=parent;
assert( "post: is_set" && parent==this->GetParent() );
this->Parent = parent;
assert( "post: is_set" && parent == this->GetParent() );
}
//---------------------------------------------------------------------------
......@@ -509,9 +502,9 @@ public:
//---------------------------------------------------------------------------
// Description:
// See GetLeafFlags()
void SetLeafFlag(int childIdx, bool flag)
void SetLeafFlag( vtkIdType childIdx, bool flag )
{
this->LeafFlags.SetLeafFlag(childIdx, flag);
this->LeafFlags.SetLeafFlag( childIdx, flag );
}
//---------------------------------------------------------------------------
......@@ -662,10 +655,10 @@ public:
//---------------------------------------------------------------------------
// NB: Public only for the vtkCompactHyperTreeCursor.
virtual int GetNumberOfNodes()
virtual vtkIdType GetNumberOfNodes()
{
assert( "post: not_empty" && this->Nodes.size()>0 );
return static_cast<int>( this->Nodes.size() );
assert( "post: not_empty" && this->Nodes.size() > 0 );
return static_cast<vtkIdType>( this->Nodes.size() );
}
//---------------------------------------------------------------------------
......@@ -676,17 +669,17 @@ public:
// We are using a vtkCompactHyperTreeCursor.
// We know that GetLeafId() return Cursor.
int leafIndex = leafCursor->GetLeafId();
vtkIdType leafIndex = leafCursor->GetLeafId();
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.
size_t nodeIndex = this->Nodes.size();
cursor->SetIndex( static_cast<int>( nodeIndex ) );
cursor->SetIndex( static_cast<vtkIdType>( nodeIndex ) );
// Nodes get constructed with leaf flags set to 1.
this->Nodes.resize( nodeIndex + 1 );
int parentNodeIdx = this->LeafParent[leafIndex];
vtkIdType parentNodeIdx = this->LeafParent[leafIndex];
this->Nodes[nodeIndex].SetParent( parentNodeIdx );
// Change the parent: it has one less child as a leaf
......@@ -714,7 +707,7 @@ public:
}
// Update the number of leaves per level.
int level = cursor->GetChildHistorySize();
vtkIdType level = cursor->GetChildHistorySize();
// Remove the subdivided leaf from the number of leaves at its level.
-- this->NumberOfLeavesPerLevel[level];
......@@ -731,7 +724,7 @@ public:
//---------------------------------------------------------------------------
// NB: Bad interface: This is really GetNumberOfLeaves.
int GetLeafParentSize()
vtkIdType GetLeafParentSize()
{
return static_cast<int>( this->LeafParent.size() );
}
......@@ -865,10 +858,10 @@ protected:
std::vector<vtkCompactHyperTreeNode<N> > Nodes;
// Storage for number of leaves in each level
std::vector<int> NumberOfLeavesPerLevel;
std::vector<vtkIdType> NumberOfLeavesPerLevel;
// Storage to record the parent of each leaf
std::vector<int> LeafParent;
std::vector<vtkIdType> LeafParent;
private:
vtkCompactHyperTree(const vtkCompactHyperTree<N> &); // Not implemented.
......@@ -914,72 +907,41 @@ vtkHyperTree* vtkHyperTree::CreateInstance( int factor, int dimension )
//-----------------------------------------------------------------------------
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( index ); \
index = node->GetChild( child ); \
isLeaf = node->IsChildLeaf( child ); \
return; \
}
switch ( this->GetDimension() )
{
case 3:
switch ( this->GetBranchFactor() )
{
case 2:
{
vtkCompactHyperTree<8>* tree = static_cast<vtkCompactHyperTree<8>*>( this );
vtkCompactHyperTreeNode<8>* node = tree->GetNode( index );
index = node->GetChild( child );
isLeaf = node->IsChildLeaf( child );
return;
}
case 3:
{
vtkCompactHyperTree<27>* tree = static_cast<vtkCompactHyperTree<27>*>( this );
vtkCompactHyperTreeNode<27>* node = tree->GetNode( index );
index = node->GetChild( child );
isLeaf = node->IsChildLeaf( child );
return;
}
case 2: GetNodeParametersMacro( 8 );
case 3: GetNodeParametersMacro( 27 );
} // case 3
break;
case 2:
switch ( this->GetBranchFactor() )
{
case 2:
{
vtkCompactHyperTree<4>* tree = static_cast<vtkCompactHyperTree<4>*>( this );
vtkCompactHyperTreeNode<4>* node = tree->GetNode( index );
index = node->GetChild( child );
isLeaf = node->IsChildLeaf( child );
return;
}
case 3:
{
vtkCompactHyperTree<9>* tree = static_cast<vtkCompactHyperTree<9>*>( this );
vtkCompactHyperTreeNode<9>* node = tree->GetNode( index );
index = node->GetChild( child );
isLeaf = node->IsChildLeaf( child );
return;
}
case 2: GetNodeParametersMacro( 4 );
case 3: GetNodeParametersMacro( 9 );
} // case 2
break;
case 1:
switch ( this->GetBranchFactor() )
{
case 2:
{
vtkCompactHyperTree<2>* tree = static_cast<vtkCompactHyperTree<2>*>( this );
vtkCompactHyperTreeNode<2>* node = tree->GetNode( index );
index = node->GetChild( child );
isLeaf = node->IsChildLeaf( child );
return;
}
case 3:
{
vtkCompactHyperTree<3>* tree = static_cast<vtkCompactHyperTree<3>*>( this );
vtkCompactHyperTreeNode<3>* node = tree->GetNode( index );
index = node->GetChild( child );
isLeaf = node->IsChildLeaf( child );
return;
}
case 2: GetNodeParametersMacro( 2 );
case 3: GetNodeParametersMacro( 3 );
} // case 1
break;
}
#undef GetNodeParametersMacro
vtkGenericWarningMacro( "Bad branching factor " << this->GetBranchFactor() );
}
......@@ -127,11 +127,11 @@ class vtkHyperTreeCursor;
class VTKCOMMONDATAMODEL_EXPORT vtkHyperTree : public vtkObject
{
public:
vtkTypeMacro(vtkHyperTree,vtkObject);
vtkTypeMacro(vtkHyperTree, vtkObject);
virtual void Initialize() = 0;
virtual vtkHyperTreeCursor* NewCursor() = 0;
virtual vtkIdType GetNumberOfLeaves() = 0;
virtual int GetNumberOfNodes() = 0;
virtual vtkIdType GetNumberOfNodes() = 0;
virtual int GetBranchFactor() = 0;
virtual int GetDimension() = 0;
virtual void SetScale( double[3] ) = 0;
......@@ -159,7 +159,7 @@ public:
// Return an instance of a templated hypertree for given branch
// factor and dimension
// This is done to hide templates.
static vtkHyperTree* CreateInstance( int factor, int dimension );
static vtkHyperTree* CreateInstance( int branchFactor, int dimension );
// Description:
// Find the Index and IsLeaf() parameters of a child for hypertree.
......
......@@ -50,94 +50,94 @@ class VTKCOMMONDATAMODEL_EXPORT vtkHyperTreeCursor : public vtkObject
public:
vtkTypeMacro(vtkHyperTreeCursor,vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Return the index of the current leaf in the data arrays.
// \pre is_leaf: IsLeaf()
virtual int GetLeafId() = 0;
virtual vtkIdType GetLeafId() = 0;
// Description:
// Is the node pointed by the cursor a leaf?
virtual bool IsLeaf() = 0;
// Are the children of the current node all leaves?
// This query can be called also on a leaf node.
// \post compatible: result implies !IsLeaf()
virtual bool IsTerminalNode() = 0;
// Description:
// Is the node pointed by the cursor the root?
virtual bool IsRoot() = 0;
// Description:
// Return the level of the node pointed by the cursor.
// \post positive_result: result>=0
virtual int GetCurrentLevel() = 0;
// Description:
// Return the child number of the current node relative to its parent.
// \pre not_root: !IsRoot().
// \post valid_range: result>=0 && result<GetNumberOfChildren()
virtual int GetChildIndex() = 0;
// Description:
// Move the cursor to the root node.
// \pre can be root
// \post is_root: IsRoot()
virtual void ToRoot() = 0;
// Description:
// Move the cursor to the parent of the current node.
// \pre not_root: !IsRoot()
virtual void ToParent() = 0;
// Description:
// Move the cursor to child `child' of the current node.
// \pre not_leaf: !IsLeaf()
// \pre valid_child: child>=0 && child<this->GetNumberOfChildren()
virtual void ToChild( int child ) = 0;
// Description:
// Move the cursor to the same node pointed by `other'.
// \pre other_exists: other!=0
// \pre same_hyper3TREE: this->SameTree(other);
// \post equal: this->IsEqual(other)
virtual void ToSameNode( vtkHyperTreeCursor* other ) = 0;
// Description:
// Is `this' equal to `other'?
// \pre other_exists: other!=0
// \pre same_hyper3TREE: this->SameTree(other);
virtual bool IsEqual( vtkHyperTreeCursor* other ) = 0;
// Description:
// Create a copy of `this'.
// \post results_exists:result!=0
// \post same_tree: result->SameTree(this)
virtual vtkHyperTreeCursor* Clone() = 0;
// Description:
// Are `this' and `other' pointing on the same hyper3TREE?
// \pre other_exists: other!=0
virtual int SameTree( vtkHyperTreeCursor* other ) = 0;
// 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())
virtual int GetIndex( int d ) = 0;
// Description:
// Return the number of children for each node of the tree.
// \post positive_number: result>0
virtual int GetNumberOfChildren() = 0;
// Description:
// Return the dimension of the tree.
// \post positive_result: result>0
virtual int GetDimension() = 0;
// 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
......@@ -148,15 +148,16 @@ public:
// \pre valid_size: sizeof(indices)==GetDimension()
// \pre valid_level: level>=0
virtual void MoveToNode( int* indices, int level ) = 0;
// Description
// Did the last call to MoveToNode succeed?
virtual int Found() = 0;
virtual bool Found() = 0;
protected:
// Constructor.
vtkHyperTreeCursor();
virtual ~vtkHyperTreeCursor();
private:
vtkHyperTreeCursor(const vtkHyperTreeCursor&); // Not implemented.
void operator=(const vtkHyperTreeCursor&); // Not implemented.
......
This diff is collapsed.
......@@ -116,11 +116,11 @@ public:
// Description:
// Get the number of leaves in the primal tree grid.
unsigned int GetNumberOfLeaves();
vtkIdType GetNumberOfLeaves();
// Description:
// Return the number of levels in an individual (primal) tree
unsigned int GetNumberOfLevels( unsigned int );
vtkIdType GetNumberOfLevels( vtkIdType );
// Description:
// Specify the grid coordinates in the x-direction.
......@@ -142,11 +142,20 @@ public:
void SetMaterialMask( vtkBitArray* );
vtkGetObjectMacro(MaterialMask, vtkBitArray);
// Description:
// Specify the visibility mask of primal leaf cells
virtual void SetMaterialMaskIndex( vtkIdTypeArray* );
vtkGetObjectMacro(MaterialMaskIndex, vtkIdTypeArray);
// Description:
// This method must be called once the tree settings change
virtual void GenerateTrees();
// Description:
// Create a new cursor: an object that can traverse
// the cells of an individual hyper tree.
// \post result_exists: result!=0
vtkHyperTreeCursor* NewCursor( int );
vtkHyperTreeCursor* NewCursor( vtkIdType );
// Description:
// Subdivide node pointed by cursor, only if its a leaf.
......@@ -301,7 +310,7 @@ public:
unsigned int,
unsigned int,
unsigned int,
unsigned int );
vtkIdType );
// Description:
// Initialize a cursor to point to a child of an existing super cursor.
// This will not work in place.
......@@ -314,13 +323,14 @@ public:
// The number of children each node can have.
vtkGetMacro(NumberOfChildren, int);
vtkIdType GetLevelZeroIndex( vtkIdType );
protected:
// Constructor with default bounds (0,1, 0,1, 0,1).
vtkHyperTreeGrid();
~vtkHyperTreeGrid();
void ComputeBounds();
void UpdateTree();
void GetCell( vtkIdType, vtkCell* );
......@@ -330,17 +340,19 @@ protected:
unsigned int Dimension; // 1, 2 or 3.
unsigned int GridSize[3];
bool TransposedRootIndexing;
unsigned int BranchFactor;
unsigned int NumberOfChildren;
bool TransposedRootIndexing;
vtkBitArray* MaterialMask;
vtkIdTypeArray* MaterialMaskIndex;
vtkDataArray* XCoordinates;
vtkDataArray* YCoordinates;
vtkDataArray* ZCoordinates;
vtkCollection* HyperTrees;
std::map<vtkIdType, vtkIdType> HyperTreesMap;
vtkIdType* HyperTreesLeafIdOffsets;
vtkPoints* Points;
......@@ -355,7 +367,7 @@ protected:
//BTX
#ifndef __WRAP__
void TraverseDualRecursively( vtkHyperTreeGridSuperCursor*, int );
void TraverseDualRecursively( vtkHyperTreeGridSuperCursor*, unsigned int );
void TraverseDualMaskedLeaf( vtkHyperTreeGridSuperCursor* );
......@@ -416,7 +428,7 @@ public:
vtkHyperTree* GetTree() { return this->Tree; }
vtkIdType GetLeafIndex() { return this->Index; } // Only valid for leaves.
vtkIdType GetGlobalLeafIndex() { return this->Offset + this->Index; }
vtkIdType GetGlobalLeafIndex() { return ( this->Offset >= 0 ) ? this->Offset + this->Index : -1; }
vtkIdType GetOffset() { return this->Offset; }
unsigned short GetLevel() { return this->Level; }
......
......@@ -24,6 +24,7 @@ create_test_sourcelist(Tests ${vtk-module}CxxTests.cxx
TestHyperTreeGridTernary3DGeometry.cxx
TestHyperTreeGridTernary3DGeometryMaterial.cxx
TestHyperTreeGridTernary3DGeometryMaterialBits.cxx
TestHyperTreeGridTernary3DGeometryLargeMaterialBits.cxx
TestHyperTreeGridTernary3DUnstructured.cxx
TestHyperTreeGridTernary3DUnstructuredMaterial.cxx
TestHyperTreeGridTernaryHyperbola.cxx
......
......@@ -44,12 +44,11 @@ int TestHyperTreeGridTernary2DMaterialBits( int argc, char* argv[] )
htGrid->SetDimension( 2 );
htGrid->SetBranchFactor( 3 );
htGrid->UseMaterialMaskOn();
const std::string descriptor = "RRRRR.|" // Level 0 refinement
"......... ..R...... RRRRRRRRR R........ R........|..R...... ........R ......RRR ......RRR ..R..R..R RRRRRRRRR R..R..R.. ......... ......... ......... ......... .........|......... ......... ......... ......... ......... ......... ......... ......... ........R ..R..R..R ......... ......RRR ......R.. ......... RRRRRRRRR R..R..R.. ......... ......... ......... ......... ......... ......... .........|......... ......... ......... ......... ......... ......... ......... ......... ......... RRRRRRRRR ......... ......... ......... ......... ......... ......... ......... ......... ......... .........|......... ......... ......... ......... ......... ......... ......... ......... ........." ;
const std::string materialMask = //"111111|" // Level 0 material is not needed, visible cells are described with LevelZeroMaterialIndex
"000000000 111111111 111111111 111111111 111111111|111111111 000000001 000000111 011011111 001001001 111111111 100100100 001001001 111111111 111111111 111111111 001111111|111111111 001001001 111111111 111111111 111111111 111111111 111111111 111111111 001001111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111|111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111|111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111";
const std::string descriptor = "_RRRR.|" // Level 0 refinement
"..R...... RRRRRRRRR R........ R........|..R...... ........R ......RRR ......RRR ..R..R..R RRRRRRRRR R..R..R.. ......... ......... ......... ......... .........|......... ......... ......... ......... ......... ......... ......... ......... ........R ..R..R..R ......... ......RRR ......R.. ......... RRRRRRRRR R..R..R.. ......... ......... ......... ......... ......... ......... .........|......... ......... ......... ......... ......... ......... ......... ......... ......... RRRRRRRRR ......... ......... ......... ......... ......... ......... ......... ......... ......... .........|......... ......... ......... ......... ......... ......... ......... ......... ........." ;
const std::string materialMask = // Level 0 materials are not needed, visible cells are described with LevelZeroMaterialIndex
"111111111 111111111 111111111 111111111|111111111 000000001 000000111 011011111 001001001 111111111 100100100 001001001 111111111 111111111 111111111 001111111|111111111 001001001 111111111 111111111 111111111 111111111 111111111 111111111 001001111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111|111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111|111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111";
vtkNew<vtkIdTypeArray> zero;
zero->InsertNextValue(0);
zero->InsertNextValue(1);
zero->InsertNextValue(2);
zero->InsertNextValue(3);
......@@ -62,8 +61,6 @@ int TestHyperTreeGridTernary2DMaterialBits( int argc, char* argv[] )
vtkBitArray* mat = htGrid->ConvertMaterialMaskStringToBitArray( materialMask );
htGrid->SetMaterialMaskBits(mat);
mat->Delete();
//htGrid->Update();
//htGrid->Print(cout);
// Geometry
vtkNew<vtkHyperTreeGridGeometry> geometry;
......
/*==================================================================
Program: Visualization Toolkit
Module: TestHyperTreeGridTernary3DGeometryMaterial.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.
===================================================================*/
// .SECTION Thanks
// This test was written by Philippe Pebay and Joachim Pouderoux, Kitware 2013
// This work was supported in part by Commissariat a l'Energie Atomique (CEA/DIF)
#include "vtkHyperTreeGridGeometry.h"
#include "vtkHyperTreeGridSource.h"
#include "vtkCamera.h"
#include "vtkCellData.h"
#include "vtkBitArray.h"
#include "vtkIdTypeArray.h"
#include "vtkNew.h"
#include "vtkProperty.h"
#include "vtkPolyDataMapper.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkHyperTreeGrid.h"
#include "vtkPointData.h"
int TestHyperTreeGridTernary3DGeometryLargeMaterialBits( int argc, char* argv[] )
{
// Hyper tree grid
vtkNew<vtkHyperTreeGridSource> htGrid;
htGrid->SetMaximumLevel( 6 );
htGrid->SetGridSize( 30, 30, 20 );
htGrid->SetGridScale( 1.5, 1., .7 );
htGrid->SetDimension( 3 );
htGrid->SetBranchFactor( 3 );
htGrid->UseMaterialMaskOn();
const std::string descriptor = ".RR _R. _RR ..R _.R .R_ |" // Level 0 refinement
"R.......................... ........................... ........................... .............R............. ....RR.RR........R......... .....RRRR.....R.RR......... ........................... ...........................|........................... ........................... ........................... ...RR.RR.......RR.......... ........................... RR......................... ........................... ........................... ........................... ........................... ........................... ........................... ........................... ............RRR............|........................... ........................... .......RR.................. ........................... ........................... ........................... ........................... ........................... ........................... ........................... ...........................|........................... ...........................";
const std::string materialMask = // Level 0 materials are not needed, visible cells are described with LevelZeroMaterialIndex
"111111111111111111111111111 000000000100110111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 000110011100000100100010100|000001011011111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111001111111101111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111|000000000111100100111100100 000000000111001001111001001 000000111100100111111111111 000000111001001111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 111111111111111111111111111 110110110100111110111000000|111111111111111111111111111 11111111111111111111111111";
vtkIdType zeroArray[] = { 0, 1, 2, 4, 5, 7, 8, 9, 30, 29*30+1, 30*30, 30*30*19, 30*30*20-2, 30*30*20-1 };
vtkNew<vtkIdTypeArray> zero;
zero->SetArray( zeroArray, sizeof(zeroArray) / sizeof(vtkIdType), 1, 0 );
htGrid->SetLevelZeroMaterialIndex( zero.GetPointer() );
vtkBitArray* desc = htGrid->ConvertDescriptorStringToBitArray( descriptor );
htGrid->SetDescriptorBits(desc);
desc->Delete();
vtkBitArray* mat = htGrid->ConvertMaterialMaskStringToBitArray( materialMask );
htGrid->SetMaterialMaskBits(mat);
mat->Delete();
// Geometry
vtkNew<vtkHyperTreeGridGeometry> geometry;
geometry->SetInputConnection( htGrid->GetOutputPort() );