VTK笔记-图形相关-判断空间上的点是否在图元内-vtkSelectEnclosedPoints

判断空间上的点是否在几何图元内,使用vtkSelectEnclosedPoints类;

vtkSelectEnclosedPoints

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

主要接口

闭合曲面

void SetSurfaceData(vtkPolyData* pd);
void SetSurfaceConnection(vtkAlgorithmOutput* algOutput);  
vtkPolyData* GetSurface();
vtkPolyData* GetSurface(vtkInformationVector* sourceInfo);

待判断点

使用vtkDataSetAlgorithm类的SetInputData设置待判定数据集,一般是点数据的vtkPoints

void SetInputData(vtkDataSet*);

查询结果

使用IsInside查询索引为inputPtId的点是否在闭合曲面中,1是在内部;0是在外部;

int IsInside(vtkIdType inputPtId);
int IsInsideSurface(double x[3]);
int IsInsideSurface(double x, double y, double z);
static int IsInsideSurface(double x[3], vtkPolyData* surface, double bds[6], double length,
     double tol, vtkAbstractCellLocator* locator, vtkIdList* cellIds, vtkGenericCell* genCell,
     vtkIntersectionCounter& counter, vtkRandomPool* poole = nullptr, vtkIdType seqIdx = 0);

示例

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

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

#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 <vtkVertexGlyphFilter.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVertexGlyphFilter.h>

#include "vtk_include.h"

class Test_Clip_Volume {
public:
	static void Test() {
		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 < 2; 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(0.0, 0.0, 1);

		//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();		
	}
};

在这里插入图片描述

平面外的点在平面上的投影是否落入圈选的范围

设定四个在XY平面上的点,组成了边长为1的正方形,判断点(1,1,10)在XY平面上的投影是否落入正方形内;
使用vtkPlane的ProjectPoint方法计算点(1,1,10)在XY平面上的投影点(1,1,0);
使用vtkSelectEnclosedPoints类判断投影点(1,1,0)是否在正方形内;

static float x[4][3] = { {0,0,0},{1,0,0},{1,1,0},{0,1,0} };
static vtkIdType pts[4] = {0,1,2,3};
vtkNew<vtkPolyData> cube;
vtkNew<vtkPoints> points;
vtkNew<vtkCellArray> polys;
vtkNew<vtkFloatArray> scalars;

for (int i = 0; i < 4; i++) {
	points->InsertPoint(i, x[i]);
	scalars->InsertTuple1(i, i);
}
polys->InsertNextCell(4, pts);
		
cube->SetPoints(points);		
cube->SetPolys(polys);
cube->GetPointData()->SetScalars(scalars);

double testInside[3] = { 1, 1, 10.0 };
double project_point[3] = { 0 };
vtkNew<vtkPlane> plane;
plane->SetOrigin(0.0, 0.0, 0.0);
plane->SetNormal(0.0, 0.0, 1.0);
plane->ProjectPoint(testInside, project_point);

vtkNew<vtkPoints> points1;
points1->InsertNextPoint(project_point);
vtkNew<vtkPolyData> pointsPolydata;
pointsPolydata->SetPoints(points1);

vtkNew<vtkSelectEnclosedPoints> selectEnclosedPoints;
selectEnclosedPoints->SetInputData(pointsPolydata);
selectEnclosedPoints->SetSurfaceData(cube);
selectEnclosedPoints->Update();
for (unsigned int i = 0; i < 1; i++)
{
	std::cout << "Point " << i << ": " << selectEnclosedPoints->IsInside(i) << std::endl;
}
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(0.0, 0.0, 1);

vtkNew<vtkPolyDataMapper> cubeMapper;
cubeMapper->SetInputData(cube);
cubeMapper->SetScalarRange(0, 7);
vtkNew<vtkActor> cubeActor;
cubeActor->SetMapper(cubeMapper);
vtkNew<vtkCamera> camera;
camera->SetPosition(1, 1, 1);
camera->SetFocalPoint(0, 0, 0);

vtkNew<vtkRenderer> renderer;
renderer->AddActor(pointsActor);
renderer->AddActor(cubeActor);
renderer->SetActiveCamera(camera);
renderer->ResetCamera();
renderer->SetBackground(1, 1, 1);

vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(renderer);
renWin->SetSize(300, 300);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
renWin->Render();
iren->Initialize();
iren->Start();

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查询结果显示,0序号的点在四边形中;
注意:在实际开发中,判断点在平面上的投影是否在圈选的范围和判断点是否在几何图元中,这两方面运用很常见,了解怎么计算和使用VTK那些类来计算,也可以试着自己使用线性代数的知识计算这两个方面的代码;有机会在补充自己写的代码;

使用vtkPolygon类的方法PointInPolygon

#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkPolygon.h>

int main(int, char*[])
{
  // Create the polygon
  vtkNew<vtkPolygon> polygon;
  polygon->GetPoints()->InsertNextPoint(0.0, 0.0, 0.0);
  polygon->GetPoints()->InsertNextPoint(1.0, 0.0, 0.0);
  polygon->GetPoints()->InsertNextPoint(1.0, 1.0, 0.0);
  polygon->GetPoints()->InsertNextPoint(0.0, 1.0, 0.0);

  double testIn[3] = {0.5, 0.5, 0.0};
  double testOut[3] = {2.0, 0.5, 0.0};

  double n[3];
  polygon->ComputeNormal(
      polygon->GetPoints()->GetNumberOfPoints(),
      static_cast<double*>(polygon->GetPoints()->GetData()->GetVoidPointer(0)),
      n);

  double bounds[6];
  polygon->GetPoints()->GetBounds(bounds);

  std::cout << "testIn in polygon? "
            << polygon->PointInPolygon(
                   testIn, polygon->GetPoints()->GetNumberOfPoints(),
                   static_cast<double*>(
                       polygon->GetPoints()->GetData()->GetVoidPointer(0)),
                   bounds, n)
            << std::endl;

  std::cout << "testOut in polygon? "
            << polygon->PointInPolygon(
                   testOut, polygon->GetPoints()->GetNumberOfPoints(),
                   static_cast<double*>(
                       polygon->GetPoints()->GetData()->GetVoidPointer(0)),
                   bounds, n)
            << std::endl;

  return EXIT_SUCCESS;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黑山老妖的笔记本

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值