这个笔记是记录学习VTK数据集和学习中练习的代码;

数据集

  在可视化流水线中,称处理的数据对象为数据集。数据集是一个抽象的概念,其对应的类vtkDataSet也是一个抽象类。在程序中使用的数据集也是其派生出来的子类。
  数据集由两部分组成:组织化的结构及结构相对应的属性;
  数据集的结构包括两部分,分别是拓扑结构和几何结构;
  拓扑结构由数据集中的一系列单元确定,几何结构由数据集中的一系列点坐标确定;单元是由数据集中一个或多个有关系的点组成的。单元描述了哪些点连成一条线,或者哪些点围成一个多边形等。线和多边形都是一种具体的单元类型。单元的意义在于描述了点与点之间的关系;
  数据集的属性是与其结构相关联的,又可分为点数据属性和单元数据属性。这些数据属性通常是代表实物体的属性,一般是标量数据,比如一个点上的数据表示那个空间点的温度或者速度或者密度;或者表示一个面单元的热流等等;这些标量信息都是放在了数据集中的属性中;

数据集的结构

  定义一个数据集的结构需要分别对数据集的几何和拓扑进行定义,即需要分别对点和单元进行定义;

几何结构-点坐标

  数据集的点组成方式极为简单,就是一个离散点的集合;
  首先将一系列点坐标插入到vtkPoints对象中,接着调用数据集对象的方法SetPoints(),并将这个vtkPoints对象作为参数传入,这样就定义好了数据的点,也就定义好了数据集的几何结构;插入到vtkPoints对象中的点会有一个相对应的id号(索引),之后使用单元(拓扑结构)就是使用这些id号来表示单元中点与点的关系;

拓扑结构-单元

  在之前笔记中有记录了vtkMapper要根据标量数据还有拓扑结构对图元进行颜色上的映射;
  单元就是拓扑结构,是表示了点与点之间的关系,点与点之间的关系多种多样,则单元的定义比较复杂,所以单元的类型比较多;定义单元需要指定单元的类型及一些有序的点id;
  VTK支持的单元类型有以下类型:

顶点

  顶点是一个基本的零维单元,由一个单一点定义;

多顶点

  多顶点是一个复合的零维单元,由任意顺序的一系列点定义;

线

  线是一个基本的一维单元,由两个点定义。其方向为第一个点到第二个点的方向;

多段线

  多段线是一个复合的一维单元,包含一个或多个连接的线,由有序的n+1个点进行定义,其中n是多段线中的线的段数,每对点(i,i+1)定义了一段线;

三角形

  三角形是一个基本的二维单元,由按顺时针或逆时针方向排列的三个点定义;根据点的顺序使用右手法则可以确定面的法线方向;如果从正对法线方向的角度看,点是按逆时针方向排列的;

三角形带

  三角形带是一个复合的二维单元,包含一个或多个三角形,这些三角形不必位于同一个面上。其由有序的n+2个点进行定义,其中n是三角形的个数。点的排列顺序必须满足是任意三个相邻点(i,i+1,i+2)都能定义一个三角形,其中i的取值范围为[0,n-1];

四边形

  四边形是一个基本的二维单元,由位于同一个面上按顺时针或逆时针排列的四个点定义;四边形必须是凸的,并且边不能相交;根据点的顺序使用右手法则可确定面的法线方向;

像素

  像素是一个基本的二维单元,由有序的四个点定义。像素单元在拓扑上与四边形等价,只是另外带有几何上的限制。像素的每条边与其邻边垂直,并与x-y-z三个坐标轴中的一个平行。因此法线方向与平行于一个坐标轴;
  定义像素的点的顺序与定义四边形单元的不同。点的顺序是按照坐标轴的正方向来排列的,先是x轴,然后是y轴,最后是z轴。像素是一种四边形的特例,用于改进计算性能;
  注意事项:这里给出的像素定义与通常的像素定义不同。一般的像素是指图像中具有常量值得图像元素。而这里给出的定义意味着四个图像元素形成了像素元旦四个角上的点。

多边形

  多边形是一个基本的二维单元,由位于同一平面上按顺时针或逆时针的三个或更多的点定义。根据点的顺序使用右手法则可确定多边形的法线方向。

四面体

  四面体是一个基本的三维单元,由四个不同平面的点定义。四面体包含六条边和四个三角面。

六面体

  六面体是一个基本的三维单元,包含六个四边形面,十二条边和八个顶点。六面体由有序的八个点定义。面和边不能与其他面和边相交,四边形必须是凸的。

体素

  体素是一个基本的三维单元。体素在拓扑上与六面体等价,只是另外带有几何上的限制。体素的每个面与x-y-z三个坐标轴中的一个垂直。点的定义顺序是按照坐标轴的正方向来排列的。体素是六面体的一个特例,用于改进计算性能。与像素一样,这里的体素的定义与常规意义上的体素不同。体素一般是指具有常量值得体积元素。根据这里的体素单元的定义,八个体积元素形成了体素单元八个角上的点。

数据集的属性

  数据集的属性(数据属性)是与数据集的结构相关联的。而数据集的结构又是建立在点和单元的基础上,因此数据属性很自然的与点和单元相关联,即每个点或每个单元都有其对应的数据属性;
  称数据属性的值为属性数据;属性数据一般设置为一些有实际意义的值,如某点处的温度(用一个数值表示),或某点处所受的力(用三个数值表示)等。点或单元的属性数据是以数据数组(vtkDataArray)的形式进行存储的,根据数据值类型的不同,它们具体存储在vtkDataArray的子类中,如vtkFloatArray或vtkIntArray等。称数组的每个元素为元组,对应着单个点或单元的属性数据。每个元组可以由多个分量(component),如速度值就有分别沿着x、y和z轴的三个分量。数组的长度必须与点或单元的个数相同,只有这样才能保证与点或单元一一对应。
  向vtkFloatArray或vtkIntArray插入数值的两种方式:
  1.在插入各个数据前,元组个数可以不指定,这样就必须调用名字前缀为Insert的方法插入数据(注意,最终插入的元组个数必须等于点或单元的个数);
  2.先指定元组个数,然后使用Set前缀的方法SetTuple?(?为元组中分量的个数),此方法比方法1快;
  数据数组可作为特殊或一般的属性数据添加到数据集中。若是作为一般属性数据,则在创建数据数组时可以用方法SetName()给数组设置一个名字,之后就可以通过这个名字来使用该数据数组。

数据集属性的使用方法

  1.调用数据集的方法GetPointData()或GetCellData()获取点或单元数据;
  2.调用Set函数设置特殊属性数据;
    方法SetScalars设置标量属性数据;
    方法SetVectors设置矢量属性数据;
    方法SetNormals设置法线向量属性数据;
    方法SetTCoords设置纹理坐标属性数据;
    方法SetTensors设置张量属性数据;
  3.调用方法AddArray将数据数组作为一般属性数据添加到数据集中,该方法可多次调用,从而可添加多个数据数组,正是由于一般属性数据没有数量上的限制,所以使用字符串来进行区分会方便些;

vtkNew<vtkPolyData> polyData;
polyData->GetPointData()->SetScalars(scalars);// 特殊属性数据
polyData->GetCellData()->SetVectors(vectors);// 特殊属性数据
polyData->GetPointData()->AddArray(anArray);// 一般属性数据

vtkPolyData

  vtkPolyData是一个数据对象类,是vtkDataSet的派生类。vtkPolyData表示由顶点、直线、多边形和/或三角形条带组成的几何结构。还表示点和单元属性值(例如,标量、向量等)。
  vtkPolyData支持的实际单元格类型,具体类型都定义在vtkCellType.h,分别有:vtkVertex、vtkPolyVertex、vtkLine、vtkPolyLine、vtkTriangle、vtkQuad、vtkPolygon和vtkTriangleStrip。
  vtkPolyData对象的一个重要特性是可以使用特殊的遍历和数据操作方法来处理数据。这些方法通常比vtkDataSet方法更有效,应该尽可能的使用。例如,遍历数据集中的单元格时,我们将使用GetCell()。要使用vtkPolyData遍历单元格,我们将检索表示多边形的单元格数组对象(例如使用GetPolys()),然后使用vtkCellArray的InitTraversal()和GetNextCell()方法。
  警告:由于vtkPolyData是通过vtkCellArray的四个独立实例实现的,它们分别表示0D顶点、1D直线、2D多边形和2D三角形条带,因此可以创建由混合单元类型组成的vtkPolyData实例。由于类的设计,混合单元类型如何插入到vtkPolyData中,以及它们的处理和呈现顺序都有一定的限制。为了保持单元ID的一致性,并确保正确呈现包含单元数据的单元,用户必须按顶点(vtkVertex和vtkPolyVertex)、线(vtkLine和vtkPolyLine)、多边形(vtkTriangle、vtkQuad、vtkPolygon)和三角形条带(vtkTriangleStrip)的顺序插入混合单元。
处理混合单元类型的vtkPolyData时,某些筛选器可能以不同的方式处理单元。有些人会将一种类型转换为另一种类型(例如,vtkTriangleStrip转换为vtkTriangles)或期望某种类型(vtkDecimatePro期望三角形或三角形条带;vtkTubeFilter需要行)。仔细阅读每个过滤器的文档,以了解vtkPolyData的每个部分是如何处理的。
  这里指定的一些方法只有在数据集被指定为“可编辑”时才能正常工作。它们是这样记录的。

vtkCellArray

  vtkCellArray将数据集拓扑存储为一个显式连接表,其中列出了构成每个单元的点id。
  在内部,连接性表表示为两个数组:偏移量和连接性。偏移量是一个[numCells+1]值的数组,表示连接数组中每个单元格的点开始的索引。最后一个值始终是连接数组的长度。连接数组存储每个单元的点ID列表。因此,对于由两个三角形、一个四边形和一条直线组成的数据集,内部数组将显示如下:

Topology:
---------
Cell 0: Triangle | point ids: {0, 1, 2}
Cell 1: Triangle | point ids: {5, 7, 2}
Cell 2: Quad     | point ids: {3, 4, 6, 7}
Cell 4: Line     | point ids: {5, 8} 
vtkCellArray (current):
-----------------------
Offsets:      {0, 3, 6, 10, 12}
Connectivity: {0, 1, 2, 5, 7, 2, 3, 4, 6, 7, 5, 8}

  其结构可理解为:(n,id1,id2,…,idn, n,id1,id2,…,idn, …),n表示一个单元包含的点的个数,id?表示单元所关联的点的Id。
在这里插入图片描述

参考资料

1.《医学图形编程技术》;

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐