Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

712 lines
26 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkKdTree.h,v $
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.
=========================================================================*/
/*----------------------------------------------------------------------------
Copyright (c) Sandia Corporation
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/
// .NAME vtkKdTree - a Kd-tree spatial decomposition of a set of points
//
// .SECTION Description
// Given one or more vtkDataSets, create a load balancing
// k-d tree decomposition of the points at the center of the cells.
// Or, create a k-d tree point locator from a list of points.
//
// This class can also generate a PolyData representation of
// the boundaries of the spatial regions in the decomposition.
//
// It can sort the regions with respect to a viewing direction,
// and it can decompose a list of regions into subsets, each
// of which represent a convex spatial region (since many algorithms
// require a convex region).
//
// If the points were derived from cells, vtkKdTree
// can create a list of cell Ids for each region for each data set.
// Two lists are available - all cells with centroid in the region,
// and all cells that intersect the region but whose centroid lies
// in another region.
//
// For the purpose of removing duplicate points quickly from large
// data sets, or for finding nearby points, we added another mode for
// building the locator. BuildLocatorFromPoints will build a k-d tree
// from one or more vtkPoints objects. This can be followed by
// BuildMapForDuplicatePoints which returns a mapping from the original
// ids to a subset of the ids that is unique within a supplied
// tolerance, or you can use FindPoint and FindClosestPoint to
// locate points in the original set that the tree was built from.
//
// .SECTION See Also
// vtkLocator vtkCellLocator vtkPKdTree
#ifndef __vtkKdTree_h
#define __vtkKdTree_h
#include "vtkLocator.h"
class vtkTimerLog;
class vtkIdList;
class vtkIdTypeArray;
class vtkIntArray;
class vtkPoints;
class vtkCellArray;
class vtkCell;
class vtkKdNode;
class vtkBSPCuts;
class vtkBSPIntersections;
class VTK_GRAPHICS_EXPORT vtkKdTree : public vtkLocator
{
public:
vtkTypeRevisionMacro(vtkKdTree, vtkLocator);
void PrintSelf(ostream& os, vtkIndent indent);
static vtkKdTree *New();
// Description:
// Turn on timing of the k-d tree build
vtkBooleanMacro(Timing, int);
vtkSetMacro(Timing, int);
vtkGetMacro(Timing, int);
// Description:
// Minimum number of cells per spatial region. Default is 100.
vtkSetMacro(MinCells, int);
vtkGetMacro(MinCells, int);
// Description:
// Set/Get the number of spatial regions you want to get close
// to without going over. (The number of spatial regions is normally
// a power of two.) Call this before BuildLocator(). Default
// is unset.
vtkGetMacro(NumberOfRegionsOrLess, int);
vtkSetMacro(NumberOfRegionsOrLess, int);
// Description:
// Set/Get the number of spatial regions you want to get close
// to while having at least this many regions. (The number of
// spatial regions is normally a power of two.) Default
// is unset.
vtkGetMacro(NumberOfRegionsOrMore, int);
vtkSetMacro(NumberOfRegionsOrMore, int);
// Description:
// Some algorithms on k-d trees require a value that is a very
// small distance relative to the diameter of the entire space
// divided by the k-d tree. This factor is the maximum axis-aligned
// width of the space multipled by 10e-6.
vtkGetMacro(FudgeFactor, double);
vtkSetMacro(FudgeFactor, double);
// Description:
// Get a vtkBSPCuts object, a general object representing an axis-
// aligned spatial partitioning. Used by vtkBSPIntersections.
vtkGetObjectMacro(Cuts, vtkBSPCuts);
// Description:
// Normally the k-d tree is computed from the dataset(s) provided
// in SetDataSet. Alternatively, you can provide the cuts that will
// be applied by calling SetCuts.
void SetCuts(vtkBSPCuts *cuts);
// Description:
// Omit partitions along the X axis, yielding shafts in the X direction
void OmitXPartitioning();
// Description:
// Omit partitions along the Y axis, yielding shafts in the Y direction
void OmitYPartitioning();
// Description:
// Omit partitions along the Z axis, yielding shafts in the Z direction
void OmitZPartitioning();
// Description:
// Omit partitions along the X and Y axes, yielding slabs along Z
void OmitXYPartitioning();
// Description:
// Omit partitions along the Y and Z axes, yielding slabs along X
void OmitYZPartitioning();
// Description:
// Omit partitions along the Z and X axes, yielding slabs along Y
void OmitZXPartitioning();
// Description:
// Partition along all three axes - this is the default
void OmitNoPartitioning();
// Description
// This class can compute a spatial decomposition based on the
// cells in a list of one or more input data sets.
// SetDataSet sets the first data set in the list to the named set.
// SetNthDataSet sets the data set at index N to the data set named.
// RemoveData set takes either the data set itself or an index and
// removes that data set from the list of data sets.
// AddDataSet adds a data set to the list of data sets.
void SetDataSet(vtkDataSet *set);
void SetNthDataSet(int index, vtkDataSet *set);
void RemoveDataSet(int index);
void RemoveDataSet(vtkDataSet *set);
void AddDataSet(vtkDataSet *set);
// Description:
// Get the number of data sets included in spatial paritioning
int GetNumberOfDataSets(){return this->NumDataSets;};
// Description:
// Get the nth defined data set in the spatial partitioning.
// (If you used SetNthDataSet to define 0,1 and 3 and ask for
// data set 2, you get 3.)
vtkDataSet *GetDataSet(int n);
vtkDataSet *GetDataSet(){ return this->GetDataSet(0); }
// Description:
// Get handle for one of the data sets included in spatial paritioning.
// Handles can change after RemoveDataSet.
int GetDataSet(vtkDataSet *set);
// Description:
// Get the spatial bounds of the entire k-d tree space. Sets
// bounds array to xmin, xmax, ymin, ymax, zmin, zmax.
void GetBounds(double *bounds);
// Description:
// There are certain applications where you want the bounds of
// the k-d tree space to be at least as large as a specified
// box. If the k-d tree has been built, you can expand it's
// bounds with this method. If the bounds supplied are smaller
// than those computed, they will be ignored.
void SetNewBounds(double *bounds);
// Description:
// The number of leaf nodes of the tree, the spatial regions
vtkGetMacro(NumberOfRegions, int);
// Description:
// Get the spatial bounds of k-d tree region
void GetRegionBounds(int regionID, double bounds[6]);
// Description:
// Get the bounds of the data within the k-d tree region
void GetRegionDataBounds(int regionID, double bounds[6]);
// Description:
// Print out nodes of kd tree
void PrintTree();
void PrintVerboseTree();
// Description:
// Print out leaf node data for given id
void PrintRegion(int id);
// Description:
// Create a list for each of the requested regions, listing
// the IDs of all cells whose centroid falls in the region.
// These lists are obtained with GetCellList().
// If no DataSet is specified, the cell list is created
// for DataSet 0. If no list of requested regions is provided,
// the cell lists for all regions are created.
//
// When CreateCellLists is called again, the lists created
// on the previous call are deleted.
void CreateCellLists(int DataSet, int *regionReqList,
int reqListSize);
void CreateCellLists(vtkDataSet *set, int *regionReqList,
int reqListSize);
void CreateCellLists(int *regionReqList, int listSize);
void CreateCellLists();
// Description:
// If IncludeRegionBoundaryCells is ON,
// CreateCellLists() will also create a list of cells which
// intersect a given region, but are not assigned
// to the region. These lists are obtained with
// GetBoundaryCellList(). Default is OFF.
vtkSetMacro(IncludeRegionBoundaryCells, int);
vtkGetMacro(IncludeRegionBoundaryCells, int);
vtkBooleanMacro(IncludeRegionBoundaryCells, int);
// Description:
// Free the memory used by the cell lists.
void DeleteCellLists();
// Description:
// Get the cell list for a region. This returns a pointer
// to vtkKdTree's memory, so don't free it.
vtkIdList *GetCellList(int regionID);
// Description:
// The cell list obtained with GetCellList is the list
// of all cells such that their centroid is contained in
// the spatial region. It may also be desirable to get
// a list of all cells intersecting a spatial region,
// but with centroid in some other region. This is that
// list. This list is computed in CreateCellLists() if
// and only if IncludeRegionBoundaryCells is ON. This
// returns a pointer to KdTree's memory, so don't free it.
vtkIdList *GetBoundaryCellList(int regionID);
// Description:
//
// For a list of regions, get two cell lists. The first lists
// the IDs all cells whose centroids lie in one of the regions.
// The second lists the IDs of all cells that intersect the regions,
// but whose centroid lies in a region not on the list.
//
// The total number of cell IDs written to both lists is returned.
// Either list pointer passed in can be NULL, and it will be ignored.
// If there are multiple data sets, you must specify which data set
// you wish cell IDs for.
//
// The caller should delete these two lists when done. This method
// uses the cell lists created in CreateCellLists().
// If the cell list for any of the requested regions does not
// exist, then this method will call CreateCellLists() to create
// cell lists for *every* region of the k-d tree. You must remember
// to DeleteCellLists() when done with all calls to this method, as
// cell lists can require a great deal of memory.
vtkIdType GetCellLists(vtkIntArray *regions, int set,
vtkIdList *inRegionCells, vtkIdList *onBoundaryCells);
vtkIdType GetCellLists(vtkIntArray *regions, vtkDataSet *set,
vtkIdList *inRegionCells, vtkIdList *onBoundaryCells);
vtkIdType GetCellLists(vtkIntArray *regions, vtkIdList *inRegionCells,
vtkIdList *onBoundaryCells);
// Description:
// Get the id of the region containing the cell centroid. If
// no DataSet is specified, assume DataSet 0. If you need the
// region ID for every cell, use AllGetRegionContainingCell
// instead. It is more efficient.
int GetRegionContainingCell(vtkDataSet *set, vtkIdType cellID);
int GetRegionContainingCell(int set, vtkIdType cellID);
int GetRegionContainingCell(vtkIdType cellID);
// Description:
// Get a list (in order by data set by cell id) of the
// region IDs of the region containing the centroid for
// each cell.
// This is faster than calling GetRegionContainingCell
// for each cell in the DataSet.
// vtkKdTree uses this list, so don't delete it.
int *AllGetRegionContainingCell();
// Description:
// Get the id of the region containing the specified location.
int GetRegionContainingPoint(double x, double y, double z);
// Description:
// Create the k-d tree decomposition of the cells of the data set
// or data sets. Cells are assigned to k-d tree spatial regions
// based on the location of their centroids.
void BuildLocator();
// Description:
// Given a list of region IDs, determine the decomposition of
// these regions into the minimal number of convex subregions. Due
// to the way the k-d tree is constructed, those convex subregions
// will be axis-aligned boxes. Return the minimal number of
// such convex regions that compose the original region list.
// This call will set convexRegionBounds to point to a list
// of the bounds of these regions. Caller should free this.
// There will be six values for each convex subregion (xmin,
// xmax, ymin, ymax, zmin, zmax). If the regions in the
// regionIdList form a box already, a "1" is returned and the
// second argument contains the bounds of the box.
int MinimalNumberOfConvexSubRegions(vtkIntArray *regionIdList,
double **convexRegionBounds);
// Description:
// Given a direction of projection (typically obtained with
// vtkCamera::GetDirectionOfProjection()), this function
// creates a list of the k-d tree region IDs in order from
// front to back with respect to the that direction.
// The number of regions in
// the ordered list is returned. (This is not actually sorting
// the regions on their distance from the view plane, but there
// is no region on the list which blocks a region that appears
// earlier on the list.)
int DepthOrderAllRegions(double *dop, vtkIntArray *orderedList);
// Description:
// Given a direction of projection, and a list of k-d tree region
// IDs, this function creates an ordered list of those IDs
// in front to back order with respect to the
// camera's direction of projection. The number of regions in
// the ordered list is returned.
int DepthOrderRegions(vtkIntArray *regionIds, double *dop,
vtkIntArray *orderedList);
// Description:
// This is a special purpose locator that builds a k-d tree to
// find duplicate and near-by points. It builds the tree from
// one or more vtkPoints objects instead of from the cells of
// a vtkDataSet. This build would normally be followed by
// BuildMapForDuplicatePoints, FindPoint, or FindClosestPoint.
// Since this will build a normal k-d tree, all the region intersection
// queries will still work, as will most other calls except those that
// have "Cell" in the name.
//
// This method works most efficiently when the point arrays are
// float arrays.
void BuildLocatorFromPoints(vtkPoints *ptArray);
void BuildLocatorFromPoints(vtkPoints **ptArray, int numPtArrays);
// Description:
// This call returns a mapping from the original point IDs supplied
// to BuildLocatorFromPoints to a subset of those IDs that is unique
// within the specified tolerance.
// If points 2, 5, and 12 are the same, then
// IdMap[2] = IdMap[5] = IdMap[12] = 2 (or 5 or 12).
//
// "original point IDs" - For point IDs we start at 0 for the first
// point in the first vtkPoints object, and increase by 1 for subsequent
// points and subsequent vtkPoints objects.
//
// You must have called BuildLocatorFromPoints() before calling this.
// You are responsible for deleting the returned array.
vtkIdTypeArray *BuildMapForDuplicatePoints(float tolerance);
// Description:
// Find the Id of the point that was previously supplied
// to BuildLocatorFromPoints(). Returns -1 if the point
// was not in the original array.
vtkIdType FindPoint(double *x);
vtkIdType FindPoint(double x, double y, double z);
// Description:
// Find the Id of the point that was previously supplied
// to BuildLocatorFromPoints() which is closest to the given point.
// Set the square of the distance between the two points.
vtkIdType FindClosestPoint(double *x, double &dist2);
vtkIdType FindClosestPoint(double x, double y, double z, double &dist2);
// Description:
// Find the Id of the point in the given region which is
// closest to the given point. Return the ID of the point,
// and set the square of the distance of between the points.
vtkIdType FindClosestPointInRegion(int regionId, double *x, double &dist2);
vtkIdType FindClosestPointInRegion(int regionId, double x, double y, double z,
double &dist2);
// Description:
// Get a list of the original IDs of all points in a region. You
// must have called BuildLocatorFromPoints before calling this.
vtkIdTypeArray *GetPointsInRegion(int regionId);
// Description:
// Delete the k-d tree data structure. Also delete any
// cell lists that were computed with CreateCellLists().
void FreeSearchStructure();
// Description:
// Create a polydata representation of the boundaries of
// the k-d tree regions. If level equals GetLevel(), the
// leaf nodes are represented.
void GenerateRepresentation(int level, vtkPolyData *pd);
// Description:
// Generate a polygonal representation of a list of regions.
// Only leaf nodes have region IDs, so these will be leaf nodes.
void GenerateRepresentation(int *regionList, int len, vtkPolyData *pd);
// Description:
// The polydata representation of the k-d tree shows the boundaries
// of the k-d tree decomposition spatial regions. The data inside
// the regions may not occupy the entire space. To draw just the
// bounds of the data in the regions, set this variable ON.
vtkBooleanMacro(GenerateRepresentationUsingDataBounds, int);
vtkSetMacro(GenerateRepresentationUsingDataBounds, int);
vtkGetMacro(GenerateRepresentationUsingDataBounds, int);
// Description:
// Print timing of k-d tree build
virtual void PrintTiming(ostream& os, vtkIndent indent);
// Description:
// Return 1 if the geometry of the input data sets
// has changed since the last time the k-d tree was built.
int NewGeometry();
// Description:
// Return 1 if the geometry of these data sets differs
// for the geometry of the last data sets used to build
// the k-d tree.
int NewGeometry(vtkDataSet **sets, int numDataSets);
// Description:
// Create a copy of the binary tree representation of the
// k-d tree spatial partitioning provided.
static vtkKdNode *CopyTree(vtkKdNode *kd);
protected:
vtkKdTree();
~vtkKdTree();
vtkBSPIntersections *BSPCalculator;
int UserDefinedCuts;
void SetCalculator(vtkKdNode *kd);
int ProcessUserDefinedCuts(double *bounds);
void SetCuts(vtkBSPCuts *cuts, int userDefined);
// Description:
// Save enough state so NewGeometry() can work,
// and update the BuildTime time stamp.
void UpdateBuildTime();
// Description:
// Prior to dividing a region at level "level", of size
// "numberOfPoints", apply the tests implied by MinCells,
// NumberOfRegionsOrMore and NumberOfRegionsOrLess. Return 1 if it's
// OK to divide the region, 0 if you should not.
int DivideTest(int numberOfPoints, int level);
//BTX
enum {
XDIM = 0, // don't change these values
YDIM = 1,
ZDIM = 2
};
//ETX
int ValidDirections;
vtkKdNode *Top;
vtkKdNode **RegionList; // indexed by region ID
vtkTimerLog *TimerLog;
static void DeleteAllDescendants(vtkKdNode *nd);
void BuildRegionList();
virtual int SelectCutDirection(vtkKdNode *kd);
void SetActualLevel(){this->Level = vtkKdTree::ComputeLevel(this->Top);}
// Description:
// Get back a list of the nodes at a specified level, nodes must
// be preallocated to hold 2^^(level) node structures.
void GetRegionsAtLevel(int level, vtkKdNode **nodes);
// Description:
// Adds to the vtkIntArray the list of region IDs of all leaf
// nodes in the given node.
static void GetLeafNodeIds(vtkKdNode *node, vtkIntArray *ids);
// Description:
// Returns the total number of cells in all the data sets
int GetNumberOfCells();
// Description:
// Returns the total number of cells in data set 1 through
// data set 2.
int GetDataSetsNumberOfCells(int set1, int set2);
// Description:
// Get or compute the center of one cell. If the DataSet is
// NULL, the first DataSet is used. This is the point used in
// determining to which spatial region the cell is assigned.
void ComputeCellCenter(vtkDataSet *set, int cellId, float *center);
void ComputeCellCenter(vtkDataSet *set, int cellId, double *center);
// Description:
// Compute and return a pointer to a list of all cell centers,
// in order by data set by cell Id. If a DataSet is specified
// cell centers for cells of that data only are returned. If
// no DataSet is specified, the cell centers of cells in all
// DataSets are returned. The caller should free the list of
// cell centers when done.
float *ComputeCellCenters();
float *ComputeCellCenters(int set);
float *ComputeCellCenters(vtkDataSet *set);
virtual void ReportReferences(vtkGarbageCollector*);
private:
static void _SetNewBounds(vtkKdNode *kd, double *b, int *fixDim);
static void CopyChildNodes(vtkKdNode *to, vtkKdNode *from);
static void CopyKdNode(vtkKdNode *to, vtkKdNode *from);
static void SetDataBoundsToSpatialBounds(vtkKdNode *kd);
static void ZeroNumberOfPoints(vtkKdNode *kd);
//BTX
int DivideRegion(vtkKdNode *kd, float *c1, int *ids, int nlevels);
void DoMedianFind(vtkKdNode *kd, float *c1, int *ids, int d1, int d2, int d3);
void SelfRegister(vtkKdNode *kd);
struct _cellList{
vtkDataSet *dataSet; // cell lists for which data set
int *regionIds; // NULL if listing all regions
int nRegions;
vtkIdList **cells;
vtkIdList **boundaryCells;
vtkIdList *emptyList;
};
//ETX
void InitializeCellLists();
vtkIdList *GetList(int regionId, vtkIdList **which);
void ComputeCellCenter(vtkCell* cell, double *center, double *weights);
void GenerateRepresentationDataBounds(int level, vtkPolyData *pd);
void _generateRepresentationDataBounds(vtkKdNode *kd, vtkPoints *pts,
vtkCellArray *polys, int level);
void GenerateRepresentationWholeSpace(int level, vtkPolyData *pd);
void _generateRepresentationWholeSpace(vtkKdNode *kd, vtkPoints *pts,
vtkCellArray *polys, int level);
void AddPolys(vtkKdNode *kd, vtkPoints *pts, vtkCellArray *polys);
void _printTree(int verbose);
int SearchNeighborsForDuplicate(int regionId, float *point,
int **pointsSoFar, int *len,
float tolerance, float tolerance2);
int SearchRegionForDuplicate(float *point, int *pointsSoFar,
int len, float tolerance2);
int _FindClosestPointInRegion(int regionId,
double x, double y, double z, double &dist2);
int FindClosestPointInSphere(double x, double y, double z, double radius,
int skipRegion, double &dist2);
int _DepthOrderRegions(vtkIntArray *IdsOfInterest, double *dop,
vtkIntArray *orderedList);
static int __DepthOrderRegions(vtkKdNode *node, vtkIntArray *list,
vtkIntArray *IdsOfInterest, double *dir, int nextId);
static int __ConvexSubRegions(int *ids, int len, vtkKdNode *tree, vtkKdNode **nodes);
static int FoundId(vtkIntArray *idArray, int id);
void NewParitioningRequest(int req);
void SetInputDataInfo(int i,
int dims[3], double origin[3], double spacing[3]);
int CheckInputDataInfo(int i,
int dims[3], double origin[3], double spacing[3]);
void ClearLastBuildCache();
//BTX
static void __printTree(vtkKdNode *kd, int depth, int verbose);
//ETX
static int MidValue(int dim, float *c1, int nvals, double &coord);
static int Select(int dim, float *c1, int *ids, int nvals, double &coord);
static float FindMaxLeftHalf(int dim, float *c1, int K);
static void _Select(int dim, float *X, int *ids, int L, int R, int K);
//BTX
static int ComputeLevel(vtkKdNode *kd);
static int SelfOrder(int id, vtkKdNode *kd);
static int findRegion(vtkKdNode *node, float x, float y, float z);
static int findRegion(vtkKdNode *node, double x, double y, double z);
//ETX
static vtkKdNode **_GetRegionsAtLevel(int level, vtkKdNode **nodes,
vtkKdNode *kd);
static void AddNewRegions(vtkKdNode *kd, float *c1,
int midpt, int dim, double coord);
void NewPartitioningRequest(int req);
int NumDataSetsAllocated;
int NumberOfRegionsOrLess;
int NumberOfRegionsOrMore;
int IncludeRegionBoundaryCells;
double CellBoundsCache[6]; // to optimize IntersectsCell()
int GenerateRepresentationUsingDataBounds;
//BTX
struct _cellList CellList;
//ETX
// Region Ids, by data set by cell id - this list is large (one
// int per cell) but accelerates creation of cell lists
int *CellRegionList;
int MinCells;
int NumberOfRegions; // number of leaf nodes
int Timing;
double FudgeFactor; // a very small distance, relative to the dataset's size
vtkDataSet **DataSets;
int NumDataSets;
// These instance variables are used by the special locator created
// to find duplicate points. (BuildLocatorFromPoints)
int NumberOfLocatorPoints;
float *LocatorPoints;
int *LocatorIds;
int *LocatorRegionLocation;
float MaxWidth;
// These Last* values are here to save state so we can
// determine later if k-d tree must be rebuilt.
int LastNumDataSets;
int LastDataCacheSize;
vtkDataSet **LastInputDataSets;
int *LastDataSetType;
double *LastInputDataInfo;
double *LastBounds;
int *LastNumPoints;
int *LastNumCells;
vtkBSPCuts *Cuts;
vtkKdTree(const vtkKdTree&); // Not implemented
void operator=(const vtkKdTree&); // Not implemented
};
#endif