VTK笔记-裁剪分割-不规则闭合圈选裁剪-vtkImplicitSelectionLoop类

vtkImplicitSelectionLoop

  vtkImplicitSelectionLoop是vtkImplicitFunction类的子类,为一个不规则的圆柱形对象计算隐式函数值和函数梯度,该对象的横截面由形成循环的一组点定义。回路不必是凸多边形,也不必所有点在同一平面上。但是,当投影到由Loop周围的累积叉积(即loop的轴)定义的平面上时,环必须是非自交的(或可以指定要使用的法线。)
  vtkClipPolyData的SetClipFunction使用vtkImplicitFunction的子类,其中vtkCylinder类输入到vtkClipPolyData后,会产生贯穿vtkClipPolyData的输入源数据,vtkImplicitSelectionLoop相对是在vtkCylinder类,不过它的横截面是不规则的多边形,由多个连续环绕的点组成,当前点与上一个点之间的连线互不交叉,保证能够定义一个闭合的多边形;一般情况下,外部设定的点集是在同一平面上的点,  vtkImplicitSelectionLoop可以自动计算出这些点所在平面的法向量,这个法向量就是柱体的纵深向量,决定被裁剪数据那些数据被裁剪;循环的每个点首先投影到由循环法线定义的平面上,这就形成了一个多边形。然后,为了计算隐式函数值,使用inside/outside来判断确定x是否在多边形内,并计算到循环闭合多边形边界的距离(负值在循环内)。
在这里插入图片描述

接口

输入点集

  通过调用方法SetLoop和GetLoop来设置和获取vtkPoints集合;
  要求点的顺序可以形成闭合多边形,且不能自我交叉;

vtkPoints* Loop;
virtual void SetLoop(vtkPoints*);
vtkGetObjectMacro(Loop, vtkPoints);

法线向量

  输入的Loop点集,构成的同一个投影平面,平面的起点和法向量由Origin和Normal成员变量记录;

double Normal[3];
vtkSetVector3Macro(Normal, double);
vtkGetVectorMacro(Normal, double, 3);
double Origin[3];
double Bounds[6]; // bounds of the projected polyon

  使用AutomaticNormalGeneration控制打开/关闭自动计算法线向量;
  默认情况下,法线是根据边的累积叉积计算的;也可以指定要使用的法线。

vtkTypeBool AutomaticNormalGeneration;
vtkSetMacro(AutomaticNormalGeneration, vtkTypeBool);
vtkGetMacro(AutomaticNormalGeneration, vtkTypeBool);
vtkBooleanMacro(AutomaticNormalGeneration, vtkTypeBool);

计算点与边界的距离

  EvaluateFunction返回有符号数值,根据符号可以判断,点在投影平面上是否处于闭合曲线内;决定是否进行裁剪,目前用处不大;

using vtkImplicitFunction::EvaluateFunction;
double EvaluateFunction(double x[3]) override;  
void EvaluateGradient(double x[3], double n[3]) override;

示例

  在网格表面绘制一个循环,并使用该循环从循环中剪裁或提取单元。

#include "vtk_include.h"
#include <vtkClipPolyData.h>
#include <vtkImplicitSelectionLoop.h>
#include <vtkLODActor.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
class Test_ImplicitSelectionLoop {
public:
	static void Test() {
		vtkNew<vtkNamedColors> colors;

		vtkNew<vtkSphereSource> sphereSource;
		sphereSource->SetPhiResolution(100);
		sphereSource->SetThetaResolution(100);
		sphereSource->Update();

		vtkNew<vtkPoints> selectionPoints;
		selectionPoints->InsertPoint(0, -0.16553, 0.135971, 0.451972);
		selectionPoints->InsertPoint(1, -0.0880123, -0.134952, 0.4747);
		selectionPoints->InsertPoint(2, 0.00292618, -0.134604, 0.482459);
		selectionPoints->InsertPoint(3, 0.0641941, 0.067112, 0.490947);
		selectionPoints->InsertPoint(4, 0.15577, 0.0734765, 0.469245);
		selectionPoints->InsertPoint(5, 0.166667, -0.129217, 0.454622);
		selectionPoints->InsertPoint(6, 0.241259, -0.123363, 0.420581);
		selectionPoints->InsertPoint(7, 0.240334, 0.0727106, 0.432555);
		selectionPoints->InsertPoint(8, 0.308529, 0.0844311, 0.384357);
		selectionPoints->InsertPoint(9, 0.32672, -0.121674, 0.359187);
		selectionPoints->InsertPoint(10, 0.380721, -0.117342, 0.302527);
		selectionPoints->InsertPoint(11, 0.387804, 0.0455074, 0.312375);
		selectionPoints->InsertPoint(12, 0.43943, -0.111673, 0.211707);
		selectionPoints->InsertPoint(13, 0.470984, -0.0801913, 0.147919);
		selectionPoints->InsertPoint(14, 0.436777, 0.0688872, 0.233021);
		selectionPoints->InsertPoint(15, 0.44874, 0.188852, 0.109882);
		selectionPoints->InsertPoint(16, 0.391352, 0.254285, 0.176943);
		selectionPoints->InsertPoint(17, 0.373274, 0.154162, 0.294296);
		selectionPoints->InsertPoint(18, 0.274659, 0.311654, 0.276609);
		selectionPoints->InsertPoint(19, 0.206068, 0.31396, 0.329702);
		selectionPoints->InsertPoint(20, 0.263789, 0.174982, 0.387308);
		selectionPoints->InsertPoint(21, 0.213034, 0.175485, 0.417142);
		selectionPoints->InsertPoint(22, 0.169113, 0.261974, 0.390286);
		selectionPoints->InsertPoint(23, 0.102552, 0.25997, 0.414814);
		selectionPoints->InsertPoint(24, 0.131512, 0.161254, 0.454705);
		selectionPoints->InsertPoint(25, 0.000192443, 0.156264, 0.475307);
		selectionPoints->InsertPoint(26, -0.0392091, 0.000251724, 0.499943);
		selectionPoints->InsertPoint(27, -0.096161, 0.159646, 0.46438);

		vtkNew<vtkImplicitSelectionLoop> loop;
		loop->SetLoop(selectionPoints);

		vtkNew<vtkClipPolyData> clip;
		clip->SetInputConnection(sphereSource->GetOutputPort());
		clip->SetClipFunction(loop);
		clip->SetValue(0.0);

		vtkNew<vtkPolyDataMapper> clipMapper;
		clipMapper->SetInputConnection(clip->GetOutputPort());
		clipMapper->ScalarVisibilityOff();

		vtkNew<vtkProperty> backProp;
		backProp->SetColor(colors->GetColor3d("Tomato").GetData());

		vtkNew<vtkLODActor> clipActor;
		clipActor->SetMapper(clipMapper);
		clipActor->SetBackfaceProperty(backProp);
		clipActor->GetProperty()->SetColor(colors->GetColor3d("Banana").GetData());

		vtkNew<vtkRenderer> renderer;
		vtkNew<vtkRenderWindow> renderWindow;
		renderWindow->AddRenderer(renderer);
		vtkNew<vtkRenderWindowInteractor> interactor;
		interactor->SetRenderWindow(renderWindow);

		// Add the actors to the renderer, set the background and size
		renderer->AddActor(clipActor);
		renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());

		renderWindow->SetSize(500, 500);
		renderWindow->SetWindowName("ImplicitSelectionLoop");

		renderWindow->Render();
		interactor->Start();
	}
};

在这里插入图片描述
修改selectionPoints内点坐标信息

vtkNew<vtkPoints> selectionPoints;
selectionPoints->InsertPoint(0, 0, 0, 0);
selectionPoints->InsertPoint(1, 0.25, 0, 0);
selectionPoints->InsertPoint(2, 0.25, 0.25, 0);
selectionPoints->InsertPoint(3, 0, 0.25, 0);
selectionPoints->InsertPoint(4, 0.125, 0.125, 0);

使用GetNormal获取当前点集合形成闭合多边形的法线向量;

double x[3] = { 0 };
loop->GetNormal(x);

获得x的值为(0,0,1),表示柱体的方向为Z方向,垂直于XY平面;
在这里插入图片描述
修改selectionPoints内点坐标信息

vtkNew<vtkPoints> selectionPoints;
selectionPoints->InsertPoint(0, 0, 0, 0);
selectionPoints->InsertPoint(1, 0, 0.25, 0);
selectionPoints->InsertPoint(2, 0, 0.25, 0.25);
selectionPoints->InsertPoint(3, 0, 0, 0.25);
selectionPoints->InsertPoint(4, 0, 0.125, 0.125);

使用GetNormal获取当前点集合形成闭合多边形的法线向量,发现法线向量仍然是(0,0,1);
在renderWindow->Render();后使用GetNormal,法线向量是(1,0,0);柱体方向是沿着X轴方向,且垂直越YZ平面;
在这里插入图片描述
在这里插入图片描述
对数据进行两次裁剪,将第一次的裁剪结果作为输入放到vtkClipPolyData中进行二次裁剪;可以实现多次累加裁剪效果。

#include "vtk_include.h"
#include <vtkClipPolyData.h>
#include <vtkImplicitSelectionLoop.h>
#include <vtkLODActor.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>

class Test_ImplicitSelectionLoop {
public:
	static void Test() {
		vtkNew<vtkNamedColors> colors;

		vtkNew<vtkSphereSource> sphereSource;
		sphereSource->SetPhiResolution(100);
		sphereSource->SetThetaResolution(100);
		sphereSource->Update();

		vtkNew<vtkPoints> selectionPoints;
		selectionPoints->InsertPoint(0, 0, 0, 0);
		selectionPoints->InsertPoint(1, 0.25, 0, 0);
		selectionPoints->InsertPoint(2, 0.25, 0.25, 0);
		selectionPoints->InsertPoint(3, 0, 0.25, 0);
		selectionPoints->InsertPoint(4, 0.125, 0.125, 0);

		vtkNew<vtkImplicitSelectionLoop> loop;
		loop->SetLoop(selectionPoints);		
		
		vtkNew<vtkClipPolyData> clip;
		clip->SetInputConnection(sphereSource->GetOutputPort());
		clip->SetClipFunction(loop);
		clip->SetValue(0.0);

		vtkNew<vtkPoints> selectionPoints2;
		selectionPoints2->InsertPoint(0, 0, 0, 0);
		selectionPoints2->InsertPoint(1, 0, 0.25, 0);
		selectionPoints2->InsertPoint(2, 0, 0.25, 0.25);
		selectionPoints2->InsertPoint(3, 0, 0, 0.25);
		selectionPoints2->InsertPoint(4, 0, 0.125, 0.125);
		vtkNew<vtkImplicitSelectionLoop> loop2;
		loop2->SetLoop(selectionPoints2);

		vtkNew<vtkClipPolyData> clip2;
		clip2->SetInputConnection(clip->GetOutputPort());
		clip2->SetClipFunction(loop2);
		clip2->SetValue(0.0);

		vtkNew<vtkPolyDataMapper> clipMapper;
		clipMapper->SetInputConnection(clip2->GetOutputPort());
		clipMapper->ScalarVisibilityOff();

		vtkNew<vtkProperty> backProp;
		backProp->SetColor(colors->GetColor3d("Tomato").GetData());

		vtkNew<vtkLODActor> clipActor;
		clipActor->SetMapper(clipMapper);
		clipActor->SetBackfaceProperty(backProp);
		clipActor->GetProperty()->SetColor(colors->GetColor3d("Banana").GetData());

		vtkNew<vtkRenderer> renderer;

		vtkNew<vtkRenderWindow> renderWindow;
		renderWindow->AddRenderer(renderer);

		vtkNew<vtkRenderWindowInteractor> interactor;
		interactor->SetRenderWindow(renderWindow);

		// Add the actors to the renderer, set the background and size
		renderer->AddActor(clipActor);
		renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());

		renderWindow->SetSize(500, 500);
		renderWindow->SetWindowName("ImplicitSelectionLoop");

		renderWindow->Render();
		interactor->Start();
	}
};

在这里插入图片描述

参考资料

1.ImplicitSelectionLoop示例
2.vtkImplicitSelectionLoop Class Reference

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黑山老妖的笔记本

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

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

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

打赏作者

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

抵扣说明:

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

余额充值