Commit 1dfea007 authored by Francois Bertel's avatar Francois Bertel
Browse files

ENH:First revision

parent 05e5bee2
This diff is collapsed.
/*=========================================================================
Program: Visualization Toolkit
Module: vtkHyperOctree.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.
=========================================================================*/
// .NAME vtkHyperOctree - A dataset structured as a tree where each node has
// exactly 2^n children.
// .SECTION Description
// An hyperoctree is a dataset where each node has either exactly 2^n children
// or no child at all if the node is a leaf.
// The class name comes from the following paper:
//
// @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}
// }
//
// 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 hyperoctree is efficient in memory usage when the
// geometry is sparse. The LOD feature allows to cull quickly part of the
// dataset.
//
// A couple of filters can be applied on this dataset: contour, outline,
// geometry.
//
// * 3D 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)
// - the -z side first
// - 0: -y -x sides
// - 1: -y +x sides
// - 2: +y -x sides
// - 3: +y +x sides
//
// +y
// +-+-+ ^
// |2|3| |
// +-+-+ O +z +-> +x
// |0|1|
// +-+-+
// - then the +z side, in counter-clockwise
// - 4: -y -x sides
// - 5: -y +x sides
// - 6: +y -x sides
// - 7: +y +x sides
//
// +y
// +-+-+ ^
// |6|7| |
// +-+-+ O +z +-> +x
// |4|5|
// +-+-+
//
// The cases with fewer dimensions are consistent with the octree case:
//
// * Quadtree:
// in counter-clockwise
// - 0: -y -x edges
// - 1: -y +x edges
// - 2: +y -x edges
// - 3: +y +x edges
//
// +y
// +-+-+ ^
// |2|3| |
// +-+-+ O+-> +x
// |0|1|
// +-+-+
//
//
// * Binary tree:
//
// +0+1+ O+-> +x
// .SECTION Caveats
// It is not a spatial search object! If you looking for this kind of
// octree see vtkCellLocator instead.
// .SECTION See Also
// vtkHyperOctreeAlgorithm
#ifndef __vtkHyperOctree_h
#define __vtkHyperOctree_h
#include "vtkDataSet.h"
class vtkHyperOctreeCursor;
class vtkHyperOctreeInternal;
class vtkHyperOctreePointsGrabber;
class vtkHyperOctreeIdSet; // Pimpl idiom
class vtkPolygon;
class vtkOrderedTriangulator;
class VTK_FILTERING_EXPORT vtkHyperOctree : public vtkDataSet
{
public:
static vtkInformationIntegerKey* LEVELS();
static vtkInformationIntegerKey* DIMENSION();
static vtkInformationDoubleVectorKey* SIZES();
static vtkHyperOctree *New();
vtkTypeRevisionMacro(vtkHyperOctree,vtkDataSet);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Return what type of dataset this is.
int GetDataObjectType();
// Description:
// Copy the geometric and topological structure of an input rectilinear grid
// object.
void CopyStructure(vtkDataSet *ds);
// Return the node describes by the path from the root.
// Path is a sequence of number between 0 and 7.
// \pre path_exists: path!=0
// \pre node_exists: IsANode(path)
// vtkOctree *GetNode(vtkPath *path);
// Status
// Return the dimension of the tree (1D:binary tree(2 children), 2D:quadtree(4 children),
// 3D:octree (8 children))
// \post valid_result: result>=1 && result<=3
int GetDimension();
// Set the dimension of the tree with `dim'. See GetDimension() for details.
// \pre valid_dim: dim>=1 && dim<=3
// \post dimension_is_set: GetDimension()==dim
void SetDimension(int dim);
// Return if the node for the given path exists or not.
// \pre path_exists: path!=0
// int IsANode(vtkPath *path);
// Return if the node for the given path is a leaf or not.
// \pre path_exists: path!=0
// \pre node_exists: IsANode(path)
// int IsALeaf(vtkPath *path);
// Measurement: topology
// Description:
// Return the number of leaves.
// \post positive_result: result>=0
vtkIdType GetNumberOfCells();
// Description:
// Return the number of points.
// \post positive_result: result>=0
vtkIdType GetNumberOfPoints();
// Description:
// Return the number of points corresponding to an hyperoctree starting at
// level `level' where all the leaves at at the last level. In this case, the
// hyperoctree is like a uniform grid. So this number is the number of points
// of the uniform grid.
// \pre positive_level: level>=0 && level<this->GetNumberOfLevels()
// \post definition: result==(2^(GetNumberOfLevels()-level-1)+1)^GetDimension()
vtkIdType GetMaxNumberOfPoints(int level);
// Description:
// Return the number of points corresponding to the boundary of an
// hyperoctree starting at level `level' where all the leaves at at the last
// level. In this case, the hyperoctree is like a uniform grid. So this
// number is the number of points of on the boundary of the uniform grid.
// For an octree, the boundary are the faces. For a quadtree, the boundary
// are the edges.
// \pre 2d_or_3d: this->GetDimension()==2 || this->GetDimension()==3
// \pre positive_level: level>=0 && level<this->GetNumberOfLevels()
// \post min_result: result>=GetMaxNumberOfPoints(this->GetNumberOfLevels()-1)
// \post max_result: result<=GetMaxNumberOfPoints(level)
vtkIdType GetMaxNumberOfPointsOnBoundary(int level);
// Description:
// Return the number of cells corresponding to the boundary of a cell
// of level `level' where all the leaves at at the last level.
// \pre positive_level: level>=0 && level<this->GetNumberOfLevels()
// \post positive_result: result>=0
vtkIdType GetMaxNumberOfCellsOnBoundary(int level);
// Description:
// Return the number of levels.
// \post result_greater_or_equal_to_one: result>=1
vtkIdType GetNumberOfLevels();
// Measurement: geometry
// Description:
// Set the size on each axis.
vtkSetVector3Macro(Size,double);
// Description:
// Return the size on each axis.
vtkGetVector3Macro(Size,double);
// Description:
// Set the origin (position of corner (0,0,0) of the root.
vtkSetVector3Macro(Origin,double);
// Return the origin (position of corner (0,0,0) ) of the root.
vtkGetVector3Macro(Origin,double);
// Description:
// Create a new cursor: an object that can traverse
// the cell of an hyperoctree.
// \post result_exists: result!=0
vtkHyperOctreeCursor *NewCellCursor();
// Description:
// 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(vtkHyperOctreeCursor *leaf);
// Description:
// Collapse a node for which all children are leaves.
// At the end, cursor points on the leaf that used to be a node.
// \pre node_exists: node!=0
// \pre node_is_node: !node->CurrentIsLeaf()
// \pre children_are_leaves: node->CurrentIsTerminalNode()
void CollapseTerminalNode(vtkHyperOctreeCursor *node);
// Description:
// Get point coordinates with ptId such that: 0 <= ptId < NumberOfPoints.
// THIS METHOD IS NOT THREAD SAFE.
virtual double *GetPoint(vtkIdType ptId);
// Description:
// 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
virtual void GetPoint(vtkIdType id, double x[3]);
// Description:
// Get cell with cellId such that: 0 <= cellId < NumberOfCells.
// THIS METHOD IS NOT THREAD SAFE.
virtual vtkCell *GetCell(vtkIdType cellId);
// Description:
// 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
virtual void GetCell(vtkIdType cellId, vtkGenericCell *cell);
// Description:
// 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
virtual int GetCellType(vtkIdType cellId);
// Description:
// 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
virtual void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds);
// Description:
// 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
virtual void GetPointCells(vtkIdType ptId, vtkIdList *cellIds);
// Description:
// 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 METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND
// THE DATASET IS NOT MODIFIED
virtual void GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds,
vtkIdList *cellIds);
virtual vtkIdType FindPoint(double x[3]);
// Description:
// 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.
// THIS METHOD IS NOT THREAD SAFE.
virtual vtkIdType FindCell(double x[3], vtkCell *cell, vtkIdType cellId,
double tol2, int& subId, double pcoords[3],
double *weights);
// Description:
// 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
virtual vtkIdType FindCell(double x[3], vtkCell *cell,
vtkGenericCell *gencell, vtkIdType cellId,
double tol2, int& subId, double pcoords[3],
double *weights);
// Description:
// Restore data object to initial state,
// THIS METHOD IS NOT THREAD SAFE.
void Initialize();
// Description:
// 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
virtual int GetMaxCellSize();
// Description:
// Shallow and Deep copy.
void ShallowCopy(vtkDataObject *src);
void DeepCopy(vtkDataObject *src);
// Description:
// Get the points of node `sibling' on its face `face'.
// \pre sibling_exists: sibling!=0
// \pre sibling_not_leaf: !sibling->CurrentIsLeaf()
// \pre sibling_3d: sibling->GetDimension()==3
// \pre valid_face: face>=0 && face<6
// \pre valid_level_not_leaf: level>=0 level<(this->GetNumberOfLevels()-1)
void GetPointsOnFace(vtkHyperOctreeCursor *sibling,
int face,
int level,
vtkHyperOctreePointsGrabber *grabber);
// Description:
// Get the points of the parent node of `cursor' on its faces `faces' at
// level `level' or deeper.
// \pre cursor_exists: cursor!=0
// \pre cursor_3d: cursor->GetDimension()==3
// \pre valid_level: level>=0
// \pre boolean_faces: (faces[0]==0 || faces[0]==1) && (faces[1]==0 || faces[1]==1) && (faces[2]==0 || faces[2]==1)
void GetPointsOnParentFaces(int faces[3],
int level,
vtkHyperOctreeCursor *cursor,
vtkHyperOctreePointsGrabber *grabber);
// Description:
// Get the points of node `sibling' on its edge `axis','k','j'.
// If axis==0, the edge is X-aligned and k gives the z coordinate and j the
// y-coordinate. If axis==1, the edge is Y-aligned and k gives the x coordinate
// and j the z coordinate. If axis==2, the edge is Z-aligned and k gives the
// y coordinate and j the x coordinate.
// \pre sibling_exists: sibling!=0
// \pre sibling_3d: sibling->GetDimension()==3
// \pre sibling_not_leaf: !sibling->CurrentIsLeaf()
// \pre valid_axis: axis>=0 && axis<3
// \pre valid_k: k>=0 && k<=1
// \pre valid_j: j>=0 && j<=1
// \pre valid_level_not_leaf: level>=0 level<(this->Input->GetNumberOfLevels()-1)
void GetPointsOnEdge(vtkHyperOctreeCursor *sibling,
int level,
int axis,
int k,
int j,
vtkHyperOctreePointsGrabber *grabber);
// Description:
// Get the points of the parent node of `cursor' on its edge `axis','k','j'
// at level `level' or deeper.
// If axis==0, the edge is X-aligned and k gives the z coordinate and j the
// y-coordinate. If axis==1, the edge is Y-aligned and k gives the x
// coordinate and j the z coordinate. If axis==2, the edge is Z-aligned and
// k gives the y coordinate and j the x coordinate.
// \pre cursor_exists: cursor!=0
// \pre cursor_3d: cursor->GetDimension()==3
// \pre valid_level: level>=0
// \pre valid_range_axis: axis>=0 && axis<3
// \pre valid_range_k: k>=0 && k<=1
// \pre valid_range_j: j>=0 && j<=1
void GetPointsOnParentEdge(vtkHyperOctreeCursor *cursor,
int level,
int axis,
int k,
int j,
vtkHyperOctreePointsGrabber *grabber);
// Description:
// Get the points of node `sibling' on its edge `edge'.
// \pre sibling_exists: sibling!=0
// \pre sibling_not_leaf: !sibling->CurrentIsLeaf()
// \pre sibling_2d: sibling->GetDimension()==2
// \pre valid_edge: edge>=0 && edge<4
// \pre valid_level_not_leaf: level>=0 level<(this->Input->GetNumberOfLevels()-1)
void GetPointsOnEdge2D(vtkHyperOctreeCursor *sibling,
int edge,
int level,
vtkHyperOctreePointsGrabber *grabber);
// Description:
// Get the points of the parent node of `cursor' on its edge `edge' at
// level `level' or deeper. (edge=0 for -X, 1 for +X, 2 for -Y, 3 for +Y)
// \pre cursor_exists: cursor!=0
// \pre cursor_2d: cursor->GetDimension()==2
// \pre valid_level: level>=0
// \pre valid_edge: edge>=0 && edge<4
void GetPointsOnParentEdge2D(vtkHyperOctreeCursor *cursor,
int edge,
int level,
vtkHyperOctreePointsGrabber *grabber);
protected:
// Constructor with default bounds (0,1, 0,1, 0,1).
vtkHyperOctree();
~vtkHyperOctree();
void ComputeBounds();
int Dimension; // 1, 2 or 3.
double Size[3]; // size on each axis
double Origin[3]; // position of corner (0,0,0) of the root.
vtkHyperOctreeInternal *CellTree;
vtkHyperOctreeInternal *PointTree; // not used
vtkHyperOctreeCursor *TmpChild; // to avoid allocation in the loop
private:
vtkHyperOctree(const vtkHyperOctree&); // Not implemented.
void operator=(const vtkHyperOctree&); // Not implemented.
};
#endif
/*=========================================================================
Program: Visualization Toolkit
Module: vtkHyperOctreeAlgorithm.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 "vtkHyperOctreeAlgorithm.h"
#include "vtkCommand.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkHyperOctree.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkTrivialProducer.h"
vtkCxxRevisionMacro(vtkHyperOctreeAlgorithm, "1.1");
//----------------------------------------------------------------------------
vtkHyperOctreeAlgorithm::vtkHyperOctreeAlgorithm()
{
// by default assume filters have one input and one output
// subclasses that deviate should modify this setting
this->SetNumberOfInputPorts(1);
this->SetNumberOfOutputPorts(1);
}
//----------------------------------------------------------------------------
vtkHyperOctreeAlgorithm::~vtkHyperOctreeAlgorithm()
{
}
//----------------------------------------------------------------------------
void vtkHyperOctreeAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
vtkHyperOctree* vtkHyperOctreeAlgorithm::GetOutput()
{
return this->GetOutput(0);
}
//----------------------------------------------------------------------------
vtkHyperOctree* vtkHyperOctreeAlgorithm::GetOutput(int port)
{
return vtkHyperOctree::SafeDownCast(this->GetOutputDataObject(port));
}
//----------------------------------------------------------------------------
void vtkHyperOctreeAlgorithm::SetOutput(vtkDataObject* d)
{
this->GetExecutive()->SetOutputData(0, d);
}
//----------------------------------------------------------------------------
vtkDataObject* vtkHyperOctreeAlgorithm::GetInput()
{
return this->GetInput(0);
}
//----------------------------------------------------------------------------
vtkDataObject* vtkHyperOctreeAlgorithm::GetInput(int port)
{
if (this->GetNumberOfInputConnections(port) < 1)
{
return 0;
}
return this->GetExecutive()->GetInputData(port, 0);
}
//----------------------------------------------------------------------------
vtkHyperOctree* vtkHyperOctreeAlgorithm::GetHyperOctreeInput(int port)
{
return vtkHyperOctree::SafeDownCast(this->GetInput(port));
}
//----------------------------------------------------------------------------
int vtkHyperOctreeAlgorithm::ProcessRequest(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
// generate the data
if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
{
return this->RequestData(request, inputVector, outputVector);
}
if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
{
return this->RequestUpdateExtent(request, inputVector, outputVector);
}
// execute information
if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
{
return this->RequestInformation(request, inputVector, outputVector);
}
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}
//----------------------------------------------------------------------------
int vtkHyperOctreeAlgorithm::FillOutputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
// now add our info
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkHyperOctree");
return 1;
}
//----------------------------------------------------------------------------
int vtkHyperOctreeAlgorithm::FillInputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkHyperOctree");
return 1;
}
//----------------------------------------------------------------------------
int vtkHyperOctreeAlgorithm::RequestInformation(
vtkInformation* vtkNotUsed(request),
vtkInformationVector** vtkNotUsed(inputVector),
vtkInformationVector* vtkNotUsed(outputVector))
{
// do nothing let subclasses handle it
return 1;
}
//----------------------------------------------------------------------------
int vtkHyperOctreeAlgorithm::RequestUpdateExtent(
vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector,
vtkInformationVector* vtkNotUsed(outputVector))
{
int numInputPorts = this->GetNumberOfInputPorts();
for (int i=0; i<numInputPorts; i++)
{
int numInputConnections = this->GetNumberOfInputConnections(i);
for (int j=0; j<numInputConnections; j++)
{
vtkInformation* inputInfo = inputVector[i]->GetInformationObject(j);
inputInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1);
}
}
return 1;
}
//----------------------------------------------------------------------------
// This is the superclasses style of Execute method. Convert it into
// an imaging style Execute method.
int vtkHyperOctreeAlgorithm::RequestData(
vtkInformation* request,
vtkInformationVector** vtkNotUsed( inputVector ),
vtkInformationVector* outputVector)
{
// the default implimentation is to do what the old pipeline did find what
// output is requesting the data, and pass that into ExecuteData