《vtk9 book》 官方web版 第五章 - 数据表示 1/2

        在第四章 - 可视化流程中,我们制定了一个实用的可视化过程定义:将信息映射到图形基元。我们看到这种映射通过一个或多个步骤进行,每个步骤将数据从一种形式或数据表示转换为另一种形式。在本章中,我们将研究常见的数据形式用于可视化。目标是让您熟悉这些形式,以便您可以使用本文提供的工具和技术可视化您自己的数据。

5.1 引言

         要为数据设计表示方案,我们需要了解可能遇到的数据。我们还需要牢记设计目标,以便我们能够设计高效的数据结构和访问方法。接下来的两节将讨论这些问题。

        表征可视化数据 由于我们的目标是可视化数据,显然我们需要了解数据的性质。这种知识将有助于我们创建有用的数据模型和强大的可视化系统。如果没有对数据的清晰理解,我们就有可能设计出不灵活、功能有限的可视化系统。接下来我们描述数据的重要特征。这些特征包括数据的离散性、是否规则或不规则以及其拓扑维度。

        首先,可视化数据是离散的。这是因为我们使用数字计算机来获取、分析和表示我们的数据,并且通常在有限数量的点上测量或采样信息。因此,所有信息必然以离散形式表示。

        考虑可视化简单的连续函数 。如果我们使用传统的数字计算机,我们必须将这个方程离散化以处理它所代表的数据(我们忽略符号/模拟计算机和方法)。例如,要绘制此方程,我们将在某个区间内对该函数进行采样,比如(-1,1),然后计算该区间内一系列离散点 处的函数值y。结果点 连接成直线段。因此,我们的(连续)数据由离散采样表示。

        由于数据的离散性,我们不了解数据值之间的区域。在我们之前的例子中,我们知道数据是从函数 生成的,但一般来说,当我们测量甚至计算数据时,我们无法推断出数据点之间的数据值。这带来了一个严重的问题,因为重要的可视化活动之一是确定任意位置的数据值。例如,我们可能会探测我们的数据,并希望在探测位置不落在已知点上时获取数据值。

        解决这个问题有一个明显的解决方案:插值。我们假定相邻数据值之间存在关系。通常这是一个线性函数,但我们可以使用二次、三次、样条或其他插值函数。第八章 - 高级数据表示更详细地讨论了插值函数,但现在只需要说插值函数会在已知点之间生成数据值。

        可视化数据的第二个重要特征是其结构可以是规则的或不规则的(或者称为结构化的或非结构化的)。规则数据具有数据点之间的固有关系。例如,如果我们在均匀间隔的点上采样,我们不需要存储所有点坐标,只需要存储间隔的开始位置、点之间的间隔以及总点数。然后点的位置就是隐含的,这可以利用起来节省计算机内存。

        不规则数据是不规则的。不规则数据的优点是我们可以在变化快速的地方更密集地表示信息,在变化不那么大的地方则更少地表示信息。因此,不规则数据允许我们创建自适应的表示形式,这在计算资源有限的情况下可能很有益处。

        将数据表征为规则或不规则允许我们对数据做出有用的假设。正如我们刚才看到的,我们可以更紧凑地存储规则数据。通常情况下,相对于不规则数据,我们也可以更有效地计算规则数据。另一方面,不规则数据为我们提供了更多自由来表示数据,并且可以表示没有规则模式的数据。

        最后,数据具有拓扑维度。在我们的示例中, 的数据维度为一,因为我们有单独的自变量x。数据的维度可能是任意的,从0D点、1D曲线、2D曲面、3D体积,甚至更高维度的区域。

        数据的维度很重要,因为它意味着适合的可视化和数据表示方法。例如,在一维情况下,我们自然会使用x-y图、条形图或饼图,并将数据存储为值的一维列表。对于二维数据,我们可以将数据存储在矩阵中,并使用变形的表面绘图(即高度场 - 参见练习4.2)来可视化它。

        在本章和第八章 - 高级数据表示中,我们将展示这些特性:离散、规则/不规则和数据维度,如何塑造我们的可视化数据模型。在阅读这些章节时请记住这些特性。

        图5-1. 数据集的架构。数据集包括一个组织结构,具有拓扑和几何属性,以及与结构相关联的属性数据。


设计标准


        数据可视化涉及与外部数据接口对接,映射到内部形式,处理数据,并在计算机显示设备上生成图像。我们提出了一个问题:我们应该使用什么形式来表示数据?显然,我们有许多选择。选择表示形式很重要,因为它影响与外部数据接口的能力以及整个可视化系统的性能。为了解决这个问题,我们使用以下设计标准:

        紧凑 - 可视化数据往往很大,因此我们需要紧凑的存储方案来最小化计算机内存需求。

        高效 - 数据必须在计算上可访问。我们希望以恒定时间(即,与数据大小无关)检索和存储数据。这个要求为我们提供了开发时间复杂度为线性或O(n)的算法的机会。

        可映射的 - 有两种类型的映射。首先,数据表示需要有效地映射到图形基元。这确保了我们的数据能够快速、交互式地显示。其次,我们必须能够轻松地将外部数据转换为内部可视化数据结构。否则,我们将承担复杂的转换过程或不灵活的软件的负担。

        覆盖最小 - 单一的数据表示不能有效地描述所有可能的数据类型。我们也不希望对每种遇到的数据类型都使用不同的数据表示。因此,我们需要一组最小的数据表示,以在效率和数据类型数量之间取得平衡。

        简单 - 应用计算的一个重要经验教训是,简单的设计优于复杂的设计。简单的设计更容易理解,因此更容易优化。简单性的价值不可过分强调。本文中的许多算法和数据表示都高度重视这个设计标准。

        本章的其余部分描述了基于这些设计标准的常见可视化数据形式。我们的基本抽象是数据对象,这是各种具体可视化数据类型的子类。

5.2 数据对象


在VTK中找到的数据的最一般形式是数据对象。数据对象可以被视为一组没有任何形式的数据。数据对象代表被可视化管线处理的数据(参见前一章和图4-2)。单独看,数据对象携带的信息很少有用。只有当它们被组织成某种结构时,它们才提供了我们可以用可视化算法操作的形式。

5.3 数据集


        具有组织结构和关联数据属性的数据对象(图5-11)形成数据集。数据集是一个抽象形式;我们将结构的表示和实现留给它的具体子类。VTK中的大多数算法(或处理对象)都在数据集上操作。

        结构有两个部分:拓扑和几何。拓扑是在某些几何变换下不变的属性集[Weiler86]。这里我们考虑的变换包括:旋转、平移和非均匀缩放。几何是拓扑的实例化,是在三维空间中位置的规定。例如,说一个多边形是一个“三角形”,就是指定了拓扑。通过提供点坐标,我们指定了几何。

        数据集属性是与几何和/或拓扑相关联的补充信息。这些信息可能是点上的温度值或单元的惯性质量。

        我们对数据集的模型假设结构由单元和点组成。单元指定了拓扑,而点指定了几何。典型的属性包括标量、矢量、法线、纹理坐标和张量。

        数据集结构的定义作为单元和点集合的直接结果是我们数据的离散性质。点位于已知数据的位置,而单元允许我们在点之间进行插值。我们在以下部分详细描述了数据集结构和属性。

5.4 单元类型


        数据集由一个或多个单元组成(图5-2和图5-4)。单元是可视化系统的基本构建块。单元通过指定类型和有序点列表来定义。有序列表,通常称为连接列表,与类型规范一起,隐含地定义了单元的拓扑。x-y-z点坐标定义了单元的几何。

        图5-3显示了一个单元类型,一个六面体。有序列表是一个指向点坐标列表的点id序列。这个单元的拓扑隐含地已知:我们知道(8,10)是六面体的12条边之一,而(8,10,22,21)是它的六个面之一。

"图5-2. 在VTK中发现的线性单元类型。数字定义了定义点的顺序。"

"六面体单元的示例。拓扑结构由点列表的顺序隐含定义。生成图像的物理过程。"

        在第8章《高级数据表示》中,当我们探索数据集的拓扑结构时,“使用”和“使用集”的重要性将变得明显起来。

        虽然我们在三维空间中定义了点,但单元的拓扑维度可能有所不同。顶点、线段、三角形和四面体是拓扑维度分别为0、1、2和3的单元的示例,它们嵌入在三维几何空间中。单元也可以是主要的或复合的。复合单元由一个或多个主要单元组成,而主要单元不能分解为其他主要单元类型的组合。例如,三角形带由一个或多个排列紧凑的三角形组成。三角形带是一个复合单元,因为它可以分解成三角形,而三角形是主要单元。

        当然,可能存在无限种类的单元类型。在可视化工具包中,每种单元类型都是根据应用需求选择的。我们已经看到了一些单元类型:顶点、线段、多边形和三角形带(见图3-19),它们用于表示几何图形到图形子系统或库。其他单元类型,如四面体和六面体,在数值模拟中很常见。每种单元类型的效用将通过本书中的可视化实践变得明显。在接下来的章节中,将介绍可视化工具包中发现的单元类型,包括它们的分类,如线性、非线性或其他。

线性单元


        线性单元的特征是线性或常数插值函数(有关更多信息,请参见第8章中的“插值函数”)。因此,维度为一或更大的单元的特征是直线边缘。因此,任何边缘都可以由两个顶点ID来描述。以下是目前在VTK中发现的线性单元。

- 顶点。顶点是一个主要的零维单元。它由一个单点定义。
- 多顶点。多顶点是一个复合的零维单元。多顶点由一个任意排序的点列表定义。
- 线段。线段是一个主要的一维单元。它由两个点定义。沿着线段的方向是从第一个点到第二个点。
- 多线段。多线段是由一个或多个连接的线段组成的复合一维单元。多线段由一个包含n+1个点的有序列表定义,其中n是多线段中线段的数量。每一对点(i,i+1)定义了一条线段。
- 三角形。三角形是一个主要的二维单元。三角形由一个逆时针有序的三点列表定义。点的顺序使用右手定则确定表面法线的方向。

        三角形带。三角形带是由一个或多个三角形组成的复合二维单元。定义三角形带的点不需要位于一个平面上。三角形带由一个包含n+2个点的有序列表定义,其中n是三角形的数量。点的顺序是这样的,每组三个点(i,i+1,i+2)定义一个三角形。

        四边形。四边形是一个主要的二维单元。它由一个有序的四个点列表定义,这些点位于一个平面上。四边形是凸的,其边不能相交。点在四边形周围按逆时针顺序排列,使用右手定则定义表面法线。

        像素。像素是由一个有序的四个点列表定义的主要二维单元。该单元在拓扑上等同于四边形,并添加了几何约束。像素的每条边都垂直于其相邻边,并且平行于坐标轴x、y、z中的一个。因此,像素的法线也与坐标轴之一平行。

        定义像素的点的顺序与四边形单元不同。点按增加的轴坐标方向排序,从x开始,然后是y,然后是z。像素是四边形的特例,用于提高计算性能。

        重要的一点是,这里给出的像素单元的定义与通常对像素的定义不同。通常,像素被认为是图像中的常值“图像元素”(见第3章中的“图形硬件”)。这里给出的定义暗示着四个图像元素形成了像素单元的四个角点。我们通常使用术语像素来描述像素单元,但术语的含义将根据上下文而变化。

        多边形。多边形是一个主要的二维单元。多边形由一个有序的三个或多个点列表定义,这些点位于一个平面上。多边形的法线通过其点的逆时针顺序使用右手定则隐含定义。

多边形可以是非凸的,但不能有内部环,也不能自相交。多边形有n条边,其中n是多边形中的点数。

        四面体。四面体是一个主要的三维单元。四面体由四个非共面点的列表定义。四面体有六条边和四个三角形面,如图5-2所示。

        六面体。六面体是一个主要的三维单元,由六个四边形面,十二条边和八个顶点组成。六面体由一个有序的八个点列表定义,如图5-2所示。面和边不能与任何其他面和边相交,并且六面体必须是凸的。

        体素。体素是一个主要的三维单元。体素在拓扑上等同于六面体,并添加了额外的几何约束。体素的每个面都垂直于坐标轴x-y-z中的一个。定义点列表按增加坐标值的方向排序,如图5-2所示。体素是六面体的一个特例,用于提高计算性能。

        与像素类似,我们对体素单元的定义与术语“体素”的传统定义不同。通常,体素被称为常值的“体积元素”。使用我们的定义,八个体积元素形成了体素单元的八个角点。我们通常使用术语体素来描述体素单元,但术语的含义将根据上下文而变化。

        楔形体。楔形体是一个主要的三维单元,由三个四边形面,两个三角形面,九条边和六个顶点组成。楔形体由一个有序的六个点列表定义,如图5-2所示。面和边不能与任何其他面和边相交,并且楔形体必须是凸的。

        金字塔。金字塔是一个主要的三维单元,由一个四边形面,四个三角形面,八条边和五个顶点组成。金字塔由一个有序的五个点列表定义,如图5-2所示。定义四边形基平面的四个点必须是凸的;第五个顶点不能与基点共面。

        五边形棱柱体。五边形棱柱体是一个主要的三维单元,由五个四边形面,两个五边形面,十五条边和十个顶点组成。五边形棱柱体由一个有序的十个点列表定义,如图5-2所示。面和边不能与任何其他面和边相交,并且五边形必须是凸的。

        六边形棱柱体。六边形棱柱体是一个主要的三维单元,由六个四边形面,两个六边形面,十八条边和十二个顶点组成。六边形棱柱体由一个有序的十二个点列表定义,如图5-2所示。面和边不能与任何其他面和边相交,并且六边形必须是凸的。

非线性类型

        在数值分析中使用非线性单元是很常见的,即使用非线性基函数的单元形式。这些基函数通常由多项式的组合形成。非线性单元提供了更准确的插值函数(有关更多信息,请参见第8章中的“插值函数”),并更好地近似了曲线几何。然而,可能的非线性基函数数量是无限的,这给任何可视化系统带来了组合问题(即不可能实现所有非线性单元类型)。为了解决这个问题,VTK采取了双重方法。首先,VTK直接支持具有二次插值函数的非线性单元类型(见图5-4)。这些单元通过添加中间边缘节点以及偶尔的中间面和内部节点来构造,需要扩展连接列表以反映这些额外条目的添加。其次,VTK具有一个复杂的单元适配器框架,使用户能够将任何基函数与VTK进行接口化,只要基函数可以在r-s-t参数坐标系统中被唯一地表征。(注意:我们将在第8章《高级数据表示》中更详细地描述单元适配器框架。)

图5-4. 在VTK中找到的非线性单元类型。

 

        线性单元和非线性单元之间的一个显著区别是它们在各种可视化算法中的呈现和操作方式。线性单元可以轻松地转换为线性图形基元,然后由图形库处理。另一方面,非线性单元在图形库中通常没有直接支持。(一个例外是非均匀有理B样条族或NURBS。即使这些通常也被图形库分割为线性基元。)因此,非线性单元必须由可视化系统进行特殊处理。一些可能性包括:

1. 将非线性单元分割为线性单元,然后对线性单元进行操作。
2. 开发定制的渲染和可视化算法,直接对非线性单元进行操作。
3. 在图形库中编程定制渲染操作。

        以上问题是可视化研究中的活跃话题。在VTK中,目前采用了分割方法,因为一旦分割,单元就可以被现有的线性算法处理。上述解决方案2和3的困难在于,创建新的渲染和可视化算法的工作量很大,可能需要针对每种类型的非线性单元使用不同的解决方案。此外,专用渲染硬件(例如处理线性单元)所达到的性能可能远远超过对于高阶单元的任何软件渲染解决方案。以上解决方案1的困难在于,必须仔细执行分割,否则可能会引入不可接受的误差到可视化中。或者,如果单元过度分割,将产生过多的线性基元。未来的研究指向开发自适应方法,根据选定的误差度量进行分割(请参阅第8章《高级数据表示》了解更多信息)。

        VTK使用固定细分来分割非线性二次单元,如图5-5所示。这通常适用于二次单元,因为插值的阶数较低,并且定义单元的点数较少。

- 二次边。二次边是一个主要的一维单元。它由三个点定义。前两个点定义了边的端点;第三个点位于边的中心,如图5-4所示。沿着线的方向是从第一个点到第二个点。
- 二次三角形。二次三角形是一个主要的二维单元。它由六个点定义。前三个点位于三角形的顶点;接下来的三个点位于三条边的中点,如图5-4所示。
- 二次线性四边形。二次线性四边形是一个主要的二维单元。它由六个点定义。前四个点位于四边形的顶点;接下来的两个点位于第一条边和第三条边的中点,如图5-4所示。

Figure 5-5. Decomposing quadratic nonlinear cells into linear cells. The quadratic tetrahedron is tessellated into six linear tetrahedron; the quadratic hexahedron is tessellated into eight linear hexahedra. Note that some tessellations require the addition of new points. In VTK, a cell adaptor framework is available for tessellating cells with basis functions of arbitrary complexity, see [Chapter 8 - Advanced Data Representation](08Chapter8) for more information.

图5-5. 将二次非线性单元分解为线性单元。二次四面体被分割为六个线性四面体;二次六面体被分割为八个线性六面体。请注意,一些分割需要添加新的点。在VTK中,有一个单元适配器框架可用于将具有任意复杂度基函数的单元进行分割,详情请参阅[第8章-高级数据表示](08Chapter8)。

        二次四边形。二次四边形是一个主要的二维单元。它由八个点定义。前四个点位于四边形的顶点;接下来的四个点位于四条边的中点,如图5-4所示。

        双二次四边形。双二次四边形是一个主要的二维单元。它由九个点定义。前四个点位于四边形的顶点;接下来的四个点位于四条边的中点;最后一个点位于四边形的中心,如图5-4所示。

        二次四面体。二次四面体是一个主要的三维单元。它由十个点定义。前四个点位于四面体的顶点;接下来的六个点位于六条边的中点,如图5-4所示。

        二次金字塔。二次金字塔是一个主要的三维单元。它由十三个点定义。前五个点位于金字塔的顶点;接下来的八个点位于八条边的中点,如图5-4所示。

        二次线性楔形体。二次线性楔形体是一个主要的三维单元。它由十二个点定义。前六个点位于楔形体的顶点;接下来的六个点位于属于一个三角面的六条边的中点,如图5-4所示。

        二次楔形体。二次楔形体是一个主要的三维单元。它由十五个点定义。前六个点位于楔形体的顶点;接下来的九个点位于九条边的中点,如图5-4所示。

        双二次楔形体。双二次楔形体是一个主要的三维单元。它由十八个点定义。前六个点位于楔形体的顶点;接下来的九个点位于九条边的中点;接下来的三个点位于四边形面的中心,如图5-4所示。

        二次六面体。二次六面体是一个主要的三维单元。它由二十个点定义。前八个点位于六面体的顶点;接下来的十二个点位于十二条边的中点,如图5-4所示。

        双二次六面体。双二次六面体是一个主要的三维单元。它由二十四个点定义。前八个点位于六面体的顶点;接下来的十二个点位于十二条边的中点;接下来的四个点位于前四个面的中心,如图5-4所示。

        三二次六面体。三二次六面体是一个主要的三维单元。它由二十七个点定义。前八个点位于六面体的顶点;接下来的十二个点位于十二条边的中点;接下来的六个点位于每个面的中心;最后一个点位于六面体的中心,如图5-4所示。

5.5 属性数据


        属性数据是与数据集的结构相关联的信息。这个结构包括数据集的几何和拓扑。大多数情况下,属性数据与数据集的点或单元相关联,但有时属性数据也可以分配给单元组件,如边或面。属性数据也可以分配给整个数据集,或者分配给一组单元或点。我们将这些信息称为属性数据,因为它是数据集结构的属性。典型的例子包括点处的温度或速度,单元的质量,以及进出单元面的热流量。

Figure 5-6. Attribute data.

        属性数据通常被分类为特定类型的数据。这些类别是针对常见的数据形式创建的。可视化算法也根据它们操作的数据类型进行分类。

        单值函数,例如温度或压力,是标量数据的示例,这是一种属性类型。更一般地,属性数据可以被视为n维数据数组。例如,单值函数温度可以被视为一个1 x 1数组,而速度可以被视为x、y和z方向分量的3 x 1数组。这种对数据属性的抽象模型可以在整个可视化系统中扩展。一些系统将此模型扩展到包括数据的结构。例如,一个三维图像数据集(即卷)可以表示为一个l x m x n数据值的三维数组。非结构化数据可以表示为一个位置的三维向量,加上一个连通性数组。我们将这种通用方法称为可视化数据的超数据模型(请参阅“其他数据抽象”)。

        在接下来的几节中,我们使用更简单的类型特定模型描述数据属性(图5-6)。我们还限制自己只涉及三维结构,因为假设数据集结构和图形都是三维的。

标量
标量数据是数据集中每个位置上的单值数据。标量数据的示例包括温度、压力、密度、海拔和股票价格。标量数据是可视化数据的最简单和最常见的形式。

矢量
矢量数据是具有大小和方向的数据。在三维中,这表示为一组值(u、v、w)。矢量数据的示例包括流速、粒子轨迹、风向运动和梯度函数。

法向量
法向量是方向向量:即它们的大小为|n|=1。法向量通常被图形系统用于控制物体的阴影。法向量也可能被一些算法用于控制单元基元的方向或生成,例如从定向线创建带状带。

纹理坐标
纹理坐标用于将笛卡尔空间中的点映射到一维、二维或三维纹理空间中。纹理空间通常被称为纹理图。纹理图是颜色、强度和/或透明度值的常规数组,可为渲染对象提供额外的细节。

在二维中,纹理映射的一个应用是将照片“贴”到一个或多个多边形上,从而得到一个详细的图像,而不需要大量的图形基元。(纹理映射在第7章-高级计算机图形中有更详细的介绍。)

张量
张量是向量和矩阵的复杂数学泛化。秩为k的张量可以被认为是一个k维表格。秩为0的张量是一个标量,秩为1的是一个向量,秩为2的是一个矩阵,秩为3的是一个三维矩形数组。更高秩的张量是k维矩形数组。

一般张量可视化是当前研究的一个领域。到目前为止,努力集中在二维、秩为2的张量上,它们是3 x 3矩阵。这些张量的最常见形式是应力和应变张量,它们代表受载物体中一个点处的应力和应变。VTK只处理实值、对称3 x 3张量。

 

5.6 数据集类型


        数据集由组织结构和相关属性数据组成。结构具有拓扑和几何属性,由一个或多个点和单元组成。数据集的类型源自组织结构,并指定了单元和点之间的关系。常见的数据集类型如图5-7所示。数据集根据其结构是规则的还是不规则的进行表征。如果数据集的结构存在单一的数学关系,则数据集是规则的。如果点是规则的,则数据集的几何形状是规则的。如果单元的拓扑关系是规则的,则数据集的拓扑是规则的。规则(或结构化)数据可以以隐式方式表示,节省了大量的内存和计算资源。不规则(或非结构化)数据必须以显式方式表示,因为没有固有的可以简洁描述的模式。非结构化数据往往更通用,但需要更多的内存和计算资源。

多边形数据


        我们已经看到了图形库是如何设计来渲染诸如线段和多边形等几何原语的。这些原语也经常由计算几何和可视化算法生成或使用。在可视化工具包中,我们将这些图形原语的集合称为多边形数据。多边形数据集由顶点、多顶点、线段、折线、多边形和三角条组成。多边形数据的拓扑和几何是不规则的,组成该数据集的单元在拓扑维度上也各不相同。多边形数据集构成了数据、算法和高速计算机图形之间的桥梁。

        顶点、线段和多边形形成了表示0维、1维和2维几何的最小原语集。我们还包括了多顶点、折线和三角条单元,以方便、紧凑和提高性能。特别是三角条,它们是高性能的原语。用三角条表示n个三角形只需要n+2个点,而传统表示需要3n个点。此外,许多图形库可以以更高的速度渲染三角条,而不是三角形。

图5-7. 数据集类型。

        非结构化网格包括所有单元类型。我们对单元的最小选择基于常见应用和性能,代表了一些图形库中可用单元的子集。其他类型包括四边形网格、贝塞尔曲线和曲面,以及其他样条类型,如NURBS(非均匀有理B样条)[Mortenson85]。样条曲面通常用于准确建模和可视化几何形状。除了几何形状可视化之外,几乎没有开发需要样条曲面的可视化算法。

图像数据

        图像数据集是一组点和单元,排列在一个规则的矩形格子上。格子的行、列和平面与全局x-y-z坐标系平行。如果点和单元排列在一个平面上(即二维),则数据集被称为像素图、位图或图像。如果点和单元排列成堆叠的平面(即三维),则数据集被称为体积。请注意,术语图像数据指的是图像、体积或一维点数组的集合。请注意,一些作者将图像数据称为均匀网格和结构化点。(在VTK的早期版本中,结构化点是使用的术语。)

矩形网格

        矩形网格数据集是一组排列在规则格子上的点和单元。该格子的行、列和平面与全局x-y-z坐标系平行。尽管数据集的拓扑结构是规则的,但几何形状只部分规则。也就是说,点沿着坐标轴对齐,但点之间的间距可能会变化。

        与图像数据集类似,矩形网格由像素(2D)或体素(3D)组成。拓扑结构通过指定网格维度来隐式表示。几何形状则通过维护独立的x、y和z坐标列表来表示。要获取特定点的坐标,必须适当地组合三个列表中的值。

非结构化点

        非结构化点是空间中不规则定位的点。在非结构化点数据集中,没有拓扑结构,几何形状完全不规则。顶点和多顶点单元被用来表示非结构化点。

        非结构化点是一种简单但重要的数据集类型。通常数据没有固有的结构,可视化任务的一部分是发现或创建结构。例如,考虑一辆汽车上装有温度计的活塞。温度计的数量和位置选择在一个有限的点集上,导致了在活塞表面的“无关”(至少在可视化拓扑上)位置处的温度值。为了可视化表面温度,我们必须创建一个插值表面和方案来填补中间值。

        非结构化点用于表示这种无结构的数据。通常,为了可视化的目的,这种数据形式会被转换成另一种更结构化的形式。将非结构化点转换成其他形式的算法在第9章“可视化非结构化点”中有描述。

非结构化网格

非结构化网格是数据集的最一般形式。拓扑结构和几何形状完全不规则。在非结构化网格中,可以任意组合任何单元类型。因此,单元的拓扑结构范围从0D(顶点、多顶点)到3D(四面体、六面体、体素)。在可视化工具包中,任何数据集类型都可以表示为非结构化网格。通常情况下,我们仅在绝对必要时才使用非结构化网格来表示数据,因为这种数据集类型需要最多的内存和计算资源来表示和操作。

其他数据抽象

        除了这里介绍的数据集模型之外,还提出了其他数据模型。我们简要介绍了成功应用的另外两种模型。它们分别是AVS场模型和由商业IBM数据探索系统改编的Haber、Lucas和Collins模型。本节以这两种模型与VTK数据模型的简要比较结束。

应用可视化系统

        AVS(应用可视化系统)是第一个大规模商业化的可视化系统[AVS89]。由于直接应用AVS或AVS对其他研究人员的影响,可视化技术在早期得到了很大的发展、可见度和成功应用。AVS是一个数据流可视化系统,具有清晰的用户界面,用于创建、编辑和操作可视化网络。通过使用明确的执行器来控制网络的执行,AVS可以运行分布式和并行可视化应用程序。由于AVS架构是开放的,研究人员和开发人员可以并且已经为他人捐赠了用于使用的过滤器。

        AVS数据模型由基本数据和聚合数据组成。基本数据是数据的基本表示,如字节、整数、实数和字符串。聚合类型是基本类型的复杂组织,包括场、颜色映射、几何和像素图。场可以被认为是AVS的基本数据类型,稍后将对其进行详细描述。颜色映射用于将功能值(即标量值)映射到颜色和透明度值。几何包括图形原语,如点、线和多边形,并由几何渲染器用于显示对象。像素图是可视化的渲染图像或输出。

        场是AVS数据模型中最有趣的部分。一般来说,它是一个n维数组,每个点都有标量或矢量数据。标量是一个单一的值,而矢量是两个或更多个值(不一定是三个)。场数组可以具有任意数量的维度,并且维度可以具有任何大小。场中没有隐含的结构,而是定义了一个映射函数。也就是说,从数据元素到坐标点的关系被指定为隐含或显式的。因此,场是两种空间之间的映射:场数据的计算空间和坐标空间,后者通常是全局坐标系。AVS支持三种类型的映射:均匀(即结构化)、矩形和不规则(即非结构化)。

数据探索

        Haber、Lucas和Collins的数据模型[Haber91]基于纤维丛数学。他们的工作目标是创建一个用于正规和不规则网格的分段表示字段的通用模型。他们将其模型称为场数据模型,但他们对字段这个词的定义与AVS模型不同。一个场是一个由基础和相关数据组成的对象。非正式地说,基础是一个流形,其坐标是字段的独立变量,而相关数据将相关变量的值与基础的独立变量相关联。可视化数据由描述基础和相关变量在局部区域上的场元素组成。

这段文章讨论了数据模型之间的相似性和差异性,特别是与VTK(可视化工具包)的数据集模型之间的比较。它指出了其他模型相对于VTK更为抽象,能够表示更广泛的数据范围,并且更加灵活。AVS场模型能够以简洁而优雅的方式表示任意数字流。Haber等人的场数据模型也很强大,可以利用数据中的规律性来获得紧凑的表示。然而,所有这些模型(包括VTK的)都共享结构与数据的概念。AVS场模型通过使用映射函数引入结构。Haber等人模型的场数据类似于VTK的数据集模型,其中基本数据相当于VTK的单元,而依赖数据模型的相关数据类似于VTK的属性数据。

这种抽象级别的差异在可视化系统的设计中引发了重要问题。文中将数据模型分为抽象和具体两种,其中具体模型的相对抽象级别较低。抽象和具体类比如下:

- 抽象模型比具体模型更灵活,能够表示更广泛的数据形式。
- 抽象模型更适合编写紧凑的计算机代码。
- 具体模型比抽象模型更容易描述、接口化和实现。
- 抽象模型的抽象级别影响与数据模型的计算机代码和/或数据库接口的关系。抽象模型导致抽象代码和数据表示;具体模型导致具体代码和数据表示。
- 抽象模型的复杂性可以通过创建简单的、特定于应用程序的接口来隐藏。然而,这需要额外的努力。另一方面,具体模型不能通过修改接口使其更抽象。
- 计算机系统的设计需要注意抽象和具体系统之间的平衡。特别是可视化系统,因为它们要与其他系统和数据模型进行接口。过于抽象的模型可能导致令人困惑的计算机代码和接口,并且可能由于用户误解而被误用。另一方面,具体模型在灵活性和功能上受到限制,但往往更容易学习和应用。

在可视化工具包的设计中,我们选择相对于AVS和场数据模型更具体的数据模型。我们的决定基于该系统旨在既具有信息性又具有功能性,并且我们希望清楚地展示基本概念。另一方面,VTK的数据模型足够通用,可以支持我们的可视化实践。我们与用户的经验也表明,相对于更抽象的模型,VTK的数据模型更容易让普通可视化用户理解。如果您决定设计自己的系统,我们建议您研究其他数据模型。然而,我们认为可视化工具包中体现的代码清晰性是设计抽象和简单之间良好平衡的一个例子。

图5-8。连续数组的实现。这个例子是vtkFloatArray类定义的片段。

5.8 将所有内容整合在一起


        在本节中,我们将描述先前介绍的数据集类型的实现细节。我们还将通过各种C++示例向您展示如何创建这些数据集。

内存分配和数据数组


        由于数据的大小和范围,必须仔细管理内存以创建高效的可视化系统。在可视化工具包中,我们使用连续数据数组作为大多数数据结构的基础。与其他数据结构(如链表或指向结构体的指针数组)相比,连续数组可以更快地创建、删除和遍历。在VTK中,我们将这些称为数据数组,并用vtkDataArray类来表示它们。

        连续数组也可以很容易地通过网络传输,特别是如果数组中的信息独立于计算机内存地址。内存独立性避免了将信息从一个内存位置映射到另一个位置的开销。因此,在VTK中,我们根据“id”访问信息,即数组对象中的整数索引。数据数组与C++数组一样是从0开始的。也就是说,给定n个数据值,我们可以使用id(0、1、2,…,n - 1)依次访问这些值。

        一个重要的设计决策是不使用对象数组来表示数据(例如,为单元和/或点使用单独的类)。我们的经验表明,这种设计严重影响性能,因为构建和删除的成本很高。相反,我们专注于以更高层次的抽象设计类。从性能的角度来看,面向对象的方法在应用程序级别而不是实现级别上表现最佳。

        vtkFloatArray类是连续数组的一个示例。我们将使用这个类来描述在VTK中如何实现连续数组。如图5-8所示,实例变量Array是指向float类型内存的指针。数组的分配长度由Size给出。数组是动态的,因此尝试在已分配大小之外插入数据将自动生成Resize()操作。调整大小时,数组每次都会大约加倍。MaxId字段是定义插入数据结束的整数偏移量。如果没有插入数据,则MaxId等于-1。否则,MaxId是一个整数值,其中0 ≤ MaxId < Size。

元组抽象


        许多可视化数据由多个分量值定义。一个x-y-z坐标三元组或RGBA颜色像素值就是这样的例子。为了在连续数据数组中表示这样的数据,引入了元组数据抽象。正如图5-8所示,连续数组被分组成具有NumberOfComponents个分量的较小子数组。这些子数组称为元组,在给定数组中,元组大小或NumberOfComponents对于所有元组都是恒定的,如图5-9所示。

使用数据数组表示数据


        在VTK中,属性数据和点以及其他一些数据对象都用数据数组表示。某些属性数据,如点、向量、法线和张量,需要具有与其定义一致的元组大小。例如,点、向量和法线需要具有元组大小为三的数据数组;张量需要具有元组大小为九的数据数组(即3 x 3矩阵)。标量不对元组大小提出任何要求。处理这种标量数据的算法通常作用于每个元组的第一个分量。(在VTK中存在一些过滤器,用于将多组分数据数组拆分为单独的数组,并将单独的数据数组合并为单个数组。参见vtkSplitField和vtkMergeFields。)

Figure 5-9. Data array structure. In this example, each tuple has 3 components.

图5-9。数据数组结构。在这个例子中,每个元组有3个分量。

见《vtk9 book》 官方web版 第五章 - 数据表示 2/2

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小道士写程序

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值