/*========================================================================= Program: Visualization Toolkit Module: vtkHyperTreeGrid.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 vtkHyperTreeGrid * @brief A dataset containing a grid of vtkHyperTree instances * arranged as a rectilinear grid. * * * An hypertree grid is a dataset containing a rectilinear grid of root nodes, * each of which can be refined as a vtkHyperTree grid. This organization of the * root nodes allows for the definition of tree-based AMR grids that do not have * uniform geometry. * Some filters can be applied on this dataset: contour, outline, geometry. * * @warning * It is not a spatial search object. If you are looking for this kind of * octree see vtkCellLocator instead. * Extent support is not finished yet. * * @sa * vtkHyperTree vtkRectilinearGrid * * @par Thanks: * This class was written by Philippe Pebay, Joachim Pouderoux and Charles Law, * Kitware 2013 * This work was supported in part by Commissariat a l'Energie Atomique (CEA/DIF) */ #ifndef vtkHyperTreeGrid_h #define vtkHyperTreeGrid_h #include "vtkCommonDataModelModule.h" // For export macro #include "vtkDataSet.h" #include // STL header for dual point coordinates ajustment class vtkHyperTreeCursor; class vtkHyperTree; class vtkBitArray; class vtkCellLinks; class vtkCollection; class vtkDataArray; class vtkDataSetAttributes; class vtkIdTypeArray; class vtkLine; class vtkPixel; class vtkPoints; class vtkVoxel; class VTKCOMMONDATAMODEL_EXPORT vtkHyperTreeGrid : public vtkDataSet { public: class vtkHyperTreeSimpleCursor; class vtkHyperTreeIterator; struct vtkHyperTreeGridSuperCursor; static vtkInformationIntegerKey* LEVELS(); static vtkInformationIntegerKey* DIMENSION(); static vtkInformationDoubleVectorKey* SIZES(); static vtkHyperTreeGrid* New(); vtkTypeMacro(vtkHyperTreeGrid, vtkDataSet); void PrintSelf( ostream&, vtkIndent ) VTK_OVERRIDE; /** * Return what type of dataset this is. */ int GetDataObjectType() VTK_OVERRIDE; /** * Copy the internal geometric and topological structure of a * vtkHyperTreeGrid object. */ void CopyStructure( vtkDataSet* ) VTK_OVERRIDE; //@{ /** * Set/Get sizes of this rectilinear grid dataset */ void SetGridSize( unsigned int[3] ); void SetGridSize( unsigned int i, unsigned int j, unsigned int k ); vtkGetVector3Macro(GridSize, unsigned int); //@} //@{ /** * Set/Get extent of this rectilinear grid dataset */ void SetGridExtent(int extent[6]); void SetGridExtent(int iMin, int iMax, int jMin, int jMax, int kMin, int kMax); //@} //@{ /** * Specify whether indexing mode of grid root cells must be transposed to * x-axis first, z-axis last, instead of the default z-axis first, k-axis last */ vtkSetMacro(TransposedRootIndexing, bool); vtkGetMacro(TransposedRootIndexing, bool); void SetIndexingModeToKJI() { this->SetTransposedRootIndexing( false ); } void SetIndexingModeToIJK() { this->SetTransposedRootIndexing( true ); } //@} //@{ /** * Set/Get the subdivision factor in the grid refinement scheme * NB: Can only be 2 or 3 */ void SetBranchFactor( unsigned int ); vtkGetMacro(BranchFactor, unsigned int); //@} //@{ /** * Set/Get the dimensionality of the grid * NB: Can only be 1, 2 or 3 */ void SetDimension( unsigned int ); vtkGetMacro(Dimension, unsigned int); //@} /** * Return the number of cells in the dual grid. */ vtkIdType GetNumberOfCells() VTK_OVERRIDE; /** * Return the number of points in the dual grid. */ vtkIdType GetNumberOfPoints() VTK_OVERRIDE; /** * Get the number of leaves in the primal tree grid. */ vtkIdType GetNumberOfLeaves(); /** * Return the number of levels in an individual (primal) tree */ vtkIdType GetNumberOfLevels( vtkIdType ); /** * Return the number of trees in the level 0 grid. */ vtkIdType GetNumberOfTrees(); //@{ /** * Specify the grid coordinates in the x-direction. */ void SetXCoordinates( vtkDataArray* ); vtkGetObjectMacro(XCoordinates, vtkDataArray); //@} //@{ /** * Specify the grid coordinates in the y-direction. */ void SetYCoordinates( vtkDataArray* ); vtkGetObjectMacro(YCoordinates, vtkDataArray); //@} //@{ /** * Specify the grid coordinates in the z-direction. */ void SetZCoordinates( vtkDataArray* ); vtkGetObjectMacro(ZCoordinates, vtkDataArray); //@} //@{ /** * Specify the blanking mask of primal leaf cells */ void SetMaterialMask( vtkBitArray* ); vtkGetObjectMacro(MaterialMask, vtkBitArray); //@} //@{ /** * Specify the visibility mask of primal leaf cells */ virtual void SetMaterialMaskIndex( vtkIdTypeArray* ); vtkGetObjectMacro(MaterialMaskIndex, vtkIdTypeArray); //@} /** * This method must be called once the tree settings change */ virtual void GenerateTrees(); /** * Create a new cursor: an object that can traverse * the cells of an individual hyper tree. * \post result_exists: result!=0 */ vtkHyperTreeCursor* NewCursor( vtkIdType ); /** * 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() */ void SubdivideLeaf( vtkHyperTreeCursor*, vtkIdType ); /** * This method should be avoided in favor of cell/point iterators. * Random access to points requires that arrays are created explicitly. * Get point coordinates with ptId such that: 0 <= ptId < NumberOfPoints. * THIS METHOD IS NOT THREAD SAFE. */ double* GetPoint( vtkIdType ) VTK_OVERRIDE; /** * This method should be avoided in favor of cell/point iterators. * Random access to points requires that arrays are created explicitly. * Copy point coordinates into user provided array x[3] for specified * point id. * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND * THE DATASET IS NOT MODIFIED */ void GetPoint( vtkIdType, double[3] ) VTK_OVERRIDE; /** * This method should be avoided in favor of cell/point iterators. * Random access to cells requires that connectivity arrays are created explicitly. * Get cell with cellId such that: 0 <= cellId < NumberOfCells. * THIS METHOD IS NOT THREAD SAFE. */ vtkCell* GetCell( vtkIdType ) VTK_OVERRIDE; /** * This method should be avoided in favor of cell/point iterators. * Random access to cells requires that connectivity arrays are created explicitly. * Get cell with cellId such that: 0 <= cellId < NumberOfCells. * This is a thread-safe alternative to the previous GetCell() * method. * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND * THE DATASET IS NOT MODIFIED */ void GetCell( vtkIdType, vtkGenericCell* ) VTK_OVERRIDE; /** * All cell types are 2: quadrilaters,3d: hexahedrons. They may be degenerate though. * Get type of cell with cellId such that: 0 <= cellId < NumberOfCells. * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND * THE DATASET IS NOT MODIFIED */ int GetCellType( vtkIdType ) VTK_OVERRIDE; /** * This method should be avoided in favor of cell/point iterators. * Random access to cells requires that connectivity arrays are created explicitly. * Topological inquiry to get points defining cell. * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND * THE DATASET IS NOT MODIFIED */ void GetCellPoints( vtkIdType, vtkIdList* ) VTK_OVERRIDE; /** * Return a pointer to a list of point ids defining cell. * NB: More efficient than alternative method. */ virtual void GetCellPoints( vtkIdType, vtkIdType&, vtkIdType*& ); /** * This method should be avoided in favor of cell/point iterators. * Random access to cells requires that connectivity arrays are created explicitly. * Topological inquiry to get cells using point. * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND * THE DATASET IS NOT MODIFIED */ void GetPointCells( vtkIdType, vtkIdList* ) VTK_OVERRIDE; /** * This method should be avoided in favor of cell/point iterators. * Random access to cells requires that connectivity arrays are created explicitly. * Topological inquiry to get all cells using list of points exclusive of * cell specified (e.g., cellId). Note that the list consists of only * cells that use ALL the points provided. * This is exactly the same as GetCellNeighbors in unstructured grid. * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND * THE DATASET IS NOT MODIFIED */ void GetCellNeighbors( vtkIdType, vtkIdList*, vtkIdList* ) VTK_OVERRIDE; /** * Find cell to which this point belongs, or at least closest one, * even if the point is outside the grid. * Since dual points are leaves, use the structure of the Tree instead * of a point locator. */ vtkIdType FindPoint( double x[3] ) VTK_OVERRIDE; /** * Locate cell based on global coordinate x and tolerance * squared. If cell and cellId is non-NULL, then search starts from * this cell and looks at immediate neighbors. Returns cellId >= 0 * if inside, < 0 otherwise. The parametric coordinates are * provided in pcoords[3]. The interpolation weights are returned in * weights[]. (The number of weights is equal to the number of * points in the found cell). Tolerance is used to control how close * the point is to be considered "in" the cell. * NB: There is actually no need for a starting cell, just use the * point, as the tree structure is efficient enough. * THIS METHOD IS NOT THREAD SAFE. */ vtkIdType FindCell( double x[3], vtkCell *cell, vtkIdType cellId, double tol2, int& subId, double pcoords[3], double *weights ) VTK_OVERRIDE; /** * This is a version of the above method that can be used with * multithreaded applications. A vtkGenericCell must be passed in * to be used in internal calls that might be made to GetCell() * THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND * THE DATASET IS NOT MODIFIED */ vtkIdType FindCell( double x[3], vtkCell *cell, vtkGenericCell *gencell, vtkIdType cellId, double tol2, int& subId, double pcoords[3], double *weights ) VTK_OVERRIDE; /** * Restore data object to initial state, * THIS METHOD IS NOT THREAD SAFE. */ void Initialize() VTK_OVERRIDE; /** * Initialize an iterator to browse level 0 trees. */ void InitializeTreeIterator( vtkHyperTreeIterator& ); /** * Convenience method returns largest cell size in dataset. This is generally * used to allocate memory for supporting data structures. * This is the number of points of a cell. * THIS METHOD IS THREAD SAFE */ int GetMaxCellSize() VTK_OVERRIDE; //@{ /** * Shallow and Deep copy. */ void ShallowCopy( vtkDataObject* ) VTK_OVERRIDE; void DeepCopy( vtkDataObject* ) VTK_OVERRIDE; //@} /** * Structured extent. The extent type is a 3D extent */ int GetExtentType() VTK_OVERRIDE { return VTK_3D_EXTENT; } /** * Return the actual size of the data in kibibytes (1024 bytes). This number * is valid only after the pipeline has updated. The memory size * returned is guaranteed to be greater than or equal to the * memory required to represent the data (e.g., extra space in * arrays, etc. are not included in the return value). THIS METHOD * IS THREAD SAFE. */ unsigned long GetActualMemorySize() VTK_OVERRIDE; /** * Generate the table before calling InitializeSuperCursorChild. */ void GenerateSuperCursorTraversalTable(); #ifndef __VTK_WRAP__ //@{ /** * Initialize a super cursor to point to one of the root trees * in the grid. The super cursor points to a node in a tree and * also keeps pointers to the 26 neighbors of said node. */ void InitializeSuperCursor( vtkHyperTreeGridSuperCursor*, unsigned int, unsigned int, unsigned int, vtkIdType ); void InitializeSuperCursor( vtkHyperTreeGridSuperCursor*, vtkIdType ); //@} /** * Initialize a cursor to point to a child of an existing super cursor. * This will not work in place. */ void InitializeSuperCursorChild( vtkHyperTreeGridSuperCursor* parent, vtkHyperTreeGridSuperCursor* child, unsigned int childIdx ); #endif //@{ /** * The number of children each node can have. */ vtkGetMacro(NumberOfChildren, unsigned int); //@} /** * Convert a level 0 index to its ijk coordinates according the grid size. */ void GetLevelZeroCoordsFromIndex( vtkIdType index, unsigned int &i, unsigned int &j, unsigned int &k ); protected: // Constructor with default bounds (0,1, 0,1, 0,1). vtkHyperTreeGrid(); ~vtkHyperTreeGrid() VTK_OVERRIDE; void ComputeBounds() VTK_OVERRIDE; void GetCell( vtkIdType, vtkCell* ); void ComputeDualGrid(); vtkPoints* GetPoints(); vtkIdTypeArray* GetConnectivity(); unsigned int Dimension; // 1, 2 or 3. unsigned int GridSize[3]; int Extent[6]; unsigned int BranchFactor; unsigned int NumberOfChildren; bool TransposedRootIndexing; vtkBitArray* MaterialMask; vtkIdTypeArray* MaterialMaskIndex; vtkDataArray* XCoordinates; vtkDataArray* YCoordinates; vtkDataArray* ZCoordinates; std::map HyperTrees; vtkPoints* Points; vtkIdTypeArray* Connectivity; std::map PointShifted; std::map PointShifts[3]; std::map ReductionFactors; void DeleteInternalArrays(); void DeleteTrees(); #if !defined(__VTK_WRAP__) && !defined(__WRAP_GCCXML__) void TraverseDualRecursively( vtkHyperTreeGridSuperCursor*, unsigned int ); void TraverseDualMaskedLeaf( vtkHyperTreeGridSuperCursor* ); void TraverseDualLeaf( vtkHyperTreeGridSuperCursor* ); void EvaluateDualCorner( vtkHyperTreeSimpleCursor* ); #endif // Used to advance the super cursor; One Entry per cursor node. // Private. struct vtkSuperCursorEntry { // For the new node, start with the node in super cursor as parent. unsigned char Parent; // Traverse to this child. unsigned char Child; }; // Generalizing for 27 tree. Cannot use 3 bits to encode the child to move to. // Input: root in supercursor(3x3x3=27), child(3x3x3=27) // Output: root, child // It is easier to abstract dimensions when we use a single array. vtkSuperCursorEntry SuperCursorTraversalTable[27*27]; // for the GetCell method vtkLine* Line; vtkPixel* Pixel; vtkVoxel* Voxel; // I would like to get rid of this. // Is it a part of the vtkDataSet API? vtkCellLinks* Links; void BuildLinks(); vtkIdType RecursiveFindPoint( double x[3], vtkHyperTreeSimpleCursor* cursor, double* origin, double* size); public: // A simplified hyper tree cursor, to be used by the hyper tree // grid supercursor. class VTKCOMMONDATAMODEL_EXPORT vtkHyperTreeSimpleCursor { public: vtkHyperTreeSimpleCursor(); void Clear(); void Initialize( vtkHyperTreeGrid*, vtkIdType, int[3] ); void ToRoot(); void ToChild( int ); bool IsLeaf(); vtkHyperTree* GetTree() { return this->Tree; } vtkIdType GetLeafIndex() { return this->Index; } // Only valid for leaves. vtkIdType GetGlobalNodeIndex(); unsigned short GetLevel() { return this->Level; } private: vtkHyperTree* Tree; vtkIdType Index; unsigned short Level; bool Leaf; }; class VTKCOMMONDATAMODEL_EXPORT vtkHyperTreeIterator { public: vtkHyperTreeIterator() {} /** * Initialize the iterator on the tree set of the given HyperTreeGrid. */ void Initialize( vtkHyperTreeGrid* ); /** * Get the next tree and set its index then increment the iterator. * Returns 0 at the end. */ vtkHyperTree* GetNextTree( vtkIdType &index ); /** * Get the next tree and set its index then increment the iterator. * Returns 0 at the end. */ vtkHyperTree* GetNextTree(); protected: std::map::iterator Iterator; vtkHyperTreeGrid* Tree; }; // Public structure filters use to move around the tree. // The super cursor keeps neighbor cells so filters can // easily access neighbor to leaves. // The super cursor is 'const'. Methods in vtkHyperTreeGrid // initialize and compute children for moving toward leaves. struct vtkHyperTreeGridSuperCursor { double Origin[3]; double Size[3]; int NumberOfCursors; int MiddleCursorId; vtkHyperTreeSimpleCursor Cursors[3*3*3]; vtkHyperTreeSimpleCursor* GetCursor( int idx ) { return this->Cursors + this->MiddleCursorId + idx; } }; private: vtkHyperTreeGrid(const vtkHyperTreeGrid&) VTK_DELETE_FUNCTION; void operator=(const vtkHyperTreeGrid&) VTK_DELETE_FUNCTION; }; #endif