VTK User\\'s Guide中文版
更新时间:2024-05-30 10:24:01 阅读量: 综合文库 文档下载
- vtk推荐度:
- 相关推荐
VTK用户指南 版本4.0
William J. Schroeder 1998-2000
第一部分 VTK 介绍
第1章 欢迎
1.1 机构-----------------------------------------------------------------------------------------------8 1.2 怎样使用VTK----------------------------------------------------------------------------------8 1.3 附加资源-----------------------------------------------------------------------------------------8
第2章 安装
2.1 概述-----------------------------------------------------------------------------------------------9 2.2 安装VTK到Windows9x/NT/ME/2000/XP------------------------------------------------9 二进制安装-------------------------------------------------------------------------------------9 源代码安装-------------------------------------------------------------------------------------9 2.3 安装VTK到Unix操作系统
源代码安装------------------------------------------------------------------------------------10 运行CMake------------------------------------------------------------------------------------11 编译源代码
建立VTK多平台 安装VTK 第3章 系统概述
3.1 系统设计---------------------------------------------------------------------------------------12 图形模型--------------------------------------------------------------------------------------13 可视化模型-----------------------------------------------------------------------------------15 3.2 创建一个应用---------------------------------------------------------------------------------19 用户方法、对象和命令--------------------------------------------------------------------19 Tcl----------------------------------------------------------------------------------------------19 C++---------------------------------------------------------------------------------------------20 Java Phthon
Visual Basic/COM/ActiveX 3.3 在两种语言间转换
第二部分 通过例子学习VTK
第4章 基础
4.1 创建1个简单的模型-------------------------------------------------------------------------24 程序化源对象---------------------------------------------------------------------------------24 读取源对象------------------------------------------------------------------------------------26
4.2 使用VTK交互器-----------------------------------------------------------------------------27
vtk绘制窗口交互器
交互风格
4.3 滤波数据---------------------------------------------------------------------------------------29 4.4 控制相机---------------------------------------------------------------------------------------30 安装相机 简单操作方法 控制视角方向 透视与正交视
保存与恢复相机状态
4.5 控制光线---------------------------------------------------------------------------------------32 位置光
4.6 控制3D道具-----------------------------------------------------------------------------------32 指定vtk道具3D位置 演员
演员的详细级 装配 体
vtk装载3D道具
4.7 作用纹理---------------------------------------------------------------------------------------37 4.8 拾取---------------------------------------------------------------------------------------------38 vtk装配路线 例子
4.9 vtk坐标和坐标系---------------------------------------------------------------------------40 4.10 控制vtk演员2D----------------------------------------------------------------------------41 4.11 注释--------------------------------------------------------------------------------------------41 2D注释
3D注释和vtk跟踪
4.12 特殊绘图类-----------------------------------------------------------------------------------44 尺度棒 X-Y绘制 边界盒轴 标记数据
4.13 变换数据--------------------------------------------------------------------------------------48 高级变换 第5章 可视化技术
5.1 可视化VTK数据集vtkDataSet(和子类) -------------------------------------------------50 使用数据属性进行工作 颜色映射 轮廓化 浮雕化 流线图 流线表面 剪裁 融合数据 附加数据
用另外一个尺度给等值面赋颜色 抽取单元格子集
抽取单元格作为多边形数据
5.2 可视化多边形数据---------------------------------------------------------------------------67 手工产生多边形数据 产生表面当量 十比一抽取 平滑网格 粘贴数据 产生纹理坐标
5.3 可视化结构网格-----------------------------------------------------------------------------74 手工产生结构化网格 抽取计算平面 结构网格子样化
5.4 可视化直线网格-----------------------------------------------------------------------------76 手工产生VTK直线网格 抽取计算平面
5.5 可视化非结构网格--------------------------------------------------------------------------77 手工产生VTK非结构网格 抽取部分网格 非结构网格轮廓化 第6章 可视化图像和体数据
6.1 VTK结构化点的历史表示-----------------------------------------------------------------80 6.2 手工产生VTK图像数据-------------------------------------------------------------------80 6.3 抽取图像数据子样--------------------------------------------------------------------------81 6.4 基于尺度值的弯曲--------------------------------------------------------------------------83 6.5 图像显示--------------------------------------------------------------------------------------83 图像观察者 图像演员
6.6 图像源-----------------------------------------------------------------------------------------85 2D帆布图像源 3D椭圆体图像源 高斯图像源 网格图像源 噪声图像源 正弦曲线源
6.7 图像处理--------------------------------------------------------------------------------------88 梯度化 高斯平滑 直方图 图像逻辑 重新切片
6.8 体绘制-----------------------------------------------------------------------------------------92 一个简单的例子
为什么会有多种体绘制技术? 产生一个VTK体 使用片层化函数 使用颜色变换函数
在一个体属性中控制颜色和透明度 在一个体属性中控制阴影 产生一个体映射 裁剪一个体 粘贴一个体
对一个体应用3D纹理 控制标准编码 体素光线计算 2D纹理映射
VolumePro绘制硬件 速度和精确度交替使用
使用vtkLODProp3D改善性能 可行性/局限性技术 第7章 建立模型
7.1 隐模型----------------------------------------------------------------------------------------114 定义隐函数
对隐函数进行抽样
7.2 挤压-------------------------------------------------------------------------------------------117 7.3 构建表面-------------------------------------------------------------------------------------119 Delaunay三角形化 高斯油彩
无组织点产生表面
第三部分 VTK研发者指南
第8章 数据接口和其他
8.1 读入器----------------------------------------------------------------------------------------130 多边形数据读入器 图像和体素读入器 数据集读入器 结构化网格读入器 线性网格读入器 非结构化网格读入器
8.2 写入器----------------------------------------------------------------------------------------131 多边形数据读入器 图像和体素读入器 结构化网格读入器 线性网格读入器 非结构化网格读入器
8.3 输入者----------------------------------------------------------------------------------------132
8.4 输出者----------------------------------------------------------------------------------------132 8.5 创建硬拷贝----------------------------------------------------------------------------------132 保存图像
保存大(高分辨率)图像
8.6 产生动画(使用样条) -----------------------------------------------------------------------134 8.7 使用现场数据工作--------------------------------------------------------------------------136
第9章 贡献编码
9.1 编码补偿--------------------------------------------------------------------------------------141 为VTK贡献编码的条件 编码风格 如何贡献编码
9.2 标准方法: 创建和消除对象---------------------------------------------------------------142 9.3 拷贝对象和受保护的方法------------------------------------------------------------------143 9.4 写一个VTK类: 综述-----------------------------------------------------------------------144 找到一个相似类 识别一个超类 单个类Per.h 文件 必需的方法 文档编码
使用SetGet宏 向VTK中添加类
9.5 对象工厂--------------------------------------------------------------------------------------145 综述
如何写一个工厂 如何安装一个工厂 例子工厂
第10章 流水线执行管理
10.1 执行过程--------------------------------------------------------------------------------------151 概述和术语 更新信息通道 传播更新扩展通道 触发异步更新通道 更新数据通道
10.2 使用流---------------------------------------------------------------------------------------162
第11章 VTK数据对象接口
11.1 数据组---------------------------------------------------------------------------------------166 方法
11.2 数据集---------------------------------------------------------------------------------------169 11.3 VTK数据集接口---------------------------------------------------------------------------170 方法 例子
11.4 VTK图像数据接口-----------------------------------------------------------------------174 方法 例子
11.5 VTK点集接口-----------------------------------------------------------------------------176 方法 例子
11.6 VTK结构化网格接口---------------------------------------------------------------------178 方法 例子
11.7 VTK线性网格接口-----------------------------------------------------------------------178 方法 例子
11.8 VTK多边形数据接口---------------------------------------------------------------------179 方法 例子
11.9 VTK非结构化网格接口-----------------------------------------------------------------184 方法 例子
11.10 单元格接口(VTK单元格子类) ------------------------------------------------------185
11.11 其他接口----------------------------------------------------------------------------------187 点
单元格数组 单元格类型 单元格连接
11.12 现场和属性数据接口------------------------------------------------------------------193 现场数据方法 数据集属性方法
第12章 如何写一个过程方法
12.1 概述----------------------------------------------------------------------------------------196 永远不要修改输入数据 参考计数数据 使用Debug宏
回收/删除截入的内在 修改时间
过程事件和异常终止执行
12.2 如何写一个绘图过滤器---------------------------------------------------------------199 概述
简单过滤器
复杂过滤器和流水线执行 抽取绘图过滤器 程序过滤器
重载流水执行方法
12.3 如何写一个图像过滤器---------------------------------------------------------------210
实现一个图像过滤器
第13章 用窗口系统集成
13.1 绘制窗口交互风格--------------------------------------------------------------------------216 13.2 GUI交互的总指导线------------------------------------------------------------------------217 13.3 X Window, Xt, and Motif--------------------------------------------------------------------221 13.4 MS Windows/Microsoft Foundation Classes---------------------------------------------226 13.5 Tcl/Tk-------------------------------------------------------------------------------------------227 13.6 Java
第14章 编码资源
14.1 对象图表--------------------------------------------------------------------------------------230 基础 单元格 数据集 流水线 源 过滤器 映射器 图形 体绘制 成像
OpenGL绘制器 拾取
变换塔形结构
14.2 过滤器总结-----------------------------------------------------------------------------------237 可视化过滤器 映射者对象 演员对象
14.3 VTK文件格式--------------------------------------------------------------------------------244 二进制文件 数据集属性格式 例子
第15章 光盘
15.1 源代码 15.2 例子代码
15.3 Window 9x/NT/ME/2000/XP 预编译二进制 15.4 数据 15.5 文档
15.6 退化测试图像 15.7 Kitware 应用
第1章 欢迎
欢迎来到VTK可视工具箱用户指南,这本书已经对VTK4.0以后的版本进行了更新,VTK是一个开放的、面向对象的软件系统,主要功能是计算机图形学、可视化和图像处理。尽管它庞大和复杂,但它是为易学易用设计的,一旦你学会了基本的面向对象的设计和实现方法。
VTK是个大系统,因此,不可能将所有对象和方法的文档在这本书中体现,本书将介绍VTK一些重要的概念,引导你尽快和高效的学习。一旦你掌握了这些基础,我们建议你从VTK用户社区里获得许多资源(附加资源见第4页)。
VTK是个源代码开放的系统,这意味着有数十个或数百个像你一样的研发者和用户为系统作出了贡献。如果你认为VTK是个有用的工具,我们鼓励你贡献程序修正、算法、思想或应用返回给VTK社区(见204页)。你也可支持商业公司研发或加进新的特性和工具。 1.1 结构
本手册分为三部分,每一部分又分为若干独立章节。第一部分是VTK总论,包括如何在你机器上安装VTK。这部分包括安装预编译库和可执行程序,或者从源代码编译软件。还包括系统设计概述和如何创建C++、Tcl、Java和Python语言程序的应用。第二部分是用户指南的核心,数十个例子来展示重要的系统特性。第三部分是VTK高级用户。第三部分解释如何创建自己的类、扩展系统、同各种窗口和GUI系统交互。第十四章包括简化对象图表,当你读写自己数据时,它提供VTK对象之间关系、过滤器列表、VTK文件模式描述。第十五章介绍随书光盘内容,最后是随机访问用户指南的方便索引。 1.2 如何使用VTK
有两类VTK用户,一类是类开发者,他们用C++来创建类,另一类是应用开发者,他们使用C++类库来建立组合应用程序。类开发者必须是C++高手,如何想扩展或修改VTK类,你必有对它的内部结构和设计非常熟悉(见第三部分)。应用程序开发者不必会使用C++,由于编译过的C++类库已经被封装起来,使用的解释型语言Tcl、Python、Visual Basic、Java。作为应用开发者你必须知道VTK对象的外部接口和它们之间的关系。
使用VTK的关键是要熟悉它的对象模板和混合它们的方式。如何你是一个新用户,首先以安装软件开始。如果你是一个类开发者,你要安装源代码,然后编译它们。应用开发者只需要预编译二进制文件和执行文件,我们建议你通过例子学习系统(应用开发者),通过源代码来学习系统(类开发者)。从第三章开始阅读,它给出了一些系统关键概念,然后复习第二章的例子。你也许希望运行许多例子,它们源代码位于目录VTK/Examples中(详见描述在子目录的VTK/Examples/README.txt文件中)。还有数百个试验在源程序中,例如在VTK/Graphics/Testing/Tcl和VTK/Graphics/Testing/Cxx,多数是无文档的脚本。然而,它们对理解类在VTK中是如何组织的,非常有用。 1.3 附加资源
为得到VTK工具箱更多的信息,我们推荐下列资源:
· The Visualization Toolkit An Object-Oriented Approach To 3D Graphics, 3rd Edition Will
Schroeder, Ken Martin, Bill Lorensen 520 pages, printed in full color includes CD-ROM with software/data updated for VTK version 4.2. 《可视化工具箱3D图像面向对象方法(第三版)》,
这本书深入详细地论述VTK中的算法、数据结构和系统问题。
· 网站http://public.kitware.com/包含引擎,指向许多其它资源,如在线手册、问题解答、VTK用户邮件列表,特别是Doxygen手册面相当精彩。尽管这些内容都可以从光盘获得,也可从在线页http://public.kitware.com/VTK/doc/nightly/html获得。
· 许多VTK用户和开发者也在维护自己网站,值得推荐的一个是Sebastien Barre’s与VTK
资源相连的网站 http://public.barre.nom.fr/vtk/link.html 。
· VTK用户邮件列表允许用户和开发者提出问题和接受答复,快速更新、bug补丁和进展及改善系统的建议。http://public.kitware.com/mailman/listinfo/vtkusers给出如何加入列表的说明。
· 也可以从http://public.kitware.com/获得商业支持和咨询,Kitware也出售和支持用VTK开发的商业化的产品,像VolView, ActiViz, GoFly等。
最后,你还可以e-mail给kitware@kitware.com,只要时间和人力许可,都会得到回答。
第2章 安装
这一章来介绍安装VTK步骤,这个过程总的困难之处有几个因素。如果你使用编译过的、解释过的可执行程序和库来进行开发的话,可以进行无痛和快速的安装。如果想编译VTK源代码建立自己的库,在快速的、多处理器系统上可能需要半个小时,在慢的、内存有限的系统上可能需要几个小时。并且,安装也取决于你要用多少解释性语言将VTK C++核心封装和你的配置。
如果参考19页的“系统设计”来浏览一下VTK设计,这会使随后的安装容易一些,如果遇到困难,就与VTK用户列表(第4页)联系。
2.1 概述
安装VTK可易可难,取决于指定的设置。一个简单的PC机二进制安装只需一分钟。一个全代码的编译可能需要几个小时。一个运气差的人可能需要几天时间,遇到很大挫折。这章帮助你避免陷入这种情况。注意下面的安装说明,将会你花费最小的精力进行成功的安装。本章分为两部分取决你所安装的操作系统,是Windows还是UNIX。VTK不能安装在Windows3.1或Macintosh OS的OSX以前的版本。
2.2 安装VTK到Windows9x/NT/ME/2000/XP
在Windows可以进行两种类型的安装。一个是二进制/可执行安装,你可以用C++、Java、Tcl、Python等编译和接连已编译库,或运行预编译的可执行程序。另一个是全源码安装,要求你编译VTK源代码(生成C++库)和VTK封装代码(生成JAVA、TCL、PYTHON可执行程序)。二进制安装相对容易也是我们推荐的,全代码安装的好处在于可以监控、调试和修改VTK代码,如果你是一个类开发者,这是你所需要的。然而,即使选择了二进制安装,你也可以各种方法扩展你自己的类(见208页)、使用运用时程序过滤器(见292页)、在运行时用自己的类代替VTK类(见211页,“对象工厂”)。
二进制安装
要安装VTK库和可执行程序,先运行Setup.exe,会出现一个安装界面,如图2-1所示。首先要决定的是你需要安装VTK的哪部分。二进制安装过程被打包成五部分,如下所示 1.vtk40Core__这部分包含VTK为Windows系统的动态链接库DLL。 2.vtk40Cpp__这部分包含在MVC6.0开发环境下的文件和程序库。 3.vtk40Tcl__这部分包含Tcl程序库和动态链接库。 4.vtk40Java__这部分包含的程序库和动态链接库。
5.vtk40Python__这部分包含Python程序库和动态链接库。
6.CMake__这部分包含源代码和使用CMake生成的Windows二进制代码,一个从源程序创建VTK的工具。
图2-1
图2-1 VTK Windows系统安装向导。选择VTK组件,然后按照指定的目录进行安装。你也可使用相同方法安装网址 http://public.kitware.com/vtk上的 nigthly或其它发布的版本,你也可选择安装30天免费的商业化产品VolViewt和ActiViz。
取决于你用VTK做什么,你可以安装2-5部分到任何地方(vtkCore必须安装)。例如,如果作C++开发,就安装vtkCore和vtkCpp。如果你想创建Tcl程序,就要安装vtkTcl。如果你想安装在Windows98/WindowsME/2000/XP下,你应该在行进中选择WindowsNT而不是Windows95。在PC机上的最好效果,显示模式要多于256色。
这就完成了Windows平台的二进制安装过程。第3章我们将进一步讨论编写自己的C++程序。
源代码安装
为了开发C++程序和扩展VTK,你需要做源代码安装。这具有挑战性,编译会占用机器数小时。第一步你要确定你的机器具有创建VTK源码发布能力,你必须在Windows95/98 /ME/2000/XP系统上运行,还需要安装C++编译器,本指南是以MVC6或MVC.NET为例,它们在VTK上运行良好。我们也支持Borland C++编译器,但必须首先安装。下一个问题是计划使用什么样的工具,如果想使用Java语言,必须下载和安装JDK;如果使用Tcl/Tk,就需要下载和安装Tcl/Tk源代码,网址为http://www.scriptics.com,下载Tcl/Tk v8.3.2。
拷贝源代码
VTK光盘在VTK目录中拥有完整的源代码,不要试图修改已有的类或创建自己的类。我们建议将VTK-src-windows文件夹从光盘拷贝到硬盘上,这会改善你的编译速度。
安装CMake
为编译VTK,首先必须安装一个称为CMake的程序。CMake是一个开放的资源,跨平台的创建工具。使用CMake可以使用相同资源树和创建文件,使VTK定制或创建在各种类型的机器上。你可以从http://public.kitware.com/CMake/HTML/Download.html获得CMake。对于Microsoft或Borland公司来说,有一个预编译的二进制程序可以下载和安装,这是一个较好的安装方法。
运行CMake
建立C++编译器后,安装CMake,并安装附件如Tcl、Java和Python。运行CMake,开始菜单下有一个CMake项,位于Programms->CMake->CMakeSetup。CMakeSetup.exe界面,图2-2是一个简单的界面,允许定制到特殊的机器和所希望VTK项。首先,我们必须告诉CMakeSetupVTK源代码树在哪里,所建的VTK二进制文件在哪里。你可以用浏览器按钮来指定这些目录,也可以手动地键入路径。下一步是选择使用的创建系统,MVC6或MVC.NET或Borland。一旦选择了源代码、二进制和创建系统,就可以点击Configure按钮,这将会用CMake缓存中一列变量和值来填充CMakeSetup界面。首次运行,所有的变量显示为红色。红色表示在先前定制步骤中,缓存项产生或被改变。
图2-2
这时,你可以定制自己的VTK创建。例如,想要激活VTK的Tcl的封装特性,向下滚动缓存值编辑器至VTK_WRAP_TCL,从YES或NO里选中一个值。然后,再次点击Configure按钮,这将会导致大多值变灰,新的值变红。如果从二进制文件中安装Tcl/Tk,非新值不会被发现,就不得不用CMake界面手工地指定这些路径。在CMake界面中设置任何值,需点变量的右边,依据变量的类型,将会出现一个文件选择器、编程框或下拉框,供你编辑值。VTK有一些重要的缓存值:
·BUILD_SHARED_LIBS—如果布尔值设置为YES,那么DLLs或共享库将会被创建;如果是NO,那么静态库将被创建。缺省是静态库。静态库易于执行,当可执行程序运行时,它们不必包含在路径中,可执行程序将会自我包含。这对基于应用的VTK分布比较好。
·VTK_WRAP_TCL—它决定是否建立TCL封装;
·VTK_WRAP_PYTHON—它决定是否建立PYTHON封装; ·VTK_WRAP_JAVA—它决定是否建立JAVA封装.
为了得到CMake变量的在线帮助,简单地单击变量的右边,选择“缓存项帮助”,大多数缺省值是可以更改的。
继续点击Configure按钮直到不再出现红色的值,这时都是你期望的值。此时,你再点击OK按钮。这将导致CMake写出所选的创建类型文件。对于Microsoft,工程文件被创建于所选的二进制目录中,简单于装载这个工程文件VTK.dsw到Visual Studio,在BUILD菜单下设置Set Active Configuration,选择Debug, Release, MinsizeRel和RelWithDebInfo。你可以选择ALL_BUILD工程,就像其它工程一样编译它。
VTK建立的所有库和可执行文件,都会被放于二进制目录下一个称为bin子目录下,
除非改变了EXECUTABLE_OUTPUT_PATH或LIBRARY_OUTPUT_PATH变量。(注意: 不要使用MSVC的“Rebuild All”来重新创建原代码,这会删除CMakeLists.txt文件,这些文件是先前产生的作为创建的一部分。MSVC会重新装载它们,将导致错误提示。如果想重新创建,必须先删除VTK二进制目录,重新运行CMake,然后再创建。)
创建VTK后,如果选择动态库,必须让Windows知道dlls文件的路径,这样做有几种方法:可以将dlls拷贝到系统目录system32;另一个办法是修改path环境变量,将库文件包含在目录中。如果你要拷贝DLLs和可执行程序,你需要拷贝bin/selected configuration/directory中所有的文件。
如果你不拷贝DLLs,那么你需要编辑path环境变量。在Windows95/98中,可以使用sysedit在autoexec.bat文件中加一行,下面给出4个例子分别对应4种不同的设置,假设4个例子都建立在VTK的C:\\vtkbin目录下。
在WindowsNT/ME/2000/XP中,点击“我的计算机”选择“属性”选择环境变量表,像上面一样添加或修改环境变量。如果PATH环境变量已经存在,就将VTK路径加在它的前面。例如
如果走到了这一步,说明你在PC机上成功地安装了VTK,这是一个富有挑战性的过程,部分由于当前编译器的限制,部分是由于软件大小和复杂程度,要小心前面的指令,遇到问题可以加入vtkusers mailing list寻求帮助,商业支持可以从Kitware公司得到。
第3章 系统总览
本章从整体上介绍Visualization Toolkit系统,介绍一些基本的信息,以便你用C++、Java、Tcl和Python创建应用程序。首先介绍基本的系统概念和对象模型抽象,最后来演示基本概念,描述所创建的应用程序。
3.1 系统设计
VTK由两个基本的子系统,一个是编译过的C++类库;一个是“解释型”的封装层,允许你使用Java、Tcl和Python等解释型语言操作编译过的类库,见图3-1
图3-1
可视化工具箱是一个用各种解释型语言(Java,Tcl,Python)封装的编译过的(C++)心
这样设计的优点能使你创建高效率的C++编译算法,保留解释型语言快速开发特点,当然对于C++高手来说,也有这样的工具,整个应用程序可以由C++来创建。
VTK是一个面向对象的系统,高效使用VTK的关键,是要逐渐较好地理解底层的对象模型,这样做是为了去掉数百个对象的神秘外衣。理解力达到一定程度,你很容易建立应用程序。也许你想知道许多对象的功能,只有反复练习代码例子,才能对对象有所理解。在本用户指南中,我们努力提供有用的对象组合来满足你的应用。
接下来的部分,我们来构成VTK的两个对象模型:图形对象模型和可视化对象模型。这部分相对高级—我们建议你强化阅读,运行本章和下一章数百个源代码布置的例子。
图形模型
VTK图形模型包含下列核心对象(这不是无穷对象列表,而是我们经常用到的对象):
我们把这些对象组合起来产生一个场景(参见对象表图14-8可以知道这些对象是如何联系在一起的)。Props代表我们在场景中“看见”的东西,在3D中(有一个4*4的变换矩阵)被定位和操作的Props就是vtkProp3D(例如vtkActor就是vtkProp3D的一个具体的子类,我们要进行体绘制,这个子类就是vtkVolume)。Props用来定位和表示2D数据(即图像)的类是vtkActor2D。Props不直接表示几何形状,它借助Mappers对象,Mapper负责表达数据。Props也借助于一个属性对象,属性对象控制着Props的外观(颜色、漫射光、反射光效果;绘制外观:线框或面片等)。Actors和Volumes(通过超类vtkProp3D)还有一个
内部变换对象(vtkTransform),这个对象封装了一个4*4矩阵,它依次控制着Prop的位置、朝向和尺度。
光照(vtkLight)用来表示和操作场景的光线,光照仅用于3D,2D不需要光照。
相机对象(vtkCamera)在绘制过程中控制如何将3D投影到2D,相机具有定位、定标和定向的几种方法。此外,相机还控制透视投影和立体视(若开启),2D图像不需要相机。
映射对象(vtkMapper)与查找表相连(vtkLookupTable),用来变换和绘制几何图形,映射提供可视化流水线与图形对象模型之间的接口。vtkLookupTable是一个vtkScalarsToColors类的子类,就像vtkColorTransferFunction(典型vtkColorTransferFunction用来体绘制,参见136页)。vtkScalarsToColors的子类将映射数据转变成颜色,是最重要的可视化技术之一。
Renderers(vtkRenderer) 和render windows(vtkRenderWindow)用来管理图形引擎和计算机窗口系统,绘制窗就是所绘制的计算机窗口。多个绘制者可在一个绘制窗口中绘图,也可以创建多个绘制窗口。绘制区称为视口,可能在一个绘制窗口存在多个绘制区。将绘制对象绘制到窗口后,就获得了与数据交互的机会。VTK有几种与数据进行交互的方法,其一就是vtkRenderWindowInteractor,它是一种简单的工具,用来操作相机、拾取对象、调用用户方法、进出立体视、改变actors属性等。
上面提到的许多对象都有子类,这些子类具体化对象行为,例如vtkAssembly、vtkFollower和vtkLODActor都是vtkActor子类。vtkAssembly允许Actors分级,恰当地管理平移、转变和尺度变换。vtkFollower是一个总是面向特定相机的Actor。vtkLODActor是一个Actor对象,可改变几何表达、保持交互帧频。
图3-2 VTK数据类型。非结构点能被多边形数据集和非结构网格来表示,因此不能在系统工程中显式表示。
可视化模型
图形流水线角色是将图形数据变换成图片,可视化流水线角色是将信息变换成图形数据。换句话说,可视化流水线负责构成几何表达,然后由图形流水线来绘制。VTK使用数
据流方法将信息变换成图形数据,在这个方法中涉及两个基本对象类型。
图3-3 与点集和单元数据集相关的数据属性
·vtkDataObject 数据对象 ·vtkProcessObject 处理对象
数据对象表示各种类型的数据,vtkDataObject可以看成是通用的“blob”数据(blob数据类型的列可以存储大型二进制对象,如图形、视频和声音等。具有正式结构的数据称为数据集(DataSet类)。图3-2表明VTK支持的数据集对象,图中数据集对象由几何和拓扑结构构成,以及与些相关的属性数据如尺度或向量。属性数据是与数据集相关的点和单元格。单元格是一种点的拓扑组织,格是数据集的原子,用来在点之间进行插值。图4-15表示VTK支持的各种单元格类型。图3-3显示VTK支持的属性对象。
处理对象,也即常指的滤波器,作用于数据对象产生新的数据对象。处理对象表示系统的算法。处理对象和数据对象通过可视化流水线相连(数据流网),图3-4就是可视流水线的描述。
该图和图3-5一起显示了一些重要的可视化概念。源处理对象靠读取(reader对象)或构造一个或更多数据对象(程序化源对象)。滤波器吸入数据对象,产生一个或更多数据对
象输出。我们前面见过的图形对象Mappers,将数据对象转换成图形对象,然后由图形对象来绘制。Writers是一种类型的映射器,将数据写入一个文件或流中。
图3-4 数据对象和处理对象相连产生可视化流水线,箭头所指是数据流向
关于构建可视化流水线有一些重要的问题,简要在这里介绍一下。首先,流水线拓扑结构由方法变化而构成
A Filter->SetInput (anotherFilter->GetOutput());
这些方法将一个过滤器的输出作为另一个过滤器的输入(具有多输入和输出的过滤器类似)。其次,必须建立一个机制来控制流水线的执行,仅执行那些流水线的必要部分,产生输出的更新。可视化工具箱使用一个懒评估方案(当数据被请求时才执行),依据每个对象内部修改时间。第三,流水线组装仅需要那些兼容的对象,使用SetInput() 和GetOutput()方法能与其它对象很好地结合在一起。在VTK中,C++编译时类型检查强迫做到这一点。最后,我们必须决定一旦流水线执行,数据对象是否需要缓存或保留。由于可视化数据集相当大,如何成功应用VTK工具相当重要。VTK提供了将数据缓存开或关的方法,使用计数参数来避免拷贝数据,以及当整个数据不能装入内存时将数据流分块的方法(建议参考第四章可视化工具箱内容获得更多的信息)。
图3-5 多输入和多输出
请注意,处理对象和数据对象都有很多变化,图11-2 显示了VTK当前版本支持的6种不同对象类型。处理对象在输入和输出之间变化,当然实现的是特殊算法。
流水线执行
前面我们讨论了流水线执行,本节将拓宽对流水线执行一些重要概念的理解。如前所示,当需要计算时流水线才执行,例如你初始化一个读对象,想得到点的数目
读对象将从调用的GetNumberOfPoints()方法返回“0”,尽管数据文件包含了上千个点。然而,如果你加入Update()方法
读对象就会返回正确的点数。因为第1个例子GetNumberOfPoints()方法,没有要求计算,因此返回点数为“0”。第2个例子中,Update()方法迫使读入器执行,从文件中读入数据。
图3-6 流水线执行概念总览
通常不必须手工调用Update(),因为过滤器与可视化流水线相连。在这种情况下,当演员收到一个需要绘制自己的请求时,它会朝着它的映射方法,Update()方法会自动被送到流水线。流水线的执行从高处开始,如图3-6所示,绘制方法经常会初始化所需数据,这些数据通过流水线向下传送,由于流水线部分过时,流水线过滤器重新执行,导致流水线末端数据更新,然后由演员来进行绘制。(想得到更多执行处理信息,参见第十章管理流水线执行,219页)。
图像处理
VTK支持广泛的图像处理和体素绘制功能,2D(图像)和3D(体素)数据均看成是vtkImageData,VTK的图像数据集是一个规则的、轴向排列的数组。图像、像素映射、位图都是2D图像数据集例子,体素(2D图像堆积)就是3D图像数据集。
在图像流水线中的处理对象的输入和输出均是图像处理对象,由于数据特性相对规则和简单,图像流水线有一些其它的重要特性。体绘制用来可视化3D vtkImageData(见36页),特殊的图像浏览器 观察2D图像。图像流水线中几乎所有的处理对象都是多线程,具有数据流分片能力(以满足用户特殊的内存局限)。滤波器自动感知系统处理器的数目,在运行过程中产生多线程数,自动将通过流水线的数据分片(参见使用流232页)。
本章简要介绍了可视化系统设计,建议读者详细了解VTK中许多算法细节。通过例子来学习是一种很好的方法,第4-8章包含许多带注释的例子,展示VTK各种功能,希望读者研究源代码以及数百个例子。
3.2 创建一个应用
这部分包含使用Tcl、C++、Java和Python语言开发VTK程序(Kitware使用VB或ActiveX/COM创建的VTK商业产品,参见38页)。读过介绍以后,应该跳到所感兴趣语言的子部分。除了为你提供指令来创建和运行一个简单程序以外,每部分将演示如何在该语言中进行调用。
用户方法,观察者和命令
调用(用户方法)在VTK中使用Subject/Observer和Command设计格式来实现。这意味着VTK中每一个类(每个vtkObject子类)都有一个AddObserver()方法,可能从VTK中建立调用。观察者观看每一个调用对象的事件,如果它观察者观察的事件之一匹配,相关的命令就会被调用。例如,所有滤波器在开始执行前都调用StartEvent,如果加入了一个观察StartEvent观察者,那么它会在滤波器每次开始执行时被调用。考虑下列Tcl 脚本产生一个vtkElevationFilter,为StartEvent加入一个观察者,调用程序PrintStatus。
所有VTK支持语言都有这种功能。下面每一部分有一个小例子来说明如何使用它。进一步关于用户方法的讨论,请参见303页“用窗口系统来集成”。要产生自己的应用程序,建议你从VTK的例子着手,它们在VTK/Example源代码布置和以及PC机可执行布置的子目录中。在源代码布置中,例子是按先题目后语言来组织的。 Tcl
Tcl是创建VTK应用程序最容易的语言之一,一旦安装了VTK,就可以与布置一起来运行Tcl例子。在Windows下,可以安装自我解压文档,见8页“在Windows 9X/NT/ME/2000/XP”。
Microsoft Visual C++
你为Cone例子运行了CMake以后,就可以启动Microsoft Visual C++,装载Cone.dsw,选择创建类型(Release 或 Debug),创建应用程序。如果想将VTK集成到已有的不使用CMake的工程中,可以从简单例子中拷贝设置到存在的工作区中。现在考虑一个真实的 Windows应用程序,这个过程类似于上面的例子,只是创建的是Windows应用程序,而不是控制台程序。大多数代码是标准的Windows代码,对于任何Windows开发工具都是合适的。这个例子位于Examples/GUI/Win32/SimpleCxx,只有CMakeLists.txt文件中的命令行ADD_EXECUTABLE的WIN32参数有所不同。
我们从包含必要的VTK include文件开始,无须包含标准的windows头文件,因为VTK头文件已经包含它们。接下来,在两个标准的windows原型后定义一个小型的myVTKApp类。当使用C++开发时,应该使用面向对象方法而不是许多Tcl例子中的脚本编程风格。这里我们将VTK应用程序组件封装到这个小类中。
这是类myVTKApp的构造函数,它装载了必要的VTK对象,设置实例变量,并将它们联结起来组成一个可视化流水线。除了vtkRenderWindow外大多数都直接是VTK源代码。这个构造函数将HWND句柄带给父窗口,该父窗口包含VTK绘制窗。然后我们在vtkRenderWindow的SetParentId()方法中使用句柄,产生一个窗口作为父窗口的子窗口,传递给构造函数。
析构函数释放构造函数中所有的对象。
这里WinMain代码是标准的windows代码,没有包含VTK在里面。由于这个程序控制循环事件,事件是由下面WndProc函数来处理的
WndProc是非常简单事件处理者。作为一个全应用程序它可能非常复杂,但关键集成的东西是相同的。函数的上部声明一个静态myVTKApp实例,处理WM_CREATE方法时,我们创建一个Exit按钮,然后构造和实例化myVTKApp通过句柄传递给当前窗口。vtkRenderWindowInteractor将会处理vtkRenderWindow事件,不用我们处理它们。也许你想加入代码来处理缩放事件,以便render window适当地调整尺寸覆盖用户接口。如果不设置 vtkRenderWindow的父窗口句柄,将会显示一个顶层独立窗。所有功能与前面一样。
VTK所支持的语言可以相互转化,但由于指针操作,某些C++程序不能转化为其它语言。
第四章 基础
本章我们将通过一些例子来介绍VTK的一些功能,关注点是通用方法、对象以及对象组合,也会介绍一些重要的概念和应用程序,但决没有覆盖VTK所有的特点。本章尽可能给你一个宽阔的视野。你可借助于用户手册或类的.h文件来学习每个类的其它功能。大多数例子在Tcl语言上实现,很容易在语言之间直接代码转换(参见38页语言之间转换)。C++具有优势,可以直接操作数据结构和指针,一些例子说明了这种情况。
这里的每个例子都有源程序和辅助图象。我们指出源程序文件的名字(当附随的CD中存在一个时),因此你不必手工进入。我们建议你运行和理解这个例子接着用对象方法和参数实验。你也可能希望尝试可选的方法和/或类。通常,Visualization Toolkit提供了一些方法来得到类似的结果。注意脚本通常从自己布置测试的代码中修改。这样做可以简化概念或者去掉无关的代码。
学习类似VTK的一个面向对象的系统首先需要理解程序抽象,然后接着逐渐熟悉对象和方法库。我们建议你复习19页的“系统设计”得到关于程序抽象的信息。本章的例子将为你提供许多VTK对象的一个好的总览。
4.1创建简单的模型
Visualization Toolkit的使用如下:读入/产生一些数据,过滤,绘制,与它交互。本节,我们通过查看读入/产生数据的方法开始。
有两种基本方法可以获得数据。存在于一个文件中的数据可能被读入系统;或者,数据可能程序化地生成(通过一个算法或者数学表达式)。回想起在可视化流水线中初始化数据处理的对象叫做源对象(看图3-5)。产生数据的对象叫做程序化(源)对象,而且读入数据的对象叫做读入(源)对象。 程序化源对象
我们将通过绘制一个简单的圆柱体开始。下面的例子(VTK/Examples/Rendering/Tcl/Cylinder.tcl)程序揭示了可视化和图象学系统中的许多基本概念。参考图4-1来看运行脚本的结果。
我们通过调用一个Tcl命令来下载VTK包(包需要vtk)和创建一个GUI解释程序(包需要vtkinteractor)开始这个脚本,这使你在运行时键入命令。同样,我们下载了定义了一个颜色集的vtktesting,其中的一个(西红柿)在以后的脚本中使用。 注意历史:在VTK过去的版本中,共享的VTK库通过调用catch{load vtktcl}来代替需要vtk的包。
我们接着创建一个程序化的源对象:vtkCylinderSource。这个源创建了一个圆柱体的多边形展示。圆柱体的输出通过SetInput()方法作为vtkPolyDataMapper的输入。我们创建一个actor(被绘制的对象),它把投射器作为它的定义的几何。注意对象用Tcl构建的方式:我们使用由期望实例名跟随的类名:
(为了提醒C++实施与Tcl(或者其他的解释语言)实施的相似,用C++实施的同样的代码如下所示,而且可以在VTK/Examples/Rendering/Cxx/Cylinder.cxx)
注意源对象初始化可视化流水线,而且投射对象终止了流水线,因此在这个例子中我们有一个由两个过程对象组成的一个流水线(i.e,一个源和投射器)。VTK流水线使用一个懒评估体系,即使流水线已经连通,数据或者数据处理还没有发生。(因为我们还没有请求数据)。 接着我们创建允许我们绘制actor的图象学对象。vtkRenderer实例ren1调整了绘制窗口renWin一个视口的绘制过程。绘制窗口交互者iren是一个允许我们操作相机的一个3D配件。
注意我们已经把绘制者与绘制窗口通过AddRenderer()方法联系起来。我们必须使用AddActor()方法把actor与绘制者也联系起来。
SetBackground()方法使用位于(0,1)之间的RGB值指定了绘制窗口的背景颜色,SetSize()用像素指定了窗口的规模。最后,我们通过把GUI interactor与绘制窗口交互者的用户定义方法联系来结束这个例子。(当鼠标焦点在绘制窗口中时,用户-定义方法通过u键调用。
看48页的“使用VTK Interactors”)Initialize()方法开始了事件循环,和Tcl/Tk命令wm withdraw。确保解释程序配件。当应用开始时Interact不可见。
当运行脚本时,可视化流水线会执行因为绘制过程会请求数据。(窗口曝光事件会使绘制窗口绘制它自己。)只有在流水线执行以后才是关于输入数据的滤波器。如果你希望,你可以通过调用renWinRender手工执行流水线。在你运行这个例子以后,你可能尝试一些事情。首先,通过在绘制窗口中的鼠标动作使用interactor。接着,通过调用cylinders SetResolution12改变圆柱体对象的精度。你可以通过编辑这个例子然后重新执行它来作到这点,或者通过绘制窗口中的u键来产生解释程序GUI而且在那里键入命令。记住,如果你在使用Tcl interactor popup,只有请求数据后你造成的改变才可见,因此接下来用一个renWin Render命令,或者窗口中的鼠标操作来改变。 读入源对象
这个例子类似于前面的例子,只是我们读一个数据文件而不是程序化地产生数据。使用二进制STL数据格式读一个表示多边形数据的立体—平版印刷术文件(suffix。Stl)(参考图4-2和Tcl脚本VTK/Examples/Rendering/Tcl/CADPart.tcl)
注意vtkLODActor的使用。这个Actor改变了它的表达,保留了交互行为。它的默认行为是产生一个点云和线框,边界—盒轮廓代表中介和低水平表达。(看61页的Actor详细水平得到更多信息)。你可能要用一个vtkActor实例代替vtkLODActor来看看不同。
当输入文件改变和重新执行时许多读者没有意识到。例如,如果文件42400—IDGH.stl改变,流水线不会重新执行。你可以手工调用Modified()方法修改对象。这会造成滤波器
及下游部分滤波器的重新执行。
Visualization Toolkit已经限制了,嵌入建模能力。如果你想要使用VTK来编辑和操作复杂模型(e.g,由立体建模器或者建模工具创建的那些),你通常将使用一个阅读器(看185页的“阅读器”)来与数据相接。(其它的选择是输入,被用来吸收完整的场景。看189页的“重要部分”得到更多细节) 4.2使用VTK Interactors
一旦你已经显示了你的数据,你通常想要与其交互。Visualization Toolkit提供了一些方法来作到这点。第一种方法是在vtkRenderWindow中使用built。第二种方法是通过确定事件绑定创建你自己的interactor。不要忘记(如果你在使用解释语言)你可以在运行时输入命令。你也可能希望参考65页的采集来看看如何从屏幕中选择数据。(注意:开发者也可以与他们选择的windows窗口相接。看303页的“windows系统的结合”) vtkRenderWindowInteractor
与你的数据相接的最简单的方式是实例化vtkRenderWindowInteractor。这个类对应了前面定义的事件和行动的集合,而且提供了重载默认行动的一个方法。vtkRenderWindowInteractor允许你控制相机和ractors,而且提供了两种interaction风格:位置感应(i.e.. 操纵杆模式)和行动感应(i.e.. trackball模式)。
vtkRenderWindowInteractor响应了绘制窗口中的以下事件。(注意多个绘制者可以在一个绘制窗口中绘制,而且在绘制窗口中绘制进一个视点。Interactors在一个绘制窗口中支持多个绘制者).
? J键/T键—在操纵杆(位置感应)和trackball(行动感应)之间反复触发。使用操纵杆
模式,只要点击鼠标,一个动作就连续发生。使用行动感应,当点击鼠标和鼠标指针移动时,动作就发生。
? C键/A键—在相机和actor(对象)模式之间反复触发。使用相机模式,鼠标事件影响
了相机位置和焦点。使用对象模式,鼠标事件影响了鼠标指针下的actor。
? 按钮1—把相机围绕它的焦点旋转(如果是相机模式)或者把actor围绕它的原点旋转
(如果是actor模式)。旋转的方向是从绘制器视点的中心到鼠标位置。使用操纵杆模式,旋转的大小由鼠标到绘制窗口中心的距离定义。
? 按钮2—(如果是相机模式)就摇动相机或者(如果是对象模式)就平移actor。使用操
纵杆模式,摇动或者平移的方向是从视点的中心到鼠标位置。使用trackball模式,运动的方向是鼠标移动的方向。(注意:使用一个2—按钮的鼠标,摇动是定义为
? 按钮3—(如果是相机模式)就缩放相机或者(如果是对象模式)就缩放对象。如果鼠
标位置在视点的上半部分就放大/增加比例;如果鼠标位置在视点的底部就缩小比例。使用操纵杆模式,缩放的量由鼠标指针到窗口水平中心线的距离来控制。
? 3键—使绘制窗口进入或者退出立体模式。默认情况下批,创建了红—蓝立体对。某些
系统支持水晶LCD立体眼镜;你必须调用绘制窗口中的SetStereoTypeToCrystalEyes()。 ? e键—退出应用。
? f键—在光标下移向点。这样做设置了焦点,允许围绕着哪个点的旋转。
? p键—执行一个采集操作。绘制窗口interactor有一个用来采集的的vtkPropPicker内部
实例。看65页的“采集”得到更多关于采集的信息。
? r键—沿着当前的视场方向重新设置相机视场。把actors放到中间而且移动相机因此所
有的actors都是可见的。
? s键—修改所有的actors表示因此它们是表面。
? u键—调用用户—定义方法。通常,这个键会带来一个interactor因此你可以输入命令。
? w键—修改所有的actors表示因此它们是线框。
默认的交互作用模式是位置敏感的(i.e,操纵杆模式)—即,只要鼠标键按下它就一直操作相机或者actor,还有绘制器。如果你不喜欢这个默认行为,你可以改变它,或者写出自己的。(看303页的“vtkRenderWindow Interaction Style”得到更多关于你自己风格的信息。 vtkRenderWindowInteractor有其它有用的特征。调用LightFollowCameraOn()(默认的行为)使光源位置和焦点与相机位置和焦点同步(i.e,创建了一个“headlight”)。当然,这可以使用LightFollowCameraOff()关掉。对应“u”键的一个回叫信号可以使用AddObserver(用户事件)方法添加。设定相关的采集方法也是可能的。AddObserver(开始采集事件)定义了一个被称为比采集更高级的方法,而且AddObserver(结束采集事件)定义了在采集被执行完之后的一个方法。(请看28页的“用户方法,观察者,和命令”得到更多定义了用户方法的信息。)你也可以确定vtkAbstractPicker的一个子类实例通过SetPicker()方法来使用(看65页的“采集”)。
如果你在使用vtkLODActor,你可能希望通过interactor中的SetDesiredUpdateRate()来设定期望的帧频。通常,这是自动操作地(当鼠标按钮被激发时,期望的更新率被增加;当释放鼠标按钮,又返回期望的更新率。)参考61页的“Actors细节”得到更多信息。 前面我们已经看了如何使用vtkRenderWindowInteractor,这里是一个摘要。
Iteractor风格
有两种完全不同的方式来控制VTK中的交互风格。首先使用vtkInteractorStyle的一个子类,或者是系统提供的或者是你自己写的。第二个方法是直接安排事件循环。
vtkInteractorStyle.类vtkRenderWindowInteractor可以支持不同的交互风格。当你在interactor中键入“t”或者“j”键(看前面的部分)你就在trackball模式和操纵杆交互模式之间转换。工作的方式是vtkRenderWindowInteractor发送它收到的任何事件(e.g,鼠标按钮,鼠标运动,击键事件,etc)给它的风格。风格接着负责操纵事件和执行正确的行为。为了看这个风格,使用vtkRenderWindowInteractor::SetInteractorStyle()方法。例如:
(注意:当例示vtkRenderWindowInteractor时,事实上例示了一个窗口—系统特定的绘制窗口。例如,在Unix系统上实际上创建了类vtkRenderWindowInteractor,而且作为vtkRenderWindowInteractor的一个实例返回。在窗口中,例示了vtk Win32RenderWindowInteractor。)
安排时间循环。你可能希望创建你自己的事件绑定。绑定可以使用VTK支持的任何语言来安排,包括C++,Tcl,Python,和Java。(通常你会在你构建GUI的系统中做到这一点。为了得到更多关于把VTK与窗口系统相接的信息,看303页的“Windows系统的整合。)一个例子是查看Wrapping/Tcl/TkInteractor.tcl,它为Tcl/Tk定义了绑定。绑定命令是一个把配件中的事件与一个回叫信号或者函数调用相联系的一个Tcl/Tk命令。 注意绑定与vtkRenderWindowInteractor非常类似。这些绑定就像trackball interactor模式;即,直到鼠标移动时相机才改变。
4.3过滤数据
前面的例子由一个源和投射器对象组成;流水线没有滤波器。本节我们展示如何给一个流水线添加一个滤波器。
使用SetInput()和GetOutput()方法连接滤波器。例如,我们可以修改46页的“绘制源对象”的脚本来压缩组成模型的多边形。脚本如下所示。(只展示了流水线和其它的相干的对象)完整的脚本可以在VTK/Examples/Rendering/Tcl/FilterCADPart.tcl。
如你所看到的,创建一个可视化流水线是简单的。你需要根据手头的任务选择正确的类,保证相连接的滤波器的输入和输出类型是兼容的,而且设定了必要的实例变量。(当输出数据集类型与输入会接受的类型一致,或者是输入类型的一个子类时,输入和输出类型是兼容的。)可视化流水线可以包括循环,尽管一个滤波器的输出不能直接连接到它的输入。 4.4相机控制
你可能注意到在进程脚本中相机或者光源没有被例示。如果你熟悉3D图象学,你知道绘制对象必须要有相机和光源。在VTK中,如果没有直接创建相机和光源,绘制器自动例示它们。 例示相机
以下的Tcl脚本展示了如何用一个绘制器来例示和与一个相机相联系。
可以选择地,如果你希望访问一个已经存在的相机(例如,绘制器已经自动例示的一个相机),在Tcl中你可以使用
让我们来重新回顾一些我们已经介绍的相机方法。SetClippingPlane()有两个论点,沿着视平面法线到最近和最远切割平面的距离。记住在绘制过程中不在这些平面之间的所有图象元素都被删除,因此你需要保证你想要看的对象位于切割平面之间。焦点和位置(在world 坐标)实例变量控制相机的方向和位置。Compute ViewPlaneNormal()重新根据当前位置和焦点设定视平面的法线。(如果视平面的法线不垂直于视平面你可以得到一些有趣的shearing渲染效果。)对ViewUp的设定控制了相机的“上”方向。最后,Zoom()方法通过改变视角(e.g,SetViewAngle())放大对象。你也可以使用Dolly()方法来沿着视平面法线把相机移入和移出而且放大或者缩小可见的actors。
简单的操作方法
上面描述的方法不一直是控制相机的最方便的方法。如果相机“看到”了你要看的点(i.e,焦点被设好了),你可以使用Azimuth()和Elevation()方法对于焦点移动相机。
这些方法在一个中心为焦点的球形坐标系统中沿着经度方向(azimuth)和纬度方向(elevation)移动给定的角度来移动相机。这些方法依赖保持不变的view-up向量,而且没有修改view-up向量。注意在北极点和南极点有异常—view-up向量平行于视平面法线。为了避免这点,通过使用OrthogonalizeViewUp(),你可以强迫view-up向量垂直于view向量。可是,这改变了相机坐标系统,因此如果你使一个自然水平的或者view-up向量(例如地形)围绕一个对象飞来飞去,相机操作不再与数据自然相关。 控制视方向
相机的一个通用的功能是生成来自一个特定方向的场景。你可以通过调用SetFocalPoint(),SetPosition(),和通过调用绘制器上与相机相关的ResetCamera()而跟随的ComputeViewPlaneNormal()作到这一点。
初始方向(view向量或者视平面法线)由焦点和相机的位置计算,相机的位置与ComputeViewPlaneNormal()一起定义了初始view向量。随意地,你可以确定一个初始view-up向量而且使它与view向量正交。ResetCamera()方法接着沿着view向量的方向移动相机因此绘制器的actors对相机都是可见的。 透视画法和正交视场 在目前展示的例子中,我们已经假设相机是透视相机;即,一个视角控制了绘制过程中actors到视平面的投射。透视投射,在产生更多自然观察图象时,引入了在某些应用中不期望得到的失真。正交(或平行)投射是另外一种投射方法。在透视投射中,视光线是平行的,而且对象的绘制没有距离效果。
为了设定相机使用正交投射,使用vtkCamera::ParallelProjectionOn()方法。在平行投射模式中,相机视角对于控制缩放不再有效。替代地,使用SetParallelScale()方法来控制actors的放大倍率。
保存/重新储存相机状态
应用的另外一个通用的需求是保存和重新储存相机状态(i.e..,复原一个view)的能力。为了保存相机状态,你需要保存(最小限度地)剪切范围,焦点和位置,和view-up向量。你也会要计算视平面法线(53页的“安装相机”的例子)接着,为了恢复相机状态,简单地用保存下来的信息例示一个相机而且把它赋给合适的绘制器(i.e,SetActiveCamera())。 在某些情况下你可能需要存储额外的信息。例如,如果相机视角(或者平行比例)被设定,你会需要保存这些。或者,如果你在使用相机来进行立体观察,就需要EyeAngle和Stereo。
4.5控制光源
光源比相机容易控制。最通用的方法是SetFocalPoint(),SetPosition(),和SetColor()。光源的位置和焦点控制了光源点的方向。光源的颜色表达为一个RGB向量。同样,通过SwitchOn()和SwitchOff()方法可以打开或者关闭光源,而且光源的亮度可以用SetIntensity()方法来设定。
默认地,vtkLight的实例是方向光源。即,位置和焦点定义了平行于光线传播的一个向量,而且光源被认为是在无穷大点处。这意味着如果位置和焦点等价地转换,那么在一个物体上的光线不改变。
光源与如下的绘制器相联系。
这里我们已经创建了一个红色前灯:定位于相机(caml’s)而且指向相机焦点的一个光源。这是一个有用的诀窍,而且被交互的绘制器用来定位相机移动时的光源(看48页的“使用VTK Interactors”) 位置光源
通过使用PositionOn()方法创建位置是可能的。这个方法结合SetConeAngle()方法使用来控制点的传播。180度的一个cone角意味着没有哪个点光源效果会被应用(i.e..,截短的光源cone);只有位置的效果。 4.6控制3D 道具
VTK中的将要被在绘制窗口中画出的对象通常被称为“道具”(道具是出现在舞台上的东西)有一些不同类型的道具包括vtkProp3D和vtkActor。vtkProp3D是存在于3D空间中的那些道具类型的一个抽象超类(vtkProp3D有支持平移、旋转、缩放,和3D空间中几何投射的一个4*4变换矩阵。)类vtkActor是vtkProp3D的一个类型,它的几何由分析元素例如多边形和线来定义。我们会研究vtkActor和vtkProp3D的其他类型。 确定vtkProp3D的位置
我们已经看了如何使用相机来围绕一个对象移动;可以选择地,我们也可以稳定地掌握相机和转换道具。可以使用以下的方法来定义一个vtkProp3D的位置(和它的子类) ? SetPosition(x,y,z)——在world坐标中确定了vtkProp3D的位置。
? AddPosition(deltaX,deltaY,deltaZ)——沿着每个x,y,z轴变换确定数量的道具。 ? RotateX(theta),RotateY(theta),RotateZ(theta)——分别围绕x,y,z轴旋转theta角
度。
? SetOrientation(x,y,z)——通过围绕z轴旋转设定道具的方位,接着是y轴,然后是z
轴。
? AddOrientation(x,y,z)——添加到道具的当前方位。
? RotateWXYZ(theta,x,y,z)——把道具围绕定义的x-y-z向量旋转theta角度。 ? Scale(sx,sy,sz)——在x,y,z轴坐标方向上缩放道具。
? SetOrigin(x,y,z)——确定道具的原点。旋转和缩放围绕原点发生。
这些方法用复杂的方式组合起来以控制结果变换矩阵。要记住的最重要的事情是上面的操作应用于一个特定的顺序,而且应用的顺序影响了结果actor位置。在VTK中应用这些变换的顺序如下:
到原点和来自原点的变化分别是原点值的正负变换。Net变换由vtkProp3D的位置值给定。这些变换最令人困惑的部分是旋转。例如,执行一个由y旋转跟随的x旋转与相反顺序的操作结果不同(看图4-4)。为了得到更多关于actor变换的信息,参考Visualization Toolkit的74页。
在本节中我们描述了一系列的vtkProp3D——在VTK中最通用的类是vtkActor。接下来(看70页的“控制vtkActor2D”)我们会研究2D道具(i.e..,vtkActor2D),它将被用来进行注释和其它的2D操作。
Actors
Actor是最通用的vtkProp3D类型。像其他具体的vtkProp3D子类那样,vtkActor用来把例如表面属性(e.g,ambient,散播,镜射颜色),表达(e.g,表面或者线框),纹理图片,和/或一个几何定义(一个绘图者)的绘制属性分组。
定义几何。一个actor的几何用 SetMapper()方法来确定:
在这种情况下mapper是vtkPolyDataMapper的类型,它使用分析元素例如点,线,多边形,和三角形条来绘制几何。mapper终止了可视化流水线,而且作为可视化子系统和图象子系统之间的桥梁。
Actor属性。Actor指vtkProperty的一个实例,它反过来控制actor的外观。可能最通用的属性是actor颜色。其他重要的属性特征是它的表示(点,线框,或者表面),它的消隐方法(flat或者Gouraud消隐),actor的不透明度(相对透明度),和ambient(氛围),散播,镜射颜色及相关的系数。以下脚本展示了如何设定这些实例变量中的一些。
注意我们如何通过GetProperty()方法废弃actor的属性。我们也可以创建一个属性而且把它赋给actor:
后一种方法的优点是我们通过赋予同样的属性控制了一些actors的属性。
Actor颜色。颜色可能是应用于actor的最重要的属性。最简单的程序是使用SetColor()方法设定actor的RGB值。每个值的范围是从0到1。
你也可以分别设定ambient,散播,镜射颜色。
在这个例子中我们已经把ambient颜色设为黑色灰度,散播颜色设为蓝色阴暗,镜射颜色为白色。(注意。SetColor()方法把ambient,散播,镜射颜色设为特定的颜色。)
重要:如果没有对actor的mapper可用的标量数据,actor的属性中设好的颜色才发挥作用。默认地,mapper的输入标量数据对actor着色,而且actor的颜色被忽略了。为了忽略标量数据,使用以下的Tcl脚本ScalarVisibilityOff()。
Actor透明度。很多时候调整一个actor的透明度是有用的。例如,如果你希望展示由一个病人皮肤包围的内部组织,调整皮肤的透明度允许用户看到与皮肤相关的组织。使用以下的vtkProperty()方法:
(请注意使用绑定过程在绘制库中实施透明度。过程需要以正确的顺序绘制多边形。实践中,这很难得到,特别是如果你有多重透明的actor。对于有序的多边形,你应该把透明的actor添加到actor的绘制器列表的末端。(i.e,,最后添加它们)。同样,你可以使用滤波器vtkDepthSortPolyData对沿着观察向量的多边形进行排序。请看
VTK/Examples/VisualizationAlgorithms/Tcl/DepthSort.tcl得到使用这个滤波器的一个例子。 混杂的特征。Actors有其它的一些重要特征。你可以使用VisibilityOn()和0VisibilityOff()方法来控制一个actor是否是可见的。如果你不想在一个采集操作过程中采集一个actor,就使用PickableOff()方法(看65页的“采集”得到更多的信息)Actors也有一个当它们被采集时就被调用的一个采集事件。你也可以使用GetBounds()方法得到轴线排列的actor bounding 盒子。 细节层次Actors
图象系统的一个主要问题是交互使用时变地太慢。为了解决这个问题,VTK使用细节层次Actors以低精度的分辩率为代价得到可以接受的绘制效果。
在47页的“绘制器源对象”中我们看到如何使用一个vtkLODActor。基本地,最简单的使用vtkLODActor的方法是用vtkLODActor的实例来代替vtkActor的实例。此外,你可以控制细节层次的显示。vtkLODActor的默认行为是创建两个额外的,来自原始投射器的低分辩率模型。第一个是一个从定义了投射器输入的点采样的点云。你可以如下控制云中点的数目。(默认地是150个点)
最低分辩率模型是actor的一个bounding 盒子。使用AddLODMapper()方法可以添加额外的细节层次。它们可以不必按照复杂度的顺序来添加。
为了控制绘制过程中由actor选择的细节层次,你可以在绘制窗口中设定期望的帧频:
它每分钟转化为五个帧。vtkLODActor会自动地选择合适的细节层次来得到要求的速度。(注意:例如vtkRenderWindowInteractor的交互器配件自动地控制期望的更新。当释放一个鼠标按钮时它们通常把帧频设地很低,当按下一个鼠标按钮时增加帧频。当相机运动时得到低分辩率/高帧频的模型,当相机停止时得到高分辩率低帧频的模型。如果你要控制更多的细节层次,看64页的“vtkLODProp3D”。vtkLODProp3D允许你指定每个层次。) 集合
Actors通常分级地组装以便一个actor的动作影响其它actors的位置。例如,一个机械臂可能包括一个上臂,前臂,腕和末端效应器,所有的这些通过关节连接。当上臂绕肩关节旋转时,我们期望剩余的部分随之旋转。这个行为通过使用集合来实施,它是vtkActor的一种类型(子集)。以下的脚本展示了它是如何做的(来自VTK/ Examples/Rendering/Tcl/assembly.tcl)
注意我们如何使用vtkAssembly的AddPart()方法来构建层次的。只要没有任意的自引用循环,集合就可以以任意深度被嵌入。注意vtkAssembly是vtkProp3D的一个子集,因此它没有属性的概念或者一个相关投射器的概念。因此,vtkAssembly的叶层次节点必须带有材料属性(颜色等)的信息,和任意的相关几何。Actors也可能被一个以上的集合使用(注意coneActor如何在集合中使用并且作为绘制器)同样,绘制器的AddActor()方法被用来把集合的顶部和绘制器联系起来;这些在集合层次中是低层的actors不需要被添加到绘制器上因为它们是递归地被绘制。
你可能要考虑如果一个以上的集合使用了一个actor,或者与一个集合混合时,如上面例子所示,如何把actor的使用与它的上下文区别开。(这在像采集那样的行为中特别重要,那里用户可能需要知道哪个vtkProp被采集和被采集的上下文。)我们随着类vtkAssemblyPath的引入解释了这个问题,它是与变换矩阵相关的vtkProps的一个有序列表,(如果有的话),在65页中仔细讲述了“采集”的细节。
体
类vtkVolume被用来进行体绘制。像vtkActor那样,vtkVolume继承了vtkProp3D的方法来对体进行定位和定向。vtkVolume有一个相关的属性对象,这种情况下是一个vtkVolumeProperty。请看136页的“体绘制”得到对vtkVolume使用的一个深入描述和体绘制的描述。
vtkLODProp3D
类vtkLODProp3D类似于vtkLODActor(看61页的“细节层次Actors”)它使用不同的表示来得到交互帧频。不同于vtkLODActor,vtkLODProp3D同时支持体绘制和表面绘制。这意味着你可以使用体绘制应用中的vtkLODProp3D来得到交互帧频。以下的例子展示了如何使用类。
基本上,你创建了对应一个不同的绘制复杂度的投射器,而且把投射器添加到vtkLODProp3D上。AddLOD()方法接收了体或者几何投射器,和随意地一个文理图片和属性对象。(根据你希望提供的信息对这个方法有不同的鲜明特征)。域中的最后一个值是绘制的一个估计时间。通常你把它设为0来表示没有初始的估计。这个方法返回可以用来访问适当的LOD的一个整数id。(i.e,选择一个层次或者删除它)
vtkLODProp3D测量了用来绘制每个LOD的时间而且把它们适当地排序。接着,根据绘制窗口的期望更新率,vtkLODProp3D选择了合适的层次来绘制。看162页的“使用一个vtkLODProp3D来提高效率”得到更多的信息。 4.7使用纹理
纹理投射是创建现实的,引人注目的可视化的一个强大的图象工具。2D纹理投射背后的基本思想是图象可以在绘制过程中被“糊制”到一个表面,因此创建了更丰富且更细节的图象。纹理投射需要两块信息:在VTK中是一个vtkImageData数据集(i.e,一个2D图象)的一个纹理图片;和控制一个表面上纹理定位的的纹理坐标(注意:3D纹理也是可能的,但是并不广泛地被多数绘制硬件支持。)
以上的例子(图4-5)揭示了纹理投射的使用(看VTK/ Examples/Rendering/Tcl/Tplane.tcl)。注意纹理图片(为vtkTexture类)与actor相关,而且纹理坐标来自平面(当创建平面时由
vtkPlaneSource生成纹理坐标)
很多情况下纹理坐标是不可见的,通常是因为它们不是在流水线上生成。如果你需要产生纹理坐标,参考112页的“产生纹理坐标”。同样,你应该注意到当图象硬件/库(e.g,OpenGL)只支持二维纹理图片时(e.g,128*256等等)在VTK中不为二维的纹理会被自动重新采样为二维,这在某些应用中会产生效果) 4.8采集
采集是一个通用的可视化任务。采集被用来选择数据和actors,或者询问潜在的数据值。当选择并且使用一个显示位置(i.e,像素坐标)来调用vtkAbstractPicker的Pick()方法时,进行一个采集。根据采集类类型的不同,从采集中返回的信息可能同x-y-z全局坐标一样简单,或者可能包括所有的单元ids,点ids,单元参数坐标,被采集的vtkProp实例,和/或集合路径。采集方法的语法如下。
注意采集方法需要一个绘制器。与绘制器相关的actors是采集选择的候缺者。同样,选择通常也被设定为0.0——它与z—缓冲器上的深度有关,(这个方法不直接调用。而且用户与安排采集的类vtkRender交互。这种情况下,用户通过把采集类的一个实例赋予vtkRenderWindowInteractor控制这个采集过程,我们会在以下的例子中看到)
Visualization Toolkit支持不同功能和效果的某些类型的采集者(请看图14-12,它是采集类层次的一个说明)类vtkAbstractPicker作为所有采集者的基类。它定义了一个允许用户使用GetPickPosition()方法检索采集位置(在全局坐标中)的最小API。
存在vtkAbstractPicker的三个直接类。第一个,vtkWorldPointPicker,是一个使用z—缓冲器返回x-y-z全局采集位置的快速(通常用硬件)采集类。可是,没有返回其它信息(关于被采集的vtkProp,etc)。类vtkAbstractPropPicker是vtkAbstractPicker的其它的直接子类。它定义了可以采集一个vtkProp实例的采集者的一个API。在这个类中有一些方便的方法允许返回一个采集类型的检索。这些方法的功能通过调用采集者上的GetPath()和使用IsA()方法定义类型来得到。
? GetProp()——返回被采集的vtkProp实例。如果采集了任何根本的东西,那么这个方
法会给vtkProp实例返回一个指针,否则返回NULL。
? GetProp3D()——如果采集了vtkProp3D的一个实例,返回一个指向vtkProp3D的指
针。
? GetActor2D()——如果采集了vtkActor2D的一个实例,返回一个指向vtkActor2D的
指针。
? GetActor——如果采集了vtkActor的一个实例,返回一个指向vtkActor的指针。
? GetVolume()——如果采集了vtkVolume的一个实例,返回一个指向vtkVolume的指
针。
? GetAssembly()——如果采集了vtkAssembly的一个实例,返回一个指向vtkAssembly
的指针。
? GetPropAssembly()——如果采集了vtkPropAssembly的一个实例,返回一个指向
vtkPropAssembly的指针。
小心这些方法。类(和它的子类)返回关于被采集的集合路径的顶层信息。因此如果你有一个顶层是类型vtkAssembly,叶节点是类型vtkActor的一个集合,方法GetAssembly()会返回一个NULL指针(i.e,不是vtkActor)。如果你有一个包括集合,actors,和其他Props类型的的一个复杂场景,,可以采用的最安全的方法是使用GetProp()方法来决定是否采集了任何根本的东西,接着使用GetPath()。
有vtkAbstractPropPicker的一个直接子类。vtkPropPicker使用硬件采集来决定被采集的vtkProp实例,和采集位置(在全局坐标中)。它通常比vtkPicker和它的子类快,但是不能返回关于采集了什么单元的信息,etc。警告:使用某些图象硬件(特别是低价PC板),采集操作实施地并不适当。这种情况下,你必须使用vtkAbstracPicker的一个软件版本(接下来描述的三个类中的一个)
vtkAbstracPicker的第三个子类是vtkPicker,根据它们的bounding 盒子选择vtkProp的一个基于软件的采集者。它的采集方法从相机位置发出一条光线,穿过选择点与每个Prop3D的bounding 盒子相交;当然,可能采集了一个以上的Prop3D。返回根据沿着光线的它的bounding 盒子交叉点的“最近的”Prop3D。(可以使用GetProp3Ds()方法来得到所有的bounding 盒子被交叉的Prop3D)。vtkPicker相当快但是不能产生一个单一的采集。
vtkPicker有两个可以用来检索关于更多被采集的(e.g,点ids,单元ids,etc)细节信息的子集。vtkPropPicker选择了一个点而且返回了点id和坐标。它通过从相机位置发出一条光线,穿过选择点,而且把位于容许量范围内的那些点投射到光线上。沿着它的相关actor选择离相机位置最近的被投射的点。(注意:实例变量Tolerance表达为一个绘制器窗口的对角线长度的一个片断)vtkPointPicker比vtkPicker慢但是比vtkCellPicker快。它不能总是返回一个唯一的采集是因为被调用的tolerance。
vtkCellPicker选择了一个单元而且返回关于交叉点(单元id,全局坐标,和参数单元坐标)的信息。通过发出一条光线,而且与每个actor的主要几何上的所有单元相交,决定在一个特定的tolerance范围内是否每个都与这个光线相交来进行这个操作。沿着特定光线,沿着它的相关actor选择离相机位置最近的单元(注意:实例变量Tolerance在交互计算过程中被使用,而且你可能需要用这个值进行实验来得到满意的行为。)vtkCellPicker是所有采集者中最慢的,但是提供了最多的信息。它会产生在特定的tolerance范围内的一个独特的采集。
某些事件被定义用来与采集操作相交。采集者调用优于执行采集操作的StartPickEvent。EndPickEvent在完成采集操作之后被调用。每当采集了一个actor时调用了PickEvent和actor的PickEvent。
vtkAssemblyPath
如果你要在一个场景中使用不同类型的vtkProp执行采集操作,特别是如果场景包括vtkAssembly实例,对类vtkAssemblyPath的一个理解是重要的。vtkAssemblyPath是简单的vtkAssemblyNode的一个有序列表,那里每个节点包括一个vtkProp指针,和一个可选择的
vtkMatrix4*4。列表的顺序是重要的:列表的开始表示根,或者在一个集合层次上的顶层;列表的结束表示集合层次上的一个叶节点。节点的顺序也影响相关的矩阵。每个矩阵是节点的vtkProp矩阵与前面列表中矩阵的串联。因此,对于一个给定的vtkAssemblyNode,相关的vtkMatrix4*4代表了vtkProp的位置和方向。(假设vtkProp最初没有被转换) 例子
通常,采集被vtkRenderWindowInteractor自动地安排(使用48页的“使用VTK交互者”得到更多关于交互者的信息)例如,当压下p键时,vtkRenderWindowInteractor用vtkPropPicker的内部实例调用一个采集。你可以接着向vtkRenderWindowInteractor要求它的采集者,而且收集你需要的信息。你也可以为vtkRenderWindowInteractor确定一个特定的vtkAbstracPicker实例来使用,如以下脚本所示。一个例子数据集合的结果如图4-6。这个例子的脚本可以在VTK/ Examples/Annotation/Tcl/annotatePick.tcl)中找到。
这个例子使用一个vtkTextMapper在屏幕上绘制采集的world坐标(看71页的“Annotation”得到更多信息)。注意我们登记 EndPickEvent在采集发生后执行setup调整。当采集完成时,配置这个方法来调用annotatePick()程序。 4.9vtkCoordinate和Coordinate系统
Visualization Toolkit支持不同的坐标系统,而且类vtkCoordinate安排了它们之间的变换。被支持的坐标系统如下。
? DISPLAY——(绘制)窗口中的x-y像素值。(注意vtkRenderWindow是vtkWindow的
一个子类)原点是左下角(对于以下描述的所有2D坐标系统是对的)
正在阅读:
VTK User\\'s Guide中文版05-30
教育科学研究课题11-06
多屏互动(Screen+)使用参数说明08-18
一轮洁白的明月作文450字06-19
抗溶性水成膜泡沫灭火剂3% AFFFAR性能与试用范围04-03
SAP-销售定价条件技术 - 图文09-20
创建国家二级乙等医院动员会讲话稿07-19
酒店消防安全责任书10-15
2014年高考数学全程总复习课时提升作业五十五第八章第六节练习卷04-05
有关茉莉花的作文300字06-13
- 1Digital Booklet - Let&39;s Get To What&39;
- 2EndNoteX5_User_Guide_20110727
- 3America&39;s economy
- 4Father&39;s Day
- 5Head First Servlets & JSP(中文版)9-14章
- 6三下Unit3 At the zoo B let's learn & let's do
- 7sc6531 AT Command User Guide
- 8A Wolf in Sheep&39;s Clothing
- 9Speech_on_Hitler\\'s_Invasion_of_the_U.S.S.R.
- 10Shanghai,Disney,boasts,the,world's,longest,parade
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 中文版
- Guide
- User
- VTK
- amp
- 39
- 七年级历史上册学案与作业
- 浙江省台州市2018年高三年级第一次(4月)调考数学试题 word版含答
- 成型娶酰胺尼龙软管接头的注射模具设计
- 《烹调技术》教案
- 从传统爱情故事看中国古代女性悲剧的社会因素 - 图文
- 企业常用网站推广、网络营销方法介绍
- 贝亿教育整理200个句子涵盖了高中英语4500词汇
- 从内聚焦叙事谈《失乐园》中撒旦复杂形象的塑造
- 哈尔滨商业大学毕业论文模板(鞠成东)
- 盛世黔城应急救援预案方案
- 计算机与电子工程学院课程设计(实习)报告撰写格式模版
- 张寄岗老师小儿推拿教材
- 尼龙6模具设计2
- 美文欣赏之新媒体融入国企党建刍议
- 2016届高考备考+三角函数教案
- 河兴煤矿老系统作业规程
- 驾驶员理论考试试题
- 新闻记者考试《新闻法规》练习题标准答案
- 定州二中高二期末试题成品
- 2011届中考物理电功和电功率复习题 - 图文