VTK编程指南<六>:VTK可视化管线与渲染详解
1、VTK渲染引擎
回顾前几章节的RenderCylinder示例 可以找到以下的类:
vtkProp;
ytkAbstractMapper;
vtkProperty;
vtkCamera;
vtkLight;
vtkRenderer;
vtkRenderWindow;
vtkRenderWindowInteractor
vtkTransform;
vtkLookupTable;
可以发现这些类都是与数据显示或渲染相关的。用计算机图形学的专业词汇来说,就是它们构成了VTK的渲染引擎(Rendering Engine)。渲染引擎主要负责数据的可视化表达,是VTK里的两个重要概念之一,而另一个重要概念就是可视化管线(Visualization Pipeline)。
可视化管线是指用于获取或创建数据、处理数据以及把数据写入文件或者把数据传递给渲染引擎进行显示,这样的一种结构在VTK里就称为可视化管线。数据对象(Data Object)、处理对象(Process Object)和数据流方向(Direction of Data Flow)是可视化管线的三个基本要素。每个VTK程序都会有可视化管线存在,比如示例2.1RenderCylinder,其可视化管线可以简单地表示成如图所示的连接关系。
示例RenderCylinder 的可视化管线非常简单,先是创建一个柱体数据,接着经 Mapper后生成的图元直接送入渲染引擎渲染,创建的数据没有经过任何处理。再看一个稍微复杂的可视化管线。在该示例中,先读入一个后缀为vtk的文件(head.vtk),然后用移动立方体法(vtkMarchingCubes)提取等值面,最后把等值面数据经 Mapper 送往渲染引擎进行显示,示例代码如下:
#include <iostream>#include <vtkSmartPointer.h>
#include <vtkStructuredPointsReader.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageDataGeometryFilter.h>
#include <vtkMarchingCubes.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyDataReader.h>
#include <vtkActor.h>#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);//测试文件:data/head.vtk
int main(int argc, char* argv[])
{std::string sFilePath = "D:\\VTK_Learn\\Examples\\Chap02\\data\\head.vtk";//读入Structured_Points类型的vtk文件。vtkSmartPointer<vtkStructuredPointsReader> reader =vtkSmartPointer<vtkStructuredPointsReader>::New();reader->SetFileName(sFilePath.c_str());//用移动立方体法提取等值面。vtkSmartPointer<vtkMarchingCubes> marchingCubes =vtkSmartPointer<vtkMarchingCubes>::New();marchingCubes->SetInputConnection(reader->GetOutputPort());marchingCubes->SetValue(0, 550);//将生成的等值面数据进行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, 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 EXIT_SUCCESS;
}
2、VTK可视化管线
比较代码可以看出多了一个vtkMarchingCubes用于处理读入的数据。VTK 中把与类似 vtkMarchingCubes 对数据做处理的类称为 Filter。
Source 是指用于创建数据(如vtkCylinderSource)或者读取数据(如 vtkBMPReader、vtkStructuredPointsReader 等)类的统称,即 VTK 的数据源。Source 输出的数据作为 Filter 的输入,经Filter 处理以后(可以经多个 Filter 处理),生成新的数据。Filter 的输出可以直接写入文件,或者经 Mapper 变换后传入渲染引擎进行渲染、显示,结束可视化管线。
图 2-12 所示的箭头方向即为VTK里数据流流动的方向。可视化管线的三要素分别是数据对象、处理对象和数据流方向,Source、Filter 和 Mapper一起构成了处理对象,它们的区别是基于数据流的初始化、维持和终止。根据数据的生成方式,Source 可以分为程序源对象(Procedural,如vtkCylinderSource,通过程序代码生成相关的数据)和读取源对象(Reader,如 vtkBMPReader,从外部文件中导入数据)。
关于 Source、Filter 和 Mapper 的区别,可以简单地通过图 2-13 所示的示意图进行表示。Source 没有输入,但至少有一个输出;Filter 可以有一个或多个输入,产生一个或多个输出;Mapper 接受一个或多个输入,但没有输出,写文件的Writer(如 vtkBMPWriter)可以看作Mapper,负责把数据写入文件或者流(Stream)中,因此,Mapper 是可视化管线的终点,同时也是可视化管线和渲染引擎(有时也称之为图形管线)的桥梁。
2.1、可视化管线的连接
由示例可知,可视化管线里各个模块的连接是通过接口SetInputConnection()和 GetOutputPort()来完成的。VTK 5.0 版本之前,可视化管线之间的连接使用 SetInput()和 GetOutput(),VTK 5.0 版本的可视化管线使用 SetInputConnection()和GetOutputPort()连接,同时也保留了对旧版本的支持。
marchingCubes->SetInputConnection(reader->GetOutputPort));
vtkMarchingCubes作为 Filter 只接受一个输入,Filter 概括起来有以下三种类型(见图2-14):单个输入,产生单个输出;多个输入,产生单个输出,但输出的数据可有多种用途,比如,读入数据后,可以对其作等值面提取,另外还可以针对读入的数据生成轮廓线(Outline);单个输入,产生多个输出。
使用 SetInputConnection()和 GetOutputPort()连接可视化管线时,还要求连接的两部分之间的数据类型必须一致。由于管线是运行时才执行的,如果连接的两部分类型不匹配,程序运行时就会报错。比如,vtkMarchingCubes 要求输入的是 vtkImageData 类型的数据,如果给它输入的是vtkPolyData类型的,程序运行时就会报如下的错误:
ERROR:In ..L.lVTK-5.10\FilteringlvtkDemandDrivenPipeline.cxx,line 827
vtkStreamingDemandDrivenPipeline (0000000000BAAB90):Input for connection index 0 on input port index 0 for algorithm vtkMarchingCubes(0000000000BA9590) is of type vtkPolyData,but a vtkImageData is required.
2.2、可视化管线的执行
可视化管线连接完成后,必须有一种机制来控制管线的执行。有时,对某一部分数据做了改变,只希望改变的这部分数据在可视化管线里做更新,而不要影响其他没做改变的数据。如图2-15 所示,假如 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();std::cout<<"Modification Time of reader (After New()): "<<reader->GetMTime()<<std::endl;reader->SetFileName(argv[1]);std::cout<<"Modification Time of reader (After SetFileName()): "<<reader->GetMTime()<<std::endl;vtkImageData* imageData = reader->GetOutput();std::cout<<"Modification Time of reader (After GetOutput()): "<<reader->GetMTime()<<std::endl;reader->Update();std::cout<<"Modification Time of reader (After Update()): "<<reader->GetMTime()<<std::endl;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-1 0 -1 0 -1”。该结果显然是错误的,所读图像实际大小为300X246 像素,这就是因为没有“请求数据(RequestData())。
只有在 reader->GetOutput()之前,调用 reader->Update(),才会迫使管线的执行,即 reader 从磁盘中读取数据,然后才可获得 imageData 的正确信息。通常,程序不用显式地调用 Update()函数,因为在渲染引擎的最后,当调用 Render()函数时,Actor 就会收到渲染请求,接着 Actor 会请求 Mapper 给它发送数据,而 Mapper 又会请求上一层的 Filter 的数据,Filter 最后请求 Source 给它数据,于是,整条管线就被执行。除非像以上代码所列,读入数据以后,中间需要输出某些信息,在得到这些信息之前,就应该显式地调用 Update()函数。管线的执行过程大致如图 2-16 所示。
相关文章:
VTK编程指南<六>:VTK可视化管线与渲染详解
1、VTK渲染引擎 回顾前几章节的RenderCylinder示例 可以找到以下的类: vtkProp; ytkAbstractMapper; vtkProperty; vtkCamera; vtkLight; vtkRenderer; vtkRenderWindow; vtkRenderWindowInteractor vtkTransform; vtkLookupTable;可以发现这些类都是与数据显示或渲染相关的。…...
基于STM32的智能计步器
引言 随着健康意识的提高,计步器逐渐成为人们日常生活中重要的健康管理工具。本文将指导你如何使用STM32微控制器制作一个智能计步器。该计步器通过加速度传感器检测步伐,并使用OLED显示屏显示步数。通过这个项目,你将学习到STM32开发的基本流…...
VB.NET 从入门到精通:开启编程进阶之路
摘要: 本文全面深入地阐述了 VB.NET 的学习路径,从基础的环境搭建与语法入门开始,逐步深入到面向对象编程、图形用户界面设计、数据访问、异常处理、多线程编程以及与其他技术的集成等核心领域,通过详细的代码示例与理论讲解&…...
射频电路屏蔽简略
电磁波的干扰是每个射频设备的自带属性,不管是内部还是外部,怎样去更好的抑制掉干扰,关系到射频设备的工作状态,而能够找到产生干扰的来源就是重中之重,电磁波的干扰与其产生的源密不可分,而源就离不开所需…...
基础算法——搜索与图论
搜索与图论 图的存储方式2、最短路问题2.1、Dijkstra算法(朴素版)2.2、Dijkstra算法(堆优化版)2.3、Bellman-Ford算法2.4、SPFA求最短路2.5、SPFA判负环2.6、Floyd算法 图的存储方式 2、最短路问题 最短路问题可以分为单源最短路…...
redis优化编码之字符串
redis 优化编码之字符串 ### 字符串优化 字符串对象是redis内部最常用的数据类型。 所有的键是字符串对象值对象除了整数之外都是使用字符串存储lpush cache:type "redis" "tair" "memcache" "leveldb"创建如上一个链表 需要创建一…...
Python特定版本的安装/卸载/环境配置,Spyder安装教程
目录 1.Python安装 1.1 Python下载 1.2 下载特定版本 1.3 安装Python 1.4 修改安装 1.5 环境配置 1.6 卸载Python 2.Spyder安装使用 2.1 Spyder下载 2.1.1 官网下载Spyder 2.2.2 Github下载Spyder 2.2 安装 参考资料:网盘 1.Python安装 1.1 Python下载…...
全局搜索正则表达式(grep)
一.grep简介 grep 全程Globally search a Regular Expression and Print,是一种强大的文本搜索工具,它能使用特定模式匹配(包括正则表达式)搜索文本,并默认输出匹配行。Unix的grep家族包括grep和egrep 二.grep的工作…...
linux-12 关于shell(十一)ls
登录系统输入用户名和密码以后,会显示给我们一个命令提示符,就意味着我们在这里就可以输入命令了,给一个命令,这个命令必须要可执行,那问题是我的命令怎么去使用,命令格式有印象吗?在命令提示符…...
编写指针函数使向右循环移动m个位置
题目描述:有n个整数,要求你编写一个函数使其向右循环移动m个位置 请仔细阅读右侧代码,结合相关知识,在Begin-End区域内进行代码补充。 输入 输入n m表示有n个整数,移动m位 输出 输出移动后的数组 样例输入: 10 5 1 2 3…...
xvisor调试记录
Xvisor是一种开源hypervisor,旨在提供完整、轻量、移植且灵活的虚拟化解决方案,属于type-1类型的虚拟机,可以直接在裸机上启动。 启动xvisor步骤: 1、搭建riscv编译环境 首先从github上下载riscv-gnu-toolchain很费劲,建议直接从国内的源下载 git clone https://gitee…...
MongoDB-ObjectID 生成器
前言 MongoDB中一个非常关键的概念就是 ObjectID,它是 MongoDB 中每个文档的默认唯一标识符。了解 ObjectID 的生成机制不仅有助于开发人员优化数据库性能,还能帮助更好地理解 MongoDB 的设计理念。 什么是 MongoDB ObjectID? 在 MongoDB …...
CUDA 计时功能,记录GPU程序/函数耗时,cudaEventCreate,cudaEventRecord,cudaEventElapsedTime
为了测试GPU函数的耗时,可以使用 CUDA 提供的计时功能:cudaEventCreate, cudaEventRecord, 和 cudaEventElapsedTime。这些函数可以帮助你测量某个 CUDA 操作(如设置设备)所花费的时间。 一、记录耗时案例 以下是一个示例程序&a…...
PDF 文件如何转为 CAD 图纸?PDF2CAD 使用教程
在工程设计和建筑行业中,PDF 文件常常被用来分享和存档图纸。然而,当需要对这些图纸进行编辑或进一步开发时,静态的 PDF 格式就显得力不从心了。这时候,将 PDF 文件转换为可编辑的 CAD(计算机辅助设计)格式…...
【YashanDB知识库】php查询超过256长度字符串,数据被截断的问题
本文内容来自YashanDB官网,原文内容请见:https://www.yashandb.com/newsinfo/7488290.html?templateId1718516 问题现象 如下图,php使用odbc数据源,查询表数据,mysql可以显示出来,yashan显示数据被截断。…...
暴雨AI加速计算服务器新品X8840上市
用户输入简短的文字,大模型可以自动生成创意文本或图像;金融机构的风险评估和预测,大模型通过对金融数据的分析,可以识别异常交易行为;15秒内完成中英文作文的批改和评分,并提供针对性的改进建议࿰…...
在多个分布式机器间设置和使用 NFS(Network File System)共享目录的步骤如下:
在多个分布式机器间设置和使用 NFS(Network File System)共享目录的步骤如下: 1. 准备工作 确保所有参与的机器都在同一个网络中,并安装了 NFS 软件包。 在 Linux 系统上: sudo apt update && sudo apt install nfs-kernel-server -y # Ubuntu/Debian sudo yu…...
机器学习中的 Transformer 简介(第 1 部分)
目录 一、说明 二、为什么是 Transformer? 三、什么是 Transformer? 3.1 译者的类比 四、编码器部分 4.1 、从文本输入到输入嵌入 4.2 词嵌入 4.2 N倍编码器段 4.4 多头注意力机制 4.5 添加残差和层归一化 4.6 添加残差和层归一化 五、总结 一、说明 西如…...
D3实现站点路线图demo分享
分享一下通过D3实现的站点路线分布图,这是一个demo。效果图如下: 源码如下: <template><div class"map-test" ref"d3Chart"><div class"tooltip" id"popup-element"><span>…...
非文件形式的内存动态函数库调用接口
使用memfd的系统调用接口将动态库加载到proc虚拟文件系统,提供的fd为进程持有的句柄,通过dlopen的path指向此句柄,即可实现非文件系统加载动态链接库。 文章目录 一、memfd_create二、dl_open三、示例参考 一、memfd_create 接口名称int mem…...
liunx docker 部署 nacos seata sentinel
部署nacos 1.按要求创建好数据库 2.创建docker 容器 docker run -d --name nacos-server -p 8848:8848 -p 9848:9848 -p 9849:9849 -e MODEstandalone -e SPRING_DATASOURCE_PLATFORMmysql -e MYSQL_SERVICE_HOST172.17.251.166 -e MYSQL_SERVICE_DB_NAMEry-config -e MYSQL…...
解决没法docker pull问题
没想到国内源死差不多了,以下内容需要提前科学上网 su cd /etc/systemd/system/docker.service.d vim proxy.conf 参照下图修改,代理服务器改成你自己的。 [Service] Environment"HTTP_PROXYsocks5://192.168.176.180:10810" Environment&…...
面试小札:闪电五连鞭_2
1 请简单描述一下Java中的多线程。 多线程是指在一个程序中可以同时运行多个线程来执行不同的任务。在Java中,通过 java.lang.Thread 类来创建和控制线程。可以通过继承 Thread 类或者实现 Runnable 接口的方式来定义线程的执行逻辑。 线程有多种状态,…...
Milvus向量数据库06-RAG检索增强
Milvus向量数据库06-RAG检索增强 文章目录 Milvus向量数据库06-RAG检索增强1-学习目标2-参考网址3-执行过程记录1-到底什么是RAGRAG 的基本流程:为什么 RAG 优于传统的基于检索的方法:示例流程: 2-RAG和Elasticsearch对比3-RAG和向量数据库之…...
信创国产化时代:打造安全高效的信创网站解决方案
在全球科技竞争日益激烈的背景下,信创国产化已经成为中国信息技术领域的重要战略选择。信创国产化,即信息技术应用创新与国产化,旨在通过自主研发和创新,推动核心技术的国产化,减少对外部技术的依赖,确保国…...
python编程Day13-异常介绍捕获异常抛出异常
异常 介绍 1, 程序在运行时, 如果Python解释器遇到到一个错误, 则会停 止程序的执行, 并且提示一些错误信息, 这就是异常. 2, 程序停止执行并且提示错误信息这个动作, 通常称之为: 抛出 (raise) 异常 # f open(aaaa.txt) # FileNotFoundError: [Errno 2] No such file or dire…...
【JAVA高级篇教学】第二篇:使用 Redisson 实现高效限流机制
在高并发系统中,限流是一项非常重要的技术手段,用于保护后端服务,防止因流量过大导致系统崩溃。本文将详细介绍如何使用 Redisson 提供的 RRateLimiter 实现分布式限流,以及其原理、使用场景和完整代码示例。 目录 一、什么是限流…...
力扣-图论-8【算法学习day.58】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…...
Spring 中的验证、数据绑定和类型转换
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
Github----提交人不是自己
账号用户名都设置对的,但是提交人不是自己 解决 发现是用户名和账号都夹了"号导致 git config --global user.name "Your Name" git config --global user.email "your.emailexample.com"不用引号 git config --global user.name Your Name git …...
政府做网站/企业网站建设的重要性
redis zset 有序集合 zadd 命令 zadd runoob 0 redis 添加 zrem runoob redis 删除 zarangebyscore 命令(查询列表中值) zincrby zset 2 one 如果one存在,则顺序增加2,如果one存在,则添加 zrank zset one 返回one在zset中排名(从小到大) zrevrank zset one 返回one在zeset中排名…...
重庆网站推广营销/如何用手机免费创建网站
代码举例: # 小应用:问卷调查,记录下调查者名字和回答,询问是否继续。 # 运用数据字典、while、input()、title()和upper()。 responses {} flag True while flag:name input("\n请输入姓名:")answer in…...
做app和网站怎样/企业网站推广有哪些方式
gPXE无盘中有一个补丁叫sanbootconf,它可以让XP通过ISCSI启动。它有一个功能,就是把无盘系统的IP地址固定为DHCP获取到的IP,以免多机启动造成IP冲突。但是它有一个问题没有解决,就是多机同时启动计算机名也会冲突。本程序就是解决…...
wordpress 访问权限/杭州百度推广
CentOS安装微软雅黑,解决drawImage中文乱码相关问题使用Graphics的drawString方法向图片上添加汉字时候,Windows是没问题的,在Linux上中文总是乱码,小方块,之前在网上看多很多说是因为Linux系统没有字体的原因…...
做网站要有什么功能/什么软件能搜索关键词能快速找到
该脚本可以用来导出IIS配置、任务计划、服务列表和APP,同时支持Windows 2003和2008。 #定义备份位置 $iisfolder "d:\Backup_all\IIS" $taskfolder "d:\Backup_all\Task" $servicesfolder "d:\Backup_all\Service" $appfolder &q…...
集翔网大网站建设/网站友情链接有什么用
WCF中的序列化[下篇] XMLSerializer提到XMLSerializer,我想绝大多数人都知道这是asmx采用的Serializer。首先我们还是来看一个例子,通过比较Managed Type的结构和生成的XML的结构来总结这种序列化方式采用的是怎样的一种Mapping方式。和DataContractSeri…...