问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

计算机图形学:三维图形的平移、缩放和旋转

创作时间:
作者:
@小白创作中心

计算机图形学:三维图形的平移、缩放和旋转

引用
CSDN
1.
https://blog.csdn.net/jianmo1993/article/details/144384544

在计算机图形学中,三维图形的变换是实现复杂视觉效果的基础。本文将详细介绍三维图形的平移、缩放和旋转的原理,并提供相应的代码实现。

平移(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()

运行效果如下:

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号