使用 VTK 进行可视化

作者:James C. Moore

大多数科学家和工程师都擅长处理和解决问题。如果他们使用科学方法,他们甚至可能得到正确的答案。然而,分析结果和测量数据通常很困难,因为缺乏可视化工具。如果您的经验和我一样,那么用于研究数据的工具要么过于专业 (vis5d),要么过于薄弱 (plotmtv),要么过于昂贵 (AVS)。虽然存在一些优秀的商业软件包,例如 Amtec Engineering 的 Tecplot,但它们通常对用户施加限制(例如在 X 中不允许远程显示)和约束。

为了解决这个问题,三位非常聪明的人集思广益(在开始编码之前花了九个月时间),编写了可视化工具包 (VTK)。Will Schroeder、Bill Lorensen 和 Ken Martin 创建了用于执行科学可视化的最佳系统之一。它是当今能找到的性价比最高的工具。

在本文中,我将简要介绍获取、编译和使用 VTK 所需的步骤。目标是让您了解 VTK 的范围以及使用它所需的投入程度。您可能无法立即开始创建可视化管线;但是,您将对它适合解决的问题范围以及解决这些问题所需的条件有一个很好的了解。

概述

VTK 是可视化“对象”的集合,这些对象可以连接起来构成可视化管线。VTK 严格遵循面向对象模型,其中存在对象层次结构,并且作为另一个对象的“子对象”的任何对象都继承父对象的方法和属性。对象还被分解为“类”,这些“类”代表作者对构建可视化所需的最有效工具集的最佳估计。这些对象按功能分为 14 个类别:基础、单元、数据集、管线、源、过滤器、映射器、读取器/写入器/导入器/导出器、图形、体绘制、图像处理、OpenGL 渲染器、Tcl/Tk 和窗口系统特定。用户最常关注的是数据集、管线、源、过滤器、读取器/写入器以及图形和/或图像处理或体绘制,尽管在大多数情况下隐式使用了其他类。

通过这些类,我们能够构建一个“管线”,该管线读取或创建数据,根据需要对其进行过滤,最后在屏幕上渲染或将渲染导出到文件。虽然这些类遵循对象模型,但管线是过程式的,这在减少数据时最常需要。管线从源(数据)开始,由任意数量的过滤器(甚至递归地)操作,最后作为输出呈现。“数据”源可以是无结构点、结构点、结构网格、无结构网格、规则网格或多边形数据。数据的类别决定了可用于操作数据的过滤器类型,结构化程度越高的数据可用的过滤器越多。例如,无结构点可能无法等值线化,但可以将其重新映射到可以等值线化的结构点集。有了这些工具,可视化几乎任何数据所需要的只是一个合理的数据缩减方法。有了良好的数据可视化能力,速率限制步骤现在已降级为性能,这可能是一个大问题。数据集很容易变得非常大,或者需要大量的计算工作来操作。VTK 也提供了处理这些问题的工具。

使用 VTK

首先,我推荐 Will Schroeder、Ken Martin 和 Bill Lorensen 编写,Prentice Hall 出版的 The Visualization Toolkit 第二版。它是理解可视化过程和 VTK 的宝贵参考资料。在您阅读了简洁(但完整)的 man 手册后,您就会明白为什么需要这本书。

以下所有示例都是使用 VTK 的 Tcl/Tk 绑定创建的。这些示例也可以在 C++、Python 或 Java 中创建;后两者对于 VTK 来说相对较新,因此您的结果可能会有所不同。一些示例经许可借用自 VTK 发行版,并且所有示例都偏向于计算数据的缩减,而不是图像数据或图形应用程序。

通常,当我们有一个大型数据集时,我们首先要求看到的是“数据在哪里?”。这是一个足够简单的请求,但大多数工具都无法轻易地提供给您。假设我们有光滑粒子流体动力学代码,它使用并生成无结构点。对于每个点,我们都有 x、y 和 z 坐标以及几个标量值(目前,张量分量将被视为标量)。

虽然不是最节省内存的方法,但“看到”粒子的方法之一是在每个粒子位置放置字形,并根据粒子大小进行缩放。可视化管线必须接收点数据,创建一个字形对象,并在每个点位置放置一个字形,并根据粒子大小进行缩放。然后必须在屏幕上渲染这组字形。列表 1 是执行此操作的 Tcl 代码版本,假设您已将点位置读入数组 xposyposzpos,并将半径读入 rad

图 1. 球形字形,根据粒子大小进行缩放

当此管线运行时,将在桌面上打开一个可视化窗口,其中球形字形位于每个点的位置中心,半径等于粒子大小(参见图 1)。如果需要,可以指定场景中隐式包含但上面未列出的对象。这些对象包括灯光、相机和对象属性。隐式定义的对象也可以通过其“父”对象(在本例中为渲染器)进行访问和控制。在 Tcl 中,VTK shell 提供了一个方便的命令 ListMethods,它可以告知您任何对象可用的所有方法(以及参数数量)。将命令 ren ListMethods 添加到列表 1 将返回大约有 60 种方法可供您使用的信息。在对多个对象使用此命令后,您将开始看到方法的结构,并了解对象如何组合在一起。

通过添加 Tk 输入框,可以交互式地控制所有对象的所有可控属性。但是,只有当使用新值重新执行管线并请求 Update 时,才会看到对管线的更改。这可以通过在从 Tk 接口调用的过程中设置所有属性,或者通过将方法附加到设置属性值的窗口小部件的“command”参数来处理。我推荐前一种方法。

对场景的可见属性的主要访问是通过 Actor 对象和 Mapper 对象。诸如可见性、颜色、不透明度、镜面反射率、镜面功率和表示形式(线框、点、表面)等属性是通过为 vtkActor 自动创建的 vtkProperty 对象设置的,如果未显式定义。

现在,假设您要评估使用自动网格生成器创建的网格,并且您想标记具有最小间距的单元格。从节点和连通性列表开始,可以通过将连接的节点与线段连接起来,并在包含最短和最长连接的每个节点处放置一个几何对象来构建“网格”。列表 2 是一段“快速而简陋”的代码,我花了大约 15 分钟编写(嗯,可能更长一点)。它假设节点位置已知,并且它们的右侧、后侧和上方邻居是已知的,并分别存储在数组 i1tabi3tabi8tab 中。

图 2. 网格节点、连通性和最小单元格尺寸

列表 2 中的代码创建了图 2 中所示的可视化效果。此管线不包括使边界可见的代码。我们将在接下来介绍。此管线的关键特征是在一个场景中呈现的多个源(网格数据、球体)。球体放置在在上述三个坐标方向之一中具有最近邻居的节点上。由名为 meshvtkPolyData 对象表示的多边形数据由两点多边形(即线)组成。多边形数据通常通过读取器读入,或由源或过滤器自动创建,例如 vtkSphereSource(列表 1)或 vtkContourFilter。请注意,网格和球体的映射器是不同的。网格映射器直接将网格作为输入,但球体映射器对 vtkSphereSource 进行操作,vtkSphereSource 不是 vtkPolyData。原因是映射器 读取 vtkPolyData 作为输入。网格 vtkPolyData。球体是一个源,可以发送 vtkPolyData,在请求时,就像我们在 vtkSphereSource 上使用 GetOutput 方法时所做的那样。

对我们的网格感到满意后,让我们看一些数据。列表 3 中的管线摘录基于与上面相同的网格数据,但包括显示模型中的边界和矢量场的方法。[本文的完整列表可通过匿名下载文件 ftp://ftp.linuxjournal.com/pub/lj/listings/issue53/3010.tgz 获取。]

列表 3 中所示的管线中发生了很多事情。首先,“mesh”多边形数据集获得了两个属性:标量和矢量(例如,SetScalarsSetVectors)。矢量是在 vtkFloatVector 对象中创建的。它们的幅度被计算出来并存储在名为 fieldvtkFloatScalar 字段中。标量由映射器用于为矢量着色,矢量数据由 vtkHedgeHog(矢量绘图器)用于创建定向和大小调整的矢量字形。单独的管线用于绘制对象的表面,并使用 7 情况开关来构建每个单元格的表面面板的点连通性。它利用给定单元格上可能存在的任何连通性,并构建一种称为“三角形带”的特殊类型的多边形数据。三角形带允许使用 n + 2 个点创建 n 个连接的三角形。必须告知 vtkPolyData 给定的单元格数组值是三角形带,以便正确设置连通性。这是通过 SetStrips 方法完成的,与网格示例中的 SetLines 相比。面板通过将不透明度设置为 .5 而变得透明,这允许看到矢量。矢量的颜色图已明确设置为在最小和最大速度幅度之间变化。默认情况下,映射是从 0 到 1 的红色到蓝色。SetScalarRange 方法允许在映射器中重置范围。请注意图 3 左后角的红色矢量——错误从边界蔓延进来,并且它开始的位置非常清楚。除了验证网格、边界和边界条件的正确性之外,我可以轻松地诊断计算中的问题点。

图 3. 流体速度的矢量图,按大小着色,外边界以透明方式可视化。

最后,最后两张图展示了 VTK 的一些高级功能。图 4 是从 VTK 导出的 BMRT 渲染(Blue Moon Rendering Tool)。复杂的形状完全由等值线化的隐式函数构建而成。图 5 来自 VTK 示例目录,显示了从位于加热器通风口的“种子”发出的流线。

图 4. VTK 场景的 BMRT 渲染视图。此可视化包含隐式函数、多边形数据和过滤器的复杂组合。

图 5. 来自 VTK 示例套件的图表。此可视化包括按温度着色的流线流。

虽然本文仅触及了 VTK 功能的表面,但您可以开始看到它为用户提供的灵活性和强大功能。除了本文讨论的功能外,VTK 还具有用于图像分析和操作、隐式函数、数据转换、数据采样、体(实体对象)绘制、内存管理、纹理映射、数据操作和导出等方面的对象。诚然,熟练掌握 VTK 的学习曲线有些陡峭,但当进行复杂的分析时,它可以节省大量时间,从而多次收回成本。

获取 VTK

VTK 的官方源代码版本可从 VTK 主页 https://#/vtk.html 获取。对于更敢于冒险的用户,几乎每天都有 beta 版本从 https://#/vtkData/Nightly.html 提供。在普通的 Linux 系统上,编译和运行 VTK 所需的软件包括以下内容:C++、OpenGL(或 Mesa)、tkUnixPort.h(来自 Tk 源代码发行版)、Tcl 7.4 或更高版本、Tk 4.0 或更高版本。如果您计划使用 VTK 的 Python 或 Java 绑定,您还需要这些软件包。

编译 VTK

VTK 源代码完全用 C++ 编写,并且截至 Linux 2.0.31 和 libc5 或 libc6 的 2.0 版本,它在使用 Mesa 2.5 和 Tcl/Tk 8.0 的情况下成功编译,没有错误。在发行版顶部的 README 文件中,用户将找到执行构建所需的所有说明。以下是我所做的

  1. 获取并编译 Mesa(简单)。

  2. 从 Tk 源代码发行版检索 tkUnixPort.h,并将其放置在 (vtk_top_dir)/unix/目录中(我使用了 Tcl/Tk 8.0)。

  3. 运行 ./configure --with-mesa --with-tcl --with-shared --with-tkwidget --with-patented

  4. 编辑 user.make 以查找所有必要的支持文件。

  5. 运行 make

  6. 运行 make install(可选;仅当您有磁盘空间时才运行)。

还有更多配置选项可用,可以通过键入 ./configure --help 查看。我在 Python 和 Java 绑定方面遇到了问题。如上配置的构建在 Pentium-Pro 200MHz 机器上大约需要一个小时。

许多示例可用于测试 (vtk_top_dir)/[graphics|imaging|patented|contrib]/examples[Cxx|tcl|Python] 目录中的安装。大多数图像处理示例还需要 vtkdata 存档也位于 VTK 主站点。图形示例在很大程度上将按原样运行。对于 C++ 示例,使用 make 编译并运行。可以通过从 Tcl 示例目录键入以下内容来运行 Tcl 示例:../../tcl/vtk example_file.tcl,或者,如果已安装 vtk,则键入 vtk example_file.tcl。使用 TkRenderWidget 对象的示例在使用 XFree SVGA 服务器时会导致段错误,但在 S3 服务器上可以工作。(我没有测试过其他服务器。)幸运的是,任何可视化管线都不需要 TkRenderWidget;您无法将渲染窗口嵌入到 Tk 窗口中。但是,这个问题很可能在您阅读本文时得到解决。

Visualizing with VTK
James C. Moore 是俄亥俄州哥伦布市应用研究协会的研究科学家。他的兴趣包括铸造过程的数值模拟、园艺和通过修理旧梅赛德斯赔钱。他和 Kim(真正的作者)有两个女儿,Lorien 和 Kathryn。Jim 不使用 Windows。可以通过电子邮件 jmoore@ara.com 与他联系。
加载 Disqus 评论