程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 坐標變換

坐標變換

編輯:關於VC++

摘要

坐標變換是圖形學中很基本的操作。無論繪制二維還是三維圖形都會遇到。下面將會講到:

  1. 如何根據坐標架進行點的坐標變換。
  2. 如何根據坐標架生成變換矩陣。
  3. 如何通過矩陣作點的坐標變換。
  4. 曲線、曲面方程如何作變換。

1、如何根據坐標架進行點的坐標變換

首先坐標架定義成:

struct PNT3D{
  double x,y,z;
};
struct FRAME{
  PNT3D O, OX, OY, OZ;
};

假設有一個點 p 定義在 frame 所在坐標系 WC(World Coordinate) 之中,也就是說 p 在 frame 之外。為了將 p 轉入 frame,我們首先需要作平移 p1 = p - frame.O; 這個時候 p1 相當於定義在一個將 WC 平移到 frame.O 的一個坐標架之中。這個坐標架和 frame.O 供用坐標原點,但是三個坐標軸並不一定相同。為了得到 frame 中的三個坐標分量我們只須將 p1 和三個基矢量作點積 :

WC->frame 變換公式:
p2.x = p1*frame.OX = (p-frame.O)*frame.OX;
p2.y = p1*frame.OY = (p-frame.O)*frame.OY;
p2.z = p1*frame.OZ = (p-frame.O)*frame.OZ;

其中 * 代表點積。這裡所得到的 p2 就是 WC 中的 p 在 frame 中對應的點。到此為止我們完成了電從坐標架之外變換到坐標架內。同樣的,我們也可以采用簡單的方法把點從坐標架內變換到坐標架之外。假設 p 是 frame 之內的點,首先

p1 = p.x*frame.OX + p.y*frame.OY + p.z*frame.OZ;

上面的公式將 p 的各個分量作為權值將三個坐標架的基矢量累加起來,得到的 p1 相當於平移 WC 和 frame 重合坐標原點的坐標架中的點。接下來,自然是處理平移

frame->WC 變換公式:
p2 = p1 + freame.O;
 = p.x*frame.OX + p.y*frame.OY + p.z*frame.OZ + frame.O;

p2 就是轉換到 WC 的點。

2、如何根據坐標架生成變換矩陣

矩陣在圖形程序中應用十分廣泛。它可以表達更復雜的變換形式。這裡所指的矩陣是左乘矩陣,即矩陣位於點的左邊。

我們可以用一個矩陣來代表從坐標架外到坐標架中的變換,也可以用一個矩陣代表從坐標架之中到坐標架之外的變換。下面的 mat 是按照行優先規則存放的矩陣。從坐標架中變換到坐標架外 frame->WC 的矩陣如下 frame->WC 變換矩陣:

mat[0] = OX.x;  mat[1] = OY.x;  mat[2] = OZ.x;  mat[3] = Oc.x;
mat[4] = OX.y;  mat[5] = OY.y;  mat[6] = OZ.y;  mat[7] = Oc.y;
mat[8] = OX.z;  mat[9] = OY.z;  mat[10] = OZ.z;  mat[11] = Oc.z;
mat[12] = 0;  mat[13] = 0;  mat[14] = 0;  mat[15] = 1;

其中,OX, OY, OZ 是坐標架的三個基矢量,Oc 是坐標架的坐標原點。我們將這個矩陣乘以點 p(x,y,z,1)

p1 = mat*p;

我們可以得到 p1 就是 WC 坐標系下面的點。下面是這個矩陣的推導過程,如果覺得頭大,可以跳過去。

推導過程:

首先我們來看上面得到的根據一個坐標架,從坐標架內轉換到坐標架外的公式:

Px 是被轉換的點,P1 是轉換後的點。為了書寫方便,我們把 frame.OX 寫成 OX,其余類推。於是得到:

這個公式已經可以看到矩陣的影子了。為了進一步向 4*4 的矩陣靠近,我們采用齊次形式:

我們把它逐漸展開,我們就得到了這一大堆東西,這下子矩陣相乘的形式出來了。這裡的 4*4 的矩陣,就是上面的 mat 數組。

搞定了 frame->WC 的矩陣,我們現在來搞 WC->frame 的矩陣,

WC->frame 變換矩陣:

mat[0] = OX.x;  mat[1] = OX.y;  mat[2] = OX.z;  mat[3] = -(Oc.x*OX.x + Oc.y*OX.y + Oc.z*OX.z);
mat[4] = OY.x;  mat[5] = OY.y;  mat[6] = OY.z;  mat[7] = -(Oc.x*OY.x + Oc.y*OY.y + Oc.z*OY.z);
mat[8] = OZ.x;  mat[9] = OZ.y;  mat[10] = OZ.z;  mat[11] = -(Oc.x*OZ.x + Oc.y*OZ.y + Oc.z*OZ.z);
mat[12] = 0;  mat[13] = 0;  mat[14] = 0;  mat[15] = 1;

寫代碼的時候把這一堆抄過去就行了。如果不想看推導,就跳過下面的部分。

推導過程:

同樣的我們根據上面的式子出發進行推導:

在這裡,我們把點也搞成了齊次形式,位的是更好的向 4*4 矩陣邁進。我們繼續拆解上面第二個式子的右面部分

其實也很容易出來(不過炮炮是想了很長時間才想出來的:)。

3、如何通過矩陣作點的坐標變換

這個最好辦了。我們這裡討論的矩陣都是左乘矩陣,所以把矩陣乘以點就完成了變換。

x = M[0][0]*Px + M[0][1]*Py + M[0][2]*Pz + M[0][3];
y = M[1][0]*Px + M[1][1]*Py + M[1][2]*Pz + M[1][3];
z = M[2][0]*Px + M[2][1]*Py + M[2][2]*Pz + M[2][3];

這裡的 M 是一個 4*4 的二維數組,存放行優先的矩陣。

4、曲線、曲面方程如何作變換

曲線、曲面方程有參數方程、非參數方程等形式。當然曲線、曲面還可能由微分方程描述。這個時候微分方程如果沒有公式解,事情就很麻煩。計算機中一般比較容易處理參數方程。參數方程作變換形式上很簡單 。

右邊的結果會得到一個矢量,最終可以得到 (F1x, F1y, F1z) 的形式,這是一個新的參數方程。如果曲線曲面由非參數方程描述 F(x,y,z)=0,比如

這個時候,你可以嘗試解出 x,y,z:

令 x = u,y = v,可以得到

這下得到參數方程了,可以按照前面講的步驟作轉換。最後你會得到曲線、曲面變換後的參數方程。接下來你可以嘗試著消去這些中間參數 u,v。這個過程可能會比較艱難。

如果遇到隱式方程,無法解出,比如

這是最倒霉的情況,求解是沒希望的。當然,如果你不要求精確的公式,你還是可以先令 x=u, y=v,代入之後,用泰勒展開求的 z 的級數,這也是一個方法哦:)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved