当你看到找最近点时,可能会立刻想到在一堆点中,通过距离找出最近的点,没错,这是一种寻找最近点的需求。今天我们要说的是另一种寻找最近点的需求,就是在Mesh上找最近点,这个点不一定是Mesh的顶点。
多边形网格是由很多个小的单元组成,类似于这样:
我们拿其中一个单元格cell来简化模型,
空间中有一个点p,p到cell的最近点要怎么求得?
如果我们把cell想象成一个平面,那就变成了,p到平面ABCD的投影,也是从p点做垂线,求垂线与平面的交点。
没错,这就是vtkCellLocator的基本思想。
vtkCellLocator
vtkCellLocator本身是一个octree。典型的用法就是求最近的单元或者点。
使用方法
// Create the tree
auto cellLocator = vtkSmartPointer<vtkCellLocator>::New();
cellLocator->SetDataSet(sphereSource->GetOutput());
cellLocator->BuildLocator();
double testPoint[3] = {0.6, 0.5, 0.0};
//Find the closest points to TestPoint
auto assistCell = vtkSmartPointer<vtkGenericCell>::New();
double closestPoint[3];//the coordinates of the closest point will be returned here
double closestPointDist2; //the squared distance to the closest point will be returned here
vtkIdType cellId; //the cell id of the cell containing the closest point will be returned here
int subId;
cellLocator->FindClosestPoint(testPoint, closestPoint, assistCell, cellId, subId, closestPointDist2);
注意:
- 这里FindClosestPoint方法中用到的vtkGenericCell,是为了提高效率,在循环调用时,免除频繁分配和释放资源。
- 这个方法并不是线程安全的,线程安全,可以考虑,vtkStaticCellLocator
示例
在一个球体上找离测试点最近的点。绿色表示测试点,红色表示求得到最近点。
CellLocator.cxx
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkCellLocator.h>
#include <vtkGenericCell.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
int main(int, char *[])
{
auto sphereSource = vtkSmartPointer<vtkSphereSource>::New();
sphereSource->Update();
// Create the tree
auto cellLocator = vtkSmartPointer<vtkCellLocator>::New();
cellLocator->SetDataSet(sphereSource->GetOutput());
cellLocator->BuildLocator();
double testPoint[3] = {0.6, 0.5, 0.0};
//Find the closest points to TestPoint
auto assistCell = vtkSmartPointer<vtkGenericCell>::New();
double closestPoint[3];//the coordinates of the closest point will be returned here
double closestPointDist2; //the squared distance to the closest point will be returned here
vtkIdType cellId; //the cell id of the cell containing the closest point will be returned here
int subId;
cellLocator->FindClosestPoint(testPoint, closestPoint, assistCell, cellId, subId, closestPointDist2);
std::cout << "Coordinates of closest point: " << closestPoint[0] << " " << closestPoint[1] << " " << closestPoint[2] << std::endl;
std::cout << "Squared distance to closest point: " << closestPointDist2 << std::endl;
std::cout << "CellId: " << cellId << std::endl;
auto testSource = vtkSmartPointer<vtkSphereSource>::New();
testSource->SetRadius(0.01);
testSource->SetCenter(testPoint);
testSource->Update();
auto pointSource = vtkSmartPointer<vtkSphereSource>::New();
pointSource->SetRadius(0.01);
pointSource->SetCenter(closestPoint);
pointSource->Update();
vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> testMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
testMapper->SetInputConnection(testSource->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> pointMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
pointMapper->SetInputConnection(pointSource->GetOutputPort());
auto sphereActor = vtkSmartPointer<vtkActor>::New();
sphereActor->SetMapper(sphereMapper);
sphereActor->GetProperty()->EdgeVisibilityOn();
auto pointActor = vtkSmartPointer<vtkActor>::New();
pointActor->SetMapper(pointMapper);
pointActor->GetProperty()->SetColor(1, 0, 0);
auto testActor = vtkSmartPointer<vtkActor>::New();
testActor->SetMapper(testMapper);
testActor->GetProperty()->SetColor(0, 1, 0);
auto render = vtkSmartPointer<vtkRenderer>::New();
render->AddActor(sphereActor);
render->AddActor(pointActor);
render->AddActor(testActor);
auto renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->SetSize(640, 480);
renWin->AddRenderer(render);
auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renWin);
renWin->Render();
interactor->Initialize();
interactor->Start();
return EXIT_SUCCESS;
}
Ref
vtkCellLocator Class Reference
VTKExamples/Cxx/PolyData/CellLocator