VTK笔记——轴对齐包围盒(AABB)

什么是包围盒

包围盒是指能够包容物体的立方体或者二维长方形,是包围体的一种,常常用于模型的碰撞检测。包围体主要包括球体、轴对齐包围盒(AABB)有向包围盒(OBB)和凸包(Convex Hull)。
在较早的时候,包围盒按照坐标系的坐标轴进行排列,这被称为轴对齐的包围盒(AABB/Axis-aligned bounding box)。为了将AABB与通用的情况区分开来,将任意的包围盒称为有向包围盒(OBB/Oriented bounding box)。AABB检测模型的相交要比OBB更简单,但是他的缺点是当模型旋转的时候无法随之旋转,而必须重新计算。

轴对齐包围盒

在VTK中,轴对齐包围盒被定义为包含该模型,且边平行于坐标轴的最小六面体。AABB比较简单,存储空间小,仅需六个标量。
获取的标量也很简单,vtkPolyData中定义了GetBounds()函数,用来获取包围盒的参数,即三个轴向上的最大值和最小值。

1
2
3
4
vtkSmartPointer<vtkPolyData> polydata =
vtkSmartPointer<vtkPolyData>::New();
double bounds[6];
polydata->GetBounds(bounds);

需要注意的是,通过reader或者source来的模型,需要先Update();
而有时候仅仅是获取这些参数并不直观,还需要
显示包围盒,vtkOutlineFilter提供了这一方便的操作,输入模型的数据,就很容易的可视化显示。

1
2
3
4
vtkSmartPointer<vtkOutlineFilter> outline =
vtkSmartPointer<vtkOutlineFilter>::New();
outline->SetInputData(polydata);
outline->Update();

Default Solid face is off, on:

1
outline->GenerateFacesOn();

效果

cow

示例代码

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
87
88
89
90
91
92
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkSphereSource.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkOutlineFilter.h>
#include <vtkProperty.h>

int main(int argc, char *argv[])
{
vtkSmartPointer<vtkPolyData> polydata =
vtkSmartPointer<vtkPolyData>::New();
if (argc > 1)
{
vtkSmartPointer<vtkXMLPolyDataReader> reader =
vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(argv[1]);
reader->Update();
polydata = reader->GetOutput();
}
else
{
vtkSmartPointer<vtkSphereSource> modelSource =
vtkSmartPointer<vtkSphereSource>::New();
modelSource->Update();
polydata = modelSource->GetOutput();
}

vtkSmartPointer<vtkOutlineFilter> outline =
vtkSmartPointer<vtkOutlineFilter>::New();
outline->SetInputData(polydata);
outline->Update();

double bounds[6];
polydata->GetBounds(bounds);
std::cout << "Polydata bounds: " << std::endl;
std::cout << "xmin: " << bounds[0] << " "
<< "xmax: " << bounds[1] << std::endl
<< "ymin: " << bounds[2] << " "
<< "ymax: " << bounds[3] << std::endl
<< "zmin: " << bounds[4] << " "
<< "zmax: " << bounds[5] << std::endl;

outline->GetOutput()->GetBounds(bounds);
std::cout << "Outline bounds: " << std::endl;
std::cout << "xmin: " << bounds[0] << " "
<< "xmax: " << bounds[1] << std::endl
<< "ymin: " << bounds[2] << " "
<< "ymax: " << bounds[3] << std::endl
<< "zmin: " << bounds[4] << " "
<< "zmax: " << bounds[5] << std::endl;

vtkSmartPointer<vtkPolyDataMapper> modelMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
modelMapper->SetInputData(polydata);

vtkSmartPointer<vtkActor> modelActor =
vtkSmartPointer<vtkActor>::New();
modelActor->SetMapper(modelMapper);

vtkSmartPointer<vtkPolyDataMapper> outlineMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
outlineMapper->SetInputConnection(outline->GetOutputPort());

vtkSmartPointer<vtkActor> outlineActor =
vtkSmartPointer<vtkActor>::New();
outlineActor->SetMapper(outlineMapper);
outlineActor->GetProperty()->SetColor(1, 0, 0);
outlineActor->GetProperty()->SetLineWidth(1.5);

vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(300, 300);
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);

renderer->AddActor(modelActor);
renderer->AddActor(outlineActor);

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

return EXIT_SUCCESS;
}

Ref

维基百科.包围体
VTK/Examples/Cxx/PolyData/DataBounds

The End