第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對象在渲染窗體中的位置。下一節的內容將會演示怎樣使用這種方法。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM