VTK 圖形進階_vtkPolyData屬性數據


1.從圖形着色說起

前一個實驗顯示結果中的圖像是白色的,而圖形顏色與vtkPolyData屬性數據息息相關。由於並未指定任何顏色和屬性數據,因此在顯示時默認以白色顯示。
屬性數據包括點屬性和單元屬性。可以為vtkPolyData的點數據和單元數據分別指定屬性數據。
屬性數據可以是標量,如點的曲率;可以是向量,如點或者單元的法向量;也可以是張量,主要在流場中較為常見。
顏色可以直接作為一種標量屬性數據,設置到相應的點或者單元數據中,這也是最直接的一種圖形着色方式。
下面的實例代碼僅是對上例圖形進行着色:
 1 #include <vtkAutoInit.h>
 2 VTK_MODULE_INIT(vtkRenderingOpenGL);  3  
 4 #include <vtkSmartPointer.h>
 5 #include <vtkPoints.h>
 6 #include <vtkPolygon.h>
 7 #include <vtkTriangle.h> 
 8 #include <vtkCellArray.h>
 9 #include <vtkPolyData.h>
 10 #include <vtkUnsignedCharArray.h> //Attribution
 11 #include <vtkPointData.h>
 12 #include <vtkCellData.h>
 13 ///  14 #include <vtkPolyDataMapper.h>
 15 #include <vtkActor.h>
 16 #include <vtkRenderer.h>
 17 #include <vtkRenderWindow.h>
 18 #include <vtkRenderWindowInteractor.h>
 19  
 20 int main()  21 {  22     //幾何結構數據:點集
 23     vtkSmartPointer<vtkPoints> pts =
 24         vtkSmartPointer<vtkPoints>::New();  25     pts->InsertNextPoint(0.0, 0.0, 0.0);  26     pts->InsertNextPoint(1.0, 0.0, 0.0);  27     pts->InsertNextPoint(1.0, 1.0, 0.0);  28     pts->InsertNextPoint(0.0, 1.0, 0.0);  29     pts->InsertNextPoint(2.0, 0.0, 0.0);  30     //拓撲結構數據:正四邊形
 31     vtkSmartPointer<vtkPolygon> polygon =
 32         vtkSmartPointer<vtkPolygon>::New();  33     polygon->GetPointIds()->SetNumberOfIds(4);  34     polygon->GetPointIds()->SetId(0, 0);  35     polygon->GetPointIds()->SetId(1, 1);  36     polygon->GetPointIds()->SetId(2, 2);  37     polygon->GetPointIds()->SetId(3, 3);  38     //拓撲結構數據:三角形
 39     vtkSmartPointer<vtkTriangle> triangle =
 40         vtkSmartPointer<vtkTriangle>::New();  41     triangle->GetPointIds()->SetId(0, 1);  42     triangle->GetPointIds()->SetId(1, 2);  43     triangle->GetPointIds()->SetId(2, 4);  44     //構成拓撲結構集合
 45     vtkSmartPointer<vtkCellArray> cells =
 46         vtkSmartPointer<vtkCellArray>::New();  47     cells->InsertNextCell(polygon);  48     cells->InsertNextCell(triangle);  49     //合成幾何拓撲結構用於顯示
 50     vtkSmartPointer<vtkPolyData> polygonPolyData =
 51         vtkSmartPointer<vtkPolyData>::New();  52     polygonPolyData->SetPoints(pts);  53     polygonPolyData->SetPolys(cells);  54  
 55     //添加屬性結構
 56     unsigned char red[3] = { 255, 0, 0 };  57     unsigned char green[3] = { 0, 255, 0 };  58     unsigned char blue[3] = { 0, 0, 255 };  59     vtkSmartPointer<vtkUnsignedCharArray> ptColor =
 60         vtkSmartPointer<vtkUnsignedCharArray>::New();  61     ptColor->SetNumberOfComponents(3);  62     ptColor->InsertNextTupleValue(red);  63     ptColor->InsertNextTupleValue(green);  64     ptColor->InsertNextTupleValue(blue);  65     ptColor->InsertNextTupleValue(red);  66     ptColor->InsertNextTupleValue(green);  67     polygonPolyData->GetPointData()->SetScalars(ptColor);  68  
 69     vtkSmartPointer<vtkUnsignedCharArray> cellColor =
 70         vtkSmartPointer<vtkUnsignedCharArray>::New();  71     cellColor->SetNumberOfComponents(3);  72     cellColor->InsertNextTupleValue(blue);  73     cellColor->InsertNextTupleValue(red);  74     polygonPolyData->GetCellData()->SetScalars(cellColor);  75     
 76     vtkSmartPointer<vtkPolyDataMapper> mapper =
 77         vtkSmartPointer<vtkPolyDataMapper>::New();  78     mapper->SetInputData(polygonPolyData);  79  
 80     vtkSmartPointer<vtkActor> actor =
 81         vtkSmartPointer<vtkActor>::New();  82     actor->SetMapper(mapper);  83  
 84     vtkSmartPointer<vtkRenderer> render =
 85         vtkSmartPointer<vtkRenderer>::New();  86     render->AddActor(actor);  87     render->SetBackground(0.0, 0.0, 0.0);  88  
 89     vtkSmartPointer<vtkRenderWindow> rw =
 90         vtkSmartPointer<vtkRenderWindow>::New();  91     rw->AddRenderer(render);  92     rw->SetSize(320, 240);  93     rw->SetWindowName("Creating PolyData Structure");  94  
 95     vtkSmartPointer<vtkRenderWindowInteractor> rwi =
 96         vtkSmartPointer<vtkRenderWindowInteractor>::New();  97     rwi->SetRenderWindow(rw);  98     rwi->Render();  99     rwi->Start(); 100  
101     return 0; 102 }
該示例代碼繼承了上一節中的vtkPolyData數據。定義了兩個vtkUnsignedCharArray對象ptColor和cellColor,分別為點和單元設置顏色數據。vtkUnsignedCharArray對象實際上為一個Unsigned char類型的數組。SetNumberOfComponents()函數指定了該數組中每個元組的大小。由於每個顏色是由RGB三個顏色分量組成。因此設置元組大小為3。InsertNextTupleValue()函數可以順序插入元組數據。
由於要為點集設置顏色,因此顏色數目要與點數保持一致。對於單元的顏色數據設置同樣需要注意,有多少個單元,就要設置多少個顏色。
設置點的顏色時,需要通過GetPointData()函數獲取vtkPointData類型的點數據指針,然后通過SetScalar()函數設置顏色數據。
顯示結果如下所示,從圖中可以看出,在進行顏色渲染時,使用的是點的顏色,而不是單元的顏色!
根據之前的內容,我們知道:點數據和單元的屬性數據是分別存儲在VTKPointData和VTKCellData中的。
在這里,我們還是要着重區分一下標量屬性數據和向量屬性數據的區別:
向量數據具有方向和模;而標量數據不具有。如果一個數據(可以是單組分、也可以是多組分)經過一個幾何變換后保持不變,那么該數據是一個標量,例如我們說的顏色屬性。然而,對於法向量,該數據同樣有三個組分,卻是一個矢量屬性,因為法向量經過幾何變換后(如圖像旋轉)會發生改變。因此不能簡單滴通過組分的個數來區分標量數據或者矢量數據。在對屬性數據進行賦值時,也要分清標量數據還是矢量數據,不能將兩者混淆,例如將顏色數據設置為矢量數據,那么在對圖像數據進行幾何變換后,顏色數據會發生改變。

2. 單元的標量屬性和矢量屬性數據設置

默認情況下,vtkPolyDataMapper會使用一個unsigned char類型的三元數組作為顏色值進行渲染。但是在很多情況下,模型顏色是通過屬性數據獲取的,比如根據標量數據在顏色查找表中獲取相應的顏色。
 1 #include <vtkAutoInit.h>
 2 VTK_MODULE_INIT(vtkRenderingOpenGL);  3  
 4 #include <vtkSmartPointer.h>
 5 #include <vtkPlaneSource.h>
 6 #include <vtkPolyData.h>
 7 #include <vtkFloatArray.h>
 8 #include <vtkCellData.h>
 9 #include <vtkLookupTable.h>
10 #include <vtkPolyDataMapper.h>
11 #include <vtkActor.h>
12 #include <vtkRenderer.h>
13 #include <vtkRenderWindow.h>
14 #include <vtkRenderWindowInteractor.h>
15  
16 int main() 17 { 18     vtkSmartPointer<vtkPlaneSource> gridSource =
19         vtkSmartPointer<vtkPlaneSource>::New(); 20     gridSource->SetXResolution(3); 21     gridSource->SetYResolution(3); 22     gridSource->Update(); 23  
24     vtkSmartPointer<vtkPolyData> grid = gridSource->GetOutput(); 25     //標量屬性
26     vtkSmartPointer<vtkFloatArray> cellScalars =
27         vtkSmartPointer<vtkFloatArray>::New(); 28     //矢量屬性
29     vtkSmartPointer<vtkFloatArray> cellVector =
30         vtkSmartPointer<vtkFloatArray>::New(); 31     cellVector->SetNumberOfComponents(3); 32     //設置屬性
33     for (int i = 0; i < 9; i++) 34  { 35         cellScalars->InsertNextValue(i + 1); //九個索引
36         cellVector->InsertNextTuple3(0.0, 0.0, 1.0); 37  } 38  
39     grid->GetCellData()->SetScalars(cellScalars); 40     grid->GetCellData()->SetVectors(cellVector); 41  
42     vtkSmartPointer<vtkLookupTable> lut =
43         vtkSmartPointer<vtkLookupTable>::New(); 44     lut->SetNumberOfTableValues(10); 45     lut->Build(); 46     lut->SetTableValue(0, 0, 0, 0, 1); 47     lut->SetTableValue(1, 0.8900, 0.8100, 0.3400, 1); 48     lut->SetTableValue(2, 1.0000, 0.3882, 0.2784, 1); 49     lut->SetTableValue(3, 0.9608, 0.8706, 0.7020, 1); 50     lut->SetTableValue(4, 0.9020, 0.9020, 0.9804, 1); 51     lut->SetTableValue(5, 1.0000, 0.4900, 0.2500, 1); 52     lut->SetTableValue(6, 0.5300, 0.1500, 0.3400, 1); 53     lut->SetTableValue(7, 0.9804, 0.5020, 0.4471, 1); 54     lut->SetTableValue(8, 0.7400, 0.9900, 0.7900, 1); 55     lut->SetTableValue(9, 0.2000, 0.6300, 0.7900, 1); 56     // 57     vtkSmartPointer<vtkPolyDataMapper> mapper =
58         vtkSmartPointer<vtkPolyDataMapper>::New(); 59     mapper->SetInputData(grid); 60     mapper->SetScalarRange(0, 9); 61     mapper->SetLookupTable(lut); 62     // 63     vtkSmartPointer<vtkActor> actor =
64         vtkSmartPointer<vtkActor>::New(); 65     actor->SetMapper(mapper); 66  
67     vtkSmartPointer<vtkRenderer> render =
68         vtkSmartPointer<vtkRenderer>::New(); 69     render->AddActor(actor); 70     render->SetBackground(0.0, 0.0, 0.0); 71  
72     vtkSmartPointer<vtkRenderWindow> rw =
73         vtkSmartPointer<vtkRenderWindow>::New(); 74     rw->AddRenderer(render); 75     rw->SetSize(320, 320); 76     rw->SetWindowName("Setting Attribution of Vectors and Scalars"); 77  
78     vtkSmartPointer<vtkRenderWindowInteractor> rwi =
79         vtkSmartPointer<vtkRenderWindowInteractor>::New(); 80     rwi->SetRenderWindow(rw); 81     rwi->Start(); 82  
83     return 0; 84 }
這個實例主要演示了怎樣添加單元的標量屬性數據和向量屬性數據。
VTKPlaneSource定義了一個3*3的網格數據。cellScalars定義了vtkFloatArray類型的標量屬性數據,默認情況下其元組大小為1,因此不需要顯示指定其大小;cellVectors則定義了vtkFloatArray類型的矢量屬性數組,通過SetNumberOfComponents()指定向量維數為3,並通過InsertNextTuple3()可以方便地插入向量數據。
定義完畢后,vtkPolyData的單元數據(VTKCellData)通過調用函數SetScalars()和SetVectors()設置相應的屬性數據和標量數據。
為了進一步演示利用標量數據進行顏色映射,定義了一個具有10個顏色的顏色映射表。利用vtkPolyDataMapper類的SetLookupTable()函數設置定義的顏色映射表。另外,需要注意的是,SetScalarRange()指定了顏色映射范圍的最小值和最大值,當標量值大於最大值時,按定義最大值獲取顏色;當小魚最小值時,按照指定的最小值獲取顏色。這樣做的一個好處是,可以在一個小的標量范圍內顯示更多的顏色!!!
該例的輸出結果為:


免責聲明!

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



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