VTK图形图像开发进阶-03VTK基本数据结构

3.1 可视化数据的基本特点

1.离散性

       为了让计算机能够获取、处理和分析数据,必须对无限、连续的空间体进行采样,生成有限的采样数据点,这些数据以离散点的形式存储,采样的过程是一个离散化的过程。由于可视化数据的离散性特点,在某些离散点上有精确的值存在,但点与点之间的值则是不可知的,要得到采样点之外的其他点的值,只有通过插值(Interpolation) 的方法获取。常用的插值方法是线性插值,要得到更精确的数值可以采用非线性插值。

2.数据具有规则或不规则的结构(结构化或非结构化)

        规则结构数据点之间有固定的关联关系,可以通过这些关联确定每个点的坐标,不规则结构数据之间没有固定的关联关系。对于规则结构的数据,在储时不必存储所有数据点,只需存储起始点,相邻两点之 间的间隔以及点的总数就可以保存完整的数据信息。对于不规则结构的数据,虽然不可以像规则结构的数据那样存储,但它也有自身的优势,即在数据变化频繁的区域可以密集表示,而数据变化不频繁的区域则稀疏表示。规则结构的数据可以在存储及计算时占优势,不规则结构的数据虽然在存储和计算时不能像规则结构那样高效,但它在数据表达方面相对而言更加自由、细致、灵活。

3.数据具有维度

        可视化数据的第三个特点是拓扑维度(Topological Dimension)。可视化数据具有零维、一维、二维、三维等任意维度,例如,零维数据表现为点,- -维数据表现为曲线。 二维数据表现为曲面、三维数据表现为体等。数据的维度决定了数据可视化的方法。

3.2数据对象和数据集

3.2.1 vtkDataObject

1.数据一般以数据对象(类vtkDataObject)的形式表现,数据对象是数据的基合,数据对象表现的数据是可以被可视化管线处理的数据,只有当数据对象被组织成一种结构后,才能被VTK提供的可视化算法所处理。

3.3.2 vtkDataSet

1.将数据对象组织成一种结构并且赋予相应的属性值,就形成了数据集(Dataset)

2.vtkDataSet由两个部分组成,即组织结构和与组织结构相关联的属性数据。

3.组织结构包括拓扑结构和几何结构

拓扑结构描述了对象的构成形式——点数据的连接形式形成单元数据,有单元数据形成了数据集的拓扑结构

几何结构描述了对象的空间位置关系——点数据所定义的一些列坐标构成了vtkDataset数据集的几何结构

4.属性数据是对拓扑结构和结合结构信息的补充,属性数据可以是每个空间点的温度值,也可以看作某个单元的质量等。

5.示例——如何将几何结构和拓扑结构加入数据集中

(1)将几何结构加入数据集

        先创建一个点数据(vtkPoints),里面含有三个点,再创建一个具体数据集(vtkPolyData)然后将创建的点加入数据集,最后把vtkPolyData的数据用类vtkPolyDataWriter写入triangle.vtk文件,保存路径为工程的当前目录。

        可以利用ParaView软件打开.vtk文件。

#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataWriter.h>
 
int main(int argc, char* argv[])
{
 
	// 创建点数据
	vtkSmartPointer<vtkPoints> points =
				vtkSmartPointer<vtkPoints>::New();
	points->InsertNextPoint(1.0, 0.0, 0.0);
	points->InsertNextPoint(0.0, 0.0, 0.0);
	points->InsertNextPoint(0.0, 1.0, 0.0);
 
	// 创建vtkPolyData类型数据,vtkPolyData派生自vtkPointSet
	// vtkPointSet是vtkDataSet子类,即vtkPolyData是一种数据集
	vtkSmartPointer<vtkPolyData> polyData =
		vtkSmartPointer<vtkPolyData>::New();
 
	// 将创建的点数据加入到vtkPolyData数据里
	polyData->SetPoints(points);
 
	//将vtkPolyData类型的数据写入到一个vtk文件,保存位置是工程当前目录
	vtkSmartPointer<vtkPolyDataWriter> writer =
		vtkSmartPointer<vtkPolyDataWriter>::New();
	writer->SetFileName("triangle.vtk");
	writer->SetInputData(polyData);
	writer->Write();
 
	return 0;
 
}

(2)将拓扑结构加入数据集

        以下示例实例化了一个vtkCellArray对象,其中vtkCellArray类型中的vertices就是指定数据集polydata的拓扑结构,points定义几何结构。

        该示例中定义的数据集的拓扑结构为零维的点,单元类型为vertices

#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkPolyDataWriter.h>
 
int main(int argc, char* argv[])
{
 
	// 创建点坐标
	double X[3] = { 1.0, 0.0, 0.0 };
	double Y[3] = { 0.0, 0.0, 0.0 };
	double Z[3] = { 0.0, 1.0, 0.0 };
 
	// 创建点数据以及在每个点坐标上加入顶点(Vertex)类型的单元
	// vtkPointSet是vtkDataSet子类,即vtkPolyData是一种数据集
	vtkSmartPointer<vtkPoints> points =
						vtkSmartPointer<vtkPoints>::New();
	vtkSmartPointer<vtkCellArray> vertices =
		vtkSmartPointer<vtkCellArray>::New();
 
	for (unsigned int i = 0; i < 3; ++i)
	{
		// 定义用于存储点索引的中间变量,vtkIdType就相当于int long等类型
		vtkIdType pid[1];
 
		// 把每个点坐标加入vtkPoints中,InsertNextPoints()返回加入的点的索引号
		// 下面需要使用这个索引号来创建顶点类型的单元
		pid[0] = points->InsertNextPoint(X[i], Y[i], Z[i]);
 
		// 在每个坐标点上分别创建一个顶点,顶点是单元(Cell)里的一种类型
		vertices->InsertNextCell(1, pid);
 
	}
	// 创建vtkPolyData对象
	vtkSmartPointer<vtkPolyData> polyData =
		vtkSmartPointer<vtkPolyData>::New();
 
	// 指定数据集的几何结构(由points指定)以及数据集的拓扑结构(由vertices指定)
	polyData->SetPoints(points);
	polyData->SetVerts(vertices);
 
	//将生成的数据集写入到TriangleVerts.vtk文件,保存位置是工程当前目录
	vtkSmartPointer<vtkPolyDataWriter> writer =
		vtkSmartPointer<vtkPolyDataWriter>::New();
	writer->SetFileName("TriangleVerts.vtk");
	writer->SetInputData(polyData);
	writer->Write();
 
	return 0;
 
}

        该示例定义的是一维拓扑结构。 

#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkLine.h>
#include <vtkPolyData.h>
#include <vtkPolyDataWriter.h>
 
int main(int argc, char* argv[])
{
 
	// 创建三个坐标点
	vtkSmartPointer<vtkPoints> points =
		vtkSmartPointer<vtkPoints>::New();
	points->InsertNextPoint(1.0, 0.0, 0.0); // 返回第一个点的ID:0
	points->InsertNextPoint(0.0, 0.0, 0.0); // 返回第一个点的ID:1
	points->InsertNextPoint(0.0, 1.0, 0.0); // 返回第一个点的ID:2
	
	// 每两个坐标点之间分别创建一条线
	// SetId()的第一个参数是线段的端点ID,第二个参数是连接的点ID
	vtkSmartPointer<vtkLine> line0 =
		vtkSmartPointer<vtkLine>::New();
	line0->GetPointIds()->SetId(0, 0);
	line0->GetPointIds()->SetId(1,1);
 
	vtkSmartPointer<vtkLine> line1 =
		vtkSmartPointer<vtkLine>::New();
	line1->GetPointIds()->SetId(0, 1);
	line1->GetPointIds()->SetId(1, 2);
 
	vtkSmartPointer<vtkLine> line2 =
		vtkSmartPointer<vtkLine>::New();
	line2->GetPointIds()->SetId(0, 2);
	line2->GetPointIds()->SetId(1, 0);
 
	// 创建单元数组,用于存储以上创建的线段
	vtkSmartPointer<vtkCellArray> lines =
		vtkSmartPointer<vtkCellArray>::New();
	lines->InsertNextCell(line0);
	lines->InsertNextCell(line1);
	lines->InsertNextCell(line2);
 
	// 创建vtkPolyData对象
	vtkSmartPointer<vtkPolyData> polyData =
		vtkSmartPointer<vtkPolyData>::New();
 
	// 指定数据集的几何结构(由points指定)以及数据集的拓扑结构(由lines指定)
	polyData->SetPoints(points);
	polyData->SetVerts(lines);
 
	//将生成的数据集写入到TriangleVerts.vtk文件,保存位置是工程当前目录
	vtkSmartPointer<vtkPolyDataWriter> writer =
		vtkSmartPointer<vtkPolyDataWriter>::New();
	writer->SetFileName("TriangleLines.vtk");
	writer->SetInputData(polyData);
	writer->Write();
 
	return 0;
 
}

3.3 单元类型

1.数据集由一个或多个单元组成。一系列有序的点按指定类型连接所定义的结构就是单元。

2.单元是由单元的类型和构成的定点列表(由点的检索号表示)两部分构成。

3.3.1 线性单元

(a)VTK_VERTEX。顶点,零维的基本类型。

(b)VTK_POLY_VERTEX。多顶点,多个顶点组成,零维的基本类型。

(c)VTK_LINE。直线,一维的基本类型,方向由第一个点指向第二个点。

(d)VTK_POLY_LINE。折线

(e)VTK_TRIANGLE 三角形,三个点逆时针防线连接

(f)VTK_TRIANGLE_STRIP 三角形条带

(g)VTK_QUAD。四边形,二维的基本类型,非自交的凸多边形

(h)VTK_PIXEL。二维的基本类型

(i)VTK_POLYGON。多边形,二维的基本类型,逆时针方向顺序定义,可以是非凸的

(j)VTK_TETRA。四面体,三维的基本类型

(k)VTK_HEXAHEDRON。六面体,三维的基本类型

(l)VTK_VOXEL。三维的基本类型

(m)VTK_WEDGE。楔形,三维的基本类型

(n)VTK_PYRAMID 。角椎体

(o)VTK_PENTAGONAL_PRISM 。五棱柱

(p)VTK_HEXAGONAL_PRISM。六角柱

3.3.2 非线性单元

        非线性单元常见的处理方式是将非线性单元细分成线性单元,再把细分结果当作线性单元处理,采用固定细分的方法。

3.4 属性数据

        属性数据主要用于描述数据集的属性特征,对数据集的可视化实质上就是对属性数据的可视化。在VTK中,用vtkPointData类和vtkCellDta类表达数据集属性,他们是类vtkDataSetAttributes(vtkDataSetAttributes派生自vtkFieldData)的子类,构成数据集的每个点(或单元)和属性数据之间存在一对一的关系。

3.4.1 标量数据

        标量数据是数据集里的每个位置具有单值的数据,它只表示数据的大小。例如温度、压力、密度、高度等。

#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkDoubleArray.h>
#include <vtkPolyData.h>
 
int main(int , char* [])
{
 
	// 创建点集数据:包含两个坐标点
	vtkSmartPointer<vtkPoints> points =
		vtkSmartPointer<vtkPoints>::New();
	points->InsertNextPoint(0, 0, 0); // 返回第一个点的ID:0
	points->InsertNextPoint(1, 0, 0); // 返回第一个点的ID:1
 
	// 创建多边形数据
	vtkSmartPointer<vtkPolyData> polyData =
		vtkSmartPointer<vtkPolyData>::New();
	polyData->SetPoints(points);
	
	// 准备加入点数据的标量值,两个标量值分别为1和2
	vtkSmartPointer<vtkDoubleArray> weights =
		vtkSmartPointer<vtkDoubleArray>::New();
	weights->SetNumberOfValues(2);
	weights->SetValue(0, 1);
	weights->SetValue(1, 2);
 
	// 先获取多边形数据的点数据指针,然后设置该点数据的标量属性值
	polyData->GetPointData->SetScalars(weights);
		
	// 输出索引号为0的点标量值
	double weight = vtkDoubleArray::SafeDownCast(
					polyData->GetPointData->GetScalars())->GetValue(0);
	std::cout << "double weight:" << weight << std::endl;
 
	return 0;
 
}

        要给数据集里的点数据或单元数据设置标量属性数据,只有先获得该数据集对应的点数据或单元数据,然后设置标量属性数据即可。

GetPointData->SetScalars();

3.4.2 矢量数据

        与物理学的矢量概念一样,VTK的矢量数据也是指既有大小也有方向的量,三维方向上用三元组(Triple)表示为(u, v, w),如速度、应力、位移等。

       除了矢量数据用三元组表示,颜色等标量数据也会用类似三元组的结构表示。比如,从2.2.3节可知,颜色可以用RGB三个分量表示,RGB分量是构成颜色标量数据的三个组分,尽管颜色vtkColor也是使用vtkVector 容器,但它与矢量数据是有本质区别的。

         标量数据在数据集的几何变换过程中具有不变性。比如,假设有一个矢量数据存储在某个vtkDataSet 数据集里,当使用vtkTransformFilter对该数据集做变换时,希望的结果是该矢量数据也随着数据集的变换而变换;而对于RGB系统的颜色,假如把该颜色的RGB三个分量当成矢量方向的三个方向,对该数据集做变换时,颜色值也会随着变化,对于某一点的颜色,显然需要的结果是变换前后它的值应该保持不变。法向量是指大小恒为1的方向向量,也是一种常用的矢量数据,通常用于计算投影、光照等。当对数据集做变换时,法向量是会随之发生改变的。

3.4.3 纹理坐标

        为了使物体看起来更加真实,计算机图形学通常对显示的三维物体采用纹理映射。纹理坐标可以将点从笛卡儿坐标空间映射到一维、二维或三维的纹理空间中。

3.4.4 张量数据

        张量是矢量和矩阵通过复杂的数学算法得到的,一个k阶的张量可当作一个k维的表格。零阶的张量是标量,一阶的张量是矢量,二阶的张量是纹理坐标,三阶的张量是一个三维阵列,VTK只支持3×3的对称的张量。

3.5 不同类型的数据集

(a)vtkImageData

        vtkImageData类型的数据是按规则排列在矩形方格中的点和单元的集合。如果数据集的点和单元排列在平面(二维)上,则称此数据集为像素映射、位图或图像;如果排列在层叠面(三维)上,则称为体。

(b)vtkRectilinearGrid

        vtkRectilinearGrid类型的数据是排列在矩形方格中的点和单元的集合。线性网格的拓扑结构是规则的,但其几何结构只有部分是规则的。

(c)vtkStructuredGrid

        vtkStructuredGrid是结构化网格数据,是具有规则的拓扑结构和不规则的几何结构。

(d)vtkUnstructuredPoints

        vtkUnstructuredPoints 为非结构化点集,是指不规则地分布在空间的点集。非结构化点集具有不规则的几何结构,不具有拓扑结构,非结构化点集用离散点来表达。

(e)vtkPolyData

        多边形数据集vtkPolyData由顶点、多顶点、线、折线和三角形条带等单元构成,多边形数据是不规则结构的,并且多边形数据集的单元在拓扑维度上有多种类型。

(f)vtkUnstructuredGrid

        vtkUnstructuredPoints为非结构化点集,是指不规则地分布在空间的点集。非结构化点集具有不规则的几何结构,不具有拓扑结构,非结构化点集用离散点来表达。

3.6 数据的存储与表达

3.6.1  vtkDataArray

1.VTK中的内存分配采用连续内存,可以快速的创建、删除和遍历,称之为数据数组(Data Array),用类vtkDataArray实现。

2.以vtkFloatArray类来说明如何在VTK中实现连续内存的数据数组。变量Array是一个指向浮点型数组的指针,数组的长度由变量Size指定,由于数组的长度是动态地增加的,所以当存储数据的数组长度超出指定的长度时,会自动触发Resize()操作来调整数组的长度,使数组的长度变成原来的两倍,Maxld是一个整型的偏移量,用来定义最后一个被插入的数据的索引。如果没有数据插入,Maxld等于-1,否则,Maxld 的值介于0和Size之间,即О≤MaxId<Size。

3.元组是数据数组的子数组,用于存储数据类型相同的分量数据,元组的组分成为元组的大小。

3.6.2  数据对象的表达

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值