Python基于欧拉角绘制一个立方体

目录
  • 先画个立方体
  • 欧拉角和旋转矩阵
  • 初步演示
  • 不同转动顺序的影响
  • 旋转演示

先画个立方体

工欲善其事、必先利其器,在开始学习欧拉角模拟之前,可先绘制一个立方体。

matplotlib中,这个任务可通过plt.voxels实现,下面先绘制一个最质朴的立方体

代码为

import matplotlib.pyplot as plt
import numpy as np

x, y, z = np.indices((2, 2, 2))
filled = np.ones((1,1,1))
ax = plt.subplot(projection='3d')
ax.voxels(x,y,z, filled=filled)
plt.show()

其中,x,y,z表示顶点,filled表示被填充的区域。由于其顶点数量为2×2×2,故只有一个立方体,从而filled是一个1×1×1的张量。

有了立方体之后,就可以进行欧拉角仿真了。

欧拉角和旋转矩阵

为了尽快进入演示部分,故对原理的介绍从略,仅从二维平面上的旋转矩阵出发,做一个简单的推导,而三维旋转矩阵,至少在形式上与二维是雷同的。

假设坐标系中有一个向量(x,y),其模长为r=√x2+y2,角度为θ0=arctan(y/x).若将其围绕坐标原点逆时针旋转θ,则其坐标变为

由于x=rcosθ0, y=rsinθ0,则上式可以写为

写成矩阵形式即为

也就是说,在平面直角坐标系上,向量绕原点顺时针旋转θ,相当于左乘一个旋转矩阵。

推广到三维,为了限制xy坐标平面上的旋转,要将其旋转中心从原点扩展为绕着z轴旋转,从而三维旋转矩阵可推广为

同理可得到绕三个轴转动的旋转矩阵,为了书写方便,记Sθ=sinθ,Cθ=cosθ,可列出下表。

初步演示

将旋转矩阵写成函数是十分方便的,下面用lambda表达式来实现

import numpy as np
# 将角度转弧度后再求余弦
cos = lambda th : np.cos(np.deg2rad(th))
sin = lambda th : np.sin(np.deg2rad(th))

# 即 Rx(th) => Matrix
Rx = lambda th : np.array([
    [1, 0,       0],
    [0, cos(th), -sin(th)],
    [0, sin(th), cos(th)]])
Ry = lambda th : np.array([
    [cos(th),  0, sin(th)],
    [0      ,  1, 0],
    [-sin(th), 0, cos(th)]
])
Rz = lambda th : np.array([
    [cos(th) , sin(th), 0],
    [-sin(th), cos(th), 0],
    [0       , 0,       1]])

有了旋转矩阵,就可以旋转,接下来让正方体沿着三个轴分别旋转30°,其效果如下

由于ax.voxels在绘图时,要求输入的是拥有三个维度的数组,而旋转矩阵是3 × 3 3\times33×3矩阵,相当于是二维数组,彼此之间可能很难计算,所以实际计算时,需要对数组维度进行调整

import matplotlib.pyplot as plt
# 用于批量调节x,y,z的数组维度
Reshape = lambda x,y,z : [x.reshape(2,2,2), y.reshape(2,2,2), z.reshape(2,2,2)]

filled = np.ones((1,1,1))
x, y, z = np.indices((2, 2, 2))
# 将x,y,z展开,以便于矩阵计算
xyz = np.array([x,y,z]).reshape(3,-1)

fig = plt.figure("rotate")
# 此为未旋转的正方体
ax = fig.add_subplot(1,4,1, projection='3d')
ax.voxels(x,y,z, filled=filled)

# 绕x轴旋转30°
X, Y, Z = Rx(30) @ xyz
ax = fig.add_subplot(1,4,2, projection='3d')
ax.voxels(*Reshape(X, Y, Z), filled=filled)

# 绕y轴旋转30°
X, Y, Z = Ry(30) @ xyz
ax = fig.add_subplot(1,4,3, projection='3d')
ax.voxels(*Reshape(X, Y, Z), filled=filled)

# 绕z轴旋转30°
X, Y, Z = Rz(30) @ xyz
ax = fig.add_subplot(1,4,4, projection='3d')
ax.voxels(*Reshape(X, Y, Z), filled=filled)

plt.show()

不同转动顺序的影响

众所周知,矩阵计算是不能交换的,反映到实际生活中,就是不同的旋转次序,可能会导致完全不同的结果,接下来沿着不同的旋转次序,来对正方体进行旋转,效果如下

需要注意的是,由于矩阵左乘向量表示对向量进行旋转,所以距离向量最近的矩阵表示最先进行的操作,即RzRyRxr ⃗  表示先转Rx ,Ry次之,Rz最后。

代码如下

filled = np.ones((1,1,1))
x, y, z = np.indices((2, 2, 2))
xyz = np.array([x,y,z]).reshape(3,-1)

fig = plt.figure("rotate")
# 旋转顺序 x, y, z
X, Y, Z = Rz(30) @ Ry(30) @ Rx(30) @ xyz
ax = fig.add_subplot(1,3,1, projection='3d')
ax.voxels(*Reshape(X, Y, Z), filled=filled)

# 旋转顺序 z, y, x
X, Y, Z = Rx(30) @ Ry(30) @ Rz(30) @ xyz
ax = fig.add_subplot(1,3,2, projection='3d')
ax.voxels(*Reshape(X, Y, Z), filled=filled)

# 旋转顺序 y, x, z
X, Y, Z = Rz(30) @ Rx(30) @ Ry(30) @ xyz
ax = fig.add_subplot(1,3,3, projection='3d')
ax.voxels(*Reshape(X, Y, Z), filled=filled)

plt.show()

总之,虽然分不清谁是谁,但最起码可以看清楚,不同的旋转顺序的确导致了不同的旋转结果。

旋转演示

为了更加清楚地表示这一过程,可以将正方体的旋转过程绘制下来,先考虑单轴旋转,假设每次旋转3°,绕X轴旋转30次,则可得到

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
import imageio

filled = np.ones((1,1,1))
x, y, z = np.indices((2, 2, 2))
xyz = np.array([x,y,z]).reshape(3,-1)

def saveGif(X,Y,Z, gifs):
    plt.cla()
    ax = plt.subplot(projection='3d')
    ax.voxels(*Reshape(X, Y, Z), filled=filled)
    ax.set_xlim(-0.5,1.5)
    ax.set_ylim(-0.5,1.5)
    ax.set_zlim(-0.5,1.5)
    ax.set_title(f"theta={th}")
    plt.tight_layout()
    plt.savefig(f"tmp.jpg")
    gifs.append(imageio.imread(f"tmp.jpg"))

gifImgs = []
th = 0

for i in range(30):
    X,Y,Z = Rx(th)@xyz
    th += 3
    saveGif(X, Y, Z, gifImgs)

imageio.mimsave("test.gif",gifImgs,fps=10)

通过这个方法,可以将不同顺序的旋转矩阵可视化表示,

filled = np.ones((1,1,1))
x, y, z = np.indices((2, 2, 2))
xyz = np.array([x,y,z]).reshape(3,-1)

gifImgs = []
th = 0
for _ in range(10):
    X,Y,Z = Rz(0) @ Rx(0) @ Ry(th) @ xyz
    th += 3
    saveGif(X, Y, Z, gifImgs)

th = 0
for i in range(10):
    X,Y,Z = Rz(0) @ Rx(th) @ Ry(30) @ xyz
    th += 3
    saveGif(X, Y, Z, gifImgs)

th = 0
for i in range(10):
    X,Y,Z = Rz(th) @ Rx(30) @ Ry(30) @ xyz
    th += 3
    saveGif(X, Y, Z, gifImgs)

imageio.mimsave("test.gif",gifImgs,fps=10)

最后得到三种不同旋转顺序的区别

x-y-z

z-y-x

y-x-z

到此这篇关于Python基于欧拉角绘制一个立方体的文章就介绍到这了,更多相关Python欧拉角实现刚体转动内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 一文教你如何使用Python绘制瀑布图

    目录 前期准备 方法一:waterfall_ax 方法二:waterfall_chart 方法三:plotly 什么是瀑布图?瀑布图用表达两个数值之间的变化过程,过程值为正的时候,向上加,过程值为负的时候向下减[1]. 今天分享在Python中绘制瀑布图的3种简单方法(使用不同的库)! 前期准备 首先先安装所需的库: pip install waterfallcharts (注意该库名) pip install waterfall_ax (注意该库名) pip install plotly 接着

  • Python绘制分形图案探索无限细节和奇妙之美

    目录 一.目标 二.表示图像 三.画一条线 四.画三角形 五.生成分形 六.结论 分形是无限复杂的模式,在不同的尺度上具有自相似性.例如,一棵树的树干会分裂成更小的树枝.这些树枝又分裂成更小的树枝,以此类推. 通过编程的方式生成分形,可以将简单的形状变成复杂的重复图案. 本文将探讨如何利用一些简单的几何学基础和编程知识,在Python中建立令人印象深刻的分形图案. 分形在数据科学中发挥着重要作用.例如,在分形分析中,对数据集的分形特征进行评估,以帮助理解基础过程的结构.此外,处于分形生成中心的循

  • 基于Python实现绘制一个足球

    目录 前情提要 先画六边形 再画五边形 前情提要 如果想优雅地绘制一个足球,那首先需要绘制正二十面体:用Python绘制正二十面体 其核心代码为 import numpy as np from itertools import product G = (np.sqrt(5)-1)/2 def getVertex(): pt2 = [(a,b) for a,b in product([1,-1], [G, -G])] pts = [(a,b,0) for a,b in pt2] pts += [(

  • 用Python绘制一个仿黑洞图像

    目录 简介 单位制 观测绘图 简介 黑洞图像大家都知道,毕竟前几年刚发布的时候曾火遍全网,甚至都做成表情包了. 问题在于,凭什么认为这就是黑洞的照片,而不是一个甜甜圈啥的给整模糊了得到的呢?有什么理论依据吗? 单位制 利用einsteinpy模块中的Shadow类,可以实现黑洞吸积盘的发射强度,换言之,用理论模拟一下黑洞的照片应该是什么样子的. 22年5月份发布的是人马座A*的照片,这个"黑洞"的质量为8.26×1036kg,距离地球26673光年. 根据源码推测,einstenipy

  • Python实现绘制多种激活函数曲线详解

    利用numpy.matplotlib.sympy绘制sigmoid.tanh.ReLU.leaky ReLU.softMax函数 起因:深度学习途中,老师留一作业,绘制激活函数及其导数,耗时挺久,记录学习过程 准备工作:下载numpy.matplotlib.sympy pip install numpy matplotlib sympy 查找对应库的文档: numpy文档 matplotlib文档 sympy文档 写代码的时候发现vscode不会格式化我的python?查了一下原来还要安装fla

  • Python实现绘制3D地球旋转效果

    目录 画一个地球 让地球转起来 画一个地球 想画一个转动的地球,那么首先要有一个球,或者说要有一个球面,用参数方程可以表示为 x​=rcosϕcosθ y=rcosϕsinθ z=rsinϕ​ 然后要有一个地球,或者说要有一个地图,用来作为贴图,映射到球面上. import numpy as np import matplotlib.pyplot as plt path = "earth1.jpg" img = plt.imread(path) h, w, c = img.shape

  • python 基于opencv 绘制图像轮廓

    图像轮廓概念 轮廓是一系列相连的点组成的曲线,代表了物体的基本外形. 谈起轮廓不免想到边缘,它们确实很像.简单的说,轮廓是连续的,边缘并不全都连续(下图).其实边缘主要是作为图像的特征使用,比如可以用边缘特征可以区分脸和手:而轮廓主要用来分析物体的形态,比如物体的周长和面积等,可以说边缘包括轮廓. 寻找轮廓的操作一般用于二值图像,所以通常会使用阈值分割或Canny边缘检测先得到二值图. 注意:寻找轮廓是针对白色物体的,一定要保证物体是白色,而背景是黑色,不然很多人在寻找轮廓时会找到图片最外面的一

  • python基于turtle绘制几何图形

    1. 什么是turtle turtle模拟了人在画布前画画的过程:给你一支笔(Pen), 下笔(pendown),移动画笔绘制你的图形,然后填色等等.turtle提供了几种简单的命令,通过组合他们的顺序,只要够耐心,turtle可以画出令人惊叹的作品,很适合用来引导小朋友学习编程. 先来感受下作品: 2. turtle例子 我们通过一个简单的例子来了解turtle的基本操作 import turtle # screen 画布属性设置 canvas = turtle.Screen() canvas

  • Python基于matplotlib绘制栈式直方图的方法示例

    本文实例讲述了Python基于matplotlib绘制栈式直方图的方法.分享给大家供大家参考,具体如下: 平时我们只对一组数据做直方图统计,这样我们只要直接画直方图就可以了. 但有时候我们同时画多组数据的直方图(比如说我大一到大四跑大学城内环的用时的分布),大一到大四用不同颜色的直方图,显示在一张图上,这样会很直观. #!/usr/bin/env python # -*- coding: utf-8 -*- #http://www.jb51.net/article/100363.htm # nu

  • python 基于opencv 实现一个鼠标绘图小程序

    需求 在画布上用鼠标画图,可以画圆或矩形,按m键在两种模式下切换.左键按下时开始画图,移动到哪儿画到哪儿,左键释放时结束画图. 实现思想 用鼠标画图:需要定义鼠标的回调函数mouse_event 画圆或矩形:需要定义一个画图的模式mode 左键单击.移动.释放:需要捕获三个不同的事件 开始画图,结束画图:需要定义一个画图的标记位drawing 实现代码 import cv2 as cv import numpy as np drawing = False # 是否开始画图 mode = True

  • python基于Kivy写一个图形桌面时钟程序

    Kivy 是一个开源的 Python 第三方库,可以用来快速开发应用程序. 它有如下三个特点: 跨平台 Kivy 编写的程序可在 Linux,Windows,OS X,Android,iOS 和 Raspberry Pi 上运行. 商业友好 Kivy 基于 MIT 许可证进行开源,可以进行免费的商业使用. GPU 加速 Kivy 的图像引擎基于 Open ES 2 构建,性能出众. 除此之外 Kivy 也存在一些缺点,比如: 非原生的图形界面: 打包后的体积很大: 缺乏社区支持: 缺乏足够的示例

  • Python基于Tkinter开发一个爬取B站直播弹幕的工具

    简介 使用Python Tkinter开发一个爬取B站直播弹幕的工具,启动后在弹窗中输入房间号即可,弹幕内容会保存在脚本文件同级目录下的.log扩展名的文件中 开发工具 python 3.7.9 pycharm 2019.3.5 实现代码 import threading import time import tkinter.simpledialog # 使用Tkinter前需要先导入 from tkinter import END, messagebox import requests # 全

  • Python基于pandas绘制散点图矩阵代码实例

    1.示例 1 代码 import numpy as np import pandas as pd import matplotlib.pyplot as plt # 生成数据 v1 = np.random.normal(0, 1, 100) v2 = np.random.randint(0, 23, 100) v3 = v1 * v2 # 3*100 的数据框 df = pd.DataFrame([v1, v2, v3]).T # 绘制散点图矩阵 pd.plotting.scatter_matr

  • Python基于matplotlib实现绘制三维图形功能示例

    本文实例讲述了Python基于matplotlib实现绘制三维图形功能.分享给大家供大家参考,具体如下: 代码一: # coding=utf-8 import numpy as np import matplotlib.pyplot as plt import mpl_toolkits.mplot3d x,y = np.mgrid[-2:2:20j,-2:2:20j] #测试数据 z=x*np.exp(-x**2-y**2) #三维图形 ax = plt.subplot(111, project

  • 基于Python绘制一个摸鱼倒计时界面

    目录 前言 实现过程 前言 前段时间在微博看到一段摸鱼人的倒计时模板,感觉还挺有趣的. 于是我用了一小时的时间写了个页面出来 摸鱼办地址 (当然是摸鱼的时间啦). 模板是这样的: 摸鱼办公室 [摸鱼办公室]今天是 2021-11-30 星期二 你好,摸鱼人,工作再累,一定不要忘记摸鱼哦 ! 有事没事起身去茶水间去廊道去天台走走,别老在工位上坐着.多喝点水,钱是老板的,但命是自己的 ! 距离 周末 放假还有 2 天 距离 元旦 放假还有 3 天 距离 过年 放假还有 34 天 距离 清明节 放假还

随机推荐