【图形学】三维几何变换理论和实现

发布时间:2024年01月24日

和二维几何变换一样,三维几何变换也要引入齐次坐标。点(x,y,z)的规范化齐次坐标为(x,y,z,1)。那么三维变换矩阵就是一个4*4的方阵。
T = ( a b c l d e f m g h i n p q r s ) T=\begin{pmatrix} a&b&c&l\\d&e&f&m\\g&h&i&n\\p&q&r&s \end{pmatrix} T= ?adgp?behq?cfir?lmns? ?
这个矩阵可以分为如下4个子矩阵
T 0 = ( a b c d e f g h i ) T 1 = ( l m n ) T 2 = ( p q r ) T 3 = ( s ) T_0=\begin{pmatrix} a&b&c\\d&e&f\\g&h&i \end{pmatrix} T_1=\begin{pmatrix} l\\m\\n\end{pmatrix}T_2=\begin{pmatrix}p&q&r\end{pmatrix}T_3=\begin{pmatrix}s\end{pmatrix} T0?= ?adg?beh?cfi? ?T1?= ?lmn? ?T2?=(p?q?r?)T3?=(s?)
其中 T 0 T_0 T0?进行比例、旋转、对称、错切变换 T 1 T_1 T1?进行平移变换, T 2 T_2 T2?进行投影变换, T 3 T_3 T3?对物体进行整体的比例变换。

平移变换

{ x ′ = x + T x y ′ = y + T y z ′ = z + T z ( T x , T y , T z 是平移系数 ) \begin{cases} x^{\prime}=x+T_x\\ y^{\prime}=y+T_y\\ z^{\prime}=z+T_z \end{cases}(T_x,T_y,T_z是平移系数) ? ? ??x=x+Tx?y=y+Ty?z=z+Tz??(Tx?,Ty?,Tz?是平移系数)
设三维平移变换矩阵为T
( x ′ y ′ z ′ 1 ) = ( x + T x y + T y z + T z 1 ) = T ( x y z 1 ) 得到 T = ( 1 0 0 T x 0 1 0 T y 0 0 0 T z 0 0 0 1 ) \begin{pmatrix} x^{\prime}\\y^{\prime}\\z^{\prime}\\1 \end{pmatrix}=\begin{pmatrix}x+T_x\\y+T_y\\z_+T_z\\1\end{pmatrix}=T\begin{pmatrix}x\\y\\z\\1\end{pmatrix}得到T=\begin{pmatrix}1&0&0&T_x\\0&1&0&T_y\\0&0&0&T_z\\0&0&0&1\end{pmatrix} ?xyz1? ?= ?x+Tx?y+Ty?z+?Tz?1? ?=T ?xyz1? ?得到T= ?1000?0100?0000?Tx?Ty?Tz?1? ?

比例变换

P ( x , y , z ) 相对于原点,沿 x 轴方向缩放 S x 倍,沿 Y 轴方向缩放 S y 倍 , 沿 z 轴方向缩放 S z 倍到点 P ′ ( x ′ , y ′ , z ′ ) P(x,y,z)相对于原点,沿x轴方向缩放S_x倍,沿Y轴方向缩放S_y倍,沿z轴方向缩放S_z倍到点P_{\prime}(x^{\prime},y^{\prime},z^{\prime}) P(x,y,z)相对于原点,沿x轴方向缩放Sx?倍,沿Y轴方向缩放Sy?,沿z轴方向缩放Sz?倍到点P?(x,y,z)
设三维变换矩阵为T
( x ′ y ′ z ′ 1 ) = ( x T x y T y z T z 1 ) = T ( x y z 1 ) 得到 T = ( T x 0 0 0 0 T y 0 0 0 0 T z 0 0 0 0 1 ) \begin{pmatrix} x^{\prime}\\y^{\prime}\\z^{\prime}\\1 \end{pmatrix}=\begin{pmatrix}xT_x\\yT_y\\zT_z\\1\end{pmatrix}=T\begin{pmatrix}x\\y\\z\\1\end{pmatrix}得到T=\begin{pmatrix}T_x&0&0&0\\0&T_y&0&0\\0&0&T_z&0\\0&0&0&1\end{pmatrix} ?xyz1? ?= ?xTx?yTy?zTz?1? ?=T ?xyz1? ?得到T= ?Tx?000?0Ty?00?00Tz?0?0001? ?

更一般的情况, P 相对于点 ( p x , p y , p z ) 进行比例变换到 P ′ P相对于点(p_x,p_y,p_z)进行比例变换到P^{\prime} P相对于点(px?,py?,pz?)进行比例变换到P。有 { x ′ = S x ( x ? p x ) + p x y ′ = S y ( y ? p y ) + p y z ′ = S z ( z ? p z ) + p z \begin{cases} x^{\prime}=S_x(x-p_x)+p_x\\ y^{\prime}=S_y(y-p_y)+p_y\\ z^{\prime}=S_z(z-p_z)+p_z \end{cases} ? ? ??x=Sx?(x?px?)+px?y=Sy?(y?py?)+py?z=Sz?(z?pz?)+pz??
此时的三维变换矩阵T为 T = ( S x 0 0 p x ( 1 ? S x ) 0 S y 0 p y ( 1 ? S y ) 0 0 S z p z ( 1 ? S z ) 0 0 0 1 ) \\T=\begin{pmatrix} S_x&0&0&p_x(1-S_x)\\ 0&S_y&0&p_y(1-S_y)\\ 0&0&S_z&p_z(1-S_z)\\ 0&0&0&1 \end{pmatrix} T= ?Sx?000?0Sy?00?00Sz?0?px?(1?Sx?)py?(1?Sy?)pz?(1?Sz?)1? ?

旋转变换

对点(x,y,z)相对于原点(0,0,0)进行旋转操作,采用右手坐标系,即大拇指指向旋转轴的正方向,四指的转向为转角的正方向。旋转我们可分为绕x轴、y轴、z轴旋转。假设绕x轴旋转角度为 α \alpha α,绕y轴旋转角度为 β \beta β,绕z轴旋转的角度为 γ \gamma γ。则相应的变换如下:

绕x轴旋转

{ x ′ = x y ′ = y cos ? α ? z sin ? α z ′ = y sin ? α + z cos ? α 三维旋转矩阵 T = ( 1 0 0 0 0 cos ? α ? sin ? α 0 0 sin ? α cos ? α 0 0 0 0 1 ) \begin{cases} x^{\prime}=x\\ y^{\prime}=y\cos\alpha-z\sin\alpha\\ z^{\prime}=y\sin\alpha+z\cos\alpha \end{cases}\\三维旋转矩阵T=\begin{pmatrix} 1&0&0&0\\ 0&\cos\alpha&-\sin\alpha&0\\ 0&\sin\alpha&\cos\alpha&0\\ 0&0&0&1 \end{pmatrix} ? ? ??x=xy=ycosα?zsinαz=ysinα+zcosα?三维旋转矩阵T= ?1000?0cosαsinα0?0?sinαcosα0?0001? ?

绕Y轴旋转

{ x ′ = x cos ? β + z sin ? β y ′ = y z ′ = ? x sin ? β + z cos ? β 三维旋转矩阵 T = ( cos ? β 0 sin ? β 0 0 1 0 0 ? sin ? β 0 cos ? β 0 0 0 0 1 ) \begin{cases} x^{\prime}=x\cos\beta+z\sin\beta\\ y^{\prime}=y\\ z^{\prime}=-x\sin\beta+z\cos\beta \end{cases}\\三维旋转矩阵T=\begin{pmatrix} \cos\beta&0&\sin\beta&0\\ 0&1&0&0\\ -\sin\beta&0&\cos\beta&0\\ 0&0&0&1 \end{pmatrix} ? ? ??x=xcosβ+zsinβy=yz=?xsinβ+zcosβ?三维旋转矩阵T= ?cosβ0?sinβ0?0100?sinβ0cosβ0?0001? ?

绕Z轴旋转

{ x ′ = x cos ? γ ? y sin ? γ y ′ = y sin ? γ + z cos ? γ z ′ = z 三维旋转矩阵 T = ( cos ? γ ? sin ? γ 0 0 sin ? γ cos ? γ 0 0 0 0 0 0 0 0 0 1 ) \begin{cases} x^{\prime}=x\cos\gamma-y\sin\gamma\\ y^{\prime}=y\sin\gamma+z\cos\gamma\\ z^{\prime}=z \end{cases}\\三维旋转矩阵T=\begin{pmatrix} \cos\gamma&-\sin\gamma&0&0\\ \sin\gamma&\cos\gamma&0&0\\ 0&0&0&0\\ 0&0&0&1 \end{pmatrix} ? ? ??x=xcosγ?ysinγy=ysinγ+zcosγz=z?三维旋转矩阵T= ?cosγsinγ00??sinγcosγ00?0000?0001? ?

对称变换

  • 关于x轴对称
    三维变换矩阵T
    T = ( 1 0 0 0 0 ? 1 0 0 0 0 ? 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ 0&-1&0&0\\ 0&0&-1&0\\ 0&0&0&1 \end{pmatrix} T= ?1000?0?100?00?10?0001? ?
  • 关于y轴对称,三维变换矩阵T
    T = ( ? 1 0 0 0 0 1 0 0 0 0 ? 1 0 0 0 0 1 ) T=\begin{pmatrix} -1&0&0&0\\ 0&1&0&0\\ 0&0&-1&0\\ 0&0&0&1 \end{pmatrix} T= ??1000?0100?00?10?0001? ?
  • 关于z轴对称,三维变换矩阵T
    T = ( ? 1 0 0 0 0 ? 1 0 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} -1&0&0&0\\ 0&-1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= ??1000?0?100?0010?0001? ?
  • 关于xOy面对称
    三维变换矩阵T
    T = ( 1 0 0 0 0 1 0 0 0 0 ? 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ 0&1&0&0\\ 0&0&-1&0\\ 0&0&0&1 \end{pmatrix} T= ?1000?0100?00?10?0001? ?
  • 关于yOz面对称
    三维变换矩阵T
    T = ( ? 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} -1&0&0&0\\ 0&1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= ??1000?0100?0010?0001? ?
  • 关于zOx面对称
    三维变换矩阵T
    T = ( 1 0 0 0 0 ? 1 0 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ 0&-1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= ?1000?0?100?0010?0001? ?

错切变换

沿xy平面错切(z不变)
{ x ′ = x + λ x z y ′ = λ y z + y \begin{cases} x^{\prime}=x+\lambda _x z\\y^{\prime}=\lambda _yz+y \end{cases} {x=x+λx?zy=λy?z+y?
三维变换矩阵T为 T = ( 1 0 λ x 0 0 1 λ y 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&\lambda _x&0\\ 0&1&\lambda _y&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= ?1000?0100?λx?λy?10?0001? ?
沿xz平面错切(y不变)
{ x ′ = x + λ x y z ′ = λ y y + z \begin{cases} x^{\prime}=x+\lambda _x y\\ z^{\prime}=\lambda _yy+z \end{cases} {x=x+λx?yz=λy?y+z?
三维变换矩阵T为 T = ( 1 λ x 0 0 0 1 0 0 0 λ z 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&\lambda _x&0&0\\ 0&1&0&0\\ 0&\lambda _z&1&0\\ 0&0&0&1 \end{pmatrix} T= ?1000?λx?1λz?0?0010?0001? ?
沿yz平面错切(x不变)
{ y ′ = y + λ x x z ′ = λ y x + z \begin{cases} y^{\prime}=y+\lambda _x x\\ z^{\prime}=\lambda _yx+z \end{cases} {y=y+λx?xz=λy?x+z?
三维变换矩阵T为 T = ( 1 0 0 0 λ y 1 0 0 λ z 0 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ \lambda _y&1&0&0\\ \lambda _z&0&1&0\\ 0&0&0&1 \end{pmatrix} T= ?1λy?λz?0?0100?0010?0001? ?

代码实现

class CTransform3
{
public:
	CTransform3();
	virtual ~CTransform3();
	void Identity();//单位矩阵初始化
	void SetMatrix(CPoint3* P, int ptNumber);//三维顶点数组初始化
	void Translate(double tx, double ty, double tz);//平移变换
	void Scale(double sx, double sy, double sz);//比例变换
	void Scale(double sx, double sy, double sz, CPoint3 p);//相对于任意点的比例变换
	void RotateX(double alpha);//绕X轴旋转变换
	void RotateY(double beta);//绕Y轴旋转变换
	void RotateZ(double gamma);//绕Z轴旋转变换	
	void RotateX(double alpha, CPoint3 p);//相对于任意点的绕X轴旋转变换
	void RotateY(double beta, CPoint3 p);//相对于任意点的绕Y轴旋转变换
	void RotateZ(double gamma, CPoint3 p);//相对于任意点的绕Z轴旋转变换
	void ReflectX();//关于X轴反射变换
	void ReflectY();//关于Y轴反射变换
	void ReflectZ();//关于Z轴反射变换
	void ReflectXOY();//关于XOY面反射变换
	void ReflectYOZ();//关于YOZ面反射变换
	void ReflectZOX();//关于ZOX面反射变换
	void ShearXY(double a, double b);//沿XY平面错切变换
	void ShearYZ(double a, double b);//沿YZ平面错切变换
	void ShearXZ(double a, double b);//沿XZ平面错切变换
	void MultiplyMatrix();//矩阵相乘
private:
	double	m_matrix[4][4];//三维变换矩阵	
	CPoint3* m_p;//三维顶点数组名
	int	m_pNum;//三维顶点个数
};
#define PI 3.1415926//圆周率

CTransform3::CTransform3(void)
{

}

CTransform3::~CTransform3(void)
{

}

void CTransform3::Identity(void)//单位矩阵初始化
{
	m_matrix[0][0] = 1.0; m_matrix[0][1] = 0.0; m_matrix[0][2] = 0.0; m_matrix[0][3] = 0.0;
	m_matrix[1][0] = 0.0; m_matrix[1][1] = 1.0; m_matrix[1][2] = 0.0; m_matrix[1][3] = 0.0;
	m_matrix[2][0] = 0.0; m_matrix[2][1] = 0.0; m_matrix[2][2] = 1.0; m_matrix[2][3] = 0.0;
	m_matrix[3][0] = 0.0; m_matrix[3][1] = 0.0; m_matrix[3][2] = 0.0; m_matrix[3][3] = 1.0;
}

void CTransform3::SetMatrix(CPoint3* P, int ptNumber)//顶点数组初始化
{
	this->m_p = P;
	this->m_pNum = ptNumber;
}

void CTransform3::Translate(double tx, double ty, double tz)//平移变换
{
	Identity();
	m_matrix[0][3] = tx;
	m_matrix[1][3] = ty;
	m_matrix[2][3] = tz;
	MultiplyMatrix();
}

void CTransform3::Scale(double sx, double sy, double sz)//比例变换
{
	Identity();
	m_matrix[0][0] = sx;
	m_matrix[1][1] = sy;
	m_matrix[2][2] = sz;
	MultiplyMatrix();
}

void CTransform3::Scale(double sx, double sy, double sz, CPoint3 p)//相对于任意点的比例变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	Scale(sx, sy, sz);
	Translate(p.m_x, p.m_y, p.m_z);
}
void CTransform3::RotateX(double beta)//绕X轴旋转变换
{
	Identity();
	double rad = beta * PI / 180;
	m_matrix[1][1] = cos(rad); m_matrix[1][2] = -sin(rad);
	m_matrix[2][1] = sin(rad); m_matrix[2][2] = cos(rad);
	MultiplyMatrix();
}

void CTransform3::RotateY(double beta)//绕Y轴旋转变换
{
	Identity();
	double rad = beta * PI / 180;
	m_matrix[0][0] = cos(rad); m_matrix[0][2] = sin(rad);
	m_matrix[2][0] = -sin(rad); m_matrix[2][2] = cos(rad);
	MultiplyMatrix();
}

void CTransform3::RotateZ(double beta)//绕Z轴旋转变换
{
	Identity();
	double rad = beta * PI / 180;
	m_matrix[0][0] = cos(rad); m_matrix[0][1] = -sin(rad);
	m_matrix[1][0] = sin(rad); m_matrix[1][1] = cos(rad);
	MultiplyMatrix();
}

void CTransform3::RotateX(double beta, CPoint3 p)//相对于任意点的X轴旋转变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	RotateX(beta);
	Translate(p.m_x, p.m_y, p.m_z);
}

void CTransform3::RotateY(double beta, CPoint3 p)//相对于任意点的Y轴旋转变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	RotateY(beta);
	Translate(p.m_x, p.m_y, p.m_z);
}

void CTransform3::RotateZ(double beta, CPoint3 p)//相对于任意点的Z轴旋转变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	RotateZ(beta);
	Translate(p.m_x, p.m_y, p.m_z);
}

void CTransform3::ReflectX(void)//X轴反射变换
{
	Identity();
	m_matrix[1][1] = -1;
	m_matrix[2][2] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectY(void)//Y轴反射变换
{
	Identity();
	m_matrix[0][0] = -1;
	m_matrix[2][2] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectZ(void)//Z轴反射变换
{
	Identity();
	m_matrix[0][0] = -1;
	m_matrix[1][1] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectXOY(void)//XOY面反射变换
{
	Identity();
	m_matrix[2][2] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectYOZ(void)//YOZ面反射变换
{
	Identity();
	m_matrix[0][0] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectZOX(void)//XOZ面反射变换
{
	Identity();
	m_matrix[1][1] = -1;
	MultiplyMatrix();
}

void CTransform3::ShearXY(double a, double b)
{
	Identity();
	m_matrix[0][2] = a;
	m_matrix[0][2] = b;
	MultiplyMatrix();
}

void CTransform3::ShearYZ(double a, double b)
{
	Identity();
	m_matrix[0][1] = a;
	m_matrix[2][1] = b;
	MultiplyMatrix();
}

void CTransform3::ShearXZ(double a, double b)
{
	Identity();
	m_matrix[1][0] = a;
	m_matrix[2][0] = b;
	MultiplyMatrix();
}



void CTransform3::MultiplyMatrix(void)//矩阵相乘
{
	CPoint3* PTemp = new CPoint3[m_pNum];
	for (int i = 0; i < m_pNum; i++)
		PTemp[i] = m_p[i];
	for (int i = 0; i < m_pNum; i++)
	{
		m_p[i].m_x = m_matrix[0][0] * PTemp[i].m_x + m_matrix[0][1] * PTemp[i].m_y + m_matrix[0][2] * PTemp[i].m_z + m_matrix[0][3] * PTemp[i].m_w;
		m_p[i].m_y = m_matrix[1][0] * PTemp[i].m_x + m_matrix[1][1] * PTemp[i].m_y + m_matrix[1][2] * PTemp[i].m_z + m_matrix[1][3] * PTemp[i].m_w;
		m_p[i].m_z = m_matrix[2][0] * PTemp[i].m_x + m_matrix[2][1] * PTemp[i].m_y + m_matrix[2][2] * PTemp[i].m_z + m_matrix[2][3] * PTemp[i].m_w;
		m_p[i].m_w = m_matrix[3][0] * PTemp[i].m_x + m_matrix[3][1] * PTemp[i].m_y + m_matrix[3][2] * PTemp[i].m_z + m_matrix[3][3] * PTemp[i].m_w;
	}
	delete[]PTemp;
}
文章来源:https://blog.csdn.net/m0_72895175/article/details/135831491
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。