6、VTK基本数据结构
我们已经学习了VTK的一个重要概念——可视化管线,了解了VTK数据的流动过程。好比我们做一道菜,在做每一道菜之前,首先要掌握这道菜的做法,什么时候放盐什么时候放酱油等调料,除了需要弄清楚做每一道菜的流程,还需要了解所做的每一道菜的原料,比如有些原料是要蒸出来才比较好吃,有些则可能会用炖的方法才比较可口,只有掌握做菜的流程以及了解菜的原料的特点,最后做出来的菜才可口美味。如果说VTK可视化管线是完成VTK应用程序这道菜的基本步骤,那么VTK的数据结构就好比我们做每一道菜的基本原料。针对可视化领域的特点,VTK定义了种类丰富的数据结构,这一章我们重点学习VTK的基本数据结构,了解这些数据结构,有助于我们写出更有针对性的、更高效的可视化应用程序。
6.1 可视化数据的基本特点
我们的目的是要对数据进行可视化,因此有必要对可视化的数据特点作一了解。归纳起来,可视化数据具有如下一些特点:
l 离散性
为了让计算机能够获取、处理和分析数据,必须对无限、连续的空间体进行采样,生成有限的采样数据点,这些数据以离散点的形式存储,采样的过程是一个离散化的过程。
由于可视化数据的离散性特点,在某些离散点上有精确的值存在,但点与点之间的值则是不可知的,要得到采样点之外的其他点的值,只有通过插值(Interpolation)的方法获取。常用的插值方法是线性插值,要得到更精确的数值可以采用非线性插值,如B样条插值方法。
l 数据具有规则或不规则的结构(或者说结构化与非结构化)
可视化数据可以分为规则(Regular)和不规则(Irregular)或者说结构化(Structured)和非结构化(Unstructured)。规则结构数据点之间有固定的关联关系,可以通过这些关联确定每个点的坐标,不规则结构数据之间没有固定的关联关系。
对于规则结构的数据,存储时不必存储所有的数据点,只需存储起始点、相邻两点之间的间隔以及点的总数就可以保存完整的数据信息。对于不规则结构的数据,虽然不可以像规则结构的数据那样存储,但它也有自身的优势,即在数据变化频繁的区域可以密集表示,而数据变化不频繁的区域则稀疏表示。规则结构的数据可以在存储及计算时占优势,不规则结构的数据虽然存储和计算时不能像规则结构的那样高效,但它在数据表达方面相对而言则更加自由,更加细致、灵活的表现数据。
l 数据具有维度
可视化数据的第三个特点是拓扑维度(Topological Dimension)。可视化数据具有零维、一维、二维、三维等任意维度。如,零维的数据表现为点,一维数据表现为曲线,二维数据表现为曲面,三维数据表现为体等。数据的维度决定了数据可视化的方法,如,对于二维的数据,可以将数据存储到一个矩阵,然后再采用针对二维数据的可视化方法进行可视化(如等高图)。
6.2vtkDataObject和vtkDataSet
6.2.1 vtkDataObject
在VTK中,数据一般以数据对象(Data Object,对应VTK里的类vtkDataObject)的形式表现,是VTK里可视化数据最一般的表达形式。数据对象是数据的集合,数据对象表现的数据是可以被可视化管线处理的数据,只有数据对象被组织成一种结构(Structure)后,才能被VTK提供的可视化算法处理。
图6.1是vtkDataObject类的继承图,VTK里所有的数据结构形式都是从这个类派生出来的,实际的VTK应用程序中,没有直接使用vtkDataObject来实例化数据对象,而是根据具体的可视化数据选用其具体的子类实现可视化的。
图6.1vtkDataObject类的继承图
6.2.2 vtkDataSet
数据对象被组织成一种结构并且被赋予相应的属性值时就形成数据集(Dataset)。VTK里与数据集对应的类是vtkDataSet,该类从vtkDataObject直接派生。vtkDataSet由两个部分组成,即组织结构(Organizing Structure)以及与组织结构相关联的属性数据(Attribute Data),图6.2描述了vtkDataSet各结构的详细构成。vtkDataSet是一个抽象基类,结构的实现及表达由其具体的子类来完成。
vtkDataSet的组织结构由拓扑结构(Topology)和几何结构(Geometry)两部分组成。拓扑结构描述了物体的构成形式,几何结构描述了物体的空间位置关系。换言之,点数据(Point Data)所定义的一系列坐标点构成了vtkDataSet(数据集)的几何结构;点数据的连接(点的连接先形成单元数据(Cell Data),由单元数据再形成拓扑)就形成了数据集的拓扑结构。比如,我们想要在屏幕上显示一个三角形,首先我们必须定义三角形三个点的坐标(即Point Data,记三个点为P1, P2和P3),然后将这三个点按照一定的顺序连接起来(P1-P2-P3,或者是P3-P2-P1的顺序),这三个点定义了数据集的几何结构,它们的连接就构成了数据集的拓扑结构。亦即,点数据(Point Data)定义数据集的几何结构,单元数据(Cell Data)定义数据集的拓扑结构,要形成完整的数据集,必须有几何和拓扑两种结构。
关于拓扑、几何结构以及属性数据的更多解释:拓扑结构具有几何变换不变性。例如,说一个多边形是三角形,即指其拓扑结构,而给定的每个点的坐标,则为其几何结构。几何结构是一种空间描述,与空间变换有紧密联系,常见的变换有旋转、平移和缩放。属性数据是对拓扑结构和几何结构信息的补充,属性数据可以是某个空间点的温度值,也可以是某个单元的质量之类的。
图6.2vtkDataSet的结构组成
接下来我们通过例子说明怎么把几何结构和拓扑结构加入到数据集(vtkDataSet)中去。先看一下只有几何结构,没有拓扑结构的vtkDataSet。
示例TrianglePoints1: #include <vtkSmartPointer.h>2: #include <vtkPoints.h>3: #include <vtkPolyData.h>4: #include <vtkPolyDataWriter.h>5: 6: int main(int argc, char *argv[])7: {8: //创建点数据9: vtkSmartPointer<vtkPoints> points =vtkSmartPointer<vtkPoints>::New();10: points->InsertNextPoint ( 1.0, 0.0, 0.0 );11: points->InsertNextPoint ( 0.0, 0.0, 0.0 );12: points->InsertNextPoint ( 0.0, 1.0, 0.0 );13: 14: //创建vtkPolyData类型的数据,vtkPolyData派生自vtkPointSet,15: //vtkPointSet是vtkDataSet的子类。16: vtkSmartPointer<vtkPolyData> polydata =vtkSmartPointer<vtkPolyData>::New();17: 18: //将创建的点数据加入到vtkPolyData数据里19: polydata->SetPoints ( points );20: 21: //将vtkPolyData类型的数据写入到一个vtk文件,保存位置是工程当前目录22: vtkSmartPointer< vtkPolyDataWriter > writer = vtkSmartPointer<vtkPolyDataWriter >::New();23: writer->SetFileName("triangle.vtk");24: writer->SetInput(polydata);25: writer->Write();26: 27: return 0;28: }
TrianglePoints示例中,首先创建了一个点数据(vtkPoints),里面含有三个点;紧接着创建了一个类型为vtkPolyData的数据,vtkPolyData派生自类vtkPointSet,而vtkPointSet又派生自vtkDataSet,所以说vtkPolyData是一种具体的数据集;然后将创建的点数据加入到数据集,于是点数据就定义了该数据集的几何;最后把vtkPolyData的数据用类vtkPolyDataWriter写入到triangle.vtk文件。
可以利用ParaView软件(http://www.paraview.org,ParaView是使用VTK和Qt编写的开源的软件)打开示例中保存的triangle.vtk文件。
图6.3TrianglePoints生成的数据在ParaView软件经Glyph(符号化)处理后的结果图
使用ParaView软件打开该文件以后,在渲染窗口中我们看不到任何东西。这是因为我们只是在数据集vtkPolyData的实例里,只定义了数据的几何结构,没有定义拓扑结构。如果你想看一下我们生成的triangle.vtk数据是怎样一种形式,可以调用ParaView的菜单Filters->Common->Glyph(在点数据的空间位置生成符号),可以看到在三角形的三个顶点位置生成了三个同向的箭头(图6.3所示),也就说明了示例中生成的文件triangle.vtk里面确实存在数据,只不过它少了某种结构,导致它无法正常显示而已。
接下来我们再看一个例子,在TrianglePoints示例的基础上给数据集定义拓扑结构。
示例TriangleVertices1: #include<vtkCellArray.h>2: #include<vtkSmartPointer.h>3: #include <vtkPoints.h>4: #include<vtkPolyDataWriter.h>5: #include <vtkPolyData.h>6: 7: int main(int argc, char*argv[])8: {9: //创建点的坐标10: double X[3] = {1.0, 0.0,0.0};11: double Y[3] = {0.0, 0.0,1.0};12: double Z[3] = {0.0, 0.0,0.0};13: 14: //创建点数据以及在每个点坐标上加入顶点(Vertex)类型的单元l15: vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();16: vtkSmartPointer<vtkCellArray> vertices =vtkSmartPointer<vtkCellArray>::New();17: 18: for ( unsigned int i = 0;i < 3; ++i )19: {20: //定义用于存储点索引的中间变量,vtkIdType就相当于int、long等类型21: vtkIdType pid[1];22: 23: //把每个点坐标加入到vtkPoints中,InsertNextPoint()返回加入的点的索引号,24: //下面我们需要使用这个索引号来创建顶类型的单元25: pid[0] =points->InsertNextPoint ( X[i], Y[i], Z[i] );26: 27: //在每个坐标点上分别创建一个顶点,顶点是单元(Cell)里的一种类型28: vertices->InsertNextCell ( 1,pid );29: }30: 31: //创建vtkPolyData对象32: vtkSmartPointer<vtkPolyData> polydata =vtkSmartPointer<vtkPolyData>::New();33: 34: //指定数据集的几何结构(由points指定),以及数据集的拓扑结构(由vertices指定)35: polydata->SetPoints (points );36: polydata->SetVerts (vertices );37: 38: //将生成的数据集写到TriangleVerts.vtk文件里,保存在工程当前目录下39: vtkSmartPointer<vtkPolyDataWriter> writer =vtkSmartPointer<vtkPolyDataWriter>::New();40: writer->SetFileName ("TriangleVerts.vtk" );41: writer->SetInput (polydata );42: writer->Write();43: 44: return 0;45: }
TriangleVertices示例中的第16行实例化了一个vtkCellArray的对象,我们已经知道“点数据(Point Data)定义数据集的几何结构,单元数据(Cell Data)定义数据集的拓扑结构。”由此我们可以知道,vtkCellArray类型的对象vertices就是用来指定数据集polydata的拓扑结构(第36行),而polydata的几何结构则是由points来定义的(第35行)。
TriangleVertices示例中定义的数据集的拓扑结构是零维的点,即单元类型是Vertex。保存的VTK文件TriangleVerts.vtk在ParaView里的显示结果如图6.4所示(为了便于观察三角形的三个顶点,图6.4显示的时候把点的大小设置成5个像素)。
图6.4TriangleVertices示例生成的VTK文件在ParaView的显示结果
接下来我们继续在TriangleVertices示例的基础上做一些更改,将零维的点拓扑结构改成一维的线拓扑结构,示例的完整代码如下:(TriangleGeometryLines.cpp)
示例TriangleGeometryLines1: #include <vtkPoints.h>2: #include <vtkLine.h>3: #include<vtkCellArray.h>4: #include<vtkSmartPointer.h>5: #include<vtkPolyDataWriter.h>6: #include <vtkPolyData.h>7: 8: int main(int argc, char*argv[])9: {10: //创建三个坐标点11: vtkSmartPointer<vtkPoints> points =vtkSmartPointer<vtkPoints>::New();12: points->InsertNextPoint( 1.0, 0.0, 0.0 ); //返回第一个点的ID:013: points->InsertNextPoint( 0.0, 0.0, 1.0 ); //返回第二个点的ID:114: points->InsertNextPoint( 0.0, 0.0, 0.0 ); //返回第三个点的ID:215: 16: //每两个坐标点之间分别创建一条线17: //SetId()的第一个参数是线段的端点ID,第二个参数是连接的点的ID18: vtkSmartPointer<vtkLine> line0 =vtkSmartPointer<vtkLine>::New();19: line0->GetPointIds()->SetId ( 0,0 );20: line0->GetPointIds()->SetId ( 1,1 );21: 22: vtkSmartPointer<vtkLine>line1 = vtkSmartPointer<vtkLine>::New();23: line1->GetPointIds()->SetId ( 0,1 );24: line1->GetPointIds()->SetId ( 1,2 );25: 26: vtkSmartPointer<vtkLine> line2 =vtkSmartPointer<vtkLine>::New();27: line2->GetPointIds()->SetId( 0,2 );28: line2->GetPointIds()->SetId ( 1,0 );29: 30: //创建单元数组,用于存储以上创建的线段31: vtkSmartPointer<vtkCellArray> lines =vtkSmartPointer<vtkCellArray>::New();32: lines->InsertNextCell (line0 );33: lines->InsertNextCell (line1 );34: lines->InsertNextCell (line2 );35: 36: vtkSmartPointer<vtkPolyData> polydata =vtkSmartPointer<vtkPolyData>::New();37: 38: //将点和线加入到数据集中,前者定义数据集的几何结构,后者定义拓扑结构39: polydata->SetPoints (points );40: polydata->SetLines (lines );41: 42: vtkSmartPointer<vtkPolyDataWriter> writer =vtkSmartPointer<vtkPolyDataWriter>::New();43: writer->SetFileName ("TriangleLines.vtk" );44: writer->SetInput (polydata );45: writer->Write();46: 47: return 0;48: }
示例TriangleGeometryLines生成的VTK文件在ParaView的显示结果如图6.5所示。
图6.5TriangleGeometryLines示例生成的VTK文件在ParaView的显示结果
对于VTK的数据集而言,数据集的几何结构和拓扑结构是其必不可少的两个部分。TrianglePoints示例只定义了数据集的几何结构,没有定义该数据集的拓扑结构,所以该数据集不能直接显示;TriangleVertices和TriangleGeometryLines除了定义数据集的几何结构(由points定义),还定义了相应的拓扑结构。其中示例TriangleVertices定义的是零维的点拓扑结构;TriangleGeometryLines定义的是一维的线拓扑结构,它们都是保存在由类vtkCellArray所实例化的对象里,除了零维的点、一维的线等类型的单元以外,VTK还定义了其他类型的单元。
==========欢迎转载,转载时请保留该声明信息==========
版权归@东灵工作室所有,更多信息请访问东灵工作室
教程系列导航:http://blog.csdn.net/www_doling_net/article/details/8763686
6、VTK基本数据结构相关推荐
- VTK:数据结构比较用法实战
VTK:数据结构比较用法实战 程序输出 程序完整源代码 程序输出 程序完整源代码 #include <vtkActor.h> #include <vtkCamera.h> #
- VTK修炼之道11:基本数据结构_数据对象数据集
1.前言 前面学习了VTK的一个重要概念--可视化管线,了解了VTK数据的流动过程.好比我们做一道菜,在做每一道菜之前,首先要掌握这道菜的做法,什么时候放盐什么时候放酱油等调料,除了需要弄清楚做每一道 ...
- 5、VTK在图像处理中的应用
5.VTK在图像处理中的应用 图像是VTK中一个非常重要的数据.数字图像广泛应用于工业生产.生物医学.媒体娱乐.地质.气象等重要领域,数字图像处理具有重要的应用价值.我们在掌握了VTK的基本知识后,这 ...
- VTK教程系列:VTK基础及应用开发教程
由于OpenCV不能使用,只能使用VTK库的图像处理库,暂时还没有找到其他可以全面替代的库: CSDN东灵工作室:http://blog.csdn.net/www_doling_net/article ...
- vtk的requestData 、getIndexMatrix和vtkImageResliceExecute讲解
目的 影像工具的mpr和mip函数的实现逻辑与上述两个函数相关,两个函数同时包含影像中最重要的坐标系和矩阵知识,记录以防以后忘记.同时为了彻底理清上述两个函数,以确保最后实现的功能没有任何问题. 先前 ...
- 在PCLVisualizer中添加坐标轴和图片和颜色表
继承PCL可视化类,实现坐标轴.PNG图片.颜色表的显示 pcl::visualization::PCLVisualizer是pcl中的可视化类,支持点云显示,点云拾取,点云框选等,但是无法添加图片和 ...
- VTK修炼之道12:基本数据结构_如何把几何结构拓扑结构加入到数据集
1. 无拓扑结构 只有几何结构,没有拓扑结构的vtkDataSet #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL) ...
- 01-从零开始学习VTK
1.从零开始学习VTK 可能在这之前你没有使用过VTK,甚至不知道VTK是什么东西.这里假定你没有一点VTK基础,但已经有了一些基本的C/C++编程基础,以及计算机图形学的理论知识储备,想使用VTK从 ...
- 基于VTK User Guide和VTK Textbook学习
Vtk userguide 组织:分为三部分,parti通用介绍,如VTK安装方法:part ii是核心部分,提供了大量的示例:partiii介绍高级应用,如何创建自己的类. HOW TO USEVT ...
最新文章
- linux trap命令
- rust游戏解封了吗_柚子君宾馆爬墙听隔壁声,潇天傲解封不罢休!继续专场嘲讽散打哥...
- 如何通俗地解释 C、C++、C#、Java、JavaScript、HTML、Python的用处
- bugku 杂项 就五层你能解开吗_长春老旧小区加装电梯,你家符合条件吗?_媒体_澎湃新闻...
- POJ1664 放苹果【递推+记忆化递归】
- 第一次c++上机实验
- 判断丑数python_263. 丑数(Python)
- “老赖”罗永浩:“首席忽悠官”,发布黑科技鲨纹技术
- 让qt应用程序拥有管理员权限
- C++ 万年历 查找年、月、日、星期数以及节日等信息
- oracle tns 启动失败,Oracle 监听启动失败 TNS-12555: TNS:permission denied 解决方案
- egret的eui以及exml使用
- 小米Recovery线刷精灵 v1.0.0 破解版
- Smart3D系列教程7之 《手动配置S3C索引加载全部的瓦片数据》
- 育儿心得,所有适龄女青年都该看一下
- Linux/Android之perf追内存泄漏工具(api级别)(一百)
- 服务器脱机18个文档正在打印,打印机提示脱机打印的解决方案.docx
- mysql数据库的基本操作语句
- KEIL工程中汇编文件添加条件编译宏
- 一元域名真假?一元域名注册有哪些风险?