本章概述了VTK庫。您將學習使用VTK所必需的基本思想,包括:對VTK管道的理解;用於讀取和過濾數據的重要對象;然後,如何安排和渲染模型。後面的章節將進一步擴展有關可視化標量和張量場,操縱網格和3D幾何以及爲可視化增加交互性的內容。
內容
高層概述
安裝
VTK管道
示例:渲染一個簡單的字形
VTK中的數據
使用和創建多數據
查找表
默認查詢表
創建漸變時指定自定義顏色範圍
創建任意的顏色映射
示例:創建自定義查找表
轉變
示例:3D繪圖腳本
關於顏色的註釋
重要命令
高層概述
VTK是用C ++實現的,但已設計爲允許綁定到其他幾種語言。這意味着可以使用多種語言來使用VTK。這些包括Java,Tcl,當然還有Python。您將獲得C ++的性能,因爲它仍然由C ++驅動可視化,但是易於使用您喜歡的語言-在這種情況下爲Python。VTK提供了一套工具,可以讀取幾乎任何種類的科學數據,包括任何格式/結構,過濾數據,然後在3D圖形環境中進行渲染。
安裝
VTK可以通過單個pip
命令安裝:
pip install vtk
並且只需要一個import語句即可從Python內部使用該庫:
import vtk
VTK管道
使用VTK的關鍵是構造管道。大多數應用程序在創建管道時都會經歷相似的階段。在大約4個常規步驟中,這些步驟是:
讀取數據:可視化需要數據才能可視化!
過濾和處理數據:將數據讀入管道後,通常需要對其進行進一步的處理和操縱,然後才能將其打包到actor中。
根據這些數據創建actor並將它們組合到場景中:將數據和幾何圖形打包到actor中(不用擔心,有關此內容的更多信息,請參見下文)。
將幾何圖形組裝成最終渲染:放置上述角色,並渲染交互式3D環境。
您現在可能已經知道,VTK在描述渲染環境時使用了劇院/電影背景的隱喻。VTK管道的早期階段的目標是讀取數據-包括有關模型幾何的信息-並將其打包爲參與者。角色是對象的實例,其中包括渲染所需的所有信息(如何執行此操作將在下面說明)。這些演員將由您安排在場景中並進行渲染。VTK創建的場景是交互式的。用戶將能夠四處移動並旋轉對象。如果編程到可視化中,則可以剪切,移動或以其他方式操縱這些角色,以精確獲得用戶最感興趣的幾何部分。
圖1. VTK可視化和渲染管道。
上面顯示了此VTK管道的基本輪廓。流程圖中的每個步驟將對應於從VTK庫實例化的至少一個對象,可能還對應於幾個對象。這樣,與本節上方的列表相比,圖1可以更好地映射到您需要構造的實際管道和需要創建的對象。
VTK文檔區分了可視化管道和渲染管道。VTK文檔中的這種區別有點用詞不當,因爲渲染是創建可視化的重要步驟。創建演員後,重點便放在渲染上。當使用術語可視化管道或渲染管道時,它們指的是圖1中所示的那些部分。術語VTK管道將指整個管道。否則,可視化將在一般意義上指的是可視化我們的數據的過程的每個部分。
將可視化管道中的各個階段鏈接在一起
爲了進一步解釋圖1,我們從數據源開始。下一節將介紹更多數據,但是現在我們注意到,每個可視化都必須從可視化讀取和處理的某些數據源開始。VTK中已經實現了許多格式。讀取數據後,將其連接到管道的下一個階段。將過濾器連接到管道中的過程是理解VTK及其工作方式的核心。
過濾器是一種以某種方式轉換數據的算法。它們的使用是可選的,但是在構建可視化管道時,您可能會使用其中的幾個。有了數據後,您可以使用以下VTK慣用法將其連接到管道中的下一步:filter2.SetInputConnection(filter1.GetOutputPort())
。此處的輸出filter1
連接到的輸入filter2
。這些過濾器通過這種方式鏈接在一起以創建管道。
延遲更新
如上圖所示,將過濾器鏈接在一起時,它們實際上不會在該步驟中處理任何數據。取而代之的是,僅連接了這些過濾器。它們對數據的計算僅在管道的更深層發出請求時才進行,通常是在呈現可視化的那一刻。評估是懶惰的,因此僅在需要時才進行評估。調用更新時,更新將向上移動到管道,然後將處理後的數據向下移動到管道的呈現步驟。
建議將這種將過濾器與延遲評估鏈接在一起的方法是創建管道的推薦方法。某些對象具有一種方法.SetInputData(data)
,該方法只讀取一次輸入數據的源,並且如果對數據源進行了更改,則不會自動更新。如果期望更改該數據,則不應使用此方法。
示例:渲染一個簡單的字形
圖2.渲染一個圓錐體。
讓我們從一個簡單的例子開始。以下是“ hello world”的VTK版本。我們將以3D渲染單個圓錐。儘管很簡單,但它將逐步創建渲染管道。一旦理解,創建非常複雜的場景就變得非常簡單。
科學可視化通常採用從現實世界中收集的數據。在這種情況下,我們將使用VTK中可用的內置幾何之一。這些是簡單的幾何形狀:箭頭,圓柱體,立方體等,它們在表示數據時很有用。它們的名稱遵循一個約定:形狀的名稱vtkXXXXSource
在哪裏XXXX
,即圓錐體,箭頭,圓柱體等。在這種情況下,我們的數據源爲圓錐體。
cone = vtk.vtkConeSource()
圓錐被隱式描述。我們可以通過調用其關聯方法爲錐體設置一些參數。這可以包括.SetRadius(radius)
或.SetResolution(facets)
設置圓錐的半徑和用來表示圓錐的小平面的數量。
要使用多邊形網格之類的幾何數據,我們需要使用此數據創建的實例vtkActor
。要到達那裏至少需要一箇中間步驟。我們從幾何圖形中創建一個映射器,然後將該映射器連接到actor。
此處,圓錐體的輸出連接到映射器以繼續管線。
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(cone.GetOutputPort())
上面的習語在前面關於VTK管道的章節中討論了。的輸出cone
連接到的輸入mapper
。vtkPolyDataMapper
該類的實例需要來自輸出非結構化多邊形數據的對象的連接。這樣的對象可以是vtkPolyData
存儲每個點和像元的實例,或者在這種情況下vtkConeSource
,是根據少量參數從程序生成幾何的。或者,可以將錐的輸出連接到濾波器,而將濾波器的輸出連接到映射器。在此示例中不使用任何過濾器。
actor = vtk.vtkActor()
actor.SetMapper(mapper)
上面的代碼與之前的代碼列表有些不同。一個vtkActor
具有使用不同的語法映射集。在VTK中,參與者被視爲可視化管道的末端(請參閱上文有關VTK管道的內容)。從這裏我們正在構建渲染管道。
映射者和演員
創建映射器是可視化管道中的中間步驟。它把數據和信息帶入演員。它的作用是將數據映射到圖形基元中。對於多邊形網格,這比其他類型的數據更直接。它還包括進行有關如何將數據轉換爲顏色的設置(請參見下面的查找表),或者是否使用單元格數據或節點數據爲模型着色。演員關心模型如何適合場景。結果,可以從角色內部設置的參數通常涉及場景中對象的紋理,光照,位置等。
下面是完成可視化的最後步驟。
window = vtk.vtkRenderWindow()
# Sets the pixel width, length of the window.
window.SetSize(500, 500)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(window)
renderer = vtk.vtkRenderer()
window.AddRenderer(renderer)
renderer.AddActor(actor)
# Setting the background to blue.
renderer.SetBackground(0.1, 0.1, 0.4)
window.Render()
interactor.Start()
VTK渲染的默認設置是默認啓用某種程度的交互性。這是我們免費獲得的,而進一步的交互性需要在可視化中進行編程。當用戶與可視化交互時,會執行諸如單擊/移動鼠標,按下鍵等操作,這些事件由交互器處理。可以使用不同的交互器設置來更改可視化如何響應特定用戶事件。在這裏我們使用了common vtkRenderWindowInteractor
。其他交互器實例具有不同的行爲,可以隨時對其進行修改。需要使用該.SetRenderWindow()
方法將交互器連接到窗口。
每個VTK可視化需要一個窗口,並且每個窗口至少需要一個渲染器(儘管每個窗口可以有多個渲染器)。該窗口由vtkRenderWindow
實例表示。渲染器可以視爲一個單獨的場景。每個對象可以具有不同的角色,相機位置,照明等。渲染器通過該.AddRenderer(renderer)
方法連接到窗口。默認情況下,整個窗口區域將具有此渲染器的渲染功能。但是,可以設置多個渲染器以在窗口的不同區域中進行繪製。如果使用多個渲染器,則必須指定一個矩形,該矩形描述渲染器將在其上繪製的窗口部分。這是使用.SetViewport( (x0, y0, x1, y1) )
(查看更多)進行控制的。
渲染器的背景色是使用.SetBackground()
方法設置的。最後的步驟是初始化可視化。
VTK中的數據
VTK管道始於一個或多個數據源。通常,這些數據是來自現實世界的實驗,計算或其他測量結果。VTK提供了許多不同的數據結構,您可以使用它們來存儲數據。它們具有需要提供多少信息來完全描述您的數據的優勢。
圖3.以4種不同方式構造的數據說明。從左上角開始,順時針移動:結構化圖像格式,直線網格,結構化網格和完全非結構化的多邊形數據。
VTK可以讀取和顯示幾乎任何類型的結構的數值數據。圖3顯示了具有4種不同結構的數據。從最大到最小的順序排列,這些是圖像,直線網格,結構化網格和多邊形數據。數據越結構化,需要提供給VTK的信息越少,以完全表示該數據。例如,要完全描述圖像數據,您只需要提供:
網格的原點。這是一個位置矢量,它指向具有最低網格的角
x
,y
,z
座標值。這是3個標量值。單元格之間的間距:這是一個標量值,它描述了所有單元格的大小(寬度)。
圖像數據的尺寸。這是3個標量值,它們描述每個方向上有多少個圖像單元。對於
l
×m
×n
圖像數據,這三個值需要被指定。對於1D和2D圖像數據,值1表示未使用相應的尺寸。例如,將使用l
×m
尺寸的圖像n = 1
。
直線網格需要更多信息才能完全定義它。需要與圖像相同的信息,以及每行節點之間的間距。如果查看圖3中的直線網格,您會注意到單元格的邊緣是對齊的,但是每行的任何單元格的寬度都是不同的。必須爲每一行指定該距離。這是每個維度中每行的一個附加標量值。然後,對於其他數據結構,信息量進一步增加。
要使用的數據結構的類型取決於它將表示的數據。理想情況下,它是最結構化的數據類型,可以完全代表現實生活中的數據/度量。來自攝像機的圖像數據可以由VTK圖像對象表示,而從CAD程序導入的多邊形網格則需要由非結構化多邊形數據表示。VTK圖像對象過於僵化,無法對多邊形網格進行建模。
使用和創建多數據
在前面的示例中,從圓錐源對象創建了多邊形網格。這是通過管道進行的,無需進一步修改即可呈現。在下面的示例中,通過手動指定每個點的位置,然後通過點之間的連接以創建單元來創建簡單的多邊形網格。每個網格僅包含一個三角形單元。數據值分配給一個網格中的點。將值分配給另一個網格中的像元。
圖4.在此示例中創建的單個三角形單元的示意圖。
科學可視化通常會涉及某種3D幾何形狀。在機械工程中,這可能是金屬結構的幾何形狀,這是有限元分析的主題,或者是使用MRI可視化的骨骼或器官的幾何形狀。與幾何一起的是分層存儲在該幾何上的數據。熱圖可以顯示組件周圍的溫度,結構上的應力場可以顯示該組件上機械應力的分佈。VTK可以可視化標量或更高階張量數據。使用VTK,您可以創建一個值數組,這些值映射到網格中的點或單元。
points = vtk.vtkPoints()
cell = vtk.vtkCellArray()
mesh_1 = vtk.vtkPolyData()
mesh_2 = vtk.vtkPolyData()
tri = vtk.vtkTriangle()
在上方,我們看到了用於生成多邊形網格幾何體的對象。將它們組合在一起以創建最終的網格。結果將是vtkPolyData
單個三角形的兩個網格,其中兩個網格均引用該三角形的幾何形狀。
# First point with default ID of 0.
points.InsertNextPoint( (0.0, 0.0, 0.0) )
points.InsertNextPoint( (0.0, 1.0, 0.0) )
points.InsertNextPoint( (1.0, 0.0, 0.0) )
VTK中的內存管理
前面已經提到,VTK是用C ++實現的,但是我們通過綁定使用Python。語言綁定允許訪問用另一種語言編寫的代碼。在Python中,內存是自動管理的,因此在以前的Python代碼中可能不需要擔心它。儘管使用C ++編寫,但在使用Python中的庫時,VTK內存管理通常對您來說是隱藏的。
在上方,我們看到了vtkPoints
通過.InsertNextPoint()
方法附加了數據的實例。還按插入順序從0開始爲所有點分配ID號。一種替代方法是使用.SetNumberOfPoints(numPoints)
其中numPoints
將要存儲的點數的方法。然後使用設置單個點.SetPoint(id, (x, y, z) )
。重要的id
是,不能超過numPoints
上一命令中使用的值;換句話說,最大允許值是id
numPoints-1。超過最大允許ID數或.SetPoint()
在第一次調用第一次分配內存之前設置一個點將.SetNumberOfPoints()
導致錯誤。
當.InsertNextPoint()
被調用時,在RAM中新的內存分配給新的點。同樣,在調用numPoints
時分配了存儲所需的空間.SetNumberOfPoints()
。其他類的相似之處在於,必須首先指定結構的尺寸。然後可以將各個項目添加到該結構中,直到指定的數量爲止。如果附加值,則會自動設置其ID。
三角形有3個點。必須將全局點ID匹配到三角形的三個點。使用.GetPointIds().SetId(i, i)
的第一個實例i
爲0、1或2的點進行匹配,並指定三角形的局部點ID。第二個i
可以是任何全局點ID。這些對應於.InsertNextPoint()
在調用.SetPoint()
的實例時使用或顯式分配給節點的ID vtkPoints
。
for i in range(3):
tri.GetPointIds().SetId(i, i)
cell.InsertNextCell(tri)
在這種情況下,整個網格中只有1個像元和3個點,因此這很簡單。VTK中的對象通常由許多較小的對象組成。通常,通過獲取設置了參數的相關對象來設置參數/屬性,然後設置該參數。使用VTK時,上面的代碼很常見。這裏.GetPointIds()
返回一個vtkIdList
對象,然後調用其.SetId()
方法。注意,多邊形是定向的。方向由右手規則以及元素的3個局部點ID與全局點ID之間的匹配關係決定。
然後將點和像元設置爲網格。
mesh_1.SetPoints(points)
mesh_1.SetPolys(cell)
如上所述,可以在網格的點或單元處設置多邊形網格的數據。下面,我們爲的單元格數據設置了一個標量值mesh_1
。這些標量值存儲爲雙精度浮點值,適用於大多數情況。
cell_data = vtk.vtkDoubleArray()
cell_data.SetNumberOfComponents(1)
cell_data.InsertNextTuple([0.5])
mesh_1.GetCellData().SetScalars(cell_data)
在上面的數組中,首先創建了數組,然後設置了組件數。常規標量數據將具有1個分量,向量將使用3個分量,高階張量將使用更多分量。數據,甚至是標量數據,都使用列表輸入。要輸入具有三個成分的向量數量,需要將成分數設置爲3,.SetNumberOfComponents(1)
並將一個成分列表替換爲三個數量的列表。
最後一行將數據分配給網格本身。數據插入的順序vtkDoubleArray
對應於該數據如何與網格中的每個像元對齊。在此,添加到數組中的第一個(也是唯一的)元組值與添加到的第一個(也是唯一的)單元格相對應mesh_1
。以下所示的過程類似,但適用於三角形中的三個點並設置點數據。
point_data.InsertNextTuple([0.0])
point_data.InsertNextTuple([1.0])
point_data.InsertNextTuple([0.5])
mesh_2.GetPointData().SetScalars(point_data)
該代碼示例的其餘部分是樣板,除了查找表的構造之外,該模板與上一個示例基本保持不變。查找表將在本章後面討論。查找表用於確定用於表示給定數值的顏色。
圖5.兩個三角形多邊形,其中單元數據(左)和點數據(右)連接到網格。
從圖5中,我們可以看到左側的單個彩色單元格。在這裏,單元格的標量值通過查找表映射爲單一顏色。在右邊的單元格中填充了線性的顏色漸變。使用節點上的標量值選擇顏色,然後這些顏色之間的漸變填充單元格的內容。
查找表
在上一節中,使用了一個查詢表,根據單元和節點數據爲多邊形着色。精確的工作查找表在此處進行了更詳細的描述。本節假定您對指定顏色的格式有深入的瞭解。您可能需要閱讀本章末尾的小節,並獲得有關此內容的更多信息。
顏色在可視化中可能非常有用。它可以以非常直觀的方式在大範圍內傳達信息。要爲演員設置單一顏色,可以使用actor.GetProperty().SetColor(r, g, b)
命令。這會將整個模型設置爲由(r, g, b)
提供的值定義的單一顏色。但是,在可視化中,您將需要繪製各種顏色的對象,這些對象用於傳達有關與模型關聯的數據的信息。在VTK中,查找表是將標量值映射爲顏色的對象。分析人員修改查找表以調整顏色方案,或者控制標量值如何映射到顏色以表示數據。
使用創建一個多邊形數據查詢表lut = vtk.vtkPolyDataMapper()
。查找表通過映射器對象與模型關聯。該方法.SetLookupTable(lut)
將查找表連接lut
到映射器。此外,.SetUseLookupTableScalarRange(True)
需要在映射器上調用該方法。這將導致映射器使用與查找表相同的範圍。不使用此方法將導致映射器覆蓋查找表中設置的範圍,這可能不是您想要的。
無論查找表中使用的參數如何,都必須調用該.Build()
方法。這將更新查找表以反映更新的設置。
下面,我將討論設置查詢表以實現不同結果的不同方法。在本節的最後,有一個包含4個三角形元素的簡單網格的示例。每種技術都以4種不同的方式用於可視化相同的網格。
默認查詢表
默認情況下,查找表將使用科學可視化中經常出現的彩虹範圍的顏色。這些顏色大約是紅色,黃色,綠色,淺綠色,藍色,紅色映射到表格範圍的下端,藍色映射到上端。
查找表的範圍是通過方法設置的.SetTableRange(low, high)
。對於高於或低於此範圍的值,默認設置是顯示的顏色與該範圍內最接近的值的顏色相同,例如,範圍爲[500,600]的表的400.0值將具有與值爲500.0。它可以設置自定義顏色使用的方法的範圍以外的值.SetAboveRangeColor(colour)
和.SetBelowRangeColor(colour)
。這colour
是4個值的列表,通常是3個RGB值加上一個alpha通道。無論一種或兩種ofthese兩種方法是否被調用,有可能這是否特徵-使用自定義的顏色值外的範圍-用這4種方法激活控制:.UseBelowRangeColorOn()
,.UseBelowRangeColorOff()
,.UseAboveRangeColorOn()
,.UseAboveRangeColorOff()
。該功能默認情況下處於關閉狀態,因此必須激活。
創建漸變時指定自定義顏色範圍
儘管默認的彩虹配色方案在許多應用中很有用,但可以控制顏色的映射方式。可以限制色調,飽和度或值的範圍,以控制如何將數據映射到顏色。造成這種情況的方法是.SetHueRange(low, high)
,.SetSaturationRange(low, high)
和.SetValueRange(low, high)
。如果low
和high
是相同的值,則對應的參數是固定的,並且不會隨輸入數據而變化。
通過固定HSV模型的3個參數中的一些參數,同時允許其他參數隨輸入數據變化,可以創建不同的效果。默認值是飽和度和值固定爲最大值1.0,而色相隨輸入數據而變化。結果是上述的彩虹色。這可以更改。下面的示例創建一個單色顏色圖。它將色調固定爲任意值,將飽和度固定爲0.0,同時允許該值變化。這將創建一個根據輸入數據從更亮到更暗變化的映射。
lut.SetHueRange(0.5, 0.5)
lut.SetSaturationRange(0.0, 0.0)
lut.SetValueRange(0.25, 1.0)
創建任意的顏色映射
前面的示例主要依靠VTK提供的默認查找表,同時調整其某些設置。第一個是默認的Rainbow查找表。第二個修改了3個HSV參數的範圍,以提供不同的效果。VTK允許對查找表進行完全控制,以允許值到您要指定的顏色的任何特定映射。這意味着從值→顏色分別指定每個映射。
每個查詢表都有固定數量的顏色。這是通過方法設置.SetNumberOfColors(number)
爲整數值的number
。默認值爲256。這會將256種顏色映射到所指定的值的範圍內.SetTableRange(low, high)
。值之間的距離相等,並且選擇這些值可提供默認的彩虹可視化效果。顏色不一定需要以創建平滑漸變效果的方式進行設置。
一旦使用.SetNumberOfColors(number)
每種方法設置了查找表中的顏色數量,就可以使用該方法進行設置.SetTableValue(id, R, G, B, A)
。參數R
,G
和B
指定要映射到的顏色。alpha通道由指定A
。該參數A
是可選的,如果未指定,則默認爲1.0,即.SetTableValue()
僅用4個參數調用。的id
是,用於指定在範圍內的本色彩坐的整數。如果ññ在表格中使用顏色,然後id
從0到(N− 1 )(ñ--1個)。範圍底部的值映射到ID爲0的顏色;範圍中心的值將映射到ID大約爲ñ2個ñ2個; 並且,該範圍頂端的值將映射到ID爲的顏色ñ− 1ñ--1個。
顯示分類數據
在值和顏色之間設置任意映射的功能可用於表示分類信息。一個示例可能是可視化模型的熱模擬。溫度高於或低於熔點的元素可以用藍色/紅色顯示,以顯示可能發生熔化的位置。可以使用以下方法對單元進行分類,並可視化每個單元在其分配的類別中的成員資格。
爲了 ññ我們設置的數據類別.SetNumberOfColors(N)
。然後,爲每個類別分配一個浮點值,該浮點值從0.0開始並逐個增加1個ñ− 11個ñ--1個,例如,對於4個類別,這些值爲0.0、0.3333、0.6666和1.0。如果我們爲這些類別分配一個整數類別編號,cat_no
則第一個類別具有,cat_no = 0
並且該類別的所有單元格的標量單元格值爲0.0,第二個類別的cat_no = 1
單元格值爲0.3333,依此類推。然後使用設置每個類別的顏色.SetTableValue(cat_no, R, G, B)
。
創建自定義顏色漸變
前面的示例顯示瞭如何在映射數據時通過操縱跨HSV顏色模型使用的範圍來控制顏色梯度。顏色及其順序是固定的。這些大約是紅色,黃色,綠色,水綠色,藍色。我們可以像以前一樣通過指定色調範圍來在任一端切斷此顏色範圍,但是我們無法選擇這些顏色隨輸入值而變化的任意順序。VTK沒有提供方便的工具來簡單地指定幾種顏色,然後讓VTK在這些顏色之間創建平滑的漸變。例如,我們不能指定綠色,然後是黃色,然後是淺綠色,作爲查找表範圍內的顏色,並且VTK無法自動在這些顏色之間創建平滑的顏色漸變。
VTK提供了一個對象a vtkColorTransferFunction
,以實現我們所需要的。我們使用.AddRGBPoint(value, R, G, B)
帶有4個參數的方法。這些是使用RGB值指定的值和顏色。一旦設置了這些值-顏色對,.GetColor(value)
就可以查詢該方法。對於任意值,它返回一種顏色,該顏色是從具有最接近值的顏色中插入的。下面的示例是一個vtkColorTransferFunction
將黃色(RGB:1.0,1.0,0.0)設置爲值0.0和將紅色(RGB:1.0,0.0,0.0)設置爲1.0的示例。橙色(RGB:1.0、0.5、0.0)是介於兩者之間的顏色。.GetColor(value)
調用值爲0.5時,將正確返回其RGB值。
ctransfer = vtk.vtkColorTransferFunction()
ctransfer.AddRGBPoint(0.0, 1.0, 1.0, 0.0) # Yellow
ctransfer.AddRGBPoint(1.0, 1.0, 0.0, 0.0) # Red
# Correctly outputs the colour orange.
ctransfer.GetColor(0.5) # (1.0, 0.5, 0.0)
創建完之後,vtkColorTransferFunction
我們需要在查找表中設置每種單獨的顏色。爲了創建平滑的漸變,我們在查找表中需要足夠的顏色。默認的顏色數量是256,通常足夠,但是如果需要,您可以使用更大的數量。下面,將顏色數量設置爲N
,並且查找表的範圍爲[a,b]。等式我×b − añ一世×b--一種ñ給出甚至踩值a
到b
了N
。
lut = vtk.vtkLookupTable()
lut.SetTableRange(a, b)
for i in range(N):
new_colour = ctransfer.GetColor( (i * ((b-a)/N) ) )
lut.SetTableValue(i, *new_colour)
lut.Build()
示例:創建自定義查找表
一個由4個元素和5個節點組成的示例網格用於顯示具有不同查找表的同一數據的不同可視化效果。網格具有標量單元和節點數據。其值如圖6所示。如果模型中同時存在兩種類型的數據,則VTK中的默認值是可視化節點數據。
圖6.具有4個元素和5個節點的網格。方括號[]中顯示的標量節點數據以及方括號外的節點號。標量單元格數據顯示在大括號{}中。節點標籤從左下角開始,然後增加,逆時針移動。
創建了四個不同的查找表以可視化圖6中所示的數據。最終結果如圖7所示。下面以與在圖7的標題中描述的順序相同的順序討論它們。代碼清單中的查找表被命名爲lut_n
,其中n
是查找表的編號。類似地,相應的映射器和其他對象也相應地編號。僅vtkPolyData
創建一個網格(一個實例)。由於每個映射器都鏈接到其相應的查找表,因此出現了可視化方面的差異。範圍使用以下設置:
lut_1.SetTableRange(5.0, 7.5)
lut_2.SetTableRange(5.0, 7.5)
lut_3.SetTableRange(5.0, 7.5)
lut_4.SetTableRange(0.0, 1.0)
前三個查詢表使用平滑漸變顯示點數據,而第四個用於可視化爲單元格存儲的類別數據。因此,它具有不同的範圍。第一個查詢表保留默認設置。.Build()
在分配給相應的映射器之前,只有方法被調用。
lut_1.Build()
mesh_mapper_1.SetLookupTable(lut_1)
第二個查找表修改HSV顏色值以創建單個彩色漸變,其中HSV顏色描述中的V大小會發生變化,而色相和飽和度則是固定的。結果是創建了與較低和較高標量數據值相對應的較暗和較亮的區域。對於3D模型,應謹慎使用此方法。在3D陰影中,當以與網格數據無關的方式渲染模型時,也會使用陰影,因此應謹慎使用這種特殊的着色技術。
lut_2.SetHueRange(0.5, 0.5)
lut_2.SetSaturationRange(1.0, 1.0)
lut_2.SetValueRange(0.25, 1.0)
lut_2.Build()
mesh_mapper_2.SetLookupTable(lut_2)
第三個查找表創建自定義的顏色組合,在構建查找表時從中創建漸變。這是使用的方法創建如上所述。選擇了三種顏色,並將它們設置爲反映值範圍的低端,中端和高端。AvtkColorTransferFunction
用於對顏色值進行插值,以在這三個點之間創建漸變。
no_of_colours = 256
lut_3.SetNumberOfColors(no_of_colours)
ctransfer = vtk.vtkColorTransferFunction()
ctransfer.AddRGBPoint(0.0, 1.0, 0.25, 0.0) # Orange
ctransfer.AddRGBPoint(0.5, 1.0, 0.00, 0.0) # Red
ctransfer.AddRGBPoint(1.0, 1.0, 0.95, 0.95) # White
for i in range(no_of_colours):
new_colour = ctransfer.GetColor(i / float(no_of_colours))
lut_3.SetTableValue(i, *new_colour)
lut_3.Build()
mesh_mapper_3.SetLookupTable(lut_3)
最終查找表使用3種自定義顏色來顯示4個類別之一中的每個單元格的成員資格。使用設置顏色數爲3,lut_4.SetNumberOfColors(3)
並分別設置要使用的3種顏色中的每一種。表範圍[0.0,1.0]設置得較早。這意味着要將單元格的顏色設置爲紅色,琥珀色或綠色,需要將其值設置爲0.0、0.5或1.0。請注意,從圖6可以看出,每個單元格都具有這些值之一作爲其單元格數據。將查找表設置爲相應的映射器後,.SetScalarModeToUseCellData()
將使用該方法。由於網格同時包含像元數據和點數據,因此VTK將默認使用點數據進行可視化。需要調用此方法。.SetScalarModeToUsePointData()
但是,點數據的相應方法是默認值,因爲點數據是默認方法,而以前的查找表從未使用過該方法。
lut_4.SetNumberOfColors(3)
lut_4.SetTableValue(0, 1.0, 0.0, 0.0) # Red
lut_4.SetTableValue(1, 1.0, 0.75, 0.0) # Amber
lut_4.SetTableValue(2, 0.0, 1.0, 0.0) # Green
lut_4.Build()
mesh_mapper_4.SetLookupTable(lut_4)
mesh_mapper_4.SetScalarModeToUseCellData()
的實例vtkScalarBarActor
已添加到每個渲染器。它們通過顯示顏色及其對應的值來幫助註釋可視化。對於分類信息,我們的代碼使用單元格值將成員資格分配給某個類別,但是實際值本身對查看可視化效果的用戶沒有用。默認標籤被從標量欄中,通過使用該方法其數量設置爲0除去.SetNumberOfLabels(0)
上vtkScalarBarActor
bar_4
。使用查找表方法在查找表中設置每個類別的註釋.SetAnnotation(value, annotation)
。
lut_4.SetAnnotation(0.0, "Red")
lut_4.SetAnnotation(0.5, "Amber")
lut_4.SetAnnotation(1.0, "Green")
條形圖使用對應的查找表進行關聯,bar.SetLookupTable(lut)
並作爲角色添加到渲染器中。作爲2D演員,使用方法將它們添加.AddActor2D(actor)
。關於2D畫布和2D角色的更多討論將在下一章中介紹。
所有4個結果如圖7所示。
圖7.從圖6中的網格創建的可視化。左上角按順時針方向顯示的結果是:默認查找表;固定HSV模型中的色相和飽和度,並允許其值變化;通過在任意選擇的顏色之間插值顏色而創建的自定義顏色漸變;以及用於將元素分爲三類的單元格數據。
轉變
VTK可以通過多種方式轉換場景中的模型。多邊形網格將具有其自己的局部原點。分析人員正在構建的整個場景也有其起源。使用角色引用的網格的.AddActor(actor)
方法vtkRenderer
將角色添加到場景時,會將角色添加到場景中。放置網格時,應使網格的本地原點與裝配場景的全局原點重合,其中局部軸和全局軸均已對齊。
如果要移動模型,則可以修改面數據本身。如果這樣做,您將修改每個引用該數據的對象所使用的數據。先前的示例表明,可以創建一個幾何實例,然後讓多個映射器引用相同的數據。如果隨後修改了數據,則對該數據的所有引用都將被修改。相反,每個角色都允許您定義一個轉換,該轉換描述模型如何在場景中移動。有幾種定義這些轉換的方法。下面我們討論如何通過調用方法來完成此操作vtkActor
。在後面的章節中將介紹另外兩種方法,其中涉及定義該vtkTransform
參與者所引用的對象。此處描述的方法更簡單,適用於大多數情況。
演員有幾種定義轉換的方法。我們對平移,縮放和旋轉actor的3個操作感興趣。
移動演員
該.SetPosition(x, y, z)
演員的方法,將移動的演員,使得演員的本地原點移動到指定的位置x
,y
和z
。演員的當前位置可通過該.GetPosition()
方法獲得。如果你想演員相對的移動到其目前的現在的位置,而不是你可以使用一個絕對位置.GetPosition()
,添加到這些返回的x
,y
,z
座標,然後調用.SetPosition(x, y, z)
但是VTK還提供了.AddPosition(x, y, z)
執行所有這一切都從一個單一的方法方法。
縮放演員
演員的比例是通過該.SetScale()
方法設置的。它可以使用1或3個參數。單個標量值將在所有方向上均等地縮放角色,例如,用於在所有方向上將.SetScale(3.0)
模型的大小均等地增加三倍。要在模型的寬度和深度而不是高度上縮放模型(請記住VTK使用Y軸作爲其垂直方向),可以將其.SetScale(x, 1, x)
用作縮放因子x
。在actor下方,首先在每個方向上將因子縮放爲5,然後在x,y和z方向上將因子縮放爲4、2和3。
factor = 5
actor.SetScale(factor)
factor = [4.0, 2.0, 3.0]
actor.SetScale(factor)
旋轉演員
演員可以用三種方式進行旋轉:.RotateX(theta)
,.RotateY(theta)
,和.RotateZ(theta)
。這theta
是旋轉模型的角度(以度爲單位)。這些角度是相對於模型的局部座標系,而不是全局座標系。
關於訂購的注意事項
重要的是要考慮旋轉的順序。以不同順序執行的相同旋轉可能會提供不同的方向。平移發生在全局座標系中,比例因子和旋轉相對於模型的局部座標系。您不僅需要考慮旋轉是一般旋轉還是非交換(這意味着如果以不同的順序執行旋轉,它們可能會產生不同的結果),而且定義旋轉的座標系也會隨旋轉而變化。因此,調用.RotateX(theta)
實際上取決於繞其進行的旋轉來指定繞不同軸的旋轉。
與上一點在一起的是,有多種方法可以旋轉對象以達到特定方向。Actor具有一種.GetOrientation()
返回模型當前方向的方法。指定這些值,以便如果按照z,x,然後y的順序執行旋轉,則actor將到達其當前方向。類似地,該方法.AddOrientation(x, y, z)
是相當於執行.RotateZ(z)
,.RotateX(x)
和.RotateY(y)
以該順序。
示例:3D繪圖腳本
在本章的3D繪圖應用程序示例中,將本章前面開發的許多較小的技能結合在一起。VTK庫通常提供幾種方法來獲得相同的結果。有很多方法可以開發此示例。選擇此處使用的方法是因爲它們建立在上面開發的技能之上。最終結果是一個小型應用程序,可以繪製3D中任意曲面的方程式。儘管這顯示的是由方程式定義的更抽象的表面,而不是現實生活中的對象或幾何圖形-VTK非常適合該對象或幾何圖形-這是僅使用上面開發的技能創建的有用且完整的應用程序的示例。
第一步是提供用於繪製表面的必要輸入參數。當然,這些參數中的第一個是將要繪製的函數本身。函數是func_to_calculate(x, y)
。給定X和Y座標時,它可以是返回Z值的任何有效函數。
x0 = -7 # X domain low end
y0 = -7 # Y domain low end
x_max = 7 # X domain high end
y_max = 7 # Y domain high end
X = 100 # Resolution in x direction. Integer
Y = 100 # Resolution in y direction. Integer
圖8.輸入參數和它們所對應的輸出表面的尺寸圖。
上面列出了下一個輸入參數。它們描述了要繪製的函數的域以及進行該繪製的數值分辨率。這些參數也顯示在[mesh_grid_with_origin_figure]中。其中指定域中的4個變量是x0
,x_max
,y_0
,和y_max
。它們描述了XX 和 ÿÿ 指示。
在此示例的代碼清單中,沒有錯誤檢查,但是更精緻的示例將檢查這些參數以確保它們正確。這可以包括確保x_max
比x0
其他檢查更大。實際上,比起在Python文件頂部輸入參數,更精美的示例將找到一種更優雅的方式來輸入這些參數!參數X
和Y
指定要在其各自方向上使用的像元數。通過這些詳細信息,我們可以計算出XX 和 ÿÿ 每個單元的尺寸。
deltax = (x_max - x0) / float(X)
deltay = (y_max - y0) / float(Y)
並非必須使用float(),但很有用,因爲如果int
僅對(整數)個值執行除法,則Python版本2會丟棄餘數。此功能可強制進行浮點除法並避免此問題。
就像前面的示例一樣,我們創建的實例,vtkPoints
並vtkCellArray
在其中存儲單元和點以定義曲面。
points = vtk.vtkPoints()
cells = vtk.vtkCellArray()
我們需要計算網格中的所有點。該表面由在x和y方向上具有均勻間距的四邊形單元定義。對於x和y方向,點的行比單元格多。作爲X
並Y
包含每個維度上的像元數,我們遍歷X+1
並Y+1
指向每個維度。
zvals = []
for j in range(Y+1):
for i in range(X+1):
x = x0 + deltax*i
y = y0 + deltay*j
z_val = func_to_calculate(x, y)
zvals.append(z_val)
coord = x, y, z_val
points.InsertNextPoint(coord)
在上面,Z值存儲在列表中,zvals
以供以後在代碼中以及在使用該.InsertNextPoint(coord)
方法的座標點中使用。將它們存儲在本地Python數據結構中也更加方便。請注意,.InsertNextPoint()
和.append()
方法在同一循環中調用。該點的相同全局ID(在.InsertNextPoint()
調用時隱式設置)也可以用於索引zvals
以獲取相同的Z值。稍後在創建添加到網格的標量點數據時使用。
for j in range(Y):
for i in range(X):
quad = vtk.vtkQuad()
corner_id = get_id(i, j)
quad.GetPointIds().SetId(0, corner_id)
quad.GetPointIds().SetId(1, corner_id + 1)
quad.GetPointIds().SetId(2, corner_id + (X+2))
quad.GetPointIds().SetId(3, corner_id + (X+1))
cells.InsertNextCell(quad)
圖9.任意單元的全局點ID。最低角上的點的ID爲N,並且在x軸上有X個單元格。
下一步是vtkQuad
在多邊形網格中創建元素。這些元素有四個ID爲0、1、2和3的本地點,這些本地點需要與4個全局點ID關聯。使用插入點的順序分配了點ID points.InsertNextPoint(coord)
。如果使用了上面代碼清單所示的二維循環,則ID,ññ,具有最低節點的 XX 和 ÿÿ座標(請參見[arbitrary_cell])由i + j (X+ 1 )一世+Ĵ(X+1個),其中X
提供了輸入參數。和ññ其他3個點的ID可以直接確定。創建點和像元后,它們將被添加到網格中。
mesh = vtk.vtkPolyData()
mesh.SetPoints(points)
mesh.SetPolys(cells)
點數據放置在中vtkDoubleArray
(見下文)。然後將其設置爲網格中的點數據。
point_data = vtk.vtkDoubleArray()
point_data.SetNumberOfComponents(1)
for zval in zvals:
point_data.InsertNextTuple([zval])
mesh.GetPointData().SetScalars(point_data)
本可視化中有兩個新功能尚未在本章中介紹。如果您已經閱讀了本章的上一內容,儘管它們是新的,但它們的用法很簡單。當我們渲染表面時,它被框的輪廓和軸所圍繞。這兩個附加功能可以幫助可視化對象:第一個功能是在模型周圍勾勒出一個框,第二個功能是顯示座標軸以幫助確定尺寸。這兩個都要求vtkPolyDataNormals
從多邊形網格派生實例。使用以下內容可以輕鬆生成此信息:
norms_generator = vtk.vtkPolyDataNormals()
norms_generator.SetInputData(mesh)
然後使用該數據生成座標軸。
axes = vtk.vtkCubeAxesActor2D()
axes.SetInputConnection(norms_generator.GetOutputPort())
axes.SetCamera(renderer.GetActiveCamera())
axes.SetLabelFormat("%1.1g")
類似地,輪廓過濾器使用以下內容創建。
outline_filter = vtk.vtkOutlineFilter()
outline_filter.SetInputConnection(norms_generator.GetOutputPort())
軸是Actor2D,可以像其他任何actor一樣添加到渲染器中。輪廓過濾器可以像常規實例一樣對待,vtkPolyData
這意味着將其連接到avtkPolyDataMapper
和a vtkActor
,然後使用添加到渲染器renderer.AddActor(outline_actor)
。
最終結果如下所示。
圖10.最終結果顯示了函數圖:F(x ,y) =罪[ 0.2 × (X2個+ÿ2個) ]F(X,ÿ)=罪[0.2×(X2個+ÿ2個)]。
圖11.功能圖 F(x ,y) =X2個-ÿ2個F(X,ÿ)=X2個--ÿ2個。
關於顏色的註釋
對於不熟悉RGB和HSV格式以在VTK和大多數其他軟件中指定顏色的任何人,以下有關顏色的信息將附加到本章中。
在科學的可視化中,顏色的使用非常重要。在VTK中,數據通常被映射到一個調色板,當呈現時,該調色板允許用戶非常快速地吸收有關一組數據的大量信息。瞭解VTK中顏色的定義非常重要,尤其是對於定義查找表而言。
通過指定3個單獨的浮點值可以描述任何顏色。VTK使用範圍[0.0,1.0]。VTK使用兩種模型來描述顏色。第一個顏色模型是紅/綠/藍(RGB)模型[ 2 ]。VTK中的方法採用或返回[0.0,1.0]範圍內的3個浮點數。這些描述了構成該顏色的紅色,綠色和藍色的數量。RGB值(1.0,0.0,0.0)爲亮紅色;(1.0,1.0,1.0)的RGB值爲白色,(0.0,0.0,0.0)的RGB值爲黑色。同時增大或減小這三個值將使所得的顏色變亮或變暗。
圖12.三行色樣,顯示了更改HSV參數時結果顏色的效果。在每一行中,一個參數都會變化,而其他參數則保持最大值。第一行:色調變化,顯示紅色,黃色,綠色和藍色之間的變化。第二行:紫色的飽和度降低了,變爲灰色。第三行:與第二行相同的顏色值降低了,變爲黑色。
另一個模型是色相/飽和度/值(HSV)模型[ 3 ]。這也需要3個參數來描述顏色,但是這3個值描述了不同的信息。對於某些人來說,該模型可能更直觀。第一個數字hue是一個人可能會認爲的顏色。想象一下,穿過彩虹,色調將決定顏色是紅色,橙色,黃色等。飽和度和值描述了這種顏色的強度,但是以兩種不同的方式。飽和度描述了有多少種顏色。飽和度爲0.0會更改所有顏色以灰度顯示。該值描述顏色的亮或暗。不管其他值如何,值0.0始終會產生黑色,而最亮的值爲1.0。
在某些地方,指定了第4個值:alpha值。這指定了表面的透明度。Alpha值0.0是一個完全透明的表面,而與其他3種顏色值無關。Alpha值爲1.0時,表面完全是不透明/不透明,並顯示爲其他3個值指定的顏色。alpha值爲1.0時將完全不透明。
重要命令
下表總結了本章中描述的命令。
命令 | 描述 |
---|---|
基本命令 | |
vtk.vtkConeSource() |
創建圓錐多邊形網格。 |
mapper.SetInputConnection(cone.GetOutputPort()) |
將的輸出端口cone 連接到的輸入接口mapper 。這是VTK中常見的習慣用法,用於連接輸出和輸入以構建管道。 |
actor.SetMapper(mapper) |
設置mapper 了vtkActor 命名actor 。 |
window.SetSize(x, y) |
將以像素爲單位的窗口尺寸設置爲x 寬和y 高。 |
interactor.SetRenderWindow(window) |
設置interactor 爲與render一起使用window 。 |
window.AddRenderer(renderer) |
將添加renderer 到中window 。 |
renderer.SetViewport( (x0, y0, x1, y1) ) |
設置renderer 於與左下角窗口的部分在(畫x0 ,y0 )和右上角的(x1 ,y1 )。這些值是在[0.0,1.0]範圍內的比率。默認值爲(0.0, 0.0, 1.0, 1.0) 。 |
renderer.SetBackground(R, G, B) |
將背景色設置爲RGB顏色,由定義(R, G, B) 。 |
多邊形網格命令 | |
points.InsertNextPoint( (x, y, z) ) |
在插入位置的下一個點(x, y, z) 到vtkPoints 實例。 |
tri.GetPointIds().SetId(i, j) |
對於vtkTriangle 實例tri ,將i 這個三角形的本地ID設置爲j 其中tri 一個單元格的網格的全局ID 。注意:此命令與其他多邊形單元相同,包括vtkQuad 。 |
data.SetNumberOfComponents(1) |
對於該vtkDoubleArray data 集合,將每個元組的組件數設置爲1。 |
data.InsertNextTuple([val]) |
對於vtkDoubleArray data 集合,將下一個元組值設置爲float val 。 |
mesh.GetCellData().SetScalars(data) mesh.GetPointData().SetScalars(data) |
對於vtkPolyData 實例,mesh 將單元格/點數據設置爲vtkDoubleArray instance data 。 |
查找表 | |
actor.GetProperty().SetColor(r, g, b) |
用於actor 將角色的整個模型的顏色設置爲單色,由RGB值指定(r, g, b) 。 |
vtk.vtkPolyDataMapper() |
創建的實例vtkPolyDataMapper ,可以將其應用於多邊形網格的查找表。 |
lut.SetTableRange(low, high) |
將查找表的比例從設置low 爲high 。 |
mapper.SetLookupTable(lut) |
將查找表連接lut 到映射的數據mapper 。 |
mapper.SetUseLookupTableScalarRange(True) |
mapper 使用設置爲的查找表中的數據範圍。在大多數情況下,使用修改的查找表時應調用此方法。 |
lut.Build() |
設置查找表後lut ,此方法將更新查找表以反映新參數。設置查找表後需要調用。 |
lut.SetAboveRangeColor(colour) lut.SetBelowRangeColor(colour) |
設置顏色以用於查找表範圍之外的值。在這裏,color可以是4個參數,也可以是長度4的列表。這些是顏色的RGB值,alpha通道是第4個參數。必須與結合使用.UseXXXXXRangeColorOn() 以激活該顏色的使用。 |
lut.UseBelowRangeColorOn() lut.UseBelowRangeColorOff() lut.UseAboveRangeColorOn() lut.UseAboveRangeColorOff() |
對於查找表,lut 控制是否對範圍之外的值使用自定義顏色。默認情況下關閉。 |
lut.SetHueRange(low, high) lut.SetSaturationRange(low, high) lut.SetValueRange(low, high) |
對於該vtkLookupTable lut 設置,色相,飽和度或值範圍從low 到high 。設置low =high 固定爲單個值。 |
ctransfer.AddRGBPoint(val, R, G, B) ctransfer.AddRGBPoint(val, R, G, B, A) |
對於vtkColorTransferFunction ctransfer 設置顏色R, G, B 爲浮點數val 。A 可以選擇指定Alpha值。 |
ctransfer.GetColor(val) |
獲取顏色3個RGB值對應浮動val 的vtkColorTransferFunction ctransfer 。 |
lut.SetTableValue(val, R, G, B) |
手動爲查找表(R, G, B) 的值設置顏色。val``lut |
轉變 | |
actor.SetPosition(x, y, z) |
放置vtkActor actor 在座標上(x, y, z) 。 |
actor.GetPosition() |
獲取的當前(x, y, z) 座標actor 。 |
actor.AddPosition(x, y, z) |
取代actor 通過(x, y, z) 從當前位置。 |
actor.SetScale(s) actor.SetScale(x, y, z) |
actor 按的局部座標系的s 所有方向或(x, y, z) 相應方向的比例進行縮放actor 。 |
actor.RotateX(theta) actor.RotateY(theta) actor.RotateZ(theta) |
旋轉actor 圍繞其局部X,Y或Z軸按theta 度。 |
1。可視化工具包(VTK)
2。另請參閱https://en.wikipedia.org/wiki/Rgb
3。另請參閱https://en.wikipedia.org/wiki/HSL_and_HSV
原文:
https://danstoj.pythonanywhere.com/article/vtk-1
本文分享自微信公衆號 - 小弧光黑板報(gh_ba6067dca33c)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。