VTK笔记——有向包围盒(OBB)

本文详细介绍了有向包围盒(OBB)的概念及其在VTK中的应用。OBB是一种根据模型几何形状调整大小和方向的包围盒,适用于复杂模型的高效包围盒层次分解。通过vtkOBBTree算法,文章展示了如何构建和获取模型的OBB,以及如何使用OBB进行模型的层次化表示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是有向包围盒

《VTK笔记——轴对齐包围盒(AABB)》提到了有向包围盒(OBB/Oriented bounding box)。
有向包围盒,是较为常用的包围盒类型。简单的说,它就是包围模型的最小盒子,是根据模型的几何形状来决定包围盒的大小和方向,无需和坐标轴垂直,方向是任意的,这是它的特点,但也导致了生成的复杂性。

如何获取有向包围盒

在VTK中,有一个算法类vtkOBBTree可以得到有向包围盒。它是一个Tree,为什么需要Tree?这是一种为了得到复杂模型的包围盒常用的一种方法,以一种更加专业的包围盒层次对模型进行分解。基本思路就是将模型组织成一个树状结构,根节点是整个模型,每个叶子节点包括一个简单的局部。
Description

generate oriented bounding box (OBB) tree

vtkOBBTree is an object to generate oriented bounding box (OBB) trees. An oriented bounding box is a bounding box that does not necessarily line up along coordinate axes. The OBB tree is a hierarchical tree structure of such boxes, where deeper levels of OBB confine smaller regions of space.

To build the OBB, a recursive, top-down process is used. First, the root OBB is constructed by finding the mean and covariance matrix of the cells (and their points) that define the dataset. The eigenvectors of the covariance matrix are extracted, giving a set of three orthogonal vectors that define the tightest-fitting OBB. To create the two children OBB’s, a split plane is found that (approximately) divides the number cells in half. These are then assigned to the children OBB’s. This process then continues until the MaxLevel ivar limits the recursion, or no split plane can be found.

A good reference for OBB-trees is Gottschalk & Manocha in Proceedings of Siggraph `96.

	int maxLevel = 10;
	vtkSmartPointer<vtkOBBTree> obbTree =
		vtkSmartPointer<vtkOBBTree>::New();
	obbTree->SetDataSet(polydata);
	obbTree->SetMaxLevel(maxLevel);
	obbTree->BuildLocator();

	double corner[3] = { 0.0, 0.0, 0.0 };
	double max[3] = { 0.0, 0.0, 0.0 };
	double mid[3] = { 0.0, 0.0, 0.0 };
	double min[3] = { 0.0, 0.0, 0.0 };
	double size[3] = { 0.0, 0.0, 0.0 };

	obbTree->ComputeOBB(polydata, corner, max, mid, min, size);
  
	vtkSmartPointer<vtkPolyData> obbPolydata =
		vtkSmartPointer<vtkPolyData>::New();
	obbTree->GenerateRepresentation(0, obbPolydata);

SetMaxLevel设置Tree的最大层级,默认是8.
GenerateRepresentation用于获取指定层级的polydata.

效果

整个模型的OBB
图1
模型分层次的OBB
在这里插入图片描述

OrientedBoundingBox.cxx

#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 <vtkOBBTree.h>
#include <vtkProperty.h>
#include <vtkNamedColors.h>

int main(int argc, char *argv[])
{
	vtkSmartPointer<vtkNamedColors> colors =
		vtkSmartPointer<vtkNamedColors>::New();

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

	int maxLevel = 10;
	vtkSmartPointer<vtkOBBTree> obbTree =
		vtkSmartPointer<vtkOBBTree>::New();
	obbTree->SetDataSet(polydata);
	obbTree->SetMaxLevel(maxLevel);
	obbTree->BuildLocator();

	double corner[3] = { 0.0, 0.0, 0.0 };
	double max[3] = { 0.0, 0.0, 0.0 };
	double mid[3] = { 0.0, 0.0, 0.0 };
	double min[3] = { 0.0, 0.0, 0.0 };
	double size[3] = { 0.0, 0.0, 0.0 };

	obbTree->ComputeOBB(polydata, corner, max, mid, min, size);

	std::cout << "Corner:\t" << corner[0] << ", " << corner[1] << ", "
		<< corner[2] << std::endl
		<< "Max:\t" << max[0] << ", " << max[1] << ", " << max[2]
		<< std::endl
		<< "Mid:\t" << mid[0] << ", " << mid[1] << ", " << mid[2]
		<< std::endl
		<< "Min:\t" << min[0] << ", " << min[1] << ", " << min[2]
		<< std::endl
		<< "Size:\t" << size[0] << ", " << size[1] << ", " << size[2]
		<< std::endl;

	vtkSmartPointer<vtkPolyData> obbPolydata =
		vtkSmartPointer<vtkPolyData>::New();
	obbTree->GenerateRepresentation(0, obbPolydata);

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

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

	vtkSmartPointer<vtkPolyDataMapper> obbTreeMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	obbTreeMapper->SetInputData(obbPolydata);

	vtkSmartPointer<vtkActor> obbTreeActor =
		vtkSmartPointer<vtkActor>::New();
	obbTreeActor->SetMapper(obbTreeMapper);
	obbTreeActor->GetProperty()->SetInterpolationToFlat();
	obbTreeActor->GetProperty()->SetOpacity(.5);
	obbTreeActor->GetProperty()->SetColor(
		colors->GetColor4d("SpringGreen").GetData());

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

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

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

	return EXIT_SUCCESS;
}

Ref

vtkOBBTree Class Reference
VisualizeOBBTree
[算法][包围盒]球,AABB,OBB
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值