【点】三维空间坐标变换

一、平移变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(16, 12))
ax = fig.gca(projection='3d')
ax.set_aspect('equal')

#========================================================
# 变换函数
#========================================================

def get_3D_translation(tx, ty, tz):
return np.array([
[1, 0, 0, tx],
[0, 1, 0, ty],
[0, 0, 1, tz],
[0, 0, 0, 1]
])

#========================================================
# 三维结构绘制
#========================================================

def plot_3D(verts, poly3d):
'''
绘制3D图形
INPUT --> 顶点坐标, 三维结构
'''
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
# 绘制顶点
x, y, z = zip(*verts)
ax.scatter(x, y, z)
# 绘制多边形面
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.3))
# 绘制多边形的边
ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.5, linestyles=':'))

def show_3D():
# 设置图形坐标范围
ax.set_xlabel('X')
ax.set_xlim3d(-2, 5)
ax.set_ylabel('Y')
ax.set_ylim3d(-2, 5)
ax.set_zlabel('Z')
ax.set_zlim3d(-2, 5)

plt.show()

#========================================================
# 主程序
#========================================================

if __name__ == '__main__':
# 六面体顶点和面
verts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)]
faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [0, 3, 7, 4]]

# 转换为齐次坐标
verts_homogeneous = [np.insert(vert, len(vert), values=1) for vert in verts]

# 平移矩阵
T = get_3D_translation(3, 1, 3)

# 旋转后六面体顶点和面
verts2_homogeneous = [np.dot(T, vert) for vert in verts_homogeneous]

# 还原笛卡尔坐标
verts2 = [np.delete(vert, len(vert)-1) for vert in verts2_homogeneous]

# 获得每个面的顶点
poly3d = [[verts[vert_id] for vert_id in face] for face in faces]
poly3d2 = [[verts2[vert_id] for vert_id in face] for face in faces]

plot_3D(verts, poly3d)
plot_3D(verts2, poly3d2)
show_3D()

二、旋转变换

绕X轴旋转θ角的旋转矩阵为

绕Y轴旋转θ角的旋转矩阵为

绕Z轴旋转θ角的旋转矩阵为

旋转的方向
右手拇指指向转轴正向,其余四指缠绕方向便是θ角正向。

1、逆时针旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(16, 12))
ax = fig.gca(projection='3d')
ax.set_aspect('equal')

#========================================================
# 变换函数
#========================================================

def get_3D_CCW_rotate_X(angle):
angle = np.radians(angle) # 以弧度作为参数
return np.array([
[ 1, 0, 0, 0],
[ 0, np.cos(angle), -np.sin(angle), 0],
[ 0, np.sin(angle), np.cos(angle), 0],
[ 0, 0, 0, 1]
])

def get_3D_CCW_rotate_Y(angle):
angle = np.radians(angle) # 以弧度作为参数
return np.array([
[ np.cos(angle), 0, np.sin(angle), 0],
[ 0, 1, 0, 0],
[-np.sin(angle), 0, np.cos(angle), 0],
[ 0, 0, 0, 1]
])

def get_3D_CCW_rotate_Z(angle):
angle = np.radians(angle) # 以弧度作为参数
return np.array([
[ np.cos(angle), -np.sin(angle), 0, 0],
[ np.sin(angle), np.cos(angle), 0, 0],
[ 0, 0, 1, 0],
[ 0, 0, 0, 1]
])

#========================================================
# 三维结构绘制
#========================================================

def plot_3D(verts, poly3d):
'''
绘制3D图形
INPUT --> 顶点坐标, 三维结构
'''
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
# 绘制顶点
x, y, z = zip(*verts)
ax.scatter(x, y, z)
# 绘制多边形面
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.3))
# 绘制多边形的边
ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.5, linestyles=':'))

def show_3D():
# 设置图形坐标范围
ax.set_xlabel('X')
ax.set_xlim3d(-2, 2)
ax.set_ylabel('Y')
ax.set_ylim3d(-2, 2)
ax.set_zlabel('Z')
ax.set_zlim3d(-2, 2)

plt.show()

#========================================================
# 主程序
#========================================================

if __name__ == '__main__':
# 六面体顶点和面
verts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)]
faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [0, 3, 7, 4]]

# 转换为齐次坐标
verts_homogeneous = [np.insert(vert, len(vert), values=1) for vert in verts]

# 旋转矩阵
R1 = get_3D_CCW_rotate_X(45)
R2 = get_3D_CCW_rotate_Y(45)
R3 = get_3D_CCW_rotate_Z(45)

# 旋转后六面体顶点和面
verts2_homogeneous = [np.dot(R3, np.dot(R2, np.dot(R1, vert))) for vert in verts_homogeneous]

# 还原笛卡尔坐标
verts2 = [np.delete(vert, len(vert)-1) for vert in verts2_homogeneous]

# 获得每个面的顶点
poly3d = [[verts[vert_id] for vert_id in face] for face in faces]
poly3d2 = [[verts2[vert_id] for vert_id in face] for face in faces]

plot_3D(verts, poly3d)
plot_3D(verts2, poly3d2)
show_3D()

2、顺时针旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(16, 12))
ax = fig.gca(projection='3d')
ax.set_aspect('equal')

#========================================================
# 变换函数
#========================================================

def get_3D_CW_rotate_X(angle):
angle = np.radians(angle) # 以弧度作为参数
return np.array([
[ 1, 0, 0, 0],
[ 0, np.cos(angle), np.sin(angle), 0],
[ 0, -np.sin(angle), np.cos(angle), 0],
[ 0, 0, 0, 1]
])

def get_3D_CW_rotate_Y(angle):
angle = np.radians(angle) # 以弧度作为参数
return np.array([
[ np.cos(angle), 0, -np.sin(angle), 0],
[ 0, 1, 0, 0],
[ np.sin(angle), 0, np.cos(angle), 0],
[ 0, 0, 0, 1]
])

def get_3D_CW_rotate_Z(angle):
angle = np.radians(angle) # 以弧度作为参数
return np.array([
[ np.cos(angle), np.sin(angle), 0, 0],
[-np.sin(angle), np.cos(angle), 0, 0],
[ 0, 0, 1, 0],
[ 0, 0, 0, 1]
])

#========================================================
# 三维结构绘制
#========================================================

def plot_3D(verts, poly3d):
'''
绘制3D图形
INPUT --> 顶点坐标, 三维结构
'''
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
# 绘制顶点
x, y, z = zip(*verts)
ax.scatter(x, y, z)
# 绘制多边形面
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.3))
# 绘制多边形的边
ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.5, linestyles=':'))

def show_3D():
# 设置图形坐标范围
ax.set_xlabel('X')
ax.set_xlim3d(-2, 2)
ax.set_ylabel('Y')
ax.set_ylim3d(-2, 2)
ax.set_zlabel('Z')
ax.set_zlim3d(-2, 2)

plt.show()

#========================================================
# 主程序
#========================================================

if __name__ == '__main__':
# 六面体顶点和面
verts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)]
faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [0, 3, 7, 4]]

# 转换为齐次坐标
verts_homogeneous = [np.insert(vert, len(vert), values=1) for vert in verts]

# 旋转矩阵
R1 = get_3D_CW_rotate_X(45)
R2 = get_3D_CW_rotate_Y(45)
R3 = get_3D_CW_rotate_Z(45)

# 旋转后六面体顶点和面
verts2_homogeneous = [np.dot(R3, np.dot(R2, np.dot(R1, vert))) for vert in verts_homogeneous]

# 还原笛卡尔坐标
verts2 = [np.delete(vert, len(vert)-1) for vert in verts2_homogeneous]

# 获得每个面的顶点
poly3d = [[verts[vert_id] for vert_id in face] for face in faces]
poly3d2 = [[verts2[vert_id] for vert_id in face] for face in faces]

plot_3D(verts, poly3d)
plot_3D(verts2, poly3d2)
show_3D()

三、缩放变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(16, 12))
ax = fig.gca(projection='3d')
ax.set_aspect('equal')

#========================================================
# 变换函数
#========================================================

def get_3D_scale(s):
return np.array([
[s, 0, 0, 0],
[0, s, 0, 0],
[0, 0, s, 0],
[0, 0, 0, 1]
])

#========================================================
# 三维结构绘制
#========================================================

def plot_3D(verts, poly3d):
'''
绘制3D图形
INPUT --> 顶点坐标, 三维结构
'''
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
# 绘制顶点
x, y, z = zip(*verts)
ax.scatter(x, y, z)
# 绘制多边形面
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.3))
# 绘制多边形的边
ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.5, linestyles=':'))

def show_3D():
# 设置图形坐标范围
ax.set_xlabel('X')
ax.set_xlim3d(-2, 2)
ax.set_ylabel('Y')
ax.set_ylim3d(-2, 2)
ax.set_zlabel('Z')
ax.set_zlim3d(-2, 2)

plt.show()

#========================================================
# 主程序
#========================================================

if __name__ == '__main__':
# 六面体顶点和面
verts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)]
faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [0, 3, 7, 4]]

# 转换为齐次坐标
verts_homogeneous = [np.insert(vert, len(vert), values=1) for vert in verts]

# 缩放矩阵
S = get_3D_scale(1.5)

# 旋转后六面体顶点和面
verts2_homogeneous = [np.dot(S, vert) for vert in verts_homogeneous]

# 还原笛卡尔坐标
verts2 = [np.delete(vert, len(vert)-1) for vert in verts2_homogeneous]

# 获得每个面的顶点
poly3d = [[verts[vert_id] for vert_id in face] for face in faces]
poly3d2 = [[verts2[vert_id] for vert_id in face] for face in faces]

plot_3D(verts, poly3d)
plot_3D(verts2, poly3d2)
show_3D()
0%