美文网首页
计算三维图形旋转后坐标

计算三维图形旋转后坐标

作者: Byte猫 | 来源:发表于2019-04-19 13:54 被阅读0次

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

    对X、Y、Z轴旋转变换

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


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


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

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



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



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

    代码实现

    构造一个正六面体



    使其绕X轴旋转30度


    # -*- 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()
    

    相关文章

      网友评论

          本文标题:计算三维图形旋转后坐标

          本文链接:https://www.haomeiwen.com/subject/firzwqtx.html