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.

296 lines
11 KiB
C

/*=========================================================================
Program: Visualization Toolkit
Module: vtkPointLocator.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 vtkPointLocator
* @brief quickly locate points in 3-space
*
* vtkPointLocator is a spatial search object to quickly locate points in 3D.
* vtkPointLocator works by dividing a specified region of space into a regular
* array of "rectangular" buckets, and then keeping a list of points that
* lie in each bucket. Typical operation involves giving a position in 3D
* and finding the closest point.
*
* vtkPointLocator has two distinct methods of interaction. In the first
* method, you supply it with a dataset, and it operates on the points in
* the dataset. In the second method, you supply it with an array of points,
* and the object operates on the array.
*
* @warning
* Many other types of spatial locators have been developed such as
* octrees and kd-trees. These are often more efficient for the
* operations described here.
*
* @sa
* vtkCellPicker vtkPointPicker vtkStaticPointLocator
*/
#ifndef vtkPointLocator_h
#define vtkPointLocator_h
#include "vtkCommonDataModelModule.h" // For export macro
#include "vtkIncrementalPointLocator.h"
class vtkCellArray;
class vtkIdList;
class vtkNeighborPoints;
class vtkPoints;
class VTKCOMMONDATAMODEL_EXPORT vtkPointLocator : public vtkIncrementalPointLocator
{
public:
/**
* Construct with automatic computation of divisions, averaging
* 25 points per bucket.
*/
static vtkPointLocator* New();
//@{
/**
* Standard methods for type management and printing.
*/
vtkTypeMacro(vtkPointLocator, vtkIncrementalPointLocator);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@}
//@{
/**
* Set the number of divisions in x-y-z directions.
*/
vtkSetVector3Macro(Divisions, int);
vtkGetVectorMacro(Divisions, int, 3);
//@}
//@{
/**
* Specify the average number of points in each bucket.
*/
vtkSetClampMacro(NumberOfPointsPerBucket, int, 1, VTK_INT_MAX);
vtkGetMacro(NumberOfPointsPerBucket, int);
//@}
// Re-use any superclass signatures that we don't override.
using vtkAbstractPointLocator::FindClosestPoint;
/**
* Given a position x, return the id of the point closest to it. Alternative
* method requires separate x-y-z values.
* These methods are thread safe if BuildLocator() is directly or
* indirectly called from a single thread first.
*/
vtkIdType FindClosestPoint(const double x[3]) override;
//@{
/**
* Given a position x and a radius r, return the id of the point
* closest to the point in that radius.
* These methods are thread safe if BuildLocator() is directly or
* indirectly called from a single thread first. dist2 returns the squared
* distance to the point.
*/
vtkIdType FindClosestPointWithinRadius(double radius, const double x[3], double& dist2) override;
virtual vtkIdType FindClosestPointWithinRadius(
double radius, const double x[3], double inputDataLength, double& dist2);
//@}
/**
* Initialize the point insertion process. The newPts is an object
* representing point coordinates into which incremental insertion methods
* place their data. Bounds are the box that the points lie in.
* Not thread safe.
*/
int InitPointInsertion(vtkPoints* newPts, const double bounds[6]) override;
/**
* Initialize the point insertion process. The newPts is an object
* representing point coordinates into which incremental insertion methods
* place their data. Bounds are the box that the points lie in.
* Not thread safe.
*/
int InitPointInsertion(vtkPoints* newPts, const double bounds[6], vtkIdType estSize) override;
/**
* Incrementally insert a point into search structure with a particular
* index value. You should use the method IsInsertedPoint() to see whether
* this point has already been inserted (that is, if you desire to prevent
* duplicate points). Before using this method you must make sure that
* newPts have been supplied, the bounds has been set properly, and that
* divs are properly set. (See InitPointInsertion().)
* Not thread safe.
*/
void InsertPoint(vtkIdType ptId, const double x[3]) override;
/**
* Incrementally insert a point into search structure. The method returns
* the insertion location (i.e., point id). You should use the method
* IsInsertedPoint() to see whether this point has already been
* inserted (that is, if you desire to prevent duplicate points).
* Before using this method you must make sure that newPts have been
* supplied, the bounds has been set properly, and that divs are
* properly set. (See InitPointInsertion().)
* Not thread safe.
*/
vtkIdType InsertNextPoint(const double x[3]) override;
//@{
/**
* Determine whether point given by x[3] has been inserted into points list.
* Return id of previously inserted point if this is true, otherwise return
* -1. This method is thread safe.
*/
vtkIdType IsInsertedPoint(double x, double y, double z) override
{
double xyz[3];
xyz[0] = x;
xyz[1] = y;
xyz[2] = z;
return this->IsInsertedPoint(xyz);
};
vtkIdType IsInsertedPoint(const double x[3]) override;
//@}
/**
* Determine whether point given by x[3] has been inserted into points list.
* Return 0 if point was already in the list, otherwise return 1. If the
* point was not in the list, it will be ADDED. In either case, the id of
* the point (newly inserted or not) is returned in the ptId argument.
* Note this combines the functionality of IsInsertedPoint() followed
* by a call to InsertNextPoint().
* This method is not thread safe.
*/
int InsertUniquePoint(const double x[3], vtkIdType& ptId) override;
/**
* Given a position x, return the id of the point closest to it. This method
* is used when performing incremental point insertion. Note that -1
* indicates that no point was found.
* This method is thread safe if BuildLocator() is directly or
* indirectly called from a single thread first.
*/
vtkIdType FindClosestInsertedPoint(const double x[3]) override;
/**
* Find the closest N points to a position. This returns the closest
* N points to a position. A faster method could be created that returned
* N close points to a position, but necessarily the exact N closest.
* The returned points are sorted from closest to farthest.
* These methods are thread safe if BuildLocator() is directly or
* indirectly called from a single thread first.
*/
void FindClosestNPoints(int N, const double x[3], vtkIdList* result) override;
//@{
/**
* Find the closest points to a position such that each octant of
* space around the position contains at least N points. Loosely
* limit the search to a maximum number of points evaluated, M.
* These methods are thread safe if BuildLocator() is directly or
* indirectly called from a single thread first.
*/
virtual void FindDistributedPoints(int N, const double x[3], vtkIdList* result, int M);
virtual void FindDistributedPoints(int N, double x, double y, double z, vtkIdList* result, int M);
//@}
/**
* Find all points within a specified radius R of position x.
* The result is not sorted in any specific manner.
* These methods are thread safe if BuildLocator() is directly or
* indirectly called from a single thread first.
*/
void FindPointsWithinRadius(double R, const double x[3], vtkIdList* result) override;
/**
* Given a position x, return the list of points in the bucket that
* contains the point. It is possible that nullptr is returned. The user
* provides an ijk array that is the indices into the locator.
* This method is thread safe.
*/
virtual vtkIdList* GetPointsInBucket(const double x[3], int ijk[3]);
//@{
/**
* Provide an accessor to the points.
*/
vtkGetObjectMacro(Points, vtkPoints);
//@}
//@{
/**
* See vtkLocator interface documentation.
* These methods are not thread safe.
*/
void Initialize() override;
void FreeSearchStructure() override;
void BuildLocator() override;
void GenerateRepresentation(int level, vtkPolyData* pd) override;
//@}
protected:
vtkPointLocator();
~vtkPointLocator() override;
// place points in appropriate buckets
void GetBucketNeighbors(
vtkNeighborPoints* buckets, const int ijk[3], const int ndivs[3], int level);
void GetOverlappingBuckets(
vtkNeighborPoints* buckets, const double x[3], const int ijk[3], double dist, int level);
void GetOverlappingBuckets(vtkNeighborPoints* buckets, const double x[3], double dist,
int prevMinLevel[3], int prevMaxLevel[3]);
void GenerateFace(int face, int i, int j, int k, vtkPoints* pts, vtkCellArray* polys);
double Distance2ToBucket(const double x[3], const int nei[3]);
double Distance2ToBounds(const double x[3], const double bounds[6]);
vtkPoints* Points; // Used for merging points
int Divisions[3]; // Number of sub-divisions in x-y-z directions
int NumberOfPointsPerBucket; // Used with previous boolean to control subdivide
vtkIdList** HashTable; // lists of point ids in buckets
double H[3]; // width of each bucket in x-y-z directions
double InsertionTol2;
vtkIdType InsertionPointId;
double InsertionLevel;
// These are inlined methods and data members for performance reasons
double HX, HY, HZ;
double FX, FY, FZ, BX, BY, BZ;
vtkIdType XD, YD, ZD, SliceSize;
void GetBucketIndices(const double* x, int ijk[3]) const
{
// Compute point index. Make sure it lies within range of locator.
vtkIdType tmp0 = static_cast<vtkIdType>(((x[0] - this->BX) * this->FX));
vtkIdType tmp1 = static_cast<vtkIdType>(((x[1] - this->BY) * this->FY));
vtkIdType tmp2 = static_cast<vtkIdType>(((x[2] - this->BZ) * this->FZ));
ijk[0] = tmp0 < 0 ? 0 : (tmp0 >= this->XD ? this->XD - 1 : tmp0);
ijk[1] = tmp1 < 0 ? 0 : (tmp1 >= this->YD ? this->YD - 1 : tmp1);
ijk[2] = tmp2 < 0 ? 0 : (tmp2 >= this->ZD ? this->ZD - 1 : tmp2);
}
vtkIdType GetBucketIndex(const double* x) const
{
int ijk[3];
this->GetBucketIndices(x, ijk);
return ijk[0] + ijk[1] * this->XD + ijk[2] * this->SliceSize;
}
void ComputePerformanceFactors();
private:
vtkPointLocator(const vtkPointLocator&) = delete;
void operator=(const vtkPointLocator&) = delete;
};
#endif