第04章-VTK基础(4)

【译者:这个系列教程是以Kitware公司出版的《VTK User’s Guide -11th edition》一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934-23-8)。因为时间关系,我们不能保证每周都能更新本书内容。但尽量做到一周更新一篇到两篇内容。

敬请期待^_^。欢迎转载。另请转载时注明本文出处,谢谢合作!

同一时候,因为译者水平有限,出错之处在所难免,欢迎指出订正。】

【本小节内容相应原书的第52页至第63页】

4.6 控制3D Props

VTK中的渲染窗体渲染的对象通常称之为“Prop”(“Prop”这个词来源于舞台剧,指的是出如今舞台上的东西)。VTK里有几种不同类型的Prop。包含vtkProp3D和vtkActor。

当中vtkProp3D是一个抽象父类。表示的是三维场景中的对象。vtkActor是vtkProp3D的子类。用类似多边形(Polygon)和线(Lines)等基本数据来定义它的几何。

指定vtkProp3D的位置

我们已经知道了怎样绕着一个对象来移动相机;反过来,也能够保持相机不动,而对Prop进行变换。以下的方法能够用于定义一个vtkProp3D(及其子类)对象的位置。

  • SetPosition(x, y, z)—— 指定vtkProp3D对象在世界坐标系中的位置。
  • AddPosition(deltaX,deltaY, deltaZ) —— 用指定的X、Y、Z三个方向的增量来平移Prop。
  • RotateX(theta),RotateY(theta), RotateZ(theta) —— 分别用指定的角度绕X、Y、Z轴旋转Prop。
  • SetOrientation(x, y,z) —— 通过先绕Z轴。然后绕X轴,最后绕Y轴旋转,从而来确定Prop的方向。

  • AddOrientation(a1, a2,a3) —— 在当前Prop方向添加a1,a2, a3增量。

  • RotateWXYZ(theta, x,y, z) —— 绕x, y, z指定的向量旋转theta角度。

  • SetScale(sx, sy, sz)—— 分别沿X、Y、Z三个方向缩放sx,sy, sz比例。
  • SetOrigin(x, y, z) —— 指定Prop的原点,Prop的原点指的是Prop旋转或缩放时的基准点。

以上这些方法联合使用,能够产生复杂的变换矩阵。

最重要的一点是,以上方法使用时要注意它们的调用顺序。不同的顺序对Actor的位置有不同的影响。VTK里是用下面的顺序来应用这些变换的:

1.移动Prop到原点。

2.缩放。

3.绕Y轴旋转。

4.绕X轴旋转。

5.绕Z轴旋转。

6.从原点中移动回原来的位置。

7.平移。

第1步和第6步平移的大小各自是Origin的负值和正值。

单纯的平移是由vtkProp3D的Position值来确定的。

这些变换中最easy混淆的旋转操作。

比如,将一个Prop先绕X旋转。再绕Y轴旋转,它的效果与先绕Y轴旋转,再绕X轴旋转的效果是全然不一样的(图4-4)。

要了解很多其它关于Actor变换内容能够參考《VisualizationToolkit》一书。


图4-4不同旋转顺序的效果。左边是先绕X轴旋转,再绕Y轴旋转的效果;右边是先绕Y轴旋转,再绕X轴旋转的效果

接下来。我们会介绍各种类型的vtkProp3D。当中VTK里最经常使用的类是vtkActor。在“控制vtkActor2D”一节里会介绍一下2DProp (也就是vtkActor2D)。这个类主要应用于标注(Annotation)及其它的二维操作。

Actors

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)。

Level-Of-DetailActors

图形系统一个基本的问题是,交互时有时会变得非常慢。为了解决问题。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。

Assemblies

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的使用方法。

Volumes

类vtkVolume主要用于体绘制,这个类与vtkActor很类似。

vtkVolume从vtkProp3D继承了对Volume进行定位和定向的方法。vtkVolume内部也有一个与它本身相关联的Property对象,即vtkVolumeProperty。请參考第七章“体绘制”了解很多其它的关于vtkVolume的应用以及体绘制方面的内容。

vtkLODProp3D

类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)。

4.7 使用纹理

纹理映射是生成逼真的可视化效果的强大的图形工具。二维纹理映射的基本思想是在渲染过程中,图像能够“贴”到渲染对象的表面上,因此能够创建出细节更加丰富的渲染效果。

纹理映射时须要提供三类信息:待贴纹理图的面、纹理映射(在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会检索图形系统,确定这些图形系统的性能,然后会自己主动地对所设置的纹理图做採样,以求达到特定图形卡的要求。

4.8 拾取

拾取操作是可视化应用程序中常见的一种功能。拾取主要是用于选择数据和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实例的方法。

  • GetProp() —— 返回拾取的vtkProp实例指针。

    假设拾取了某个对象,就返回指向该vtkProp对象的指针,否则返回NULL。

  • GetProp3D() —— 假设拾取的是vtkProp3D对象。则返回该vtkProp3D对象的指针。
  • GetActor2D() —— 假设拾取的是vtkActor2D对象。则返回该vtkActor2D对象的指针。
  • GetActor() —— 假设拾取的是vtkActor对象。则返回该vtkActor对象的指针。

  • GetVolume() —— 假设拾取的是vtkVolume对象。则返回该vtkVolume对象的指针。
  • GetAssembly() —— 假设拾取的是vtkAssembly对象,则返回该vtkAssembly对象的指针。
  • GetPropAssembly() —— 假设拾取的是vtkPropAssembly对象,则返回该vtkPropAssembly对象的指针。

使用这些方法时须要特别注意,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事件发生。

vtkAssemblyPath

在拾取包括不同类型的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()过程。

4.9 vtkCoordinate和坐标系统

VTK支持多种不同类型的坐标系统。类vtkCoordinate管理这些坐标系统之间的变换。支持的坐标系统有:

  • DISPLAY —— X-Y坐标值定义在渲染窗体中,以像素为单位(注意vtkRenderWindow是vtkWindow的子类)。原点在窗体的左下角(这一点对于以下的二维坐标系统都是如此)。
  • NORMALIZED DISPLAY —— 窗体的X-Y坐标取值归一化。即(0,1)。

  • VIEWPORT —— X-Y坐标值定义在视口(Viewport)或者渲染器(Renderer,vtkRenderer是vtkViewport的子类)里。
  • NORMALIZED VIEWPORT ——视口里的X-Y坐标取值归一化,即(0, 1)。
  • VIEW —— X-Y-Z坐标值(取值范围为(-1,1))定义在相机坐标系统,Z表示深度。
  • WORLD —— X-Y-Z为全局坐标值。
  • USERDEFINED —— X-Y-Z定义在用户自己定义的空间里。

    用户必须为自己定义的坐标系统提供空间变换方法。

    请參考类vtkCoordinate了解很多其它信息。

类vtkCoordinate能够用于坐标系统之间的变换,也能够用于连接各个坐标系统以形成“相对”或者“偏移”等坐标值。请參考下一节内容了解vtkCoordinate的使用方法。

4.10 控制vtkActor2D

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对象在渲染窗体中的位置。下一节的内容将会演示怎样使用这种方法。


原文地址:https://www.cnblogs.com/zfyouxi/p/5234459.html