項目不等人,只能先跳過範例,先看數據集和數據屬性這一章了。範例會在空閒時間穿插在筆記中。html
第三章 數據集與數據屬性算法
定義:在可視化流水線中,稱處理的數據對象爲數據集。數組
數據集是抽象概念,對應的類vtkDataSet也是一個抽象類。因此在程序中使用的數據集是其具體化後的子類。性能
數據集的組成:spa
3.1 數據集的結構scala
由上面數據集結構的組成可知:定義一個數據集的結構須要分別對數據集的幾何和拓撲進行定義,即分別對點和單元進行定義。code
下面分別介紹對點和單元的定義進行介紹:orm
①定義數據集的點htm
定義數據集的點十分簡單。首先將一系列的點座標插入到vtkPoints對象中,接着調用數據集對象的方法SetPoint(),並將這個vtkPoints對象做爲參數傳入,這樣就定義好了數據集的點,也就是定義好了數據集的幾何。插入到vtkPoints對象中點會有一個對應的id號(索引)。以後定義單元時,就是使用這些id號來表示相應點之間的關係的。對象
舉例:
#include"vtkPolyData.h" #include"vtkPoints.h" int main() { int i; //定義點在三維座標系中的座標 static float x[8][3]={{0,0,0,},{1,0,0},{1,1,0},{0,1,0},{0,0,1},{1,0,1},{1,1,1},{0,1,1}}; vtkPolyData *cube=vtkPolyData::New();//建立數據集對象的實例 vtkPoints *points=vtkPoints ::New();//建立vtkPoints對象的實例 for(i=0;i<8;i++)points->InsertPoint(i,x[i]);//將點座標插入vtkPoints對象中 cube->SetPoints(points);//爲數據集添加點,定義其幾何 return 0; }
固然上面的例子運行起來後沒有結果能夠顯示。
②定義數據集的單元
單元的定義要複雜一些,緣由是單元的類型比較多,或者說是點之間關係的種類比較多。
VTK支持的單元類型如圖所示:
(a)頂點:基本的零維單元,由一個單一點定義。
(b)多頂點:複合的零維單元,由任意順序的一系列點定義。
(c)線:基本的一維單元,由兩個點定義,其方向爲第一個點到第二個點的方向。
(d)多線段:複合的一維單元,包含一個或多個鏈接的線,由有序的n+1個點定義,其中n是多線段中的線的段數。每對點(i,i+1)定義了一段線。
(e)三角形:基本的二維單元,按照順時針或者逆時針方向排列的三個點定義。
(f)三角形帶:複合的而爲單元,包含一個或多個三角形,這些三角形沒必要位於一個平面上。其由有序的n+2個點進行定義,其中n是三角形的個數,點的排列順序必須知足使任意三個相鄰點(i,i+1,i+2)都能定義一個三角形,其中i的取值範圍爲【0,n-1】。
(g)四邊形:基本的二維單元,由位於同一個面上的按照順時針或者逆時針方向排列的四個點定義。四邊形必須是凸的,而且不能相交。
(h)像素:基本的二維單元,由有序的四個點定義。像素單元在拓撲上與四邊形等價,只是另外有幾何上的限制。像素的每條邊與其臨邊垂直,而且與x-y-z三個座標軸中的一個平行。所以,發現方向也平行於一個座標軸。
定義像素的點的順序與定義四邊形單元的不一樣。點的順序是按照座標軸的正方向來排列的,先是x軸,而後是Y軸,最後是z軸。像素是一種四邊形的特例,用於改進計算性能。
注意事項:這裏給出的像素定義與一般的像素定義不一樣。通常像素是指圖像中具備常量值得圖像元素,而這裏給出的定義意味着,四個圖像元素造成了像素單元四個角上的點。
(i)多邊形:基本的二維單元,由位於同一平面上按照順時針或者逆時針的三個或更多個點定義。
(j)四面體:基本的三維單元,由四個不一樣平面的點定義。四面體包含六條邊和四個三角面。
(k)六面體:基本的三維單元,包含六個四邊形面,十二條邊和八個頂點。六面體由有序的8個點定義。面和邊不能與其餘面和邊相交,四邊形必須是凸的。
(l)體素:基本的三維單元。體素在拓撲上與六面體等價,只是另外帶有幾何上的限制。體素每一個面與x-y-z三個座標軸中的一個垂直。點的定義順序是按照座標軸的正方向來排列的。體素是六面體的一個特例,用於改進計算性能。
與像素同樣,這裏的體素的定義與常規意義上的體素不一樣。通常,體素是指具備長兩隻的體積元素。根據這裏體素單元的定義,8個體積元素造成了體素單元8個角上的點。
定義單元舉例:
#include"vtkPolyData.h" #include"vtkPoints.h" #include"vtkCellArray.h" int main() { int i; //定義點在三維座標系中的座標 static float x[8][3]={{0,0,0,},{1,0,0},{1,1,0},{0,1,0},{0,0,1},{1,0,1},{1,1,1},{0,1,1}}; //定義單元(經過點的索引來表達點之間的關係,因此採用vtkIdType) static vtkIdType pts[6][4]={{0,1,2,3},{4,5,6,7},{0,1,5,4},{1,2,6,5},{2,3,7,6},{3,0,4,7}}; vtkPolyData *cube=vtkPolyData::New();//建立數據集對象的實例 vtkPoints *points=vtkPoints ::New();//建立vtkPoints對象的實例 vtkCellArray *polys=vtkCellArray::New(); for(i=0;i<8;i++)points->InsertPoint(i,x[i]);//將點座標插入vtkPoints對象中 for(i=0;i<6;i++)polys->InsertNextCell(4,pts[i]);// cube->SetPoints(points);//爲數據集添加點,定義其幾何 points->Delete(); cube->SetPolys(polys);//爲數據集添加單元,定義其拓撲 polys->Delete(); return 0; }
3.2 數據集的屬性
數據集的屬性(屬性數據)是與數據集結構相關聯的。而數據集又是創建在點和單元的基礎上,因此數據屬性很天然地是與點和單元相關聯。即每一個點或每一個單元都有與其對應的數據屬性。
數據屬性的值稱爲屬性數據。屬性數據通常設置爲一些有實際意義的值,如在某點處的溫度(用一個數值表示),或在某點處所受的力(用三個數值表示)等。點或單元的屬性數據是以數據數組(vtkDataArray)的形式進行存儲的,根據數據值類型的不一樣,具體是存儲 在vtkDataArray的子類中,如vtkFloatArray或vtkIntArray等。數組的每一個元素稱爲元組,對應着但個點或單元的屬性數據。每一個元組能夠有多個份量(Component),例如速度值就有分別沿着x,y,z軸的三個份量。數組的長度必須與點或單元的個數相同,這樣才能保證與點或單元一一對應。以下是建立數組的方法:
vtkFloatArray *scalars=vtkFloatArray::New();
scalars->InsertTuple1(0,0.0);
scalars->InsertTuple1(0,1.0);
……
vtkDoubleArray *vectors=vtkDoubleArray::New();
vectors->SetNumberOfComponents(3);//設置份量個數,默認爲1
vectors->SetNumberOfTuples(10);//設置元組個數,必須等於點的個數
vectors->SetTuple3(0,0.0,0.5,1.0);//設置Id爲0的點的屬性數據
vectors->SetTuple3(1,0.0,1.5,1.0);//設置Id爲1的點的屬性數據
……
vtkIntArray *anArray=vtkIntArray::New();
anArray->SetNumberOfComponents(2);
anArray->SetName("Velocity");
anArray->SetTuple2(0,1,3);
anArray->SetTuple2(1,2,4);
從代碼能夠看出,在插入各個數據前,元組的個數能夠不指定。這樣的話,就必須調用名字前綴爲Insert的方法插入數據(注意最終插入的元組個數必須等於點或單元的個數)。若是制定了元組個數的話,就能夠調用名字前綴爲Set的方法,該方法相對較快些。方法名後綴的數字表示的是元組中份量的個數,該數字與SetNumberOfComponents()參數一致,默認份量個數爲1.設定每一個元組數據時,需提供若干個參數,第一個是點ID號,以後是元組各個份量的值。設置元組數據還有不少種方法可供選擇。
數據數組可做爲特殊或通常的屬性數據添加進數據集中。如果做爲通常屬性數據的話,那麼在建立數據數組的時候,能夠用方法SetName()給數組設置一個名字,如上面代碼中:anArray->SetName("Velocity"),以後就能夠經過這個名字來使用該數據數組。下面以多邊形數據集爲例,說明使用兩種不一樣形式添加數據數組的過程:
vtkPolyData *polyData = vtkPolyData::New();//建立數據集對象的實例
……
polyData->GetPointData()->SetScalars(scalars);//特殊屬性數據
polyData->GetCellData()->SetVectors(vectors);//特殊屬性數據
polyData->GetPointData()->AddArray(anArray);//通常屬性數據
首先須要調用數據集的方法GetPointData()或者GetCellData()獲取點或單元數據,接着調用方法SetScalars()和SetVectors()將數據數組做爲特殊屬性數據存儲。這兩個方法分別設置的是標量屬性數據和矢量屬性數據(其餘特殊屬性數據還包括法向量屬性數據、紋理座標屬性數據和張量屬性數據,分別用方法SetNormals()、SetTCoords()和SetTensors()設置)。最後調用AddArray()將數據數組做爲通常屬性數據添加進數據集中。該方法能夠屢次調用從而添加多個數據數組。正是因爲通常屬性數據沒有數量上的限制,因此使用字符串名字來進行區分會方便些。
補充:下面資料來自:http://blog.sina.com.cn/s/blog_84181a7901017tsm.html
屬性數據主要用於描述數據集的屬性特徵,屬性數據經常和數據集的幾何數據或單元數據相關聯,對數據集的可視化實質上是對屬性數據的可視化,例如,根據壓力監測數據構建一個壓力場可視化數據集後,數據集中的每一個數據點(幾何數據)或單元都必須有對應的屬性數據,VTK根據屬性數據設置顏色表,用不一樣的顏色表示不一樣的壓力,經過顏色的變化狀況,能夠直觀的分析出壓力的變化趨勢。
屬性數據依據數據的性質可分爲標量數據、向量數據、張量數據幾大類,通常標量數據和向量數據應用的比較多,大部分的例子都以這兩種數據爲主。
一、標量數據
標量數據只表示數據的大小,例如溫度、壓力、高度等。
二、向量數據
既有大小又有方向的量,如速度、應力、位移等。
三、張量數據
張量是矢量和矩陣經過複雜的數學算法獲得的,一個k階的張量可看成一個k維的表格。零階的張量是標量,一階的張量是矢量,二階的張量是紋理座標,三階的張量是一個三維陣列。
屬性數據只能和數據集中的點及單元關聯,對於構成單元的基本組成要素,如邊和麪等不能與數據屬性關聯,咱們稱與點關聯的數據屬性爲點屬性,與單元關聯的數據屬性爲單元屬性。
在VTK中用vtkPointData類和vtkCellData類表達數據集屬性,它們是類vtkFieldData的子類,構成數據集的每一個點(或單元)和屬性數據之間存在一對一的關係,如一個數據集由N個點(或單元)構成,那麼必須有N個屬性數據和這N個點(或單元)一一對應,經過點的ID號就能夠對該點的屬性數據進行訪問,例如在數據集aDataSet中訪問ID號爲129的點的標量值時(假設標量數據已被定義且不爲空)使用以下方法: aDataSet->GetPointData()->GetScalars()->GetScalar(129)。
如今前面兩節3.1 3.2 已經將數據集的構成講完了。可是數據集的結合和拓撲有各類各樣的可能,因此,還須要從數據集總體上對數據集進行分類。假設以哺乳動物這個類來比喻數據集的話,如今咱們已經知道動物是由血肉和骨頭組成的了。可是血肉和骨頭的組成由不少種,因此在實際生活中咱們可能還要將哺乳動物分紅各類可數好比貓科、犬科等等。
Σ( ° △ °|||)︴ 我這個比喻好像不恰當。原諒個人想象力吧。後面講介紹: 各類數據集類型 這是很重要的部分。