计算机图形学13:三维图形的几何变换

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 计算机图形学13:三维图形的几何变换,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

在这里插入图片描述

作者:非妃是公主
专栏:《计算机图形学》
博客地址https://blog.csdn.net/myf_666
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩
在这里插入图片描述

专栏推荐

专栏名称 专栏地址
软件工程 专栏——软件工程
计算机图形学 专栏——计算机图形学
操作系统 专栏——操作系统
软件测试 专栏——软件测试
机器学习 专栏——机器学习
数据库 专栏——数据库
算法 专栏——算法

专栏系列文章

文章名称 文章地址
直线生成算法(DDA算法) 计算机图形学01——DDA算法
中点BH算法绘制直线 计算机图形学02——中点BH算法
改进的中点BH算法 计算机图形学03——改进的中点BH算法
中点Bresenham画椭圆 计算机图形学04——中点BH绘制椭圆
中点BH算法绘制任意斜率直线 计算机图形学05——中点BH算法绘制任意斜率的直线
中点Bresenham画圆 计算机图形学06——中点BH算法画圆
有效边表法的多边形扫描转换 计算机图形学07——有效边表法绘制填充多边形
中点BH算法绘制抛物线

100

x

=

y

2

100x = y^2

100x=y2

计算机图形学08——中点BH绘制抛物线
二维观察之点的裁剪计算机图形学09——二维观察之点裁剪
二维观察之线的裁剪计算机图形学10——二维观察之线裁剪
二维观察之多边形的裁剪计算机图形学11——二维观察之多边形裁剪
二维图形的几何变换计算机图形学12——二维图形几何变换
三维图形的几何变换计算机图形学13——三维图形几何变换
三维图形的投影变换计算机图形学14——三维图形投影变换

计算机图形学(英语:computer graphics,缩写为CG)是研究计算机在硬件和软件的帮助下创建计算机图形的科学学科,是计算机科学的一个分支领域,主要关注数字合成与操作视觉的图形内容。虽然这个词通常被认为是指三维图形,事实上同时包括了二维图形以及影像处理。


一、三维图形的几何变换

在这里插入图片描述
对三维图形的几何信息经过平移、比例、旋转等变换后生成新的三维图形,复杂图形的几何变换可通过变换矩阵对图形的基本元素点、线、面作用,其中对点的矩阵是基础。
其中的变换形式如下:

[

x

y

z

1

]

=

T

2

D

[

x

y

z

1

]

=

[

a

b

c

p

d

e

f

q

h

i

j

r

l

m

n

s

]

[

x

y

z

1

]

\begin{bmatrix} x’\\y’\\z’\\1\\ \end{bmatrix}=T_{2D}\cdot\begin{bmatrix} x\\ y\\ z\\ 1\\ \end{bmatrix}=\begin{bmatrix} a&b&c&p\\ d&e&f&q\\ h&i&j&r\\ l&m&n&s\\ \end{bmatrix}\cdot\begin{bmatrix} x\\ y\\ z\\ 1\\ \end{bmatrix}


xyz1
=
T2D
xyz1
=

adhlbeimcfjnpqrs

xyz1


二、数据结构及工具函数定义

struct VERTEX3D { double x, y, z; };	// 三维空间点结构
#define PI acos(-1)
/// <summary>
/// 矩阵结构体
/// </summary>
struct Matrix {
	vector<vector<double>> matrix;
	Matrix() { // 初始化为 4 * 4 的矩阵
		matrix = vector<vector<double>>(4, vector<double>(4, 0.0));
	}
	Matrix(int m, int n) { // 初始化为 m * n 的矩阵
		matrix = vector<vector<double>>(m, vector<double>(n, 0.0));
	}
	friend ostream& operator<<(ostream& out, Matrix& m) {
		for (int i = 0; i < m.matrix.size(); i++) {
			for (int j = 0; j < m.matrix[0].size(); j++) {
				out << m.matrix[i][j] << " ";
			}
			out << endl;
		}
		return out;
	}
};

/// <summary>
/// 矩阵相乘
/// </summary>
/// <param name="m1">矩阵相乘的第一个矩阵</param>
/// <param name="m2">矩阵相乘的第二个矩阵</param>
/// <returns></returns>
Matrix dotMatrix(Matrix m1, Matrix m2) {
	Matrix res;
	for (int i = 0; i < m1.matrix.size(); i++) {
		for (int j = 0; j < m2.matrix[0].size(); j++) {
			for (int k = 0; k < m1.matrix[0].size(); k++) {
				res.matrix[i][j] += m1.matrix[i][k] * m2.matrix[k][j];
			}
		}
	}
	return res;
}

/// <summary>
/// 将点转化为其次坐标
/// </summary>
/// <param name="vertex">点</param>
/// <returns>齐次坐标</returns>
Matrix vertex3D2qici(VERTEX3D vertex3D) {
	Matrix qiciVertex(4, 1);
	qiciVertex.matrix[0][0] = vertex3D.x;
	qiciVertex.matrix[1][0] = vertex3D.y;
	qiciVertex.matrix[2][0] = vertex3D.z;
	qiciVertex.matrix[3][0] = 1;
	return qiciVertex;
}

三、平移变换

1. 平移变换矩阵

T

t

=

[

1

0

0

t

x

0

1

0

t

y

0

0

1

t

z

0

0

0

1

]

 

T_{t}=\begin{bmatrix} 1&0&0&t_x\\ 0&1&0&t_y\\ 0&0&1&t_z\\ 0&0&0&1\\ \end{bmatrix}\

Tt=
100001000010txtytz1
 

2. 代码实现

/// <summary>
/// 三维坐标平移变换
/// </summary>
/// <param name="vertex3D">待平移地三维点</param>
/// <param name="x">x方向平移距离</param>
/// <param name="y">y方向平移距离</param>
/// <param name="z">z方向平移距离</param>
/// <returns>平移后的三维点坐标</returns>
VERTEX3D transTransform3D(VERTEX3D vertex3D, int x, int y, int z) {
	Matrix qiciVertex= vertex3D2qici(vertex3D);  // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;
	
	// 设置各方向平移距离
	transform.matrix[0][3] = x;
	transform.matrix[1][3] = y;
	transform.matrix[2][3] = z;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

3. 效果展示

测试代码如下:

void testTransTransform() {
	VERTEX3D vertex3D = { 0,1,0 };
	VERTEX3D res = transTransform3D(vertex3D, 1, -1, 1);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

点(0,1,0)在x,y,z三个方向上分别平移(1,-1,1)个单位后,坐标为(1,0,1),如下图所示:

在这里插入图片描述


四、比例变换

1. 比例变换矩阵

T

t

=

[

a

0

0

0

0

e

0

0

0

0

j

0

0

0

0

1

]

 

T_{t}=\begin{bmatrix} a&0&0&0\\ 0&e&0&0\\ 0&0&j&0\\ 0&0&0&1\\ \end{bmatrix}\

Tt=
a0000e0000j00001
 

2. 代码实现

/// <summary>
/// 三维坐标比例变换
/// </summary>
/// <param name="vertex3D">待变换的三维点</param>
/// <param name="x">x方向变换比例</param>
/// <param name="y">y方向变换比例</param>
/// <param name="z">z方向变换比例</param>
/// <returns>比例变换后的三维点坐标</returns>
VERTEX3D scaleTransform3D(VERTEX3D vertex3D, double scaleX, int scaleY, int scaleZ) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = scaleX;
	transform.matrix[1][1] = scaleY;
	transform.matrix[2][2] = scaleZ;
	transform.matrix[3][3] = 1;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

3. 效果展示

测试代码如下:

void testScaleTransform3D() {
	VERTEX3D vertex3D = { 1,1,2 };
	VERTEX3D res = scaleTransform3D(vertex3D, 5, -2, 3);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

在这里插入图片描述


五、旋转变换

在这里插入图片描述


1. 旋转变换矩阵

旋转变换分为x、y、z三个方向上的旋转,遵循右手定则,拇指指向坐标轴的方向,手指的方向为正方向。
绕X轴旋转变换矩阵:

T

R

X

=

[

1

0

0

0

0

c

o

s

θ

s

i

n

θ

0

0

s

i

n

θ

c

o

s

θ

0

0

0

0

1

]

 

T_{RX}=\begin{bmatrix} 1&0&0&0\\ 0&cos\theta&-sin\theta&0\\ 0&sin\theta&cos\theta&0\\ 0&0&0&1\\ \end{bmatrix}\

TRX=
10000cosθsinθ00sinθcosθ00001
 

绕Y轴旋转变换矩阵:

T

R

Y

=

[

c

o

s

θ

0

s

i

n

θ

0

0

1

0

0

s

i

n

θ

0

c

o

s

θ

0

0

0

0

1

]

 

T_{RY}=\begin{bmatrix} cos\theta&0&sin\theta&0\\ 0&1&0&0\\ -sin\theta&0&cos\theta&0\\ 0&0&0&1\\ \end{bmatrix}\

TRY=
cosθ0sinθ00100sinθ0cosθ00001
 

绕Z轴旋转变换矩阵:

T

R

Z

=

[

c

o

s

θ

s

i

n

θ

0

0

s

i

n

θ

c

o

s

θ

0

0

0

0

1

0

0

0

0

1

]

 

T_{RZ}=\begin{bmatrix} cos\theta&-sin\theta&0&0\\ sin\theta&cos\theta&0&0\\ 0&0&1&0\\ 0&0&0&1\\ \end{bmatrix}\

TRZ=
cosθsinθ00sinθcosθ0000100001
 


2. 代码实现

VERTEX3D rotationForXTransform3D(VERTEX3D vertex3D, double theta) {
	Matrix qiciVertex(4, 1); // 转化为其次坐标
	qiciVertex.matrix[0][0] = vertex3D.x;
	qiciVertex.matrix[1][0] = vertex3D.y;
	qiciVertex.matrix[2][0] = vertex3D.z;
	qiciVertex.matrix[3][0] = 1;

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = cos(2 * PI * theta / 360);
	transform.matrix[2][2] = cos(2 * PI * theta / 360);
	transform.matrix[3][3] = 1;

	transform.matrix[1][2] = -sin(2 * PI * theta / 360);
	transform.matrix[2][1] = sin(2 * PI * theta / 360);

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

VERTEX3D rotationForYTransform3D(VERTEX3D vertex3D, double theta) {
	Matrix qiciVertex(4, 1); // 转化为其次坐标
	qiciVertex.matrix[0][0] = vertex3D.x;
	qiciVertex.matrix[1][0] = vertex3D.y;
	qiciVertex.matrix[2][0] = vertex3D.z;
	qiciVertex.matrix[3][0] = 1;

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = cos(2 * PI * theta / 360);
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = cos(2 * PI * theta / 360);
	transform.matrix[3][3] = 1;

	transform.matrix[0][2] = sin(2 * PI * theta / 360);
	transform.matrix[2][0] = -sin(2 * PI * theta / 360);

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

VERTEX3D rotationForZTransform3D(VERTEX3D vertex3D, double theta) {
	Matrix qiciVertex(4, 1); // 转化为其次坐标
	qiciVertex.matrix[0][0] = vertex3D.x;
	qiciVertex.matrix[1][0] = vertex3D.y;
	qiciVertex.matrix[2][0] = vertex3D.z;
	qiciVertex.matrix[3][0] = 1;

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = cos(2 * PI * theta / 360);
	transform.matrix[1][1] = cos(2 * PI * theta / 360);
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;

	transform.matrix[0][1] = -sin(2 * PI * theta / 360);
	transform.matrix[1][0] = sin(2 * PI * theta / 360);

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

3. 效果展示

测试代码如下:

void testRotationForXTransform3D() {
	VERTEX3D vertex3D = { 1,1,1 };
	VERTEX3D res = rotationForXTransform3D(vertex3D, 135);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

void testRotationForYTransform3D() {
	VERTEX3D vertex3D = { 1,1,1 };
	VERTEX3D res = rotationForYTransform3D(vertex3D, 135);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

void testRotationForZTransform3D() {
	VERTEX3D vertex3D = { 1,1,1 };
	VERTEX3D res = rotationForZTransform3D(vertex3D, 135);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

三个测试代码分别表示沿x,y,z轴旋转135度。

在这里插入图片描述


六、对称变换

对称变换包括关于xoy、yoz、zox三个平面对称,还包括,关于x轴、y轴、z轴对称,变换矩阵分别如下:


1. 关于坐标平面对称变换矩阵

关于xoy平面对称,因此x、y坐标不变,z坐标变为相反数(-z):

T

F

x

y

=

[

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

]

 

T_{Fxy}=\begin{bmatrix} 1&0&0&0\\ 0&1&0&0\\ 0&0&-1&0\\ 0&0&0&1\\ \end{bmatrix}\

TFxy=
1000010000100001
 

同理可得,关于yoz平面对称:

T

F

y

z

=

[

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

]

 

T_{Fyz}=\begin{bmatrix} -1&0&0&0\\ 0&1&0&0\\ 0&0&1&0\\ 0&0&0&1\\ \end{bmatrix}\

TFyz=
1000010000100001
 

关于zox平面对称:

T

F

z

x

=

[

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

]

 

T_{Fzx}=\begin{bmatrix} 1&0&0&0\\ 0&-1&0&0\\ 0&0&1&0\\ 0&0&0&1\\ \end{bmatrix}\

TFzx=
1000010000100001
 


2. 关于坐标轴对称变换矩阵

关于x轴对称,因此x坐标不变,y、z坐标变为相反数(-y、-z):

T

F

x

=

[

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

]

 

T_{Fx}=\begin{bmatrix} 1&0&0&0\\ 0&-1&0&0\\ 0&0&-1&0\\ 0&0&0&1\\ \end{bmatrix}\

TFx=
1000010000100001
 

同理可得,关于y轴对称:

T

F

y

=

[

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

]

 

T_{Fy}=\begin{bmatrix} -1&0&0&0\\ 0&1&0&0\\ 0&0&-1&0\\ 0&0&0&1\\ \end{bmatrix}\

TFy=
1000010000100001
 

关于z轴对称:

T

F

z

=

[

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

]

 

T_{Fz}=\begin{bmatrix} -1&0&0&0\\ 0&-1&0&0\\ 0&0&1&0\\ 0&0&0&1\\ \end{bmatrix}\

TFz=
1000010000100001
 


3. 代码实现

/// <summary>
/// x轴镜像/对称变换
/// </summary>
/// <param name="vertex3D">待变换的三维点</param>
/// <returns>比例变换后的三维点坐标</returns>
VERTEX3D symmetryForXTransform3D(VERTEX3D vertex3D) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = -1;
	transform.matrix[2][2] = -1;
	transform.matrix[3][3] = 1;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

/// <summary>
/// y轴镜像/对称变换
/// </summary>
/// <param name="vertex3D">待变换的三维点</param>
/// <returns>比例变换后的三维点坐标</returns>
VERTEX3D symmetryForYTransform3D(VERTEX3D vertex3D) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = -1;
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = -1;
	transform.matrix[3][3] = 1;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

/// <summary>
/// z轴镜像/对称变换
/// </summary>
/// <param name="vertex3D">待变换的三维点</param>
/// <returns>比例变换后的三维点坐标</returns>
VERTEX3D symmetryForZTransform3D(VERTEX3D vertex3D) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = -1;
	transform.matrix[1][1] = -1;
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

/// <summary>
/// XOY轴镜像/对称变换
/// </summary>
/// <param name="vertex3D">待变换的三维点</param>
/// <returns>比例变换后的三维点坐标</returns>
VERTEX3D symmetryForXOYTransform3D(VERTEX3D vertex3D) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = -1;
	transform.matrix[3][3] = 1;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

/// <summary>
/// YOZ轴镜像/对称变换
/// </summary>
/// <param name="vertex3D">待变换的三维点</param>
/// <returns>比例变换后的三维点坐标</returns>
VERTEX3D symmetryForYOZTransform3D(VERTEX3D vertex3D) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = -1;
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

/// <summary>
/// ZOX轴镜像/对称变换
/// </summary>
/// <param name="vertex3D">待变换的三维点</param>
/// <returns>比例变换后的三维点坐标</returns>
VERTEX3D symmetryForZOXTransform3D(VERTEX3D vertex3D) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = -1;
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

4. 效果展示

坐标点(4,3,2)关于坐标平面、坐标轴对称的结果如下:
在这里插入图片描述
测试代码如下:

void testSymmetryForXTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = symmetryForXTransform3D(vertex3D);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

void testSymmetryForYTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = symmetryForYTransform3D(vertex3D);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

void testSymmetryForZTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = symmetryForZTransform3D(vertex3D);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

void testSymmetryForXOYTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = symmetryForXOYTransform3D(vertex3D);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

void testSymmetryForYOZTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = symmetryForYOZTransform3D(vertex3D);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

void testSymmetryForZOXTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = symmetryForZOXTransform3D(vertex3D);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

七、错切变换

错切变换同样分为3种,分别为x、y、z三个方向进行变换。具体变换矩阵如下:


1. 变换矩阵

关于x方向错切,y、z坐标不会发生变换,x坐标发生变化的幅度会收到y、z坐标大小的影响,y、z越大,发生变换的程度也越大。

T

S

H

x

=

[

1

b

c

0

0

1

0

0

0

0

1

0

0

0

0

1

]

 

T_{SHx}=\begin{bmatrix} 1&b&c&0\\ 0&1&0&0\\ 0&0&1&0\\ 0&0&0&1\\ \end{bmatrix}\

TSHx=
1000b100c0100001
 

T

S

H

y

=

[

1

0

0

0

d

1

f

0

0

0

1

0

0

0

0

1

]

 

T_{SHy}=\begin{bmatrix} 1&0&0&0\\ d&1&f&0\\ 0&0&1&0\\ 0&0&0&1\\ \end{bmatrix}\

TSHy=
1d0001000f100001
 

T

S

H

z

=

[

1

0

0

0

0

1

0

0

g

h

1

0

0

0

0

1

]

 

T_{SHz}=\begin{bmatrix} 1&0&0&0\\ 0&1&0&0\\ g&h&1&0\\ 0&0&0&1\\ \end{bmatrix}\

TSHz=
10g001h000100001
 


2. 代码实现

/// <summary>
/// X方向错切变换
/// </summary>
/// <param name="vertex3D">待变换的点</param>
/// <param name="miscutY">Y方向错切量</param>
/// <param name="miscutZ">Z方向错切量</param>
/// <returns>变换后的点</returns>
VERTEX3D miscutForXTransform3D(VERTEX3D vertex3D, double miscutY, double miscutZ) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 平移变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;

	// 错切量
	transform.matrix[0][1] = miscutY;
	transform.matrix[0][2] = miscutZ;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

/// <summary>
/// Y方向错切变换
/// </summary>
/// <param name="vertex3D">待变换的点</param>
/// <param name="miscutX">X方向错切量</param>
/// <param name="miscutZ">Z方向错切量</param>
/// <returns>变换后的点</returns>
VERTEX3D miscutForYTransform3D(VERTEX3D vertex3D, double miscutX, double miscutZ) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 平移变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;

	// 错切量
	transform.matrix[1][0] = miscutX;
	transform.matrix[1][2] = miscutZ;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

/// <summary>
/// Z方向错切变换
/// </summary>
/// <param name="vertex3D">待变换的点</param>
/// <param name="miscutX">X方向错切量</param>
/// <param name="miscutY">Y方向错切量</param>
/// <returns>变换后的点</returns>
VERTEX3D miscutForZTransform3D(VERTEX3D vertex3D, double miscutX, double miscutY) {
	Matrix qiciVertex = vertex3D2qici(vertex3D); // 转化为其次坐标

	Matrix transform;		 // 平移变换矩阵
	transform.matrix[0][0] = 1;
	transform.matrix[1][1] = 1;
	transform.matrix[2][2] = 1;
	transform.matrix[3][3] = 1;

	// 错切量
	transform.matrix[2][0] = miscutX;
	transform.matrix[2][1] = miscutY;

	// 进行变换得到齐次坐标结果
	Matrix qicires = dotMatrix(transform, qiciVertex);
	// 将齐次坐标转化为三维点坐标
	VERTEX3D res;
	res.x = qicires.matrix[0][0];
	res.y = qicires.matrix[1][0];
	res.z = qicires.matrix[2][0];
	return res;
}

void testMiscutTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = miscutForZTransform3D(vertex3D, 2, 2);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

3. 效果展示

在这里插入图片描述

测试代码如下:

void testMiscutTransform3D() {
	VERTEX3D vertex3D = { 4,3,2 };
	VERTEX3D res = miscutForXTransform3D(vertex3D, 2, 2);
	cout << res.x << " " << res.y << " " << res.z << endl;
	res = miscutForYTransform3D(vertex3D, 2, 2);
	cout << res.x << " " << res.y << " " << res.z << endl;
	res = miscutForZTransform3D(vertex3D, 2, 2);
	cout << res.x << " " << res.y << " " << res.z << endl;
}

八、相对任意参考点的复合变换

相对于参考点F(xf,yf,zf)作比例、旋转、错切等变换的过程分为以下三步:
(1)将参考点F移至坐标原点;
(2)针对原点进行三维几何变换;
(3)进行反平移。


九、相对任意方向的复合变换

针对任意方向轴的变换的五个步骤:
①使任意方向轴的起点与坐标原点重合,此时进行平移变换。
②使方向轴与某一坐标轴重合,此时需进行旋转变换,且旋转变换可能不止一次。
③针对该坐标轴完成变换。
④用逆旋转变换使方向轴回到其原始方向。
⑤用逆平移变换使方向轴回到其原始位置。
在这里插入图片描述


the end……

三维图形的几何变换到这里就要结束啦~~到此既是缘分,欢迎您的点赞评论收藏关注我,不迷路,我们下期再见!!

😘😘😘 我是Cherries,一位计算机科班在校大学生,写博客用来记录自己平时的所思所想!
💞💞💞 内容繁杂,又才疏学浅,难免存在错误,欢迎各位大佬的批评指正!
👋👋👋 我们相互交流,共同进步!

:本文由非妃是公主发布于https://blog.csdn.net/myf_666,转载请务必标明原文链接:https://blog.csdn.net/myf_666/article/details/129847063

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/130471.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!