VTK 空間幾何變換(Transform),平移、旋轉和縮放


先看下面的模型,這是一個Cow的三維模型,

在使用中,你是否會有下面的操作?

1.將Cow移動到某個位置——平移

2.轉動到Cow背面——旋轉

3.改變它大小——縮放

等等

可能你會說,這還不簡單,通過操作相機就好了。然而並不是這樣,操作相機,只使得相機的空間位置發生了變化,對三維物體並沒有改變,要想改變模型,就需要對模形本身做空間變換。

空間變換的基礎知識

變換矩陣(Transformation Matrices)

我們都知道,在屏幕上顯示的是二維的圖形,三維圖形都是投影到二維平面的,但它們定義在三維空間的。空間變換的基本元素都是三維坐標點,在計算機圖形學中,三維坐標點用齊次坐標表示。利用齊次坐標,可以將空間變換用4x4的矩陣來表示。這些變換最終都是由矩陣的運算完成。

VTK有關空間變換的類和方法

VTK相關的類有:

vtkTransform, vtkTransformFilter, vtkMatrix4x4等

相關的方法有:

• RotateX(angle)、RotateY(angle)、RotateZ(angle)

• RotateWXYZ(angle,x,y,z)

• Scale(x,y,z)

• Translate(x,y,z)

• SetMatrix(m)、GetMatrix(m)

• PostMultiply()、PreMultiply()

• SetPosition(x,y,z)、GetPosition(x,y,z)

• SetOrientation(x,y,z)、 GetOrientation(x,y,z)

• SetScale(sx,sy,sz)

• SetOrigin(x,y,z)、GetOrigin

下面通過幾個場景來看看上面的一些類和方法是如何使用以及一些常見的問題。

[圖1 圓錐體位於(0,0,0),坐標軸向量長度為1個單位]

場景一:矩陣的順序問題

我們要對圖1中位於世界坐標系原點的圓錐體做如下操作:

1. 圓錐體在X軸正方向上移動1個單位

2.繞Z軸旋轉45^{\circ}

1 vtkSmartPointer<vtkTransform> trans = 
2     vtkSmartPointer<vtkTransform>::New(); 3 trans->PostMultiply(); 4 trans->Translate(1, 0, 0); 5 trans->RotateZ(45); 6 coneActor->SetUserTransform(trans);

試着改變一下1, 2兩步的順序:

對比來看,是兩個不同的結果。而這個結果正是因為矩陣乘法並不滿足交換定律。

因此,在使用時,進行變換的順序非常重要,將對結果產生直接的影響。

對於變換矩陣,VTK是用以下順序來應用這些變化的:

1. 移動actor到它的origin,縮放和旋轉都是基於這個點完成的。

2. 縮放幾何體。

3.actor依次繞Y, X和Z軸旋轉。

4.從旋轉中心移回到原來的位置后再移動actor到最終的位置。

在VTK中,矩陣乘法默認是左乘,即PreMultiply,上面的公式也遵循這個原則。為了便於理解,示例代碼特地使用了右乘PostMultiply.

場景二:GetMatrix和GetUserMatrix的區別

Code1:

1 coneActor->RotateZ(45);
2 coneActor->SetPosition(1, 0, 0);

Code2:

1 trans->RotateZ(45);
2 trans->Translate(1, 0, 0);
3 coneActor->SetUserTransform(trans);

 

從兩個結果可以看出,GetMatix和GetUserMatrix都是獲取變換矩陣。所不同的是:

GetMatrix始終都可以獲取到值,也就是說它得到的是圓錐體在世界坐標系的變換矩陣。

GetUserMatrix在Code2中獲取到了值,而在Code1中得到是NULL,這說明它獲取的是用戶設置的變換矩陣。

注:GetUserMatrix、SetUserMatrix和GetUserTransform、SetUserTransform具有相同的作用。

完整示例代碼

 1 #include <vtkLineSource.h>
 2 #include <vtkPolyData.h>
 3 #include <vtkSmartPointer.h>
 4 #include <vtkPolyDataMapper.h>
 5 #include <vtkActor.h>
 6 #include <vtkRenderWindow.h>
 7 #include <vtkRenderer.h>
 8 #include <vtkRenderWindowInteractor.h>
 9 #include <vtkProperty.h>
 10 #include <vtkAxesActor.h>
 11 #include <vtkConeSource.h>
 12 #include <vtkTextActor.h>
 13 #include <vtkTextProperty.h>
 14 #include <vtkTransform.h>
 15 #include <vtkSphereSource.h>
 16  
 17 int main(int, char *[])  18 {  19     vtkSmartPointer<vtkSphereSource> sphereSource =
 20         vtkSmartPointer<vtkSphereSource>::New();  21     sphereSource->SetRadius(0.1);  22     sphereSource->Update();  23  
 24     vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
 25         vtkSmartPointer<vtkPolyDataMapper>::New();  26     sphereMapper->SetInputConnection(sphereSource->GetOutputPort());  27  
 28     vtkSmartPointer<vtkActor> sphereActor =
 29         vtkSmartPointer<vtkActor>::New();  30     sphereActor->SetPosition(0, 0, 0);  31     sphereActor->SetMapper(sphereMapper);  32     sphereActor->GetProperty()->SetColor(1, 0, 0);  33  
 34     vtkSmartPointer<vtkConeSource> coneSource =
 35         vtkSmartPointer<vtkConeSource>::New();  36     coneSource->SetRadius(.2);  37     coneSource->SetHeight(.5);  38     coneSource->SetCenter(0, 0, 0);  39     vtkSmartPointer<vtkPolyDataMapper> coneMapper =
 40         vtkSmartPointer<vtkPolyDataMapper>::New();  41     coneMapper->SetInputConnection(coneSource->GetOutputPort());  42     vtkSmartPointer<vtkActor> coneActor =
 43         vtkSmartPointer<vtkActor>::New();  44     coneActor->SetMapper(coneMapper);  45  
 46     vtkSmartPointer<vtkActor> oriConeActor =
 47         vtkSmartPointer<vtkActor>::New();  48     oriConeActor->SetMapper(coneMapper);  49 #define AXIS_LEN 1.
 50     vtkSmartPointer<vtkAxesActor> oriAxesActor =
 51         vtkSmartPointer<vtkAxesActor>::New();  52     oriAxesActor->SetPosition(0, 0, 0);  53     oriAxesActor->SetTotalLength(AXIS_LEN, AXIS_LEN, AXIS_LEN);  54     oriAxesActor->SetShaftType(0);  55     oriAxesActor->SetAxisLabels(0);  56     oriAxesActor->SetCylinderRadius(0.02);  57  
 58     vtkSmartPointer<vtkAxesActor> axesActor =
 59         vtkSmartPointer<vtkAxesActor>::New();  60     axesActor->SetPosition(0, 0, 0);  61     axesActor->SetTotalLength(AXIS_LEN, AXIS_LEN, AXIS_LEN);  62     axesActor->SetShaftType(0);  63     axesActor->SetAxisLabels(0);  64     axesActor->SetCylinderRadius(0.02);  65  
 66     vtkSmartPointer<vtkTextActor> textActor = 
 67         vtkSmartPointer<vtkTextActor>::New();  68     textActor->SetPosition2(100, 40);  69     textActor->GetTextProperty()->SetFontSize(24);  70     textActor->GetTextProperty()->SetColor(1, 0, 0);  71  
 72  
 73     vtkSmartPointer<vtkTransform> trans = 
 74         vtkSmartPointer<vtkTransform>::New();  75  
 76 #if 0
 77     trans->PostMultiply();  78  
 79     coneActor->SetPosition(1, 0, 0);  80     //trans->Translate(1, 0, 0);  81     //trans->RotateZ(45);
 82     trans->RotateZ(45);  83     trans->Translate(1, 0, 0);  84     coneActor->SetUserTransform(trans);  85     //textActor->SetInput("PostMultiply()\nTranslate(1, 0, 0)\nRotateZ(45)");
 86     textActor->SetInput("PostMultiply()\nRotateZ(45)\nTranslate(1, 0, 0)");  87 #endif
 88  
 89 #if 1
 90     //coneActor->RotateZ(45);  91     //coneActor->SetPosition(1, 0, 0);  92     //textActor->SetInput("coneActor->RotateZ(45)\nconeActor->SetPosition(1, 0, 0)");
 93  
 94     trans->RotateZ(45);  95     trans->Translate(1, 0, 0);  96     coneActor->SetUserTransform(trans);  97     textActor->SetInput("trans->RotateZ(45)\ntrans->Translate(1, 0, 0)\nconeActor->SetUserTransform(trans)");  98  
 99     cout << "GetMatrix:" << endl; 100     if (coneActor->GetMatrix()!=NULL) 101  { 102         coneActor->GetMatrix()->Print(cout); 103  } 104     else
105  { 106         cout << "NULL" << endl; 107  } 108     cout << "GetUserMatrix:" << endl; 109     if (coneActor->GetUserMatrix() !=NULL) 110  { 111         coneActor->GetUserMatrix()->Print(cout); 112  } 113     else
114  { 115         cout << "NULL" << endl; 116  } 117     //cout << "GetUserTransform:" << endl; 118     //if (coneActor->GetUserTransform() !=NULL) 119     //{ 120     // coneActor->GetUserTransform()->Print(cout); 121     //} 122     //else 123     //{ 124     // cout << "NULL" << endl; 125     //}
126 #endif
127     vtkSmartPointer<vtkRenderer> renderer1 =
128         vtkSmartPointer<vtkRenderer>::New(); 129     vtkSmartPointer<vtkRenderer> renderer2 =
130         vtkSmartPointer<vtkRenderer>::New(); 131  
132     vtkSmartPointer<vtkRenderWindow> renderWindow =
133         vtkSmartPointer<vtkRenderWindow>::New(); 134     renderWindow->SetSize(800, 400); 135     renderWindow->AddRenderer(renderer1); 136     renderWindow->AddRenderer(renderer2); 137     vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
138         vtkSmartPointer<vtkRenderWindowInteractor>::New(); 139     renderWindowInteractor->SetRenderWindow(renderWindow); 140  
141     double leftViewport[] = { 0.0, 0.0, 0.5, 1.0 }; 142     double rightViewport[] = { 0.5, 0.0, 1.0, 1.0 }; 143  
144     renderer1->AddActor(oriAxesActor); 145     renderer1->AddActor(sphereActor); 146     renderer1->AddActor(oriConeActor); 147     renderer2->AddActor(axesActor); 148     renderer2->AddActor(sphereActor); 149     renderer2->AddActor(coneActor); 150     renderer2->AddActor2D(textActor); 151     renderer1->SetBackground(.3, .3, .5); 152     renderer2->SetBackground(.2, .4, .5); 153     renderer1->SetViewport(leftViewport); 154     renderer2->SetViewport(rightViewport); 155  
156     renderWindow->Render(); 157     renderWindowInteractor->Start(); 158  
159     return EXIT_SUCCESS; 160 }

 


免責聲明!

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



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