VTK中的渲染窗口渲染的对象通常称之为“Prop”(“Prop”这个词来源于舞台剧,指的是出现在舞台上的东西)。VTK里有几种不同类型的Prop,包括vtkProp3D和vtkActor。其中vtkProp3D是一个抽象父类,表示的是三维场景中的对象;vtkActor是vtkProp3D的子类,用类似多边形(Polygon)和线(Lines)等基本数据来定义它的几何。
我们已经知道了如何绕着一个对象来移动相机;反过来,也可以保持相机不动,而对Prop进行变换。下面的方法可以用于定义一个vtkProp3D(及其子类)对象的位置。
以上这些方法联合使用,可以产生复杂的变换矩阵。最重要的一点是,以上方法使用时要注意它们的调用顺序,不同的顺序对Actor的位置有不同的影响。VTK里是用以下的顺序来应用这些变换的:
1.移动Prop到原点。
2.缩放。
3.绕Y轴旋转。
4.绕X轴旋转。
5.绕Z轴旋转。
6.从原点中移动回原来的位置。
7.平移。
第1步和第6步平移的大小分别是Origin的负值和正值。单纯的平移是由vtkProp3D的Position值来确定的。这些变换中最容易混淆的旋转操作。例如,将一个Prop先绕X旋转,再绕Y轴旋转,它的效果与先绕Y轴旋转,再绕X轴旋转的效果是完全不一样的(图4-4)。要了解更多关于Actor变换内容可以参考《VisualizationToolkit》一书。
图4-4不同旋转顺序的效果。左边是先绕X轴旋转,再绕Y轴旋转的效果;右边是先绕Y轴旋转,再绕X轴旋转的效果
接下来,我们会介绍各种类型的vtkProp3D,其中VTK里最常用的类是vtkActor。在“控制vtkActor2D”一节里会介绍一下2DProp (也就是vtkActor2D),这个类主要应用于标注(Annotation)及其他的二维操作。
Actor是最常的vtkProp3D类型,像其他的vtkProp3D子类一样,vtkActor提供了一组渲染属性,如表面属性(如环境光、散射光和镜面光颜色),显示形式(Representation)(如表面模型或线框模型),纹理映射以及几何定义(即mapper)。
定义几何。前面的例子我们已经知道,一个Actor的几何是通过SetMapper()方法指定的:
vtkPolyDataMapper mapper
mapper SetInputConnection [aFilter GetOutputPort]
vtkActor anActor
anActor SetMapper mapper
在这个例子里,mapper的类型是vtkPolyDataMapper,也就是用类似点、线、多边形(Polygons)和三角形带(Triangle Strips)等几何图元进行渲染的。Mapper会结束可视化管线,在可视化子系统和图形子系统之间起到桥梁的作用。
Actor的属性。Actor里有一个类型为vtkProperty的实例,主要是用来控制Actor的显示属性。常用的属性是Actor的颜色,我们会在后面的内容详细描述。其他的重要属性有显示形式(点模型、线框模型或表面模型)、着色方法(平面着色或Gouraud着色)、Actor的不透明度(相对于透明度)以及环境光、散射光和镜面光颜色等相关参数。下面的脚本程序演示了如何设置这些变量。
vtkActor anActor
anActor SetMapper mapper
[anActor GetProperty] SetOpacity 0.25
[anActor GetProperty] SetAmbient 0.25
[anActor GetProperty] SetDiffuse 0.6
[anActor GetProperty] SetSpecular 1.0
[anActor GetProperty] SetSpecularPower 10.0
注意,我们通过方法GetProperty()间接引用Actor的属性。或者,我们也可以先实例化一个vtkProperty对象,然后把它设置到Actor中。
vtkProperty prop
prop SetOpacity 0.25
prop SetAmbient 0.5
prop SetDiffuse 0.6
prop SetSpecular 1.0
prop SetSpecularPower 10.0
vtkActor anActor
anActor SetMapper mapper
anActor SetProperty prop
后一种方法的好处是,我们可以把多个Actor设置成同一种属性。
Actor的颜色。颜色可能是Actor里最重要的属性了。设置Actor的颜色最简单的方法莫过于调用SetColor()方法,该方法用RGB值来设置一个Actor的红、绿、蓝分量的颜色,每个分量的取值范围从0到1。
[anActor GetProperty] SetColor 0.1 0.2 0.4
或者,我们也可以通过设置环境光颜色、散射光颜色和镜面光颜色来控制Actor的颜色。
vtkActor anActor
anActor SetMapper mapper
[anActor GetProperty] SetAmbientColor .1 .1 .1
[anActor GetProperty] SetDiffuseColor .1 .2 .4
[anActor GetProperty] SetSpecularColor 1 1 1
以上代码把环境光颜色设置成深灰色,散射光颜色设置成蓝色的阴影,镜面光颜色设置成白色。(注意:SetColor()方法就是用指定的RGB值来设置环境光颜色、散射光颜色和镜面光颜色。)
重要:Actor的属性中关于颜色的设置只有当Actor的Mapper没有标量数据(ScalarData)时才起作用。缺省情况下,Mapper输入的标量数据会对Actor进行着色,而Actor的颜色设置会被忽略。如果要忽略这些标量数据,可以使用方法ScalarVisibilityOff(),如下面的Tcl脚本所示:
vtkPolyDataMapper planeMapper
planeMapper SetInputConnection [CompPlaneGetOutputPort]
planeMapper ScalarVisibilityOff
vtkActor planeActor
planeActor SetMapper planeMapper
[planeActor GetProperty] SetRepresentationToWireframe
[planeActor GetProperty] SetColor 0 0 0
Actor的透明度。很多情况下,调整Actor的透明度(或者不透明度)是很有用的。比如,如果你想显示一个病人图像的内部器官,而器官的外面包含着皮肤,这时你可以调整皮肤的透明度,使得内部器官可见。可以使用vtkProperty::SetOpacity()方法,如下:
vtkActor popActor
popActor SetMapper popMapper
[popActor GetProperty] SetOpacity 0.3
[popActor GetProperty] SetColor .9 .9 .9
要注意透明度的实现是使用渲染库里的α-Blending处理技术。这种处理技术要求以正确的顺序来渲染多边形(Polygons)。实际上,这是很难做到的,特别是当你有多个透明的Actor需要渲染时。要对多边形排序,应该把透明的Actor加到待渲染的Actor列表的最后。你也可以用vtkDepthSortPolyData这个Filter沿着视向量方向对多边形排序。关于这个Filter用法,可以参考VTK/Examples/VisualizationAlgorithm/Tcl/DepthSort.tcl这个例子。更多关于这方面的内容可以参考本章的“透明多边形几何”(Translucentpolygonal geometry)一节。
其他的属性。Actor还有其他一些重要的属性。你可以用方法VisibilityOn()/VisibilityOff()来控制Actor的可见与不可见。如果在拾取过程中,不想某个Actor被拾取,可以使用方法PickableOff()关闭拾取属性(关于拾取方面的内容,可以参考本章的“拾取”一节)。Actor有一个拾取事件(PickEvent),当它们被拾取时就会调用这个事件。另外,方法GetBounds()可以获取与坐标轴对齐的Actor的包围盒(BoundingBox)。
图形系统一个主要的问题是,交互时有时会变得很慢。为了解决这个问题,VTK使用Level-of-detail技术,在与数据交互时,以低分辨率的显示形式(Representation)来表示Actor以求达到更快的渲染速度。
在本章的“读取源对象”(Reader SourceObject)一节,我们已经使用了vtkLODActor类。基本上,最简单的方法就是用vtkLODActor实例来替代vtkActor实例。另外,你也可以控制Level-of-detail的显示形式(Representation)。vtkLODActor缺省的做法是利用原始的Mapper创建另外两个低分辨率的模型。第一个是从定义Mapper输入的点采样得到的点云。你可以控制点云里点的个数(缺省是150个点),如下所示。
vtkLODActor dotActor
dotActor SetMapper dotMapper
dotActor SetNumberOfCloudPoints 1000
Actor最低分辨率的模型就是一个包围盒。其他的level-of-detail也可以通过方法AddLODMapper()加入,由于复杂性问题,一般都没有必要加入。
为了控制渲染时Actor所选的level-of-detail,你可以设置渲染窗口的期望渲染帧率:
vtkRenderWindow renWin
renWin SetDesiredUpdateRate 5.0
这样,就会以每秒5帧的速率进行渲染。vtkLODActor会自动地选择合适的Level-of-detail来达到请求的渲染速率。(注意:类似vtkRenderWindowInteractor等交互器,会自动地控制期望渲染帧率(DesiredUpdate Rate),一般的做法是,当鼠标松开时,会把帧率设置得很低,而鼠标按下时,则会提高相应的帧率。这样就能保证相机运动时产生低分辨率/高帧率,而相机停止时产生高分辨率/低帧率的理想效果。如果你想了解更多关于Level-of-detail的控制方面的内容,可以参考本章的“vtkLODProp3D”一节,通过这个类,可以指定不同的Level。)
Actors有时也会组合在一起形成层次结构,当其中的某个Actor运动时,会影响到其他Actor的位置。例如,一个机械手臂可能由上臂、前臂、手腕和末端等部分通过关节连接起来。当上臂绕着肩关节旋转时,我们希望的是其他部分也会跟着运动。这种行为的实现就要用到Assembly,vtkAssembly是vtkActor的子类。下面的程序演示了如何使用vtkAssembly(摘自VTK/Examples/Rendering/Tcl/assembly.tcl)。
vtkSphereSource sphere
vtkPolyDataMapper sphereMapper
sphereMapper SetInputConnection [sphere GetOutputPort]
vtkActor sphereActor
sphereActor SetMapper sphereMapper
sphereActor SetOrigin 2 1 3
sphereActor RotateY 6
sphereActor SetPosition 2.25 0 0
[sphereActor GetProperty] SetColor 1 0 1
vtkCubeSource cube
vtkPolyDataMapper cubeMapper
cubeMapper SetInputConnection [cube GetOutputPort]
vtkActor cubeActor
cubeActor SetMapper cubeMapper
cubeActor SetPosition 0.0 .25 0
[cubeActor GetProperty] SetColor 0 0 1
vtkConeSource cone
vtkPolyDataMapper coneMapper
coneMapper SetInputConnection [cone GetOutputPort]
vtkActor coneActor
coneActor SetMapper coneMapper
coneActor SetPosition 0 0 .25
[coneActor GetProperty] SetColor 0 1 0
#top part of the assembly
vtkCylinderSource cylinder;
vtkPolyDataMapper cylinderMapper
cylinderMapper SetInputConnection [cylinder GetOutputPort]
cylinderMapper SetResolveCoincidentTopologyToPolygonOffset
vtkActor cylinderActor
cylinderActor SetMapper cylinderMapper
[cylinderActor GetProperty] SetColor 1 0 0
#Create the assembly and add the 4 parts to it. Also set the origin, position
#and orientation in space.
vtkAssembly assembly
assembly AddPart cylinderActor
assembly AddPart sphereActor
assembly AddPart cubeActor
assembly AddPart coneActor
assembly SetOrigin 5 10 15
assembly AddPosition 5 0 0
assembly RotateX 15
#Create the Renderer, RenderWindow, and RenderWindowInteractor
#
vtkRenderer ren1
vtkRenderWindow renWin
renWin AddRenderer ren1
vtkRenderWindowInteractor iren
iren SetRenderWindow renWin
#Add the actors to the renderer, set the background and size
#
ren1 AddActor assembly
ren1 AddActor coneActor
注意是如何使用vtkAssembly里的方法AddPart()来建立层次结构的。只要不是自我嵌套,Assembly可以组合成任意层次深度的结构。vtkAssembly是vtkProp3D的子类,但没有与之相关联的Property以及Mapper。因此,vtkAssembly层次结构里的结点必须要包含关于材料的属性(如颜色等)及其他相关的几何信息。一个Actor可以用于多个Assembly(注意以上例子中的coneActor是如何作为一个单独的Actor以及作为Assembly里的一个节点的)。通过渲染器里的方法AddActor()只要加入最顶层的Assembly,而低层次的Assembly不用加入,因为它们会递归加入到渲染器中。
如果一个Actor加入到多个Assembly时(就像上面的例子),你可以会想到如何去区分不同的Actor。(关于这一点,在类似“拾取”操作时是非常重要的,因为你必须要区分一下到底哪个vtkProp对象是处于选中的姿态。)我们会在后面的“拾取”一节,详细讨论这个问题,以及介绍类vtkAssemblyPath的用法。
类vtkVolume主要用于体绘制,这个类与vtkActor非常类似。vtkVolume从vtkProp3D继承了对Volume进行定位和定向的方法。vtkVolume内部也有一个与它本身相关联的Property对象,即vtkVolumeProperty。请参考第七章“体绘制”了解更多的关于vtkVolume的应用以及体绘制方面的内容。
类vtkLODProp3D与vtkLODActor(参考本章“Level-Of-DetailActors”一节)类似,也是使用不同的显示形式(Representation)来表示它本身,以求达到更佳的交互渲染速率。与vtkLODActor不同的是,vtkLODProp3D只支持体绘制和面绘制。也就是说,你只能够在体绘制应用程序中使用vtkLODProp3D类来获取理想的交互帧率。以下的例子演示了这个类的使用。
vtkLODProp 3Dlod
set level1 [lod AddLOD volumeMappervolumeProperty2 0.0]
set level2 [lod AddLOD volumeMappervolumeProperty 0.0]
setlevel3 [lod AddLOD probeMapper_hres probeProperty 0.0]
setlevel4 [lod AddLOD probeMapper_lres probeProperty 0.0]
setlevel5 [lod AddLOD outlineMapper outlineProperty 0.0]
基本上,根据不同的渲染复杂度,会创建不同的Mapper,并把它设置到vtkLODProp3D里。AddLOD()方法可以接收Volume或几何类型的Mapper作为参数,可选的参数包括纹理映射、属性对象等。(根据提供的信息不同,该方法会有不同的函数签名(Signatures)。)AddLOD()方法的最后一个参数是渲染的估计时间。一般情况下都设置为0,即没有针对渲染的初始估计值。该方法返回一个整型的ID值,利用这个值就可以访问对应的LOD(可以用来选择某一Level或者删除某一Level)。
纹理映射是生成逼真的可视化效果的强大的图形工具。二维纹理映射的基本思想是在渲染过程中,图像可以“贴”到渲染对象的表面上,因此可以创建出细节更加丰富的渲染效果。纹理映射时需要提供三类信息:待贴纹理图的面、纹理映射(在VTK里,其实就是vtkImageData类型的数据,即2D图像)以及纹理坐标(控制纹理图在面上的位置)。
下面的例子演示了如何使用纹理映射(完整的程序代码见VTK/Examples/Rendering/Tcl/TPlane.tcl)。要注意纹理映射(类vtkTexture)是与Actor相联的,而纹理坐标则是由平面来定义(纹理坐标是由类vtkPlaneSource创建的)。
图4-5平面纹理映射
#Load in the texture map.
vtkBMPReader bmpReader
bmpReader SetFileName"$VTK_DATA_ROOT/Data/masonry.bmp"
vtkTexture atext
atext SetInputConnection [bmpReader GetOutputPort]
atext InterpolateOn
#Create a plane source and actor.
vtkPlaneSource plane
vtkPolyDataMapper planeMapper
planeMapper SetInputConnection [plane GetOutputPort]
vtkActor planeActor
planeActor SetMapper planeMapper
planeActor SetTexture atext
很多时候,纹理坐标是获取不到的,因为这些纹理坐标不能在管线中生成。如果你需要生成纹理坐标,可以参考第五章“生成纹理坐标”一节。尽管一些老的图形卡在纹理贴图时会有所限制(比如要求所贴的纹理图必须是二维的,而且每维的大小必须小于1024),但VTK支持任意尺寸的纹理图。程序运行时,VTK会检索图形系统,确定这些图形系统的性能,然后会自动地对所设置的纹理图做采样,以求达到特定图形卡的要求。
拾取操作是可视化应用程序中常见的一种功能。拾取主要是用于选择数据和Actor或者获取底层的数据值。在显示位置(以像素为坐标值)中拾取时,就会调用vtkAbstractPicker的Pick()方法。依赖于所用的拾取类不同,拾取时返回的信息也不同,最简单的是返回一个x-y-z的全局坐标值,或者是单元(cell)的ID值,点的ID值,单元参数坐标(CellParametric Coordinates),所拾取的vtkProp实例,以及Assemblypath。拾取方法的原型是:
Pick(selectionX,selectionY, selectionZ, Renderer)
注意Pick()方法需要一个渲染器作为参数。与渲染器相关联的Actor都是拾取的候选对象。另外,selectionZ通常都设置为0.0,它是与Z-buffer相关的值。(一般,Pick()这个方法都不会直接去调用它,用户使用vtkRenderWindowInteractor进行交互时,由这个类来管理拾取操作。这种情况下,用户只要选择一个拾取实例,让这个实例来控制拾取过程即可,后面的例子会演示如何使用。)
VTK支持多种不同功能的拾取类型(请参考图19-16,列出了与拾取相关的类的继承图)。类vtkAbstractPicker是所有拾取类的基类,它定义了一些公用的API,允许用户通过方法GetPickPosition()来获取拾取位置(全局坐标下)。
vtkAbstractPicker有两个直接子类。第一个是vtkWorldPointPicker,这是一种使用Z-buffer快速返回所拾取的位置的x-y-z全局坐标的类(基于硬件的),但不会返回其他的信息(比如到底拾取了哪一个vtkProp实例等)。类vtkAbstractPropPicker是从vtkAbstractPicker中直接派生的另外一个子类。它定义了可以用于拾取某个vtkProp实例的API。下面列出一些比较方便的用于获取vtkProp实例的方法。
使用这些方法时需要特别注意,vtkAbstractPropPicker及其子类拾取时返回的是最顶层的Assembly路径(top level of theassembly path)。因此,如果有一个顶层类型是vtkAssembly的Assembly对象,其叶结点类型是vtkActor时,使用方法GetAssembly()返回的是指向vtkAssembly对象的指针,而使用方法GetActor()返回则是空指针。如果有一个包含Assembly、Actor及其他类型的Prop的复杂场景时,最安全的方法是使用GetProp()来确定所拾取的对象,再使用GetPath()方法。
类vtkAbstractPropPicker有三个直接子类,分别是:vtkPropPicker、vtkAreaPicker及vtkPicker。vtkPropPicker使用硬件拾取的策略来确定所拾取的vtkProp实例,包括拾取点的世界坐标系下的位置坐标。vtkPropPicker通常比vtkAbstractPropPicker的其他子类的速度要快,但是它不能返回所拾取对象的详细信息。
vtkAreaPicker及其基于硬件实现的子类vtkRenderedAreaPicker同样无法确定所拾取对象的详细信息,它们的作用是选择屏幕上的对象。vtkAreaPicker及其子类与其他的拾取类不同,前者可以确定哪些是位于屏幕上矩阵区域的像素的开始位置,而不仅仅确定哪些是位于某个像素的后方。这些类都有方法AreaPick(x_min, y_min,x_max, y_max, Renderer),可以与标准的方法Pick(x,y,z,Renderer)一起使用。如果想获取更多的信息,比如确定位于某个区域后方的单元或点等信息,可以参考本节后续内容的介绍。
vtkPicker是一个基于软件实现的拾取类,具体实现是基于vtkProp对象的包围盒来拾取对象。该类在拾取时,会从相机的当前位置投射一条光线到拾取点,所投射的光线会与某个Prop3D对象的包围盒相交,当然,通过这种方式有可能会有多个的Prop3D对象被拾取到,最后返回的是所投射的光线与对象的包围盒相交最多的Prop3D。而方法GetProp3Ds()可以返回与投射光线相交的所有的Prop3D对象。vtkPicker拾取速度相对较快,但无法获取单一的拾取。
vtkPicker有两个子类,通过这两个子类可以获取所拾取对象更多详细的信息,比如,点的ID,单元的ID等。vtkPointPicker用于拾取单个点,返回其ID值和坐标值。拾取时,vtkPointPicker也是通过从相机当前位置投射一条光线至拾取点,然后将光线周围且位于容差(Tolerance)范围内的点投射至光线上,最后返回的是距离相机最近的点以及该点所对应的Actor对象。(注意:容差是用渲染窗口的对角线的长度作为分数的。)vtkPointPicker比vtkPicker拾取速度要慢,但比vtkCellPicker要快。因为引入的容差,所以vtkPointPicker可以返回单一的拾取对象。
vtkCellPicker用于拾取某个单元,并返回交点的信息,比如,交点所对应的单元ID、全局坐标以及参数化单元坐标(Parametric cellcoordinates)。与vtkPointPicker类似,vtkCellPicker拾取时也是投射一条光线至拾取点,在一定的容差范围内确定光线是否与Actor底层的几何相交,最后返回的就是沿着光线最靠近相机的单元及其对应的对象。(注意:在确定光线是否与单元相交时会使用到容差,可能需要多次实验才能获得满意的结果。)vtkCellPicker是所有拾取类中速度最慢的一个,但是所获取的信息也是最多的。通过指定容差,可以返回单一的拾取对象。
VTK定义了与拾取操作相关的几个事件。拾取操作发生之前会调用StartPickEvent事件,拾取完成后则调用EndPickEvent事件。当对象被拾取时会调用Picker类的PickEvent事件以及Actor类的PickEvent事件。注意:使用vtkWorldPointPicker类时,不会有PickEvent事件发生。
在拾取包含不同类型的vtkProp对象的场景时,有必要理解类vtkAssemblyPath,特别是当场景中包含有vtkAssembly对象。vtkAssemblyPath简单地可以理解为包含vtkAssemblyNode的顺序列表,每个结点含有一个指向vtkProp对象的指针以及一个可选的vtkMatrix4x4对象。列表的顺序非常重要,列表的开始是根结点或者说是Assembly层次结构的顶层结点,列表的结尾表示Assembly层次结构的叶结点。结点的顺序会影响到与之关联的矩阵。每个矩阵是列表里结点的Prop所对应的矩阵与前一个矩阵的级联。因此,对于某个给定的vtkAssemblyNode,所关联的vtkMatrix4x4表示的是该结点的vtkProp对象的位置和方向(假设vtkProp对象初始状态是没有经过变换的)。
通常,拾取是由vtkRenderWindowInteractor自动管理的(见“使用VTK交互器”一节了解更多关于交互器的内容)。比如,当按下P键时,vtkRenderWindowInteractor会调用内部的vtkPropPicker实例执行拾取操作。接着,可以通过vtkRenderWindowInteractor访问拾取器(Picker)或者其他信息。也可以给vtkRenderWindowInteractor指定一个从vtkAbstractPicker派生的拾取器。图4-6显示了对数据集拾取的结果,程序代码摘自VTK/Examples/Annotation/Tcl/annotationPick.tcl。
图4-6 带标注信息的拾取操作
vtkCellPicker picker
picker AddObserver EndPickEvent annotatePick
#Create a text mapper and actor to display the results of picking.
vtkTextMapper textMapper
settprop [textMapper GetTextProperty]
$tprop SetFontFamilyToArial
$tprop SetFontSize 10
$tprop BoldOn
$tprop ShadowOn
$tprop SetColor 1 0 0
vtkActor2D textActor
textActor VisibilityOff
textActor SetMapper textMapper
#Create the Renderer, RenderWindow, and RenderWindowInteractor
#
vtkRenderer ren1
vtkRenderWindow renWin
renWin AddRenderer ren1
vtkRenderWindowInteractor iren
iren SetRenderWindow renWin
iren SetPicker picker
#Create a Tcl procedure to create the text for the text mapper used to
#display the results of picking.
proc annotatePick {} {
if { [picker GetCellId] < 0 } {
textActor VisibilityOff
} else {
set selPt [picker GetSelectionPoint]
set x [lindex $selPt 0]
set y [lindex $selPt 1]
set pickPos [picker GetPickPosition]
set xp [lindex $pickPos 0]
set yp [lindex $pickPos 1]
set zp [lindex $pickPos 2]
textMapper SetInput "($xp, $yp,$zp)"
textActor SetPosition $x $y
textActor VisibilityOn
}
renWin Render
}
#Pick the cell at this location.
picker Pick 85 126 0 ren1
这个例子使用vtkTextMapper在屏幕上绘制拾取点的世界坐标值。(参考“文本标注”一节了解更多信息)。注意到在这个例子中,我们注册了EndPickEvent事件,拾取操作完成后,就会调用annotatePick()过程。
VTK支持多种不同类型的坐标系统,类vtkCoordinate管理这些坐标系统之间的变换。支持的坐标系统有:
类vtkCoordinate可以用于坐标系统之间的变换,也可以用于连接各个坐标系统以形成“相对”或者“偏移”等坐标值。请参考下一节内容了解vtkCoordinate的用法。
vtkActor2D与vtkActor很多功能都类似,除了vtkActor2D是在层叠(overlay)平面上绘制的以及没有与之相关联的4×4的变换矩阵。与vtkActor类似,vtkActor2D涉及到一个mapper(即vtkMapper2D)和属性对象(即vtkProperty2D)。使用vtkActor2D时,比较困难的部分是如何定位它的对象。定位vtkActor2D对象时会用到类vtkCoordinate(请参考上一部分“vtkCoordinate和坐标系统”一节)。下面的例子演示了如何使用vtkCoordinate对象。
vtkActor2D bannerActor
bannerActor SetMapper banner
[bannerActor GetProperty] SetColor 0 1 0
[bannerActor GetPositionCoordinate]SetCoordinateSystemToNormalizedDisplay
[bannerActor GetPositionCoordinate] SetValue0.5 0.5
在这个例子中,访问了坐标对象以及定义了它的坐标系统,然后设置了该坐标系统下合适的坐标值。这个例子中,使用了归一化显示坐标系统(Normalized DisplayCoordinate System),因此坐标范围定义为0到1,坐标值(0.5,0.5)就设置vtkActor2D对象在渲染窗口的中间位置。vtkActor2D也提供了一个方便的接口,SetDisplayPosition()可以设置坐标系统为DISPLAY,并且利用传入的参数(以像素为单位)设置vtkActor2D对象在渲染窗口中的位置。下一节的内容将会演示如何使用这个方法。