VTK中獲取STL模型點的坐標以及對其進行變換


  VTK是一個基於面向對象的開源三維繪圖軟件包,和其它的的三維繪圖引擎如OSG、OGRE不同之處在於,VTK可視化對象主要是各種數據,更加注重對數據分析處理后的可視化,可視化的內容是人們無法直接感受到的東西,如地質構造、地層分布、礦床分布、三維空間應力場的狀態變化等等,而OSG、OGRE是基於場景的可視化,更強調視覺感官的感受,所以OSG主要應用於虛擬現實領域,而VTK主要應用於科學計算可視化領域。 

   VTK的可視化設計是基於管線流的設計模式,將要處理的數據作為流動介質在管線中流動,不同的階段對數據有不同的處理方式,VTK的可視化管線如圖所示:

  Sources: 數據生成的源頭,數據來源主要包括從磁盤讀取數據文件,如VTK所支持的各種格式文件生成數據源對象,這種源對象被稱為讀源對象,或者利用數學方法生成源對象,如利用多個四邊形構建一個圓柱體,這種對象被稱為程序源對象。

  Filters: 對源對象進行處理,生成新的數據集輸出。

  Mappers: 映射器對象主要作用是將可視化模型生成的數據轉換到圖形模型進行繪制,或者以磁盤文件的形式進行輸出。

  渲染對象(vtkRenderer)和渲染窗口(vtkRenderWindow): 渲染對象和渲染窗口分別對應於用於顯示圖形的視口和窗口。每個渲染窗口可以容納一個或多個渲染對象。即一個渲染窗口中可以存在多個視口,它們既可以並列也可以分層排放。


 

  如下圖所示,用vtkSTLReader讀入一個邊長為50mm的立方體模型(注意模型不在原點--導出STL文件時選擇了自定義的坐標系)。如果是ASCII格式的STL文件可以直接用文本編輯器打開查看立方體各頂點的坐標,在VTK中如何獲得這些頂點的坐標位置呢?vtkProp3D類里面有幾個函數:GetPosition、GetOrigin、GetCenter不過這些都沒辦法獲取立方體頂點的坐標。不管立方體在坐標系中處於什么位置,只要沒調用SetPosition設置新位置,GetPosition都會返回(0, 0, 0)。

import vtk

# Create the reader and read a data file. 
sr = vtk.vtkSTLReader()
sr.SetFileName("cube.stl")
sr.Update()

stlMapper = vtk.vtkPolyDataMapper()
stlMapper.SetInputConnection(sr.GetOutputPort())

stlActor = vtk.vtkLODActor()
stlActor.SetMapper(stlMapper)

#stlActor.SetPosition(-50, 0, 0) p = [0, 0, 0] polydata = sr.GetOutput() for i in range(polydata.GetNumberOfPoints()): polydata.GetPoint(i, p); print p # Create the Renderer, RenderWindow, and RenderWindowInteractor ren = vtk.vtkRenderer() renWin = vtk.vtkRenderWindow() renWin.AddRenderer(ren) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) # Add the actors to the render; set the background and size ren.AddActor(stlActor) ren.SetBackground(0.1, 0.1, 0.1) renWin.SetSize(500, 500) # create coordinate axes in the render window axes = vtk.vtkAxesActor() axes.SetTotalLength(100, 100, 100) # Set the total length of the axes in 3 dimensions # Set the type of the shaft to a cylinder:0, line:1, or user defined geometry. axes.SetShaftType(0) axes.SetCylinderRadius(0.02) axes.SetAxisLabels(0) ren.AddActor(axes) style = vtk.vtkInteractorStyleTrackballCamera() style.SetDefaultRenderer(ren) iren.SetInteractorStyle(style) iren.Initialize() renWin.Render() iren.Start()

  運行后得到如下結果,即立方體8個頂點的實際坐標:

[50.0, 0.0, 100.0]
[50.0, 100.0, 100.0]
[50.0, 0.0, 0.0]
[50.0, 100.0, 0.0]
[150.0, 0.0, 100.0]
[150.0, 0.0, 0.0]
[150.0, 100.0, 100.0]
[150.0, 100.0, 0.0]

  如果將注釋"#stlActor.SetPosition(-50, 0, 0)"取消,再運行會得到同樣的結果。可以發現SetPosition這種操作並不會影響頂點的實際位置,只能控制場景中的演員的位置。vtkActor.SetPosition() simply effects where your actor is rendered, but do not modify any coordinates of the underlying polydata physically. 即VTK中的變換可分為對實際數據的變換和對演員的變換,具體可以參考PPT:Introduction to VTK: Transforms

  為了對原始數據進行處理可以添加filter,如下面代碼,將原始STL模型中的頂點向X軸負方向平移50mm

transform = vtk.vtkTransform()
transform.Translate(-50, 0, 0)
transformFilter = vtk.vtkTransformPolyDataFilter()
transformFilter.SetInputConnection(sr.GetOutputPort())
transformFilter.SetTransform(transform)
transformFilter.Update()

  再次查詢立方體的頂點,坐標如下:

[0.0, 100.0, 100.0]
[0.0, 0.0, 0.0]
[0.0, 100.0, 0.0]
[100.0, 0.0, 100.0]
[100.0, 0.0, 0.0]
[100.0, 100.0, 100.0]
[100.0, 100.0, 0.0]

  另外需要注意的是可視化管道使用惰性計算策略(lazy evaluation scheme): 直到需要數據(或被強制)時,可視化管道才會產生數據,產生的數據是最新的。對數據的需求由Update()方法提出,這一方法可以顯示調用,也可以由圖形流水線中演員對象(Actor)的Render()方法自動調用。對數據的需求會逆着流水線的方向傳遞,如果某一部分的數據過時(通過檢查時間標簽),可視化流水線中的過濾器會重新執行,最新生成的數據沿着流水線傳遞給演員(Actor)。

  在上面的代碼中如果實例化vtkSTLReader后,直接調用GetNumberOfPoints方法獲取STL模型頂點的數目,會返回0,盡管這個模型包含了8個頂點。出現這樣的原因是因為GetNumberOfPoints()方法沒有被要求執行,而使用Update()方法強制了流水線的執行,因此會返回8。

 

參考:

VTK/Examples/Cxx/PolyData/PolyDataGetPoint

VTK/Tutorials/DataStorage

Visualization Toolkit ( VTK ) Tutorial

Introduction to VTK: Transforms

how to get the world coordinate of a Prop?

what's the difference between actor 's position and sphere 's center ?


免責聲明!

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



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