VTK修炼之道52:图形基本操作进阶_多分辨率策略(模型抽取的三种方法)
时间:2022-10-28 17:00:00
原文链接:https://blog.csdn.net/shenziheng1/article/details/54850678
1.多分辨率处理策略
模型抽取(Decimation)和细化(Subdivision)三角形网格模型多分辨处理中的两个重要操作是两个相反的操作。在保持模型拓扑结构的同时,使用这两种操作可以获得不同分辨率的网格模型。模型提取的功能是减少模型中的点数据和单元数据,便于模型的后续处理和交互渲染,类似于图像数据的降采样。网格细化是利用一定的细化规则,在给定的初始网格中插入新的点,从而不断细化新的网格单元,在极端细化的情况下,网格可以收敛一个明亮的曲面
2.网格抽取(Decimation)
2.1 vtkDecimatePro
VTK网格抽取主要有三种:vtkDecimatePro、vtkQuadricDecimation、vtkQuadricClustering。
vtkDecimatePro最常用的处理方法原理参考文献[1]文献[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
VTK_MODULE_INIT(vtkRenderingOpenGL); VTK_MODULE_INIT(vtkRenderingFreeType); VTK_MODULE_INIT(vtkInteractionStyle); #include #include #include #include #include #include #include #include #include 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