前言
数据结构对于可视化领域是非常重要的一个部分,我们需要将自己的数据读取,转换成VTK能够识别的数据这样才能实现数据的可视化,同时了解了这些数据结构对我们开发出高效、有针对性的的可视化应用程序非常重要。
可视化数据的基本特点
1、数据离散性
世界是连续的、无限的,但是能被计算机处理的数据都是离散的,数据基本上是以离散点的形式在计算机种进行存储,这就需要对现实世界的物体进行采样,数据获取设备基本上是每隔一定的间距获取一个点,这个过程就是一个离散的过程,所以数据具有离散性。
2、数据规则性
数据还可以分为规则的和不规则的。对于规则数据,存储时只需要存储起点、终点、每个点之间的间隔以及点的总数即可,如DEM数据。不规则数据就是点全部是散乱的,每个地方的密度也基本不一样,需要存储每个点的位置(X,Y,Z),虽然存储上没有规则数据那么高效,但是它表达的细节更加丰富、细致。
3、数据维度
数据有零维、一维、二维、三维、等任意维度,零维数据可以表示为点、一维数据可以表示为线、二维数据表示为一条面、三维数据表示为一个体。
vtkDataObject和vtkDataSet
vtkDataObject
vtk种数据一般以数据对象vtkDataObject为表现形式,数据对象是数据的集合,数据对象表现的数据是可以被可视化管线处理的数据,只有数据对象被组织成一种结构(Structure),才能被vtk提供的可视化算法处理。下面是vtkDataObject类的继承图,vtk种所有的数据结构形式都是从这个类种继承来的,在实际的vtk程序种没有直接使用vtkDataObject来实例化对象,而是由具体的子类实例化的。
vtkDataSet
在vtk必须要实例化vtkDataSet种一个子类才能进行可视化,vtk数据集是带有拓扑和几何结构的数据对象,除此之外还包括属性数据,属性数据包括标量、矢量、张量、法向量、纹理坐标、场数据。可以用下图表示
其中几何结构就是点集,拓扑结构cells可以分为线性的和非线性的,如下图所示
属性数据是和数据集结构相关联的信息,在大多数情况下属性数据都是和点或者cells相关联
数据存储与表达
vtk中内存分配采用连续内存,用vtkDataArray类实现,vtk中给vtkDataArray定义了许多子类如vtkDoubleArray、vtkFloatArray、vtkIntArray等。他们都是大同小异,只是类型不同。
以vtkFloatArray为例,如下图所示;
Array是指向浮点型数组的指针;
Size设定数组的长度,数组长度是动态增长的,当存储的数据长度超过指定的长度就会触发Resize()调整数组的长度,使长度变为原来的两倍,和vector一样;
MaxId是一个整型的偏移量,用来定义最后一个被插入的数据的索引,如果没有数据插入,其值为-1;
NumberOfComponents表示数组中元组的组分个数,如果储存的是rgb信息那么这个值就应该是3,如下图所示,该值设定后每个元组都由三部分组成
例子
这个例子展示了如何设置数据的几何结构、拓扑结构、属性。其中几何结构和拓扑结构是必不可少的,不然无法显示!
//***********************************
//说明:数据类型,设置数据的几何结构、拓扑结构、属性
//时间:2020.08.13
//作者:BOO
//********************************
#include<vtkSmartPointer.h>
#include<vtkPolyData.h>
#include<vtkCellArray.h>
#include<vtkPointData.h>
#include<vtkFloatArray.h>
#include<vtkPolyDataMapper.h>
#include<vtkActor.h>
#include<vtkRenderer.h>
#include<vtkRenderWindow.h>
#include<vtkRenderWindowInteractor.h>
#include<vtkInteractorStyleTrackballCamera.h>
#include<vtkCamera.h>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType)
int main()
{
//定义立方体八个顶点,6个面的顶点
int i;
static float x[8][3] = { {0,0,0},{1,0,0},{1,1,0},{0,1,0},
{0,0,1},{1,0,1},{1,1,1},{0,1,1} };
static vtkIdType pts[6][4] = { {0,1,2,3},{4,5,6,7} ,{0,1,5,4}, {1,2,6,5},{2,3,7,6},{3,0,4,7} };
vtkSmartPointer<vtkPolyData>cube = vtkSmartPointer<vtkPolyData>::New();//数据
vtkSmartPointer<vtkPoints>points = vtkSmartPointer<vtkPoints>::New();//几何结构
vtkSmartPointer<vtkCellArray>cells= vtkSmartPointer<vtkCellArray>::New();//拓扑结构
vtkSmartPointer<vtkFloatArray>scalars = vtkSmartPointer<vtkFloatArray>::New();//属性数据
//写入数据
for (int i = 0; i < 8; i++) points->InsertPoint(i,x[i]);
for (int i = 0; i < 6; i++) cells->InsertNextCell(4, pts[i]);
for (int i = 0; i < 8; i++) scalars->InsertTuple1(i, i);
cube->SetPoints(points);
cube->SetPolys(cells);
cube->GetPointData()->SetScalars(scalars);
//映射器
vtkSmartPointer<vtkPolyDataMapper> cubeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
cubeMapper->SetInputData(cube);
cubeMapper->SetScalarRange(0, 7);
//对象
vtkSmartPointer<vtkActor> cubeActor = vtkSmartPointer<vtkActor>::New();
cubeActor->SetMapper(cubeMapper);
//渲染场景
vtkSmartPointer<vtkRenderer>renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(cubeActor);
renderer->SetBackground(0.0, 1.0, 1.0);
//相机
renderer->GetActiveCamera()->SetPosition(1, 1, 1);
renderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
renderer->ResetCamera();
//渲染窗口
vtkSmartPointer<vtkRenderWindow>renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer(renderer);
renWin->SetSize(600, 400);
//交互
vtkSmartPointer<vtkRenderWindowInteractor>renderInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderInteractor->SetRenderWindow(renWin);
//交互风格
vtkSmartPointer<vtkInteractorStyleTrackballCamera>style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
renderInteractor->SetInteractorStyle(style);
renderInteractor->Initialize();
renderInteractor->Start();
return 0;
}
结果显示:
参考
《VTK图形图像开发进阶》
study VTK Together 一起学习VTK教程--水灵
《VTKTextBook》