计算三维图形旋转后坐标

三维图形几何变换是二维图形几何变换的扩展。在二维空间中绕一个中心点旋转,实际上就是绕原点旋转再平移,那么在三维空间中我们可以采用类似的思路,任意一种旋转可以分解为旋转+平移两步,其中一次空间的旋转可以分解为X、Y、Z三个方向上的旋转。

对X、Y、Z轴旋转变换

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


计算三维图形旋转后坐标_第1张图片

三维变换矩阵的功能分块
有时候我们用规范化齐次坐标(x,y,z,1)表示三维点,变换矩阵用4×4阶矩阵表示,即:

计算三维图形旋转后坐标_第2张图片

1)左上角的3X3子块实现比例、旋转、对称、错切等基本变换
2)左下角的1X3子块实现平移变换
3)右上角的3X1子块实现透视变换
4)右下角的1X1子块实现全比例变换

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


计算三维图形旋转后坐标_第3张图片

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


计算三维图形旋转后坐标_第4张图片

绕Z轴旋转θ角的旋转矩阵为
计算三维图形旋转后坐标_第5张图片

代码实现

构造一个正六面体


计算三维图形旋转后坐标_第6张图片

使其绕X轴旋转30度


计算三维图形旋转后坐标_第7张图片
# -*- coding: utf-8 -*-
import numpy as np
import math
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 CW_rotate_X(angle, x, y, z):
    '''
    绕X轴正向旋转坐标计算
    INPUT --> 旋转角度, 原坐标
    '''
    angle = math.radians(angle) # 以弧度作为参数
    x = np.array(x)
    y = np.array(y)
    z = np.array(z)
    new_x = x
    new_y = y*math.cos(angle) + z*math.sin(angle)
    new_z = -(y*math.sin(angle)) + z*math.cos(angle)
    return new_x, new_y, new_z

def CW_rotate_Y(angle, x, y, z):
    '''
    绕Y轴正向旋转坐标计算
    INPUT --> 旋转角度, 原坐标
    '''
    angle = math.radians(angle) # 以弧度作为参数
    x = np.array(x)
    y = np.array(y)
    z = np.array(z)
    new_x = x*math.cos(angle) - z*math.sin(angle)
    new_y = y
    new_z = x*math.sin(angle) + z*math.cos(angle)
    return new_x, new_y, new_z

def CW_rotate_Z(angle, x, y, z):
    '''
    绕Z轴正向旋转坐标计算
    INPUT --> 旋转角度, 原坐标
    '''
    angle = math.radians(angle) # 以弧度作为参数
    x = np.array(x)
    y = np.array(y)
    z = np.array(z)
    new_x = x*math.cos(angle) + y*math.sin(angle)
    new_y = -(x*math.sin(angle)) + y*math.cos(angle)
    new_z = z
    return new_x, new_y, new_z

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

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(-0.5, 1.5)
    ax.set_ylabel('Y')
    ax.set_ylim3d(-0.5, 1.5)
    ax.set_zlabel('Z')
    ax.set_zlim3d(-0.5, 1.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]]

    # 旋转后六面体顶点和面
    verts2 = [CW_rotate_X(30, vert[0], vert[1], vert[2]) for vert in verts]
    # verts2 = [CW_rotate_Y(30, vert[0], vert[1], vert[2]) for vert in verts2]

    # 获得每个面的顶点
    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()

你可能感兴趣的:(计算三维图形旋转后坐标)