1.可视化管道综述

vtkProp; 
vtkAbstractMapper;
vtkProperty; 
vtkCamera; 
vtkLight; 
vtkRenderer; 
vtkRenderWindow;
vtkRenderWindowInteractor; 
vtkTransform; 
vtkLookupTable ……
我们发现,这些类都是与数据显示或者说渲染相关的。用一个专业的词汇来说,它们构成了VTK的渲染引擎(Rendering Engine)。渲染引擎主要负责数据的可视化表达,它是VTK里的两个重要模块之一,另外一个重要的模块就是可视化管线(Visualization Pipeline)。
可视化管线是指用于获取或创建数据,处理数据,以及把数据写入文件或者把数据传递给渲染引擎进行显示,这样的一种结构在VTK里就称之为可视化管线。数据对象(Data Object)处理对象(Process Object)数据流方向(Direction of Data Flow)是可视化管线的三个基本要素。每个VTK程序都会有可视化管线存在。
我们再来仔细研究一个稍微复杂点的可视化管线例子,这个例子也是有东灵组合首次开发的!在这个示例里,先读入后缀为vtk的文件,然后用体绘制法(vtkMarchingCubes)提取等值面,最后把等值面数据经Mapper送往渲染引擎进行显示,示例完整代码如下:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);#include<vtkSmartPointer.h>
#include<vtkStructuredPointsReader.h>
#include<vtkPolyDataMapper.h>
#include<vtkMarchingCubes.h>
#include<vtkActor.h>
#include<vtkRenderer.h>
#include<vtkRenderWindow.h>
#include<vtkRenderWindowInteractor.h>int main(int argc, char* argv[])
{//读入Structurered_Points类型的vtk文件vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();reader->SetFileName("data/head.vtk");//路径//体绘制方法提取等值面vtkSmartPointer<vtkMarchingCubes> marchingCubes = vtkSmartPointer<vtkMarchingCubes>::New();marchingCubes->SetInputConnection(reader->GetOutputPort());marchingCubes->SetValue(0,1500); //等值面应该是关心的解剖结构//将生成的等值面数据进行MappervtkSmartPointer<vtkPolyDataMapper> mapper =vtkSmartPointer<vtkPolyDataMapper>::New();mapper->SetInputConnection(marchingCubes->GetOutputPort());//送入到数据映射器中处理//把Mapper的输出送入渲染引擎进行显示/*************************渲染引擎******************************/vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();actor->SetMapper(mapper); //演员化妆vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(actor);//演员放到舞台上renderer->SetBackground(1.0, 0, 0);//设置舞台背景vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();renWin->AddRenderer(renderer);//舞台搬进戏院renWin->SetSize( 640, 480 );//戏院大小renWin->Render(); //戏院渲染renWin->SetWindowName("vtkPipelineDemo");//戏院起名vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();interactor->SetRenderWindow(renWin);//与看客交互interactor->Initialize();interactor->Start();return 0;
}

输出结果:

          

2.可视化管道细节

和前面的试验程序相比,可以知道,图4.9多了一个vtkMarchingCubes用于处理读入的数据。在VTK里,我们把与vtkMarchingCubes类似的对数据做处理的类称为Filter。
更一般的VTK可视化管道流程如下所示:
Source是指用于创建数据(如vtkCylinderSource)或者读取数据(如vtkBMPReader、vtkStructuredPointsReader等)的类的统称,即VTK的数据源。Source输出的数据作为Filter的输入,经Filter处理以后(可以经多个Filter处理),生成新的数据。Filter的输出可以直接写入文件,或者经Mapper变换后送入渲染引擎进行渲染、显示,结束可视化管线。
可视化管线的三要素分别是数据对象、处理对象和数据流方向,Source、Filter和Mapper一起就构成了处理对象,它们的区别是基于数据流的初始化、维持和终止。根据数据的生成方式,Source可以分为Procedural对象(如vtkCylinderSource,通过程序代码生成相关的数据)和Reader对象(如vtkBMPReader,从外部文件中导入数据)。
关于Source、Filter和Mapper的区别可以简单地通过下图区分。Source没有输入,但至少有一个输出Filter可以有一个或多个输入,产生一个或多个输出Mapper接受一个或多个的输出,但没有输出,写文件的Writer(如vtkBMPWriter)可以看作是Mapper,负责把数据写入文件或者流(Stream)中,因此,Mapper是可视化管线的终点,同时也是可视化管线和渲染引擎(有时也称之为图形管线)的桥梁。

3.如何连接可视化管道?

可视化管线里各个模块的连接是通过接口SetInputConnection()GetOutputPort()来完成的。
marchingCubes->SetInputConnection(reader->GetOutputPort());
上行代码把reader的输出(由GetOutputPort()得到)作为marchingCubes的输入(SetInputConnection()设置其输入)
vtkMarchingCubes作为Filter只接受一个输入,Filter概括起来有以下三种类型:单个输入,产生单个输出;多个输入,产生单个输出,但输出的数据可有多种用途,比如,我们读入数据以后,可以对其作等值面提取,另外还可以针对读入的数据生成轮廓线(Outline);第三种Filter是单个输入,产生多个输出。
使用SetInputConnection()和GetOutputPort()连接可视化管线时,还要求连接的两部分之间的数据类型必须一样。由于管线是运行时才执行的,如果连接的两部分类型不匹配,程序运行时就会报错。比如,vtkMarchingCubes要求输入的是vtkImageData类型的数据,如果我们给它输入的是vtkPolyData类型的,程序运行时就会报误。

4.可视化管道是如何执行的?

可视化管线连接完成后,必须有一种机制来控制管线的执行。比如某些时候,对某一部分数据做了改变,我们希望得到的结果是:改变的这部分数据在可视化管线里作更新,而其他没做改变的数据则不要去惊动它。如下图,假如Filter D的输入发生了变化,E和F是依赖于D的输入的,所以红色虚线框内的部分是需要重新执行的管线,而C和G是另外一个分支,D输入改变不影响C和G,所以,为了节省运行时间,C和G是不需要重新执行的。毕竟对于三维的应用程序来说,一般所处理的数据都是大得惊人的,如果真能做到这样,也有利于提高程序的运行速率。
VTK采用一种叫做“惰性赋值”(LazyEvaluation)的方案来控制管线的执行,惰性赋值是指根据每个对象的内部修改时间来决定什么时候执行管线,只有当你或者程序发出“请求数据”时,管线才会被执行(前面提到vtkObject里有一个重要的成员变量MTime,管线里的每个从vtkObject派生的类的对象都会跟踪自己的内部修改时间,当遇到“请求数据”时,该对象会比较这个修改时间,如果发现修改时间发生了改变,对象就会执行)。换言之,VTK是采用命令驱动(Demand Driven)的方法来控制管线的执行,这种方法的好处是,当对数据对象作了更改时,不必立即作计算,只有当发出请求时才开始处理,这样能最小化计算所需的时间,以便更流畅地与数据进行交互。
解释代码如下:
vtkSmartPointer<vtkBMPReader> reader =vtkSmartPointer<vtkBMPReader>::New();
reader->SetFileName("../doling.bmp");vtkImageData* imageData =reader->GetOutput();
int extent[6];
imageData->GetWholeExtent(extent);
std::cout<<"Extent of image:"<<extent[0]<<" "<<extent[1]<<" "<<extent[2]<<""<<extent[3]<<" "<<extent[4]<<" "<<extent[5]<<""<<std::endl;

我们先读入一幅BMP图像,然后把reader的输出值赋给imageData,接着我们想知道读入的图像到底有多长多宽多高,调用的方法是vtkImageData里的GetWholeExtent()。但是我们却得不到我们想要的结果,输出为:“Extent of image: 0 -10 -1 0 -1”,而我们读入的图像是640×480大小,输出结果应该是:“Extent of image: 0 640 0 480 0 0”才对。这就是因为我们没有“请求数据”(RequestData()),在reader->GetOutput()之后,调用reader->Update(),就会迫使管线的执行,也就是reader才会从磁盘中读取数据,从而才可以获取imageData里的相关信息

通常,我们不用显性地去调用Update()函数,因为在渲染引擎的最后,当我们调用Render()函数的时候,Actor就会收到渲染请求,接着Actor会请求Mapper给它发送数据,而Mapper又会请求上一层的Filter的数据,Filter最后去请求Source给它数据,于是,整条管线就被执行。除非像上面的代码段里列出的,读入数据以后,中间想要输出某些信息,在得到这些信息之前,你就应该显性地调用Update()函数。管线的执行过程大致如下图所示。

5.参考资料

《More Effective C++》
《C++ primer》
《The VTK User’s Guide – 11thEdition》
《The Visualization Toolkit – AnObject-Oriented Approach To 3D Graphics (4th Edition)》

VTK修炼之道10:可视化管道的连接与执行相关推荐

  1. VTK修炼之道29:图像统计_彩色直方图计算

    1.彩色图像直方图 彩色图像由于内部有三个通道,不能直接计算直方图,需要提取RGB三个通道数据,分别计算直方图.每个通道计算直方图的方法与灰度图像直方图计算方法一致. 实例代码如下: #include ...

  2. VTK修炼之道13:数据读写_图像数据的读写

    1.前言 VTK应用程序所需的数据可以通过两种途径获取: 第一种是生成模型 ;第二种是从外部存储介质里导入相关的数据文件,(如vtkBMPReader读取 BMP图像) .VTK 也可以将程序中处理完 ...

  3. VTK修炼之道3_VTK体系结构2

    上一篇博客主要介绍了VTK的构架以及Render Engine.接触过VTK的同学都知道,VTK主要有Pipeline和Render Engine两部分构成,这里详细介绍了Pipeline部分内容. ...

  4. VTK修炼之道2_VTK体系结构1

    1.OverView综述 The Visualization Toolkit consists of two basic subsystems: a compiled C++ class librar ...

  5. 【转】VTK修炼之道2_VTK体系结构1

    1.OverView综述 The Visualization Toolkit consists of two basic subsystems: a compiled C++ class librar ...

  6. VTK修炼之道11:基本数据结构_数据对象数据集

    1.前言 前面学习了VTK的一个重要概念--可视化管线,了解了VTK数据的流动过程.好比我们做一道菜,在做每一道菜之前,首先要掌握这道菜的做法,什么时候放盐什么时候放酱油等调料,除了需要弄清楚做每一道 ...

  7. VTK修炼之道71:交互与Widget_观察者/命令模式

    1.前言 一个强大的可视化系统不仅需要强大的数据处理能力,也需要方便易用的交互功能.图形处理软件ParaView(hhttp://www.paraview.org).德国癌症研究中心研发的MITK(h ...

  8. VTK修炼之道66:体绘制裁剪_Cripping技术

    1.基于Clipping的体绘制裁剪技术 Clipping技术支持VTKImageData和VTKUntructuredGrid数据类型.该功能由vtkAbstractMapper3D类提供,对于那些 ...

  9. VTK修炼之道60:体绘制_体绘制管线图形渲染管线

    1.几何渲染与体绘制 1.1 几何渲染 前面练习的渲染技术都是几何渲染技术.所谓的几何渲染技术,就是通过绘制几何图元(顶点.线段.面片等)来渲染数据,例如:绘制图像需要在空间中建立一个四边形图元,然后 ...

最新文章

  1. 原版销售累计超过150 000册的经典JavaScript入门书
  2. idea 设置springboot 热部署
  3. MFC 学习的基本概念
  4. 数组名和指针(这里为指向数组首元素的指针)区别?
  5. 行健设计_广西大学行健文理学院参加2019年第七届广西大学生工业设计大赛
  6. ecology9 后端开发环境搭建_利用Vagrant快速搭建开发环境
  7. JavaScript学习(四十七)—构造方法创建对象的不足
  8. gFTP不能显示中文文件(夹)名的解决方法
  9. 创建图片mat_OPENCV(二)——Mat类与几个函数的简介
  10. 《linux核心应用命令速查》连载六:batch:在系统负载水平允许的时候执行命令
  11. atitit.事件驱动的总结attilax
  12. c语言程序设计输出函数,输出函数C语言程序设计.pdf
  13. adb启动app_ADB 命令大全
  14. Ajax---菜鸟教程
  15. excel 合并单元格筛选
  16. 库克低调访华,3小时郑州行程俨然一位效率大师
  17. Bootstrap抽样和Monte Carlo思想
  18. 什么是经销商管理系统?企业经销商管理系统优势有哪些?
  19. 这是最棒的效率工具集,打通 Notion x 云盘 x 其他笔记软件,写作、设计、开发都会用到工具
  20. Unity URP中的Post-processing

热门文章

  1. IP地址、子网掩码和地址分类
  2. 设计模式:结构型模式总结
  3. Perl、PHP、Python、Java和Ruby的比较(来自知乎)
  4. for...in和for...of以及for( :)的区别
  5. MySQL Replication--复制异常1
  6. SVN的安装和启动SVN的安装
  7. BZOJ4723[POI2017]Flappy Bird——模拟
  8. docker 启动mongodb
  9. 排序算法-- 大总结
  10. HTML中字体的垂直排列