VTK笔记——多边形剪切(vtkClipPolyData)

在三维图形中,往往会涉及到对多边形的处理,多边形剪切就是其中之一。什么是多边形剪切?打个比方,如果把多边形比作西瓜的话,那剪切就相当于用水果刀切西瓜,一刀下去,西瓜就被切成两块。当然,也可以切两下,三下,甚至更多。

vtkClipPolyData

vtkClipPolyData,一个用于多边形剪切模型的方法类。
关于它的用法,引用一段描述:

clip polygonal data with user-specified implicit function or input scalar data
vtkClipPolyData is a filter that clips polygonal data using either any subclass of vtkImplicitFunction, or the input scalar data. Clipping means that it actually “cuts” through the cells of the dataset, returning everything inside of the specified implicit function (or greater than the scalar value) including “pieces” of a cell. (Compare this with vtkExtractGeometry, which pulls out entire, uncut cells.) The output of this filter is polygonal data.
To use this filter, you must decide if you will be clipping with an implicit function, or whether you will be using the input scalar data. If you want to clip with an implicit function, you must: 1) define an implicit function 2) set it with the SetClipFunction method 3) apply the GenerateClipScalarsOn method If a ClipFunction is not specified, or GenerateClipScalars is off (the default), then the input’s scalar data will be used to clip the polydata.
You can also specify a scalar value, which is used to decide what is inside and outside of the implicit function. You can also reverse the sense of what inside/outside is by setting the InsideOut instance variable. (The cutting algorithm proceeds by computing an implicit function value or using the input scalar data for each point in the dataset. This is compared to the scalar value to determine inside/outside.)
This filter can be configured to compute a second output. The second output is the polygonal data that is clipped away. Set the GenerateClippedData boolean on if you wish to access this output data.

描述清楚的表明,多边形剪切,有两种基本方式,指定隐函数和输入标量数据。

隐函数

数学中的定义是这样,

隐函数是由隐式方程所隐含定义的函数。设F(x,y)是某个定义域上的函数。如果存在定义域上的子集D,使得对每个x属于D,存在相应的y满足F(x,y)=0,则称方程确定了一个隐函数。

VTK中,继承vtkImplicitFunction类的子类都可以用作隐函数,如稍后示例用到的vtkPlane。
不一一列举了,用一幅图来表示:
在这里插入图片描述

标量数据

在物理学中,标量定义,

标量(scalar),亦称“无向量”。有些物理量,只具有数值大小,而没有方向,部分有正负之分。物理学中,标量(或作纯量)指在坐标变换下保持不变的物理量。用通俗的说法,标量是只有大小,没有方向的量。

vtk中,标量数据是数据集里的每个位置具有单值的数据,它只表示数据的大小,如温度、压力、密度、高度。是属性数据的一种。

示例

下面简单的用隐函数vtkPlane将圆球vtkSphereSource剪切成两部分。

主要代码

构造切割平面

1
2
3
4
5
vtkPlane *plane = vtkPlane::New();
vtkSmartPointer<vtkPlane> plane =
vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(0, 3, 0);
plane->SetNormal(0, -1, 0);

设置隐函数

1
2
3
4
5
6
vtkSmartPointer<vtkClipPolyData> clipPolyData =
vtkSmartPointer<vtkClipPolyData>::New();
clipPolyData->SetInputConnection(sphereSource->GetOutputPort());
clipPolyData->SetClipFunction(plane);
clipPolyData->GenerateClippedOutputOn();
clipPolyData->Update();

SetGenerateClippedOutput用于设置是否生成被剪切掉的部分,默认是不生成的。
获取剪切数据
剪切留下的部分:
clipPolyData->GetClippedOutputPort();
被剪切掉的部分(如果GenerateClippedOutput是off,将无法获取):
clipPolyData->GetOutputPort();

效果

在这里插入图片描述

ClipPolydata.cxx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkSmartPointer.h>
#include <vtkCamera.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkClipPolyData.h>
#include <vtkProperty.h>
#include <vtkPlane.h>

int main(int, char *[])
{
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetCenter(0.0, 0.0, 0.0);
sphereSource->SetRadius(5.0);
sphereSource->Update();

vtkPlane *vPlane = vtkPlane::New();
vtkSmartPointer<vtkPlane> plane =
vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(0, 3, 0);
plane->SetNormal(0, -1, 0);

vtkSmartPointer<vtkClipPolyData> clipPolyData =
vtkSmartPointer<vtkClipPolyData>::New();
clipPolyData->SetInputConnection(sphereSource->GetOutputPort());
clipPolyData->SetClipFunction(plane);
clipPolyData->GenerateClippedOutputOn();
clipPolyData->Update();

vtkSmartPointer<vtkPolyDataMapper> mapper1 =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper1->SetInputConnection(clipPolyData->GetOutputPort());

vtkSmartPointer<vtkActor> actor1 =
vtkSmartPointer<vtkActor>::New();
actor1->SetMapper(mapper1);

vtkSmartPointer<vtkPolyDataMapper> mapper2 =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper2->SetInputConnection(clipPolyData->GetClippedOutputPort());

vtkSmartPointer<vtkActor> actor2 =
vtkSmartPointer<vtkActor>::New();
actor2->SetMapper(mapper2);

vtkSmartPointer<vtkNamedColors> colors =
vtkSmartPointer<vtkNamedColors>::New();

vtkSmartPointer<vtkRenderer> renderer1 =
vtkSmartPointer<vtkRenderer>::New();
renderer1->SetBackground(colors->GetColor3d("Slate_grey").GetData());
renderer1->AddActor(actor1);
renderer1->SetViewport(0, 0, 0.5, 1);

vtkSmartPointer<vtkRenderer> renderer2 =
vtkSmartPointer<vtkRenderer>::New();
renderer2->SetBackground(colors->GetColor3d("Slate_blue").GetData());
renderer2->AddActor(actor2);
renderer2->SetViewport(0.5, 0, 1, 1);

vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(600, 300);
renderWindow->AddRenderer(renderer1);
renderWindow->AddRenderer(renderer2);

vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);

vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
renderWindowInteractor->SetInteractorStyle(style);

renderWindow->Render();
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();

return EXIT_SUCCESS;
}

Ref

vtkClipPolyData Class Reference
在这里插入图片描述