首页 > 代码库 > 第04章-VTK基础(1)
第04章-VTK基础(1)
【译者:这个系列教程是以Kitware公司出版的《VTK User’s Guide -11th edition》一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934-23-8),由于时间关系,我们不能保证每周都能更新本书内容,但尽量做到一周更新一篇到两篇内容。敬请期待^_^。欢迎转载,另请转载时注明本文出处,谢谢合作!同时,由于译者水平有限,出错之处在所难免,欢迎指出订正!】
【本小节内容对应原书的第41页至第45页】
这一章通过一系列典型的例子介绍VTK的功能。重点在于常用的方法和对象,以及对象间的组合。同时,介绍了VTK中的重要概念和应用。本章的目的是让读者对VTK有个大概的了解,并没有涵盖VTK所有的特性。读者可以参考在线文档或者类.h文件来学习每个类的其他功能。
本书的大多数例子是用Tcl程序语言实现的。这些例子可以用C++,Java和Python实现,这些编程语言之间可以直接地进行转换(参考“语言间的转换”一节)。由于C++在数据结构和指针操作方面具有显著的优势,有关这方面的例子会采用C++语言实现。
这里列出的每个例子都包括了相关的代码和补充说明的图像。如果该例子在VTK源文件目录中存在的话,我们会列出该例子文件的名字,所以你不需要手动去输入这些代码。建议你自己去运行这些例子,理解里面的代码,用不同的参数进行实验。你也可以用不同的方法或者类去实现同样的功能。通常,VTK都会提供几种不同的方法来获得类似的结果。注意,脚本文件通常会因发布的源码的改变而作修改,这是为了简化概念或者删除多余的代码。
学习像VTK这样的面向对象的系统首先需要理解抽象编程,然后要熟悉对象库及其方法。因此,建议读者先复习一下第三章“VTK系统概述”中有关抽象编程的概念。这一章的例子可以让读者对VTK对象有一个很好的认识。
4.1创建简单模型
使用VTK的步骤一般为:读入/生成数据,对数据进行Filter操作,数据的渲染和交互。这部分的主要内容就是数据的读取和生成。
获取数据有两种方法,数据可能存在于读入系统内存的文件(或数据流)中,也可能由程序生成(通过算法或者数学表达式等形式)。在可视化管道中初始化数据处理的对象称为源对象(参考图3-5)。生成数据的对象称为程序(源)对象,读入数据的对象称为读(源)对象。
程序源对象(Procedural Source Object)
我们从绘制简单的圆柱开始。以下例子代码(VTK/Examples/Rendering/Tcl/Cylinder.tcl)展示了可视化管道和渲染引擎的一些基本概念。图4-1显示了该Tcl脚本的运行结果。
图4-1 使用Tcl/Tk编写的解释性应用程序
首先我们在该脚本程序的最开始调用了Tcl命令来加载VTK工具包(packagerequired vtk),并且创建了带用户交互界面的解释器(package requiredvtkinteraction),通过该交互界面可以让你在程序运行时输入命令。另外,脚本也加载了vtktesting模块,该模块定义了一系列的颜色,其中“番茄色”在该脚本中会使用到。
Package required vtk Package required vtkinteraction Package requiredvtktesting
接着,创建一个程序源对象:vtkCylinderSource,该类创建一个横截面为多边形的柱体,柱体的输出通过方法SetInputConnection()设置为vtkPolyDataMapper对象的输入。接着创建一个actor对象(要渲染的对象),设置定义几何信息的mapper到这个actor里。注意类对象在Tcl中的构造方式:类名后面紧跟对象的名字。
vtkCylinderSourcecylinder cylinder SetResolution 8 vtkPolyDataMappercylinderMapper cylinderMapper SetInputConnection [ cylinderGetOutputPort ] vtkActor cylinderActor cylinderActor SetMapper cylinderMapper eval [ cyliderActor GetProperty ] SetColorStomato cylinderActor RotateX 30.0 cylinderActor RotateY -45.0
为了证明C++代码的实现与Tcl(及其他解释性语言)的相似性,与以上例子相同的C++实现代码也在下面列出,可以在VTK/Examples/Rendering/Cxx/Cylinder.cxx中找到该例子的C++代码。
vtkCylinderSource*cylinder = vtkCylinderSource::New(); cylinder->SetResolution(8); vtkPolyDataMapper*cylinderMapper = vtkPolyDataMapper::New(); cylinderMapper->SetInputConnection(cylinder->GetOutputPort() ); vtkActor*cylinderActor = vtkActor::New(); cylinderActor->SetMapper(cylinderMapper ); cylinderActor->GetProperty()->SetColor( 1.0000, 0.3882, 0.2784 ); cylinderActor->RotateX(30.0 ); cylinderActor->RotateY(-45.0 );
回顾之前的内容可知,源对象位于可视化管线的开始,mapper对象(或者具有mapper功能的prop对象)处于管线的终端。因此,该例子的管线包含两种算法(即源source和mapper)。VTK的管线使用惰性计算策略,即使管线已经连接,如果没有请求获取数据,程序也不会生成数据及对数据进行处理。
接下来,为了渲染actor需要创建图形对象。vtkRenderer的实例ren1协调渲染窗口renWin的视口(viewport)的渲染过程。渲染窗口交互器实例iren是一个3D的widget,可以控制三维渲染场景的相机。
#Create the graphicsstructure vtkRenderer ren1 vtkRenderWindow renWin renWin AddRenderer ren1 vtkRenderWindowInteractoriren iren SetRenderWindow renWin
注意,我们通过渲染窗口类的方法AddRenderer()把renderer和渲染窗口关联起来,接着使用renderer的方法AddActor()把要渲染的actor加入到renderer中去。
# Add the actors tothe renderer, set the background and size ren1 AddActorcylinderActor ren1 SetBackground 0.10.2 0.4 renWin SetSize 200 200
SetBackground()方法用取值范围为(0,1)的RGB(红,绿,蓝)值设置渲染窗口的背景色,SetSize()以像素为单位来确定窗口的大小。最后,将GUI交互器与用户自定义的渲染交互窗口交互器的方法关联起来。(当鼠标的焦点处在渲染窗口时,用户自定义的方法可以通过按击键盘u键激活。可参考本章的“使用VTK交互器”一节,或者参考第三章的“用户事件、观察者以及命令模式”一节)。调用Initialize()方法进入事件循环,Tcl/Tk的命令wmwithdraw .可以确保在程序开始运行时interacter widget .vtkInteract不可见。
# Associate the “u”keypress with a UserEvent and start the event loop iren AddObserver UserEvent ( wm deiconify ,vtkInteract ) iren Initialize # suppress the tkwindow wm withdraw
当以上脚本程序运行时,因为渲染引擎会请求数据,所以可视化管线就会执行。(窗口的expose事件会迫使渲染窗口自行渲染。)只有输入数据改变才能令管线执行的数据更新。读者可根据需要调用renWin Render手动控制管线的执行。
例子运行后,你可以尝试:首先,用鼠标与渲染窗口进行交互。然后,可以调用cylinder SetResolution 12改变柱体的分辨率(即柱体横截面的多边形的边数)。可以编辑脚本然后重新执行这个例子;也可以按击键盘u键,就会弹出图4-1所示的基于GUI的命令解释器,可以在上面输入命令。这些改变只有在你重新请求数据时才会生效,所以在输入cylinder SetResolution12命令以后,还必须输入renWin Renderer命令,或者用鼠标点击一下渲染窗口,所做的改变才会生效。
读取源对象ReaderSource Object
这个例子与前面的例子类似,除了用读取数据文件来生成数据替代由程序生成数据。立体成型(stereo-lithography)数据文件(后缀为.stl)是使用二进制STL数据格式来表达多边形数据。(参考图4-2和Tcl脚本VTK/Examples/Rendering/Tcl/CADPart.tcl)
图4-2读取源对象
vtkSTLReader part part SetFileName$VTK_DATA_ROOT/Data/42400-IDGH.stl vtkPolyDataMapperpartMapper partMapper SetInputConnecteion [ partGetOutputPort ] vtkLODActor patrActor partActor SetMapper partMapper
注意类vtkLODActor的使用。为保证交互时的顺畅性,这种类型的actor会更改自身的显示形式,缺省情况下会创建一个带线框的点云替代交互时actor的显示。(参考本章“Level-Of-DetailActors”一节。)本例中所用到的模型数据量较小,在现在的大多数机器上运行的话,还是显示模型完整的形式(图4-2所示)。
文件读取类不会监听输入文件是否发生变化以及是否要重新执行管线。例如,如果文件42400-IDGH.stl作了改变,管线不会重新执行。可以手动调用方法Modified()以使这些更改生效。这个方法会使得该filter重新执行以及更新它后续的数据。
VTK限制了部分建模功能,如果你想用VTK编辑或者操作复杂的模型(例如,用solid modeler或其他建模工具建立的模型),一般使用文件读取(参考第十二章关于数据读取方面的内容)来导入数据。