1.基本图形操作意义
图形处理,比如图形平滑、多分辨率分析、特征 提取等都离不开一些基本的图形操作。掌握这些基本的图形操作有助于理解和深入学习图形处理和分析方法。
VTK中提供了多种图形的基本操作,其中最简单的是点的欧式距离计算,可以使用VTKMath进行计算,也可以直接计算向量的模。一些图元类提供许多可以方便使用的静态函数,
vtkLine提供了点与线间的距离计算;
vtkTriangle提供了面积、外接圆、法向量的计算,点与三角形位置关系判断等;
vtkTetra中实现了四面体积,重心计算等。
有了这些函数可以实现很多其他功能的函数,如计算一个三角网格模型的面积,只需要遍历每个三角形单元并计算其面积即可。
另外,还有一个办法是vtkMassProperties。该类可以实现三角网格表面积和体积的计算,但是要求网格必须是封闭的三角网格数据。网格的封闭性计算在后面会有更加详细的讨论。对于非三角形网格,需要将网格转换为三角形网格。
vtkTriangleFiler可以实现多变形网格数据向三角形网格数据转换。
2.三角网格模型面积、体积计算(类:vtkMassProperties)
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkTriangleFilter.h> //其他网格类型转换成三角网格类型
#include <vtkMassProperties.h> //计算三角网格的基本属性 面积。体积等
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
int main()
{
vtkSmartPointer<vtkCubeSource> cubeSource =
vtkSmartPointer<vtkCubeSource>::New(); //vtkPolyData类型数据
cubeSource->Update();
vtkSmartPointer<vtkTriangleFilter> triFilter =
vtkSmartPointer<vtkTriangleFilter>::New();
triFilter->SetInputData(cubeSource->GetOutput());
triFilter->Update();
vtkSmartPointer<vtkMassProperties> massProp =
vtkSmartPointer<vtkMassProperties>::New();
massProp->SetInputData(triFilter->GetOutput());
float Volume = massProp->GetVolume();
float SurfaceArea = massProp->GetSurfaceArea();
float maxArea = massProp->GetMaxCellArea();
float minArea = massProp->GetMinCellArea();
std::cout << "the Volume : " << Volume << std::endl;
std::cout << "Surface Area : " << SurfaceArea << std::endl;
std::cout << "MaxAreaofCell: " << maxArea << std::endl;
std::cout << "MinAreaofCell: " << minArea << std::endl;
///
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(triFilter->GetOutput());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(0, 0, 1);
actor->GetProperty()->SetEdgeColor(1, 0, 0);
actor->GetProperty()->SetEdgeVisibility(1);
vtkSmartPointer<vtkRenderer> render =
vtkSmartPointer<vtkRenderer>::New();
render->AddActor(actor);
render->SetBackground(0, 0, 0);
vtkSmartPointer<vtkRenderWindow> rw =
vtkSmartPointer<vtkRenderWindow>::New();
rw->AddRenderer(render);
rw->SetSize(480, 420);
rw->SetWindowName("Calculating Area and Volume of Triangle grid");
vtkSmartPointer<vtkRenderWindowInteractor> rwi =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(rw);
rwi->Initialize();
rwi->Start();
return 0;
}
3.三维网格测地距离
对于三维网格模型来讲,测地距离也是一种重要的距离度量。与欧式距离不同,一个三维模型上的亮点测地距离是指沿着模型表面两者之间的最短距离。测地距离通常采用Dijkstra算法类近似值求解。vtk中的vtkDijkstraGraphGeodesicPath类就可以实现测地距离求解。
下面的例子中,我们定义了一个球形。计算测地距离时,必须指定两个点的索引号。
SetStartVertex()设置开始点;SetEndVertex()设置结束点;计算完毕后,通过GetOutPut()函数可以得到一个vtkPolyData数据,即最短路径数据,其实质为折线段集合。
代码;
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkDijkstraGraphGeodesicPath.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
int main()
{
vtkSmartPointer<vtkSphereSource> sphereSource =//定义一个球形
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->Update();
vtkSmartPointer<vtkDijkstraGraphGeodesicPath> dijstra =
vtkSmartPointer<vtkDijkstraGraphGeodesicPath>::New();
dijstra->SetInputData(sphereSource->GetOutput());
dijstra->SetStartVertex(0);//开始位置
dijstra->SetEndVertex(10);//结束位置
dijstra->Update();
///
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(sphereSource->GetOutput());
vtkSmartPointer<vtkPolyDataMapper> pathMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
pathMapper->SetInputData(dijstra->GetOutput());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkActor> pathActor =
vtkSmartPointer<vtkActor>::New();
pathActor->SetMapper(pathMapper);
pathActor->GetProperty()->SetColor(1, 0, 0);
pathActor->GetProperty()->SetLineWidth(5);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderer->AddActor(pathActor);
renderer->SetBackground(0, 0, 0);
vtkSmartPointer<vtkRenderWindow> rw =
vtkSmartPointer<vtkRenderWindow>::New();
rw->AddRenderer(renderer);
rw->SetSize(640, 480);
rw->SetWindowName("Calculating Geodesic Path");
vtkSmartPointer<vtkRenderWindowInteractor> rwi =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(rw);
rwi->Initialize();
rwi->Start();
return 0;
}
3.三维图像的包围盒
包围盒是指能够包围模型的最小立方体,常常用于模型碰撞测量中。VTKPolyData中定义函数GetBounds()来获取包围盒参数。即三个坐标方向上的最大、最小值。仅仅获取这些参数并不直观,有时候还需要显示包围盒。VTKPolyData则提供一个方便的方法来生成包围盒,其输入为一个VTKPolyData模型数据,输出同样为一个vtkPolyData类型数据,因此非常容易进行可视化显示。
代码
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkProperty.h>
#include <vtkOutlineFilter.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
int main()
{
//设置球体
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetCenter(0.0, 0.0, 0.0);
sphereSource->SetRadius(5.0);
sphereSource->Update();
vtkPolyData* sphere = sphereSource->GetOutput();
vtkSmartPointer<vtkOutlineFilter> outline =
vtkSmartPointer<vtkOutlineFilter>::New();
outline->SetInputData(sphere);
outline->Update();//算法执行完毕,必须更新!!!
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(sphere);
vtkSmartPointer<vtkPolyDataMapper> outlineMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
outlineMapper->SetInputData(outline->GetOutput());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkActor> outlineActor =
vtkSmartPointer<vtkActor>::New();
outlineActor->SetMapper(outlineMapper);
outlineActor->GetProperty()->SetColor(0, 1, 0);
outlineActor->GetProperty()->SetLineWidth(3);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderer->AddActor(outlineActor);
renderer->SetBackground(0, 0, 0);
vtkSmartPointer<vtkRenderWindow> rw =
vtkSmartPointer<vtkRenderWindow>::New();
rw->AddRenderer(renderer);
rw->SetSize(640, 480);;
rw->SetWindowName("PolyData Bounding Box");
rw->Render();
vtkSmartPointer<vtkRenderWindowInteractor> rwi =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(rw);
rwi->Start();
return 0;
}