判断 一个点 ,判断是否在风格 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