欢迎大家加入VTK社区雪易VTK社区-CSDN社区云
小结:本博文主要针对VTK中的PointLocator的分类及各接口的用途进行讲解,PointLocator主要用途为点的位置计算,希望能为各位小伙伴有所帮助。
vtk中关于Locator的关系图
目录
vtkIncrementalOctreePointLocator
vtkLocator
描述:vtkLocator是空间搜索对象或定位对象的基类。vtkLocator的工作原理是将三维空间切分为很多小区域,这样在点定位、线相交和对象之间的相交的问题求解时,可以快速给出响应。
vtkLocator作为基类,为所有的Locator接口提供数据成员和方法。
Locator的工作原理如下:
1. 在Locator划分的区域中插入一个或多个“entities”,比如Point或者Cell。这些“entities”占一个或多个区域。
2. 执行几何操作时,先对区域进行操作,若结果为正,则对区域中的“entities”进行操作。例如在碰撞测试时,首先碰撞定位器识别相交的区域,若发现交集,在对区域中的"entities"进行相交计算。
为了提高速度,Locator采用树形结构。
vtkAbstractPointLocator
描述:vtkAbstractPointLocator是一个在3D中快速定位点的基类。它将3D空间划分为规则的区域,将将Points放置在这些区域中。一个典型的操作就是找出给定点的最近点。
三个常用的虚函数
//@{
/**
* 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.
*/
virtual vtkIdType FindClosestPoint(const double x[3]) = 0;
vtkIdType FindClosestPoint(double x, double y, double z);
//@}
/**
* Given a position x and a radius r, return the id of the point
* closest to the point in that radius.
* dist2 returns the squared distance to the point.
*/
virtual vtkIdType FindClosestPointWithinRadius(
double radius, const double x[3], double& dist2) = 0;
//@{
/**
* 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.
*/
virtual void FindClosestNPoints(int N, const double x[3], vtkIdList* result) = 0;
void FindClosestNPoints(int N, double x, double y, double z, vtkIdList* result);
//@}
//@{
/**
* 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.
*/
virtual void FindPointsWithinRadius(double R, const double x[3], vtkIdList* result) = 0;
void FindPointsWithinRadius(double R, double x, double y, double z, vtkIdList* result);
//@}
vtkIncrementalPointLocator
描述:vtkIncreamentalPointLocator是一个既支持点定位也支持点插入的基类。
该Filter可支持点插入功能,搜索结构保持动态增加。以下是两个支持插入点的Filter。vtkIncrementalOctreePointLocator是vtkPointLocator所有功能的基于八叉树的加速实现。
vtkPointLocator
描述:vtkPointLocator是一个在3D中快速定位点的类。它将3D空间划分为规则的区域,将将Points放置在这些区域中。一个典型的操作就是找出给定点的最近点。
vtkPointLocator有两种不同的交互方法。在第一种方法中,您为它提供一个数据集,它对数据集中的点进行操作。在第二种方法中,为它提供一个点数组,对象对数组进行操作。
vtkMergePoints
描述:vtkMergePoints是一个定位器对象,用于快速定位3D中的点。
vtkMergePoints与其父类vtkPointLocator之间的主要区别是vtkMergePoints精确地合并重合点,因此要快得多。
//@{
/**
* 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.
* 判断点x是否被插入到点列表中,若插入则但会id,若没有插入则返回-1
*/
vtkIdType IsInsertedPoint(const double x[3]) override;
vtkIdType IsInsertedPoint(double x, double y, double z) override
{
return this->vtkPointLocator::IsInsertedPoint(x, y, z);
}
//@}
//实现步骤
//定位点x所在的Bucket的id
//查看id是否在Table表中,若不在,则表示该点不在点列表中
//若存在,则获取Bucket中的点,并于点下进行比较,返回一致点的Id
vtkIdType vtkMergePoints::IsInsertedPoint(const double x[3])
{
//
// Locate bucket that point is in.
//
vtkIdType idx = this->GetBucketIndex(x);
vtkIdList* bucket = this->HashTable[idx];
if (!bucket)
{
return -1;
}
else // see whether we've got duplicate point
{
//
// Check the list of points in that bucket.
//
vtkIdType ptId;
vtkIdType nbOfIds = bucket->GetNumberOfIds();
// For efficiency reasons, we break the data abstraction for points
// and ids (we are assuming and vtkIdList
// is storing ints).
vtkDataArray* dataArray = this->Points->GetData();
vtkIdType* idArray = bucket->GetPointer(0);
if (dataArray->GetDataType() == VTK_FLOAT)
{
float f[3];
f[0] = static_cast<float>(x[0]);
f[1] = static_cast<float>(x[1]);
f[2] = static_cast<float>(x[2]);
vtkFloatArray* floatArray = static_cast<vtkFloatArray*>(dataArray);
float* pt;
for (vtkIdType i = 0; i < nbOfIds; i++)
{
ptId = idArray[i];
pt = floatArray->GetPointer(0) + 3 * ptId;
if (f[0] == pt[0] && f[1] == pt[1] && f[2] == pt[2])
{
return ptId;
}
}
}
else
{
// Using the double interface
double* pt;
for (vtkIdType i = 0; i < nbOfIds; i++)
{
ptId = idArray[i];
pt = dataArray->GetTuple(ptId);
if (x[0] == pt[0] && x[1] == pt[1] && x[2] == pt[2])
{
return ptId;
}
}
}
}
return -1;
}
/**
* 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().
* 判断点x是否加入到点列表中,若已加入则返回0,否则返回1。
* 若点x未在点列表中,则会将其加入。加入的id将会在ptId中返回。
*/
int InsertUniquePoint(const double x[3], vtkIdType& ptId) override;
//实现步骤
//定位点x所在的Bucket的id
//查看id是否在Table表中
//若存在,则获取Bucket中的点,并于点下进行比较,若存在一致点则返回0,Id为一致点的Id
//若不存在,则通过InsertNextId和InsertPoint将该点添加,并Id设为一致点的Id
int vtkMergePoints::InsertUniquePoint(const double x[3], vtkIdType& id)
{
//
// Locate bucket that point is in.
//
vtkIdType idx = this->GetBucketIndex(x);
vtkIdList* bucket = this->HashTable[idx];
if (bucket) // see whether we've got duplicate point
{
//
// Check the list of points in that bucket.
//
vtkIdType ptId;
vtkIdType nbOfIds = bucket->GetNumberOfIds();
// For efficiency reasons, we break the data abstraction for points
// and ids (we are assuming vtkPoints stores a vtkIdList
// is storing ints).
vtkDataArray* dataArray = this->Points->GetData();
vtkIdType* idArray = bucket->GetPointer(0);
if (dataArray->GetDataType() == VTK_FLOAT)
{
float f[3];
f[0] = static_cast<float>(x[0]);
f[1] = static_cast<float>(x[1]);
f[2] = static_cast<float>(x[2]);
float* floatArray = static_cast<vtkFloatArray*>(dataArray)->GetPointer(0);
float* pt;
for (vtkIdType i = 0; i < nbOfIds; ++i)
{
ptId = idArray[i];
pt = floatArray + 3 * ptId;
if (f[0] == pt[0] && f[1] == pt[1] && f[2] == pt[2])
{
// point is already in the list, return 0 and set the id parameter
id = ptId;
return 0;
}
}
}
else
{
// Using the double interface
double* pt;
for (vtkIdType i = 0; i < nbOfIds; ++i)
{
ptId = idArray[i];
pt = dataArray->GetTuple(ptId);
if (x[0] == pt[0] && x[1] == pt[1] && x[2] == pt[2])
{
// point is already in the list, return 0 and set the id parameter
id = ptId;
return 0;
}
}
}
}
else
{
// create a bucket point list and insert the point
bucket = vtkIdList::New();
bucket->Allocate(this->NumberOfPointsPerBucket / 2, this->NumberOfPointsPerBucket / 3);
this->HashTable[idx] = bucket;
}
// point has to be added
bucket->InsertNextId(this->InsertionPointId);
this->Points->InsertPoint(this->InsertionPointId, x);
id = this->InsertionPointId++;
return 1;
}
vtkNonMergingPointLocator
描述:作为vtkPointLocator的一个特殊子类,vtkNonMergingPointLocator用于直接/无检查地将点插入到vtkPoints对象中。换句话说,任何给定的点总是直接插入的。这个名字强调了这个类与其兄弟类vtkMergePoints之间的区别,后者通过利用父类vtkPointLocator使用的统一bin机制来执行基于检查的零容忍点插入(或“合并”完全重复/重合的点)。vtkPointLocator允许一般(零和非零)公差点插入以及点定位。
vtkIncrementalOctreePointLocator
描述:与具有固定空间分辨率的统一的基于bin的搜索结构(在类vtkPointLocator中采用)相反,八叉树机制采用了3D数据域的树状细分层次结构。因此,它实现了数据感知的多分辨率,并相应地加速了点的定位和插入,特别是在处理自适应网格上定义的数据集中不常见的点的根本不平衡布局时。静态点定位器通过从一组固定的点建立一些搜索结构来支持纯位置功能,与之相比,增量点定位器还允许点插入功能,搜索结构保持动态增加的点数量。类vtkIncrementalOctreePointLocator是统一的基于二进制的增量点定位器vtkPointLocator功能的基于八叉树的加速实现。对于点定位,通过访问vtkDataSet(特别是vtkPointSet)来构建八叉树。对于点插入,会初始化一个空八叉树,然后随着点的插入逐渐填充。支持三种日益复杂的点插入方式,即直接无校验插入、零公差插入和非零公差插入。事实上,在点定位模式中使用的八叉树实际上是通过直接无校验点插入构造的。这个类还提供了八叉树边界的多边形表示。
vtkKdTreePointLocator
1. ClosestNPoints
#include <vtkCellArray.h>
#include <vtkIdList.h>
#include <vtkKdTreePointLocator.h>
#include <vtkPointSource.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
int main(int, char *[]) {
// Create some random points
vtkSmartPointer<vtkPointSource> pointSource =
vtkSmartPointer<vtkPointSource>::New();
pointSource->SetNumberOfPoints(10);
pointSource->Update();
// Create the tree
vtkSmartPointer<vtkKdTreePointLocator> pointTree =
vtkSmartPointer<vtkKdTreePointLocator>::New();
pointTree->SetDataSet(pointSource->GetOutput());
pointTree->BuildLocator();
// Find the k closest points to (0,0,0)
unsigned int k = 1;
double testPoint[3] = {0.0, 0.0, 0.0};
vtkSmartPointer<vtkIdList> result = vtkSmartPointer<vtkIdList>::New();
pointTree->FindClosestNPoints(k, testPoint, result);
for (vtkIdType i = 0; i < k; i++) {
vtkIdType point_ind = result->GetId(i);
double p[3];
pointSource->GetOutput()->GetPoint(point_ind, p);
std::cout << "Closest point " << i << ": Point " << point_ind << ": ("
<< p[0] << ", " << p[1] << ", " << p[2] << ")" << std::endl;
}
// Should return:
// Closest point 0: Point 2: (-0.136162, -0.0276359, 0.0369441)
return EXIT_SUCCESS;
}