VTK笔记——寻找最近点(vtkCellLocator)

本文介绍了一种在三维网格(Mesh)上查找最近点的方法,使用vtkCellLocator类实现。vtkCellLocator是一种八叉树结构,用于高效地在Mesh中找到离给定点最近的点或单元。文章详细展示了如何构建vtkCellLocator并使用FindClosestPoint方法查找最近点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当你看到找最近点时,可能会立刻想到在一堆点中,通过距离找出最近的点,没错,这是一种寻找最近点的需求。今天我们要说的是另一种寻找最近点的需求,就是在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);

注意:

  1. 这里FindClosestPoint方法中用到的vtkGenericCell,是为了提高效率,在循环调用时,免除频繁分配和释放资源。
  2. 这个方法并不是线程安全的,线程安全,可以考虑,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
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值