VTK 圖形基本操作進階_法向量計算


1.點法向量和單元法向量

三維平面的法向量是指垂直於該平面的三維向量。曲面在某點P處的法向量為垂直於該點切平面的向量。對於一個網格模型,其每一個點和單元都可以計算一個法向量,在三維計算機圖形學中法向量一個重要應用是光照和陰影計算。對於網格模型,模型是有一定數量的面片(單元)來逼近的,面片越多,則模型越精細;反之,則越粗糙。在計算網格模型的法向量時,單元法向量計算比較簡單,可以通過組成每個單元的任意兩條邊的叉乘向量並歸一化來表示。而,對於點的法向量,則是由所有使用該點的單元法向量的平均值來表示。
VTK中計算法向量的Filter是vtkPolyDataNormals()。該類針對單元為 三角形或者多邊形類型的vtkPolyData數據進行計算。由於法向量分為點法向量和單元法向量,可以通過函數SetComputeCellNormals()和SetComputePointNormals()來設置需要計算的法向量類型。
默認情況下計算點法向量,關閉單元法向量計算。
示例演示了一個vtkPolyData模型的點法向量和單位法向量的計算:
 1 #include <vtkAutoInit.h>
 2 VTK_MODULE_INIT(vtkRenderingOpenGL);  3 VTK_MODULE_INIT(vtkInteractionStyle);  4  
 5 #include <vtkSmartPointer.h>
 6 #include <vtkPolyDataReader.h> 
 7 #include <vtkPolyDataNormals.h> //計算法向量
 8 #include <vtkMaskPoints.h>
 9 #include <vtkArrowSource.h>
 10 #include <vtkGlyph3D.h>
 11 #include <vtkPointData.h>
 12 #include <vtkProperty.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     vtkSmartPointer<vtkPolyDataReader> plyReader =
 23         vtkSmartPointer<vtkPolyDataReader>::New();  24     plyReader->SetFileName("fran_cut.vtk");  25     plyReader->Update();  26  
 27     vtkSmartPointer<vtkPolyDataNormals> normFilter =
 28         vtkSmartPointer<vtkPolyDataNormals>::New();  29     normFilter->SetInputData(plyReader->GetOutput());  30     normFilter->SetComputePointNormals(1);//開啟點法向量計算
 31     normFilter->SetComputeCellNormals(0); //關閉單元法向量計算
 32     normFilter->SetAutoOrientNormals(1);  33     normFilter->SetSplitting(0);  34     normFilter->Update();  35  
 36     vtkSmartPointer<vtkMaskPoints> mask =
 37         vtkSmartPointer<vtkMaskPoints>::New();  38     mask->SetInputData(normFilter->GetOutput());  39     mask->SetMaximumNumberOfPoints(300);  40     mask->RandomModeOn();  41     mask->Update();  42  
 43     vtkSmartPointer<vtkArrowSource> arrow =
 44         vtkSmartPointer<vtkArrowSource>::New();  45     arrow->Update(); //一定要更新 否則數據沒有添加進來,程序會報錯
 46  
 47     vtkSmartPointer<vtkGlyph3D> glyph =
 48         vtkSmartPointer<vtkGlyph3D>::New();  49     glyph->SetInputData(mask->GetOutput());  50     glyph->SetSourceData(arrow->GetOutput());//每一點用箭頭代替
 51     glyph->SetVectorModeToUseNormal();//設置向量顯示模式和法向量一致
 52     glyph->SetScaleFactor(0.01); //設置伸縮比例
 53     glyph->Update();  54     
 55     vtkSmartPointer<vtkPolyDataMapper> mapper =
 56         vtkSmartPointer<vtkPolyDataMapper>::New();  57     mapper->SetInputData(plyReader->GetOutput());  58     vtkSmartPointer<vtkPolyDataMapper> normMapper =
 59         vtkSmartPointer<vtkPolyDataMapper>::New();  60     normMapper->SetInputData(normFilter->GetOutput());  61     vtkSmartPointer<vtkPolyDataMapper> glyphMapper =
 62         vtkSmartPointer<vtkPolyDataMapper>::New();  63     glyphMapper->SetInputData(glyph->GetOutput());  64  
 65     vtkSmartPointer<vtkActor> actor =
 66         vtkSmartPointer<vtkActor>::New();  67     actor->SetMapper(mapper);  68     vtkSmartPointer<vtkActor> normActor =
 69         vtkSmartPointer<vtkActor>::New();  70     normActor->SetMapper(normMapper);  71     vtkSmartPointer<vtkActor> glyphActor =
 72         vtkSmartPointer<vtkActor>::New();  73     glyphActor->SetMapper(glyphMapper);  74     glyphActor->GetProperty()->SetColor(1, 0, 0);  75     
 76     double origView[4] = { 0, 0, 0.33, 1 };  77     double normView[4] = { 0.33, 0, 0.66, 1 };  78     double glyphView[4] = { 0.66, 0, 1, 1 };  79     vtkSmartPointer<vtkRenderer> origRender =
 80         vtkSmartPointer<vtkRenderer>::New();  81     origRender->SetViewport(origView);  82     origRender->AddActor(actor);  83     origRender->SetBackground(1, 0, 0);  84     vtkSmartPointer<vtkRenderer> normRender =
 85         vtkSmartPointer<vtkRenderer>::New();  86     normRender->SetViewport(normView);  87     normRender->AddActor(normActor);  88     normRender->SetBackground(0, 1, 0);  89     vtkSmartPointer<vtkRenderer> glyphRender =
 90         vtkSmartPointer<vtkRenderer>::New();  91     glyphRender->SetViewport(glyphView);  92     glyphRender->AddActor(glyphActor);  93     glyphRender->AddActor(normActor);  94     glyphRender->SetBackground(0, 0, 1);  95     
 96     vtkSmartPointer<vtkRenderWindow> rw =
 97         vtkSmartPointer<vtkRenderWindow>::New();  98     rw->AddRenderer(origRender);  99     rw->AddRenderer(normRender); 100     rw->AddRenderer(glyphRender); 101     rw->SetWindowName("Calculating Point Norm & Cell Norm"); 102     rw->SetSize(960, 320); 103     rw->Render(); 104     
105     vtkSmartPointer<vtkRenderWindowInteractor> rwi =
106         vtkSmartPointer<vtkRenderWindowInteractor>::New(); 107     rwi->SetRenderWindow(rw); 108     rwi->Initialize(); 109     rwi->Start(); 110  
111     return 0; 112 }
輸出結果如下圖所示:

在計算法向量時需要注意一個問題,即法向量的方向。因為對於同一個平面來講,可以有兩個方向完全相反的法向量。一般是根據單元的點的順序確定,采用右手定則來定義一個平面的法向量方向。因此計算平面方向量的時候, 法向量的方向與單元的點的順序密切相關。必須保持單元的點順序一致,才會得到合理的法向量。當然,函數SetConsistency()可以設置自動調整模型的單元法向量。SetAutoOrientNormals()可以設置自動調整法線的方向。

2.關於類vtkGlyph3D

詳細描述:為每個輸入點拷貝相應方向和伸縮比例的輪廓幾何體
vtkGlyph3d是一個過濾器,當拷貝幾何體到每個輸入點時,它起到濾波作用.glyph從過濾輸入源中以多邊形數據形式定義,glyph根據輸入的矢量和法向量來確定方向,根據伸縮數據和矢量大小來確定伸縮比例.當glyph較多時,可能通過對象源與其相應的定義信息來創建glyph表.glyph表可以通過伸縮值或矢量大小來索引相應的gpyph對象.
要使用vtkGlyph3D對象, 我們首先需要提供一個輸入集和一個對象源來定義ghyph.然后決定是否對ghyph進行伸縮,以及怎樣對其進行伸縮,接下來決定是否對glyph設置方向,以及如何根據矢量及法向量來設置它,最終決定我們是用glyph表還是僅僅是單一的ghyph.如果使用了glyph表,我們還需要考慮相應的索引值.
 
vtkGlyph3D 實際上是一種符號化的算法工具,可以使用一個源(如球體)為輸入數據集的每一個點生成一個符號,並且可以設置符號的方向以及縮放比例, 簡單點說就是對於你想關注的數據點添加符號標注,符號的樣式由自己指定。比如你有一個曲面數據,希望將曲面數據的每個點都用錐體標注出來並且錐體的方向表示該點的法向量方向,這個時候就可以使用vtkGlyph3D。

3.本例的注意事項與經驗談

注意算法執行之后,要注意及時更新,Update()一下!!!


免責聲明!

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



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