计算机图形学:三维图形的平移、缩放和旋转
计算机图形学:三维图形的平移、缩放和旋转
在计算机图形学中,三维图形的变换是实现复杂视觉效果的基础。本文将详细介绍三维图形的平移、缩放和旋转的原理,并提供相应的代码实现。
平移(Translation)
原理
平移是指在三维空间中沿着某个方向移动图形。对于一个点P ( x , y , z ) P(x, y, z)P(x,y,z),如果我们想将其平移到新的位置P ′ ( x ′ , y ′ , z ′ ) P'(x', y', z')P′(x′,y′,z′),我们可以通过添加一个平移向量T ( a , b , c ) T(a, b, c)T(a,b,c)来实现。平移的数学表达式为:
P ′ = P + T ( x ′ , y ′ , z ′ ) = ( x + a , y + b , z + c ) \begin{aligned} P' &= P + T\ (x', y', z')&=(x + a, y + b, z + c) \end{aligned}P′(x′,y′,z′) =P+T=(x+a,y+b,z+c)
代码实现
import numpy as np
def translate(point, translation):
"""
平移一个3D点,根据给定的平移向量。
:param point: 一个3D点,表示为numpy数组 [x, y, z]。
:param translation: 一个平移向量,表示为numpy数组 [a, b, c]。
:return: 平移后的点。
"""
# 通过将点和平移向量相加来实现平移
return point + translation
# 示例用法:
# 定义一个3D点
point = np.array([1, 2, 3])
# 定义一个平移向量
translation = np.array([4, 5, 6])
# 调用translate函数进行平移
translated_point = translate(point, translation)
# 打印平移后的点
print("平移后的点:", translated_point)
缩放(Scaling)
原理
缩放是指改变图形的大小。对于一个点P ( x , y , z ) P(x, y, z)P(x,y,z),如果我们想将其缩放到新的大小P ′ ( x ′ , y ′ , z ′ ) P'(x', y', z')P′(x′,y′,z′),我们可以通过乘以一个缩放因子向量S ( s x , s y , s z ) S(s_x, s_y, s_z)S(sx ,sy ,sz )来实现。缩放的数学表达式为:
P ′ = P × S ( x ′ , y ′ , z ′ ) = ( x ⋅ s x , y ⋅ s y , z ⋅ s z ) \begin{aligned} P' &= P \times S\ (x', y', z') &= (x \cdot s_x, y \cdot s_y, z \cdot s_z) \end{aligned}P′(x′,y′,z′) =P×S=(x⋅sx ,y⋅sy ,z⋅sz )
代码实现
import numpy as np # 导入numpy库,确保后续代码能够使用numpy数组
def scale(point, scale_factors):
"""
按给定的缩放因子对3D点进行缩放。
:param point: 一个3D点,表示为numpy数组 [x, y, z]。
:param scale_factors: 缩放因子,表示为numpy数组 [sx, sy, sz]。
:return: 缩放后的点。
"""
return point * scale_factors
# 示例用法:
point = np.array([1, 2, 3]) # 定义一个3D点
scale_factors = np.array([2, 3, 4]) # 定义缩放因子
scaled_point = scale(point, scale_factors) # 调用scale函数进行缩放
print("缩放后的点:", scaled_point) # 输出缩放后的点
旋转(Rotation)
原理
旋转是指围绕某个轴旋转图形。在三维空间中,旋转可以通过旋转矩阵来实现。以下是围绕x 、 y 、 z x、y、zx、y、z轴的旋转矩阵:
围绕x轴逆时针旋转θ角度:
R x ( θ ) = [ 1 0 0 0 cos ( θ ) − sin ( θ ) 0 sin ( θ ) cos ( θ ) ] R_x(\theta) = \begin{bmatrix} 1 & 0 & 0 \ 0 & \cos(\theta) & -\sin(\theta) \ 0 & \sin(\theta) & \cos(\theta) \end{bmatrix}Rx (θ)= 100 0cos(θ)sin(θ) 0−sin(θ)cos(θ)
围绕y轴逆时针旋转θ角度:
R y ( θ ) = [ cos ( θ ) 0 sin ( θ ) 0 1 0 − sin ( θ ) 0 cos ( θ ) ] R_y(\theta) = \begin{bmatrix} \cos(\theta) & 0 & \sin(\theta) \ 0 & 1 & 0 \ -\sin(\theta) & 0 & \cos(\theta) \end{bmatrix}Ry (θ)= cos(θ)0−sin(θ) 010 sin(θ)0cos(θ)
围绕z轴逆时针旋转θ角度:
R z ( θ ) = [ cos ( θ ) − sin ( θ ) 0 sin ( θ ) cos ( θ ) 0 0 0 1 ] R_z(\theta) = \begin{bmatrix} \cos(\theta) & -\sin(\theta) & 0 \ \sin(\theta) & \cos(\theta) & 0 \ 0 & 0 & 1 \end{bmatrix}Rz (θ)= cos(θ)sin(θ)0 −sin(θ)cos(θ)0 001
代码实现
import numpy as np # 导入numpy库,用于数组和矩阵运算
def rotate_x(point, theta):
"""
绕X轴旋转三维点。
:param point: 一个表示三维点的numpy数组 [x, y, z]。
:param theta: 旋转角度,单位为度。
:return: 旋转后的点。
"""
theta_rad = np.radians(theta) # 将角度从度转换为弧度
# 定义绕X轴旋转的旋转矩阵
rotation_matrix = np.array([
[1, 0, 0], # X坐标不变
[0, np.cos(theta_rad), -np.sin(theta_rad)], # Y和Z坐标按公式变换
[0, np.sin(theta_rad), np.cos(theta_rad)]
])
# 使用矩阵乘法计算旋转后的点
return np.dot(rotation_matrix, point)
def rotate_y(point, theta):
"""
绕Y轴旋转三维点。
:param point: 一个表示三维点的numpy数组 [x, y, z]。
:param theta: 旋转角度,单位为度。
:return: 旋转后的点。
"""
theta_rad = np.radians(theta) # 将角度从度转换为弧度
# 定义绕Y轴旋转的旋转矩阵
rotation_matrix = np.array([
[np.cos(theta_rad), 0, np.sin(theta_rad)], # X和Z坐标按公式变换
[0, 1, 0], # Y坐标不变
[-np.sin(theta_rad), 0, np.cos(theta_rad)]
])
# 使用矩阵乘法计算旋转后的点
return np.dot(rotation_matrix, point)
def rotate_z(point, theta):
"""
绕Z轴旋转三维点。
:param point: 一个表示三维点的numpy数组 [x, y, z]。
:param theta: 旋转角度,单位为度。
:return: 旋转后的点。
"""
theta_rad = np.radians(theta) # 将角度从度转换为弧度
# 定义绕Z轴旋转的旋转矩阵
rotation_matrix = np.array([
[np.cos(theta_rad), -np.sin(theta_rad), 0], # X和Y坐标按公式变换
[np.sin(theta_rad), np.cos(theta_rad), 0],
[0, 0, 1] # Z坐标不变
])
# 使用矩阵乘法计算旋转后的点
return np.dot(rotation_matrix, point)
# 示例用法:
point = np.array([1, 2, 3]) # 定义一个三维点
theta = 45 # 旋转角度为45度
rotated_point_x = rotate_x(point, theta) # 绕X轴旋转
rotated_point_y = rotate_y(point, theta) # 绕Y轴旋转
rotated_point_z = rotate_z(point, theta) # 绕Z轴旋转
print("绕X轴旋转后的点:", rotated_point_x)
print("绕Y轴旋转后的点:", rotated_point_y)
print("绕Z轴旋转后的点:", rotated_point_z)
应用实例
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 定义变换函数
def translate(point, translation):
return point + translation
def scale(point, scale_factors):
return point * scale_factors
def rotate_x(point, theta):
theta_rad = np.radians(theta)
rotation_matrix = np.array([
[1, 0, 0],
[0, np.cos(theta_rad), -np.sin(theta_rad)],
[0, np.sin(theta_rad), np.cos(theta_rad)]
])
return np.dot(rotation_matrix, point)
def rotate_y(point, theta):
theta_rad = np.radians(theta)
rotation_matrix = np.array([
[np.cos(theta_rad), 0, np.sin(theta_rad)],
[0, 1, 0],
[-np.sin(theta_rad), 0, np.cos(theta_rad)]
])
return np.dot(rotation_matrix, point)
def rotate_z(point, theta):
theta_rad = np.radians(theta)
rotation_matrix = np.array([
[np.cos(theta_rad), -np.sin(theta_rad), 0],
[np.sin(theta_rad), np.cos(theta_rad), 0],
[0, 0, 1]
])
return np.dot(rotation_matrix, point)
# 定义立方体的顶点
vertices = np.array([
[0, 0, 0],
[1, 0, 0],
[1, 1, 0],
[0, 1, 0],
[0, 0, 1],
[1, 0, 1],
[1, 1, 1],
[0, 1, 1]
])
# 定义立方体的边(每条边由两个顶点组成)
edges = np.array([
[0, 1],
[1, 2],
[2, 3],
[3, 0],
[4, 5],
[5, 6],
[6, 7],
[7, 4],
[0, 4],
[1, 5],
[2, 6],
[3, 7]
])
# 绘制立方体的函数
def draw_cube(ax, vertices, color='k'):
for edge in edges:
start = vertices[edge[0]]
end = vertices[edge[1]]
ax.plot([start[0], end[0]], [start[1], end[1]], [start[2], end[2]], color=color)
# 创建图形和子图
fig = plt.figure(figsize=(15, 5))
# 平移子图
ax1 = fig.add_subplot(131, projection='3d')
draw_cube(ax1, vertices, 'k') # 原始立方体
translation = np.array([2, 3, 4])
translated_vertices = translate(vertices, translation)
draw_cube(ax1, translated_vertices, 'r') # 平移后的立方体
ax1.set_title('Translation')
# 缩放子图
ax2 = fig.add_subplot(132, projection='3d')
draw_cube(ax2, vertices, 'k') # 原始立方体
scale_factors = np.array([2, 2, 2])
scaled_vertices = scale(vertices, scale_factors)
draw_cube(ax2, scaled_vertices, 'r') # 缩放后的立方体
ax2.set_title('Scaling')
# 旋转子图
ax3 = fig.add_subplot(133, projection='3d')
draw_cube(ax3, vertices, 'k') # 原始立方体
theta_x = 45
rotated_x_vertices = np.array([rotate_x(point, theta_x) for point in vertices])
draw_cube(ax3, rotated_x_vertices, 'r') # 旋转后的立方体
ax3.set_title('Rotation about X-axis')
# 设置图形属性
for ax in [ax1, ax2, ax3]:
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
ax.set_xlim([0, 4])
ax.set_ylim([0, 4])
ax.set_zlim([0, 4])
# 显示图形
plt.show()
运行效果如下: