VTK笔记——数据抽取(vtkDecimatePro)

多边形数据,特别是三角形网格是常被用到的数据格式。有时会面临网格数据大,难以处理这样的问题,比如在一些交互使用中难以快速响应。为了解决这类问题,就要用到数据抽取技术。
抽取也被称作多边形削减,网格简化或者多分辨率建模,其在于保持近似的原始网格条件下对三角网格的三角形进行削减。

vtkDecimatePro

vtkDecimatePro是一个用于削减三角形数量的类,得到一个很好的近似原始形状的几何。相对(vtkQuadricDecimation)来说速度比较快,而且在削减过程中可以修改拓扑结构。它采用边塌陷的方法来消除顶点和三角形。它的误差度量是基于到平面或者边的距离。
vtkDecimatePro的实现类似于Proc Siggraph `92最初在"Decimation of Triangle Meshes"中描述的算法,但有三个主要区别:
1)该算法不能保证网格的拓扑结构;
2)它保证了用户给定的网格系数;
3)它建立了生成渐进网格的方法,这是一个操作流,可以很容易的传输和增量更新(详见Hugues Hoppe Siggraph '96关于"progressive meshes"的论文)。

用法

要使用这个类,至少要设定TargetReduction这个值,它代表要削减的三角形的百分比(范围为0到1)。比如,
有100个三角形,设置TargetReduction为(. 90),那么,最后将大约留下10个三角形,减少90%。

	auto decimate = vsp<vtkDecimatePro>::New();
	decimate->SetInputData(inputPD);
	decimate->SetTargetReduction(reduciton);
	decimate->Update();

另外,vtkDecimatePro的输入只能是三角形网格数据,如果是多边形数据,一开始要将它三角化(vtkTriangleFilter )。

	auto triangles = vsp<vtkTriangleFilter>::New();
	triangles->SetInputConnection(reader->GetOutputPort());
	triangles->Update();

其它的一些重要参数:
PreserveTopology:是否保持原始的拓扑结构,如果on,将不会发生网格分裂和孔洞。
Splitting
BoundaryVertexDeletion
MaximumError
FeatureAngle
SplitAngle

示例

下面的演示了对一只牛模型进行数据抽取后的效果及数据大小的对比:
在这里插入图片描述在这里插入图片描述

Decimation.cxx

#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkSphereSource.h>
#include <vtkTriangleFilter.h>
#include <vtkDecimatePro.h>
#include <vtkNamedColors.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>

#define vsp vtkSmartPointer

int main(int argc, char* argv[])
{
	vsp<vtkPolyData> inputPD;
	if (argc > 1)
	{
		auto reader = vsp<vtkXMLPolyDataReader>::New();
		reader->SetFileName(argv[1]);
		auto triangles = vsp<vtkTriangleFilter>::New();
		triangles->SetInputConnection(reader->GetOutputPort());
		triangles->Update();
		inputPD = triangles->GetOutput();
	}
	else
	{
		auto sphereSource = vsp<vtkSphereSource>::New();
		sphereSource->SetThetaResolution(30);
		sphereSource->SetPhiResolution(15);
		sphereSource->Update();
		inputPD = sphereSource->GetOutput();
	}
	std::cout << "========" << "Before decimation" << "========" << std::endl;
	std::cout << "There are " << inputPD->GetNumberOfPoints() << " points." << std::endl;
	std::cout << "There are " << inputPD->GetNumberOfPolys() << " polygons." << std::endl;

	float reduciton = .3f;
	if (argc > 2)
	{
		reduciton = atof(argv[2]);
	}
	auto decimate = vsp<vtkDecimatePro>::New();
	decimate->SetInputData(inputPD);
	decimate->SetTargetReduction(reduciton);
	decimate->PreserveTopologyOn();
	decimate->Update();
	auto decimatedPD = vsp<vtkPolyData>::New();
	decimatedPD->ShallowCopy(decimate->GetOutput());

	std::cout << "========" << "After decimation" << "========" << std::endl;
	std::cout << "There are " << decimatedPD->GetNumberOfPoints() << " points." << std::endl;
	std::cout << "There are " << decimatedPD->GetNumberOfPolys() << " polygons." << std::endl;
	std::cout << "Reduction: " <<
		static_cast<double>((inputPD->GetNumberOfPolys() - decimatedPD->GetNumberOfPolys())) /
		static_cast<double>(inputPD->GetNumberOfPolys()) << std::endl;

	auto colors = vsp<vtkNamedColors>::New();
	auto backFace = vsp<vtkProperty>::New();
	backFace->SetColor(colors->GetColor3d("gold").GetData());

	auto inputMapper = vsp<vtkPolyDataMapper>::New();
	inputMapper->SetInputData(inputPD);
	auto inputActor = vsp<vtkActor>::New();
	inputActor->SetMapper(inputMapper);
	inputActor->GetProperty()->SetInterpolationToFlat();
	inputActor->GetProperty()->SetColor(colors->GetColor3d("flesh").GetData());
	inputActor->SetBackfaceProperty(backFace);

	auto decimatedMapper = vsp<vtkPolyDataMapper>::New();
	decimatedMapper->SetInputData(decimatedPD);
	auto decimatedActor = vsp<vtkActor>::New();
	decimatedActor->SetMapper(decimatedMapper);
	decimatedActor->GetProperty()->SetInterpolationToFlat();
	decimatedActor->GetProperty()->SetColor(colors->GetColor3d("flesh").GetData());
	decimatedActor->SetBackfaceProperty(backFace);

	auto renderWindow = vsp<vtkRenderWindow>::New();
	renderWindow->SetSize(800, 400);

	auto interactor = vsp<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renderWindow);

	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };

	auto leftRenderer = vsp<vtkRenderer>::New();
	renderWindow->AddRenderer(leftRenderer);
	leftRenderer->SetViewport(leftViewport);
	leftRenderer->SetBackground(.6, .5, .4);

	auto rightRenderer = vsp<vtkRenderer>::New();
	renderWindow->AddRenderer(rightRenderer);
	rightRenderer->SetViewport(rightViewport);
	rightRenderer->SetBackground(.4, .5, .6);

	leftRenderer->AddActor(inputActor);
	rightRenderer->AddActor(decimatedActor);

	auto camera = vsp<vtkCamera>::New();
	camera->SetPosition(0, -1, 0);
	camera->SetFocalPoint(0, 0, 0);
	camera->SetViewUp(0, 0, 1);
	camera->Elevation(30);
	camera->Azimuth(30);

	leftRenderer->SetActiveCamera(camera);
	rightRenderer->SetActiveCamera(camera);

	leftRenderer->ResetCamera();
	leftRenderer->ResetCameraClippingRange();

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

	return EXIT_SUCCESS;
}

Ref

VTKExamples/Cxx/Meshes/Decimation
在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值