幾何變換

幾何變換詳解
在三維圖形學中,幾何變換大致分爲三種,平移變換(Translation),縮放變換(Scaling),旋轉變換(Rotation)。以下討論皆針對DirectX,所以使用左手座標系。

平移變換

將三維空間中的一個點[x, y, z, 1]移動到另外一個點[x’, y’, z’, 1],三個座標軸的移動分量分別爲dx=Tx, dy=Ty, dz=Tz, 即

x’ = x + Tx

y’ = y + Ty

z’ = z + Tz

平移變換的矩陣如下。
在這裏插入圖片描述

縮放變換

將模型放大或者縮小,本質也是對模型上每個頂點進行放大和縮小(頂點座標值變大或變小),假設變換前的點是[x, y, z, 1],變換後的點是[x’, y’, z’, 1],那麼

x’ = x * Sx

y’ = y * Sy

z’ = z * Sz

縮放變換的矩陣如下。
在這裏插入圖片描述

旋轉變換

這是三種變換中最複雜的變換,這裏只討論最簡單的情況,繞座標軸旋轉,關於繞任意軸旋轉,在後續的隨筆中介紹。

繞X軸旋轉
在這裏插入圖片描述

繞X軸旋轉時,頂點的x座標不發生變化,y座標和z座標繞X軸旋轉θ度,旋轉的正方向爲順時針方向(沿着旋轉軸負方向向原點看)。[x, y, z, 1]表示變換前的點,[x’, y’, z’, 1]表示變換後的點。變換矩陣如下。關於旋轉的正方向,OpenGL與多數圖形學書籍規定旋轉正方向爲逆時針方向(沿着座標軸負方向向原點看),比如Computer Graphics C Version,p409。
在這裏插入圖片描述

繞Y軸旋轉

在這裏插入圖片描述
繞Y軸旋轉時,頂點的y座標不發生變化,x座標和z座標繞Y軸旋轉θ度。[x, y, z, 1]表示變換前的點,[x’, y’, z’, 1]表示變換後的點。變換矩陣如下。
在這裏插入圖片描述

繞Z軸旋轉

在這裏插入圖片描述
繞Z軸旋轉時,頂點的z座標不發生變化,x座標和y座標繞Z軸旋轉θ度。[x, y, z, 1]表示變換前的點,[x’, y’, z’, 1]表示變換後的點。變換矩陣如下。
在這裏插入圖片描述

繞座標軸旋轉的矩陣推導
上面三個旋轉矩陣是如何得來的呢?我們推導一下,首先看一下二維的情況,再擴展到三維即可。實際上上面三種繞座標軸旋轉的情況屬於特殊的二維旋轉,比如繞Z軸旋轉,相當於在與XOY平面上繞原點做二維旋轉。

假設點P(x, y)是平面直角座標系內一點,其到原點的距離爲r,其與X軸的夾角爲A,現將點P繞原點旋轉θ度,得到點P’(x’, y’),P’與X軸的夾角爲B,則A = B - θ。(注意,在二維座標中,逆時針旋轉時角度爲正,順時針旋轉時角度爲負,下圖中由P旋轉到P’,角度爲θ,若是由P’轉到P,則角度爲-θ)。

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
於是可得下面的轉換方程

在這裏插入圖片描述(式一)

寫成矩陣的形式就是
在這裏插入圖片描述
求得旋轉矩陣爲
在這裏插入圖片描述

由於這裏使用齊次座標,所以還需加上一維,最終變成如下形式(繞Z軸旋轉矩陣)
在這裏插入圖片描述

和前面給出的繞Z軸旋轉矩陣完全吻合。

對於繞X軸旋轉的情況,我們只需將式一中的x用y替換,y用z替換,z用x替換即可。替換後得到
在這裏插入圖片描述(式二)
對應的旋轉矩陣爲(繞X軸旋轉矩陣):
在這裏插入圖片描述

對於繞Y軸旋轉的情況,只需對式二做一次同樣的替換即可,的到的變換方程爲
在這裏插入圖片描述
對應的變換矩陣爲(繞Y軸旋轉矩陣):
在這裏插入圖片描述

逆矩陣

平移變換矩陣的逆矩陣與原來的平移量相同,但是方向相反。
在這裏插入圖片描述
旋轉變換矩陣的逆矩陣與原來的旋轉軸相同但是角度相反。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
縮放變換的逆矩陣正好和原來的效果相反,如果原來是放大,則逆矩陣是縮小,如果原來是縮小,則逆矩陣是放大。
在這裏插入圖片描述

作者:zdd
出處:http://www.cnblogs.com/graphics/


動動小手

#include "rotate.h"

bool rotate_Z(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_rotated, float theta)
{
	/* Reminder: how transformation matrices work :
	|-------> This column is the translation
	| cos(theta) -sin(theta) 0 x |  \
	| sin(theta)  cos(theta) 0 y |   }-> The identity 3x3 matrix (Z axis) on the left
	| 0           0          1 z |  /
	| 0           0          0 1 |    -> We do not use this line (and it has to stay 0,0,0,1)

	This is the "manual" method, perfect to understand but error prone !
	*/

	Eigen::Matrix4f transform = Eigen::Matrix4f::Identity();
	//float theta = M_PI / 2;
	transform(0, 0) = cos(theta);
	transform(0, 1) = -sin(theta);
	transform(1, 0) = sin(theta);
	transform(1, 1) = cos(theta);
	pcl::transformPointCloud(*cloud, *cloud_rotated, transform);
	
	return true;
}

bool rotate_X(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_rotated, float theta)
{
	/* Reminder: how transformation matrices work :
	|-------> This column is the translation
	| 1 0           0          x |  \
	| 0 cos(theta)  sin(theta) y |   }-> The identity 3x3 matrix (X axis) on the left
	| 0 -sin(theta) cos(theta) z |  /
	| 0 0           0          1 |    -> We do not use this line (and it has to stay 0,0,0,1)

	This is the "manual" method, perfect to understand but error prone !
	*/

	Eigen::Matrix4f transform = Eigen::Matrix4f::Identity();
	//float theta = M_PI / 2;
	transform(1, 1) = cos(theta);
	transform(1, 2) = sin(theta);
	transform(2, 1) = -sin(theta);
	transform(2, 2) = cos(theta);
	pcl::transformPointCloud(*cloud, *cloud_rotated, transform);

	return true;
}

bool rotate_Y(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_rotated, float theta)
{
	/* Reminder: how transformation matrices work :
	|-------> This column is the translation
	| cos(theta) 0          -sin(theta) x |  \
	| 0          1          0           y |   }-> The identity 3x3 matrix (Y axis) on the left
	| sin(theta) 0          cos(theta)  z |  /
	| 0          0          0           1 |    -> We do not use this line (and it has to stay 0,0,0,1)

	This is the "manual" method, perfect to understand but error prone !
	*/

	Eigen::Matrix4f transform = Eigen::Matrix4f::Identity();
	//float theta = M_PI / 2;
	transform(0, 0) = cos(theta);
	transform(0, 2) = -sin(theta);
	transform(2, 0) = sin(theta);
	transform(2, 2) = cos(theta);
	pcl::transformPointCloud(*cloud, *cloud_rotated, transform);

	return true;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章