VTK修炼之道52:图形基本操作进阶_多分辨率策略(模型抽取的三种方法)

原文链接:https://blog.csdn.net/shenziheng1/article/details/54850678

1.多分辨率处理策略

模型抽取(Decimation)和细化(Subdivision)是两个相反的操作,是三角形网格模型多分辨处理中的两个重要操作。使用这两个操作可以在保持模型拓扑结构的同时,得到不同分辨率的网格模型。模型抽取的作用是减少模型中的点数据和单元数据,便于模型的后续处理与交互渲染,这类似于图像数据的降采样。而网格细化则是利用一定的细化规则,在给定的初始网格中插入新的点,从而不断细化出新的网格单元,在极限细化情况下,该网格能够收敛一个光华的曲面

2.网格抽取(Decimation)

2.1 vtkDecimatePro

VTK中主要有三种网格抽取类:vtkDecimatePro、vtkQuadricDecimation、vtkQuadricClustering。
vtkDecimatePro是最常用的,该处理方法的原理参考文献[1],是用一种边塌陷的方法来删除点和单元,处理速度比较快,而且可以方便的控制网格抽取的幅度,得到不同级别的模型数据。
该类的使用方法,如下:

vtkSmartPoint<vtkDecimatePro> decimate = vtkSmartPointer<vtkDecimatePro>::New();
decimate->SetInput(input);
decimate->SetTargetReduction(0.6);
decimate->update();

vtkDecimatePro接收一个单元为三角网格的vtkPolyData数据,其中函数SetTargetReduction()用于设置变量TargetReduction的大小,将网格面片抽取的比例控制在0~1.这里设置为0.6,说明有60%的三角面片单元将被移除。使用这个函数可以得到不同程度的简化网格模型,不过,为确保函数效果,一般需要满足下面四个条件:

  • vtkDecimatePro需要支持模型拓扑的改变,即将PreserveTopology变量的值设置为FALSE。
  • 支持网格分裂,即Splitting变量的值设置为TRUE。
  • 支持修改模型的边界,即将变量BoundaryVetexDeletion的值设置为TRUE。
    • 设置最大误差变量MaximumError的值为VTK_DOUBLE_MAX。

在满足这四个条件情况下,可以得到不同简化程度的模型。如果上面四个条件不满足,最终得到的模型简化率并非所期望的简化率。

2.2 vtkQuadricDecimation

该类也可以实现三角形网格简化,并能较好地逼近原模型。该简化算法思想可以参考文献[2]。该类虽然也提供了SetTargetReduction()函数用于设置模型简化程度,但是最终简化率并非严格等于程序中设置的简化率。可以通过GetActualReduction()函数来获取最终模型简化率。

2.3 vtkQuadricClustering

该类是三种实现模型抽取算法中最快的一种,能够处理大数据模型。其算法思想可以参考文献[3]。通过StartAppend()、Append()、EndAppend()函数可以将整个模型分为多个网格片处理,从而避免一次性处理整个模型,减少内存开支,提高处理效率。

3.vtkDecimatePro用于模型抽取实验

作为结果观测实验,这里仅仅使用vtkDecimatePro类实现模型抽取。
示例代码如下:

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkInteractionStyle);
 
#include <vtkSmartPointer.h>
#include <vtkPolyDataReader.h>
#include <vtkDecimatePro.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
 
int main()
{
	vtkSmartPointer<vtkPolyDataReader> reader =
		vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("fran_cut.vtk");
	reader->Update();
 
	vtkSmartPointer<vtkPolyData> original = reader->GetOutput();
	std::cout << "抽取前"<< "-----------------------" << std::endl;
	std::cout << "模型点数为: " << original->GetNumberOfPoints() << std::endl;
	std::cout << "模型面数为: " << original->GetNumberOfPolys() << std::endl;
 
	vtkSmartPointer<vtkDecimatePro> decimation =
		vtkSmartPointer<vtkDecimatePro>::New();
	decimation->SetInputData(reader->GetOutput());
	decimation->SetTargetReduction(0.6);
	decimation->Update();
 
	vtkSmartPointer<vtkPolyData> decimated = decimation->GetOutput();
	std::cout << "抽取后"<< "-----------------------" << std::endl;
	std::cout << "模型点数为:" << decimated->GetNumberOfPoints() << std::endl;
	std::cout << "模型面数为:" << decimated->GetNumberOfPolys() << std::endl;
	/
	vtkSmartPointer<vtkPolyDataMapper> origMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	origMapper->SetInputData(reader->GetOutput());
	vtkSmartPointer<vtkActor> origActor =
		vtkSmartPointer<vtkActor>::New();
	origActor->SetMapper(origMapper);
 
	vtkSmartPointer<vtkPolyDataMapper> deciMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	deciMapper->SetInputData(decimation->GetOutput());
	vtkSmartPointer<vtkActor> deciActor =
		vtkSmartPointer<vtkActor>::New();
	deciActor->SetMapper(deciMapper);
	///
	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };
 
	vtkSmartPointer<vtkRenderer> leftRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	leftRenderer->SetViewport(leftViewport);
	leftRenderer->AddActor(origActor);
	leftRenderer->SetBackground(1.0, 0, 0);
 
	vtkSmartPointer<vtkRenderer> rightRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	rightRenderer->SetViewport(rightViewport);
	rightRenderer->AddActor(deciActor);
	rightRenderer->SetBackground(0, 0, 0);
 
	leftRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
	leftRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
	leftRenderer->GetActiveCamera()->SetViewUp(0, 0, 1);
	leftRenderer->GetActiveCamera()->Azimuth(30);
	leftRenderer->GetActiveCamera()->Elevation(30);
	leftRenderer->ResetCamera();//刷新照相机
	rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());//同步显示
	///
	vtkSmartPointer<vtkRenderWindow> rw =
		vtkSmartPointer<vtkRenderWindow>::New();
	rw->AddRenderer(leftRenderer);
	rw->AddRenderer(rightRenderer);
	rw->SetSize(640, 320);
	rw->SetWindowName("PolyData Decimation");
 
	vtkSmartPointer<vtkRenderWindowInteractor> rwi =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	rwi->SetRenderWindow(rw);
	rwi->Start();
 
	return 0;
}

4.参考文献

[1].Schroeder W J. Decimation of triangle meshes[J]. Acm Siggraph Computer Graphics, 1992, 26(2):65-70.
[2].Garland M. Surface simplification using quadric error metrics[C]// Conference on Computer Graphics and Interactive Techniques. ACM Press/Addison-Wesley Publishing Co. 1997:209-216.
[3].Lindstrom P. Out-of-core simplification of large polygonal models[C]// ACM SIGGRAPH. 2000:259-262.

5.资料

2.《The VTK User’s Guide – 11thEdition》

参考博客:https://blog.csdn.net/shenziheng1/article/details/54850678

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值