什么是包围盒
包围盒是指能够包容物体的立方体或者二维长方形,是包围体的一种,常常用于模型的碰撞检测。包围体主要包括球体、轴对齐包围盒(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();
|
效果
示例代码
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