VTK 判断一个 点 是否在一个模型 stl 内部 vtk 点是否在内部 表面 寻找最近点

判断 一个点 ,判断是否在风格 stl 模型内部,或表面:

目录

1.方案一:使用vtkCellLocator  FindClosestPoint 找到模型上距离给定点最近的一点,计算两点的距离 ,小于某一阈值 则认为此点在模型上;

2.方案二 使用 vtkKdTreePointLocator

3.方案三 使用 vtkSelectEnclosedPoints


1.方案一:使用vtkCellLocator  FindClosestPoint 找到模型上距离给定点最近的一点,计算两点的距离 ,小于某一阈值 则认为此点在模型上;

vtkCellLocator本身是一个octree。典型的用法就是求最近的单元或者点

bool CheckPointInsidePolyData(vtkPolyData * poly, double* pt)
{
	bool inside=false; 
	auto cellLocator = vtkSmartPointer<vtkCellLocator>::New();
	cellLocator->SetDataSet(poly);
	cellLocator->BuildLocator();
	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=-1;
	cellLocator->FindClosestPoint(point, closestPoint, assistCell, cellId, subId, closestPointDist2);
 
	if (-1!= subId&&closestPointDist2 < 0.001)
	{
		return true;
	}
	return inside;
}

2.方案二 使用 vtkKdTreePointLocator

但这个只能找到最新的点,还需要自己判断一下距离

官方样例:

#include <vtkIdList.h>
#include <vtkKdTreePointLocator.h>
#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>

int main(int, char*[])
{
  // Setup point coordinates
  double x[3] = {1.0, 0.0, 0.0};
  double y[3] = {0.0, 1.0, 0.0};
  double z[3] = {0.0, 0.0, 1.0};

  vtkNew<vtkPoints> points;
  points->InsertNextPoint(x);
  points->InsertNextPoint(y);
  points->InsertNextPoint(z);

  vtkNew<vtkPolyData> polydata;
  polydata->SetPoints(points);

  // Create the tree
  vtkNew<vtkKdTreePointLocator> kDTree;
  kDTree->SetDataSet(polydata);
  kDTree->BuildLocator();

  double testPoint[3] = {2.0, 0.0, 0.0};

  // Find the closest points to TestPoint
  vtkIdType iD = kDTree->FindClosestPoint(testPoint);
  std::cout << "The closest point is point " << iD << std::endl;

  // Get the coordinates of the closest point
  double closestPoint[3];
  kDTree->GetDataSet()->GetPoint(iD, closestPoint);
  std::cout << "Coordinates: " << closestPoint[0] << " " << closestPoint[1]
            << " " << closestPoint[2] << std::endl;

  return EXIT_SUCCESS;
}

3.方案三 使用 vtkSelectEnclosedPoints

vtkSelectEnclosedPoints类可以判断标记点是否在封闭表面内。
vtkSelectEnclosedPoints是一个Filter,它计算所有输入点以确定它们是否位于封闭曲面中。过滤器生成一个(0,1)掩码(以vtkDataArray的形式),指示点是在提供的曲面的外部(掩码值=0)还是内部(掩码值=1)(输出vtkDataArray的名称是“SelectedPoints”。)
运行过滤器后,可以通过调用IsInside(ptId)方法来查询点是否在内部/外部。

样例:判断三个点是否在立方体内

注意:在立方体边上的点,不属于在立方体内部;

 CODE

#include <vtkVersion.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkCubeSource.h>
#include <vtkSmartPointer.h>
#include <vtkSelectEnclosedPoints.h>
#include <vtkIntArray.h>
#include <vtkDataArray.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>

int main(int, char*[])
{

	vtkNew<vtkCubeSource> cubeSource;
	cubeSource->Update();

	vtkPolyData* cube = cubeSource->GetOutput();

	double testInside[3] = { 0.0, 0.0, 0.0 };
	double testOutside[3] = { 0.7, 0.0, 0.0 };
	double testBorderOutside[3] = { 0.5, 0.0, 0.0 };
	vtkNew<vtkPoints> points;
	points->InsertNextPoint(testInside);
	points->InsertNextPoint(testOutside);
	points->InsertNextPoint(testBorderOutside);

	vtkNew<vtkPolyData> pointsPolydata;
	pointsPolydata->SetPoints(points);

	//Points inside test
	vtkNew<vtkSelectEnclosedPoints> selectEnclosedPoints;
	selectEnclosedPoints->SetInputData(pointsPolydata);
	selectEnclosedPoints->SetSurfaceData(cube);
	selectEnclosedPoints->Update();

	for (unsigned int i = 0; i < 3; i++) {
		std::cout << "Point " << i << ": " << selectEnclosedPoints->IsInside(i) << std::endl;
	}

	vtkDataArray* insideArray = vtkDataArray::SafeDownCast(selectEnclosedPoints->GetOutput()->GetPointData()->GetArray("SelectedPoints"));

	for (vtkIdType i = 0; i < insideArray->GetNumberOfTuples(); i++) {
		std::cout << i << " : " << insideArray->GetComponent(i, 0) << std::endl;
	}
	//Cube mapper, actor
	vtkNew<vtkPolyDataMapper> cubeMapper;
	cubeMapper->SetInputConnection(cubeSource->GetOutputPort());

	vtkNew<vtkActor> cubeActor;
	cubeActor->SetMapper(cubeMapper);
	cubeActor->GetProperty()->SetOpacity(0.5);

	//First, apply vtkVertexGlyphFilter to make cells around points, vtk only render cells.
	vtkNew<vtkVertexGlyphFilter> vertexGlyphFilter;

	vertexGlyphFilter->AddInputData(pointsPolydata);
	vertexGlyphFilter->Update();

	vtkNew<vtkPolyDataMapper> pointsMapper;
	pointsMapper->SetInputConnection(vertexGlyphFilter->GetOutputPort());

	vtkNew<vtkActor> pointsActor;
	pointsActor->SetMapper(pointsMapper);
	pointsActor->GetProperty()->SetPointSize(5); 
	pointsActor->GetProperty()->SetColor(1.0, 0.0, 0);

	//Create a renderer, render window, and interactor
	vtkNew<vtkRenderer> renderer;
	vtkNew<vtkRenderWindow> renderWindow;
	renderWindow->AddRenderer(renderer);
	vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
	renderWindowInteractor->SetRenderWindow(renderWindow);

	// Add the actor to the scene
	renderer->AddActor(cubeActor);
	renderer->AddActor(pointsActor);
	renderer->SetBackground(.0, 1, .0);

	renderWindow->Render();
	renderWindowInteractor->Start();
	return EXIT_SUCCESS;
}
 
 

输出:

Point 0: 1
Point 1: 0
Point 2: 0
0 : 1
1 : 0
2 : 0

VTK(Visualization Toolkit)是一个强大的开源软件库,主要用于科学可视化、医学图像处理和图形应用程序开发。当你提到将两个STL(标准三角化语言)文件合并为一个,这是VTK一个应用场景之一,尤其是在处理几何模型的时候。 在VTK中,你可以使用`vtkSTLReader`来读取单个或多个STL文件,然后使用如`vtkAppendPolyData`或者`vtkMergePolyData`这样的滤波器将它们组合在一起。具体步骤可能包括: 1. 创建`vtkSTLReader`实例,并分别加载两个STL文件。 2. 如果需要对模型进行预处理(例如清理、修剪),可以使用`vtkCleanPolyData`或`vtkClipPolyData`等。 3. 使用`vtkAppendPolyData`过滤器,设置其源数据为读取到的两个`vtkPolyData`对象,将其结果输出到一个新的`vtkPolyData`。 4. 最后,如果需要保存这个合并后的模型,可以创建一个`vtkSTLWriter`,设置输出文件名,然后调用其Write方法将合并后的`vtkPolyData`写入新的STL文件。 如果你想要代码示例,这里有一个简单的伪代码框架: ```python import vtk # 创建STL读者 reader1 = vtk.vtkSTLReader() reader1.SetFileName("file1.stl") reader2 = vtk.vtkSTLReader() reader2.SetFileName("file2.stl") # 合并数据 appendFilter = vtk.vtkAppendPolyData() appendFilter.AddInputConnection(reader1.GetOutputPort()) appendFilter.AddInputConnection(reader2.GetOutputPort()) merged_polydata = appendFilter.GetOutput() # 写入新文件 writer = vtk.vtkSTLWriter() writer.SetFileName("merged.stl") writer.SetInputData(merged_polydata) writer.Write() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恋恋西风

up up up

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值