前两篇笔记(《VTK笔记——数据抽取(vtkDecimatePro)》、《VTK笔记——数据抽取(vtkQuadricDecimation)》)介绍了数据的抽取,主要是对三角网格的数据,而且是不太大的数据进行处理。那这篇笔记我们来看下大数据的抽取。
vtkQuadricClustering
vtkQuadricClustering是一个用于削减三角形的类,得到一个近似的几何图形。它的输入是vtkPolyData类型的数据,可以处理所有类型的多边形网格。相比前两个算法,他的速度是很快的。它能快速的削减大网格模型,并且支持网格片段削减(利用startAppend, Append, endAppend方法),这样可以避免把整个模型载入内存中。对于大型网络模型,它有较好的效果,但是当网格变小时,三角化效果不是很好,需结合其它的方法。
vtkQuadricClustering算法是基于Peter Lindstrom在Siggraph 2000的论文 “Out-of-Core Simplification of Large Polygonal Models.” 实现的。该算法的通常是将顶点类聚在一个统一的箱体空间里,然后将每个箱体内的每个三角形的二次曲面(推到三角形的顶点上)累加起来,最后利用累积的二次曲面确定箱内单个顶点的最佳位置。
用法
前面介绍了,这个类的输入可以是任意多边形数据类型,因此,使用这个类也比较简单。
auto decimate = vsp<vtkQuadricClustering>::New();
decimate->SetInputData(inputPD);
decimate->UseFeatureEdgesOn();
decimate->Update();
一些方法:
SetUseFeatureEdges
StartAppend
Append
EndAppend
示例
下面的演示了对一只牛模型进行数据抽取后的效果及数据大小的对比:
QuadricClustering.cxx
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkSphereSource.h>
#include <vtkTriangleFilter.h>
#include <vtkQuadricClustering.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]);
reader->Update();
inputPD = reader->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;
auto decimate = vsp<vtkQuadricClustering>::New();
decimate->SetInputData(inputPD);
decimate->UseFeatureEdgesOn();
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;
}