VTK基本數據結構
前面介紹了基本的vtk實例,這篇blog將重點學習VTK的基本數據結構,瞭解這些數據結構,有助於我們寫出更有針對性的、更高效的可視化應用程序。
我們的目的是要對數據進行可視化,因此有必要對可視化的數據特點作一瞭解。歸納起來,可視化數據具有如下一些特點:
l 離散性
爲了讓計算機能夠獲取、處理和分析數據,必須對無限、連續的空間體進行採樣,生成有限的採樣數據點,這些數據以離散點的形式存儲,採樣的過程是一個離散化的過程。
由於可視化數據的離散性特點,在某些離散點上有精確的值存在,但點與點之間的值則是不可知的,要得到採樣點之外的其他點的值,只有通過插值(Interpolation)的方法獲取。常用的插值方法是線性插值,要得到更精確的數值可以採用非線性插值,如B樣條插值方法。
l 數據具有規則或不規則的結構(或者說結構化與非結構化)
可視化數據可以分爲規則(Regular)和不規則(Irregular)或者說結構化(Structured)和非結構化(Unstructured)。規則結構數據點之間有固定的關聯關係,可以通過這些關聯確定每個點的座標,不規則結構數據之間沒有固定的關聯關係。
對於規則結構的數據,存儲時不必存儲所有的數據點,只需存儲起始點、相鄰兩點之間的間隔以及點的總數就可以保存完整的數據信息。對於不規則結構的數據,雖然不可以像規則結構的數據那樣存儲,但它也有自身的優勢,即在數據變化頻繁的區域可以密集表示,而數據變化不頻繁的區域則稀疏表示。規則結構的數據可以在存儲及計算時佔優勢,不規則結構的數據雖然存儲和計算時不能像規則結構的那樣高效,但它在數據表達方面相對而言則更加自由,更加細緻、靈活的表現數據。
l 數據具有維度
可視化數據的第三個特點是拓撲維度(Topological Dimension)。可視化數據具有零維、一維、二維、三維等任意維度。如,零維的數據表現爲點,一維數據表現爲曲線,二維數據表現爲曲面,三維數據表現爲體等。數據的維度決定了數據可視化的方法,如,對於二維的數據,可以將數據存儲到一個矩陣,然後再採用針對二維數據的可視化方法進行可視化(如等高圖)。
數據對象被組織成一種結構並且被賦予相應的屬性值時就形成數據集(Dataset)。VTK裏與數據集對應的類是vtkDataSet,該類從vtkDataObject直接派生。vtkDataSet由兩個部分組成,即組織結構(Organizing Structure)以及與組織結構相關聯的屬性數據(Attribute Data),下圖描述了vtkDataSet各結構的詳細構成。vtkDataSet是一個抽象基類,結構的實現及表達由其具體的子類來完成。
vtkDataSet的組織結構由拓撲結構(Topology)和幾何結構(Geometry)兩部分組成。拓撲結構描述了物體的構成形式,幾何結構描述了物體的空間位置關係。換言之,點數據(Point Data)所定義的一系列座標點構成了vtkDataSet(數據集)的幾何結構;點數據的連接(點的連接先形成單元數據(Cell Data),由單元數據再形成拓撲)就形成了數據集的拓撲結構。比如,我們想要在屏幕上顯示一個三角形,首先我們必須定義三角形三個點的座標(即Point Data,記三個點爲P1, P2和P3),然後將這三個點按照一定的順序連接起來(P1-P2-P3,或者是P3-P2-P1的順序),這三個點定義了數據集的幾何結構,它們的連接就構成了數據集的拓撲結構。亦即,點數據(Point Data)定義數據集的幾何結構,單元數據(Cell Data)定義數據集的拓撲結構,要形成完整的數據集,必須有幾何和拓撲兩種結構。
關於拓撲、幾何結構以及屬性數據的更多解釋:拓撲結構具有幾何變換不變性。例如,說一個多邊形是三角形,即指其拓撲結構,而給定的每個點的座標,則爲其幾何結構。幾何結構是一種空間描述,與空間變換有緊密聯繫,常見的變換有旋轉、平移和縮放。屬性數據是對拓撲結構和幾何結構信息的補充,屬性數據可以是某個空間點的溫度值,也可以是某個單元的質量之類的。
vtkDataSet的結構組成
接下來我們通過例子說明怎麼把幾何結構和拓撲結構加入到數據集(vtkDataSet)中去。先看一下只有幾何結構,沒有拓撲結構的vtkDataSet。
下面用實例具體說明幾何模型的構建:
#include "vtkActor.h"
#include "vtkCellArray.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkIntArray.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
int main()
{
int i;
//模型頂點座標array
vtkFloatArray* pcoords = vtkFloatArray::New();
//模型數據包含三個分量
pcoords->SetNumberOfComponents(3);
//頂點座標包含的數據數目
pcoords->SetNumberOfTuples(4);
//模型幾何頂點座標
float pts[4][3] = { {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0},
{1.0, 0.0, 0.0}, {1.0, 1.0, 0.0} };
for (i=0; i<4; i++)
{
pcoords->SetTuple(i, pts[i]);
}
//添加頂點座標
vtkPoints* points = vtkPoints::New();
points->SetData(pcoords);
//strip 模型單元構建
vtkCellArray* strips = vtkCellArray::New();
strips->InsertNextCell(4);
strips->InsertCellPoint(0);
strips->InsertCellPoint(1);
strips->InsertCellPoint(2);
strips->InsertCellPoint(3);
//模型
vtkIntArray* temperature = vtkIntArray::New();
temperature->SetName("Temperature");
temperature->InsertNextValue(10);
temperature->InsertNextValue(20);
temperature->InsertNextValue(30);
temperature->InsertNextValue(40);
//創建polydata數據集合
vtkPolyData* polydata = vtkPolyData::New();
polydata->SetPoints(points);
polydata->SetStrips(strips);
//添加屬性值
polydata->GetPointData()->SetScalars(temperature);
//模型顯示,並且設置數據mapper範圍爲0-40
vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
mapper->SetInput(polydata);
mapper->SetScalarRange(0, 40);
vtkActor* actor = vtkActor::New();
actor->SetMapper(mapper);
vtkRenderer* ren = vtkRenderer::New();
ren->AddActor(actor);
vtkRenderWindow* renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren);
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
iren->Initialize();
iren->Start();
pcoords->Delete();
points->Delete();
strips->Delete();
temperature->Delete();
vorticity->Delete();
polydata->Delete();
mapper->Delete();
actor->Delete();
ren->Delete();
renWin->Delete();
iren->Delete();
return 0;
}