【译者:这个系列教程是以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()方法指定的:

  1. vtkPolyDataMapper mapper
  2. mapper SetInputConnection [aFilter GetOutputPort]
  3. vtkActor anActor
  4. anActor SetMapper mapper

在这个样例里,mapper的类型是vtkPolyDataMapper,也就是用类似点、线、多边形(Polygons)和三角形带(Triangle Strips)等几何图元进行渲染的。Mapper会结束可视化管线。在可视化子系统和图形子系统之间起到桥梁的作用。

Actor的属性。Actor里有一个类型为vtkProperty的实例,主要是用来控制Actor的显示属性。经常使用的属性是Actor的颜色,我们会在后面的内容具体描写叙述。其它的重要属性有显示形式(点模型、线框模型或表面模型)、着色方法(平面着色或Gouraud着色)、Actor的不透明度(相对于透明度)以及环境光、散射光和镜面光颜色等相关參数。以下的脚本程序演示了怎样设置这些变量。

  1. vtkActor anActor
  2. anActor SetMapper mapper
  3. [anActor GetProperty] SetOpacity 0.25
  4. [anActor GetProperty] SetAmbient 0.25
  5. [anActor GetProperty] SetDiffuse 0.6
  6. [anActor GetProperty] SetSpecular 1.0
  7. [anActor GetProperty] SetSpecularPower 10.0

注意,我们通过方法GetProperty()间接引用Actor的属性。或者,我们也能够先实例化一个vtkProperty对象。然后把它设置到Actor中。

  1. vtkProperty prop
  2. prop SetOpacity 0.25
  3. prop SetAmbient 0.5
  4. prop SetDiffuse 0.6
  5. prop SetSpecular 1.0
  6. prop SetSpecularPower 10.0
  7. vtkActor anActor
  8. anActor SetMapper mapper
  9. anActor SetProperty prop

后一种方法的优点是,我们能够把多个Actor设置成同一种属性。

Actor的颜色

颜色可能是Actor里最重要的属性了。设置Actor的颜色最简单的方法莫过于调用SetColor()方法,该方法用RGB值来设置一个Actor的红、绿、蓝分量的颜色,每一个分量的取值范围从0到1。

  1. [anActor GetProperty] SetColor 0.1 0.2 0.4

或者,我们也能够通过设置环境光颜色、散射光颜色和镜面光颜色来控制Actor的颜色。

  1. vtkActor anActor
  2. anActor SetMapper mapper
  3. [anActor GetProperty] SetAmbientColor .1 .1 .1
  4. [anActor GetProperty] SetDiffuseColor .1 .2 .4
  5. [anActor GetProperty] SetSpecularColor 1 1 1

以上代码把环境光颜色设置成深灰色,散射光颜色设置成蓝色的阴影,镜面光颜色设置成白色。

(注意:SetColor()方法就是用指定的RGB值来设置环境光颜色、散射光颜色和镜面光颜色。

)

重要:Actor的属性中关于颜色的设置仅仅有当Actor的Mapper没有标量数据(ScalarData)时才起作用。

缺省情况下,Mapper输入的标量数据会对Actor进行着色,而Actor的颜色设置会被忽略。假设要忽略这些标量数据,能够用法ScalarVisibilityOff(),如以下的Tcl脚本所看到的:

  1. vtkPolyDataMapper planeMapper
  2. planeMapper SetInputConnection [CompPlaneGetOutputPort]
  3. planeMapper ScalarVisibilityOff
  4. vtkActor planeActor
  5. planeActor SetMapper planeMapper
  6. [planeActor GetProperty] SetRepresentationToWireframe
  7. [planeActor GetProperty] SetColor 0 0 0

Actor的透明度。非常多情况下。调整Actor的透明度(或者不透明度)是非常实用的。比方,假设你想显示一个病人图像的内部器官,而器官的外面包括着皮肤。这时你能够调整皮肤的透明度,使得内部器官可见。

能够使用vtkProperty::SetOpacity()方法,例如以下:

  1. vtkActor popActor
  2. popActor SetMapper popMapper
  3. [popActor GetProperty] SetOpacity 0.3
  4. [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个点),例如以下所看到的。

  1. vtkLODActor dotActor
  2. dotActor SetMapper dotMapper
  3. dotActor SetNumberOfCloudPoints 1000

Actor最低分辨率的模型就是一个包围盒。

其它的level-of-detail也能够通过方法AddLODMapper()增加。因为复杂性问题。一般都没有必要增加。

为了控制渲染时Actor所选的level-of-detail,你能够设置渲染窗体的期望渲染帧率

  1. vtkRenderWindow renWin
  2. 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)。

  1. vtkSphereSource sphere
  2. vtkPolyDataMapper sphereMapper
  3. sphereMapper SetInputConnection [sphere GetOutputPort]
  4. vtkActor sphereActor
  5. sphereActor SetMapper sphereMapper
  6. sphereActor SetOrigin 2 1 3
  7. sphereActor RotateY 6
  8. sphereActor SetPosition 2.25 0 0
  9. [sphereActor GetProperty] SetColor 1 0 1
  10.  
  11. vtkCubeSource cube
  12. vtkPolyDataMapper cubeMapper
  13. cubeMapper SetInputConnection [cube GetOutputPort]
  14. vtkActor cubeActor
  15. cubeActor SetMapper cubeMapper
  16. cubeActor SetPosition 0.0 .25 0
  17. [cubeActor GetProperty] SetColor 0 0 1
  18.  
  19. vtkConeSource cone
  20. vtkPolyDataMapper coneMapper
  21. coneMapper SetInputConnection [cone GetOutputPort]
  22. vtkActor coneActor
  23. coneActor SetMapper coneMapper
  24. coneActor SetPosition 0 0 .25
  25. [coneActor GetProperty] SetColor 0 1 0
  26.  
  27. #top part of the assembly
  28. vtkCylinderSource cylinder;
  29. vtkPolyDataMapper cylinderMapper
  30. cylinderMapper SetInputConnection [cylinder GetOutputPort]
  31. cylinderMapper SetResolveCoincidentTopologyToPolygonOffset
  32. vtkActor cylinderActor
  33. cylinderActor SetMapper cylinderMapper
  34. [cylinderActor GetProperty] SetColor 1 0 0
  35.  
  36. #Create the assembly and add the 4 parts to it. Also set the origin, position
  37. #and orientation in space.
  38. vtkAssembly assembly
  39. assembly AddPart cylinderActor
  40. assembly AddPart sphereActor
  41. assembly AddPart cubeActor
  42. assembly AddPart coneActor
  43. assembly SetOrigin 5 10 15
  44. assembly AddPosition 5 0 0
  45. assembly RotateX 15
  46.  
  47. #Create the Renderer, RenderWindow, and RenderWindowInteractor
  48. #
  49. vtkRenderer ren1
  50. vtkRenderWindow renWin
  51. renWin AddRenderer ren1
  52. vtkRenderWindowInteractor iren
  53. iren SetRenderWindow renWin
  54.  
  55. #Add the actors to the renderer, set the background and size
  56. #
  57. ren1 AddActor assembly
  58. 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类来获取理想的交互帧率。下面的样例演示了这个类的使用。

  1. vtkLODProp 3Dlod
  2. set level1 [lod AddLOD volumeMappervolumeProperty2 0.0]
  3. set level2 [lod AddLOD volumeMappervolumeProperty 0.0]
  4. setlevel3 [lod AddLOD probeMapper_hres probeProperty 0.0]
  5. setlevel4 [lod AddLOD probeMapper_lres probeProperty 0.0]
  6. 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平面纹理映射

  1. #Load in the texture map.
  2. vtkBMPReader bmpReader
  3. bmpReader SetFileName"$VTK_DATA_ROOT/Data/masonry.bmp"
  4. vtkTexture atext
  5. atext SetInputConnection [bmpReader GetOutputPort]
  6. atext InterpolateOn
  7.  
  8. #Create a plane source and actor.
  9. vtkPlaneSource plane
  10. vtkPolyDataMapper planeMapper
  11. planeMapper SetInputConnection [plane GetOutputPort]
  12. vtkActor planeActor
  13. planeActor SetMapper planeMapper
  14. planeActor SetTexture atext

非常多时候。纹理坐标是获取不到的,由于这些纹理坐标不能在管线中生成。

假设你须要生成纹理坐标,能够參考第五章“生成纹理坐标”一节。虽然一些老的图形卡在纹理贴图时会有所限制(比方要求所贴的纹理图必须是二维的,并且每维的大小必须小于1024),但VTK支持随意尺寸的纹理图。程序执行时。VTK会检索图形系统,确定这些图形系统的性能,然后会自己主动地对所设置的纹理图做採样,以求达到特定图形卡的要求。

4.8 拾取

拾取操作是可视化应用程序中常见的一种功能。拾取主要是用于选择数据和Actor或者获取底层的数据值。在显示位置(以像素为坐标值)中拾取时,就会调用vtkAbstractPicker的Pick()方法。依赖于所用的拾取类不同,拾取时返回的信息也不同,最简单的是返回一个x-y-z的全局坐标值。或者是单元(cell)的ID值,点的ID值,单元參数坐标(CellParametric Coordinates),所拾取的vtkProp实例,以及Assemblypath。拾取方法的原型是:

  1. 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 带标注信息的拾取操作

  1. vtkCellPicker picker
  2. picker AddObserver EndPickEvent annotatePick
  3.  
  4. #Create a text mapper and actor to display the results of picking.
  5. vtkTextMapper textMapper
  6. settprop [textMapper GetTextProperty]
  7. $tprop SetFontFamilyToArial
  8. $tprop SetFontSize 10
  9. $tprop BoldOn
  10. $tprop ShadowOn
  11. $tprop SetColor 1 0 0
  12. vtkActor2D textActor
  13. textActor VisibilityOff
  14. textActor SetMapper textMapper
  15.  
  16. #Create the Renderer, RenderWindow, and RenderWindowInteractor
  17. #
  18. vtkRenderer ren1
  19. vtkRenderWindow renWin
  20. renWin AddRenderer ren1
  21. vtkRenderWindowInteractor iren
  22. iren SetRenderWindow renWin
  23. iren SetPicker picker
  24.  
  25. #Create a Tcl procedure to create the text for the text mapper used to
  26. #display the results of picking.
  27. proc annotatePick {} {
  28. if { [picker GetCellId] < 0 } {
  29. textActor VisibilityOff
  30.  
  31. } else {
  32. set selPt [picker GetSelectionPoint]
  33. set x [lindex $selPt 0]
  34. set y [lindex $selPt 1]
  35. set pickPos [picker GetPickPosition]
  36. set xp [lindex $pickPos 0]
  37. set yp [lindex $pickPos 1]
  38. set zp [lindex $pickPos 2]
  39.  
  40. textMapper SetInput "($xp, $yp,$zp)"
  41. textActor SetPosition $x $y
  42. textActor VisibilityOn
  43. }
  44.  
  45. renWin Render
  46. }
  47.  
  48. #Pick the cell at this location.
  49. 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对象。

  1. vtkActor2D bannerActor
  2. bannerActor SetMapper banner
  3. [bannerActor GetProperty] SetColor 0 1 0
  4. [bannerActor GetPositionCoordinate]SetCoordinateSystemToNormalizedDisplay
  5. [bannerActor GetPositionCoordinate] SetValue0.5 0.5

在这个样例中。訪问了坐标对象以及定义了它的坐标系统,然后设置了该坐标系统下合适的坐标值。

这个样例中。使用了归一化显示坐标系统(Normalized DisplayCoordinate System)。因此坐标范围定义为0到1。坐标值(0.5,0.5)就设置vtkActor2D对象在渲染窗体的中间位置。

vtkActor2D也提供了一个方便的接口。SetDisplayPosition()能够设置坐标系统为DISPLAY,而且利用传入的參数(以像素为单位)设置vtkActor2D对象在渲染窗体中的位置。下一节的内容将会演示怎样使用这种方法。

第04章-VTK基础(4)的更多相关文章

  1. 第04章-VTK基础(7)

    [译者:这个系列教程是以Kitware公司出版的<VTK User's Guide -11th edition>一书作的中文翻译(出版时间2010年.ISBN: 978-1-930934- ...

  2. 第04章-VTK基础(3)

    [译者:这个系列教程是以Kitware公司出版的<VTK User's Guide -11th edition>一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934- ...

  3. 第04章-VTK基础(2)

    [译者:这个系列教程是以Kitware公司出版的<VTK User's Guide -11th edition>一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934- ...

  4. python数据分析---第04章 NumPy基础:数组和矢量计算

    NumPy(Numerical Python的简称)是Python数值计算最重要的基础包.大多数提供科学计算的包都是用NumPy的数组作为构建基础. NumPy的部分功能如下: ndarray,一个具 ...

  5. 【学习笔记】 第04章 NumPy基础:数组和矢量计算

    前言 正式开始学习Numpy,参考用书是<用Python进行数据清洗>,计划本周五之前把本书读完,关键代码全部实现一遍 NumPy基础:数组和矢量计算 按照书中所示,要搞明白具体的性能差距 ...

  6. &lt;&lt;Python基础教程&gt;&gt;学习笔记 | 第04章 | 字典

    第04章:字典 当索引不好用时 Python唯一的内建的映射类型,无序,但都存储在一个特定的键中.键能够使字符.数字.或者是元祖. ------ 字典使用: 表征游戏棋盘的状态,每一个键都是由坐标值组 ...

  7. 《Python学习手册 第五版》 -第16章 函数基础

    前面的章节讲解的是一些基础数据类型.基本语句使用和一些文档查看的内容,这些都是一些基础,其实还谈不上入门,只有了解了函数,才算入门 函数是编程里面使用最多的也是最基本的程序结构, 本章重点内容 1.函 ...

  8. 异步编程系列第04章 编写Async方法

    p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...

  9. 《利用python进行数据分析》读书笔记--第四章 numpy基础:数组和矢量计算

    http://www.cnblogs.com/batteryhp/p/5000104.html 第四章 Numpy基础:数组和矢量计算 第一部分:numpy的ndarray:一种多维数组对象 实话说, ...

随机推荐

  1. 自定义seekbar中,thumb被覆盖掉一部分问题

  2. Dalvik虚拟机Java堆创建过程分析

    文章转载至罗升阳CSDN社区博客,原地址: http://blog.csdn.net/luoshengyang/article/details/6557518 近年来,手机移动平台越来越火爆.打开自己 ...

  3. python - 面向对象(一)

    python是一门面向对象的编程语言,python中的一切均是对象. 有对象就提到类,对象和类就像是儿子和老子的关系,是不可分的一对. 什么是类     类就是具有一些共同特性的事物的统称.好比人类, ...

  4. 豆瓣移动端风格的css命名方法与学习

    在CSS取名相对于刚入门来说是最头疼的事情,往往取一个可读性的名字相对以后的代码风格还是很重要的. 在配合团队方面一个好的类名可以帮助同事来理解,增加团队之间的效率有着很大的意义. 豆瓣的前段相对其他 ...

  5. Katana概述

    OWIN owin是web services和framework组件之间的抽象.抽象包括两个核心要素: environment dictionary 这个数据结构存储处理HTTP请求必须的状态和相关的 ...

  6. mysql查询分组归类函数-group_concat,通常与group_by一起使用

    select a.`name`,group_concat(b.name SEPARATOR'.') as persons from `group` as a,`person` as b,`person ...

  7. MFC中使用ADO方式连接数据库

    文章转自:http://blog.sina.com.cn/s/blog_a43aba5601014z8h.html 一.数据库操作准备 1.导入ADO动态链接库 在工程的stdafx.h中加入如下语句 ...

  8. jQuery插件学习(一)

    由于项目开发需要,经常会用到一些jquery插件,但网上已有的插件常常又不能100%满足业务需求,所以就想自己能看懂插件的代码,进行一些功能上的改动和补充,或者能自己自定义插件就更好了.所以这段时间会 ...

  9. Hough Transform直线检测

    本文原创,如转载请注明出处. Hough Transform 是一种能提取图像中某种特定形状特征的方法,可以将其描述成一种把图像空间中的像素转换成Hough空间中直线或曲线的一种映射函数.通过利用Ho ...

  10. web后台获取不到session中的值(loading sessions from persistent storage),后改用JS传值

    线上的程序似乎从session中取不到domain数据,重启了一下tomcat查看log日志发现,居然有报错.错误信息如下 22-Sep-2016 00:52:16.562 SEVERE [local ...