python坐标矩阵表示椭球的Euler旋转
目标:将Euler旋转应用于椭球体,然后使用matplotlib和mplot3d绘制它 我发现了一个函数,它将欧拉旋转应用于向量或向量数组:python坐标矩阵表示椭球的Euler旋转,python,numpy,matplotlib,rotation,Python,Numpy,Matplotlib,Rotation,目标:将Euler旋转应用于椭球体,然后使用matplotlib和mplot3d绘制它 我发现了一个函数,它将欧拉旋转应用于向量或向量数组: import numpy as np from scipy.linalg import expm def rot_euler(v, xyz): ''' Rotate vector v (or array of vectors) by the euler angles xyz ''' # https://stackoverflow.com/question
import numpy as np
from scipy.linalg import expm
def rot_euler(v, xyz):
''' Rotate vector v (or array of vectors) by the euler angles xyz '''
# https://stackoverflow.com/questions/6802577/python-rotation-of-3d-vector
for theta, axis in zip(xyz, np.eye(3)):
v = np.dot(np.array(v), expm(np.cross(np.eye(3), axis*-theta)))
return v
但是,我需要旋转的椭球体表示为一组三个坐标矩阵(以便使用ax.plot_surface()进行绘制):
如何将Euler旋转应用于此对象?我曾想过将物体从三个坐标矩阵转换成向量,然后将其输入到现有的公式中,但我觉得这样做可能会导致计算效率低下。。。这让我想知道旋转函数是否可以被修改以处理坐标矩阵
我意识到这可能是一个相当琐碎的问题,但自从我上一次做线性代数以来已经好几年了,我非常感谢这里的专家的建议
谢谢 虽然我不认为你能比应用旋转点做得更好,但仍然有显著的经济空间 (1) 使用矩阵指数计算简单的旋转矩阵是荒谬的浪费。最好使用标量指数或正弦和余弦 (2) 在较小程度上,这同样适用于使用叉积进行洗牌。这里最好使用索引 (3) 矩阵乘法的顺序很重要。当批量旋转超过三个向量时,最左边的乘法应最后进行 这些措施加在一起可将计算速度提高六倍: (在原始脚本的最后两行之前插入) 输出:
虽然我不认为你可以做得比应用旋转点更好,但仍然有显著的经济空间 (1) 使用矩阵指数计算简单的旋转矩阵是荒谬的浪费。最好使用标量指数或正弦和余弦 (2) 在较小程度上,这同样适用于使用叉积进行洗牌。这里最好使用索引 (3) 矩阵乘法的顺序很重要。当批量旋转超过三个向量时,最左边的乘法应最后进行 这些措施加在一起可将计算速度提高六倍: (在原始脚本的最后两行之前插入) 输出:
值得一提的是:感谢指针,线性代数专家的建议更容易获得。我认为在这种情况下,这更像是一个numpy的效率问题,而不是一个纯粹的数学问题。只需提及:感谢指针,线性代数专家的建议更容易获得。我认为在这种情况下,这更像是numpy中的效率问题,而不是纯粹的数学问题。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from numpy import pi,sin,cos
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
ax.set_aspect('equal','box')
ax.set_xlim3d(-1,1)
ax.set_ylim3d(-1,1)
ax.set_zlim3d(-1,1)
ax.view_init(90,90)
ellipseSteps= 100
diamCoef = 500
widthCoef = 25
coefs = (widthCoef, diamCoef, diamCoef) # Coefficients in a0/c x**2 + a1/c y**2 + a2/c z**2 = 1
# Radii corresponding to the coefficients:
rx, ry, rz = 1/np.sqrt(coefs)
# Set of all spherical angles:
u = np.linspace(0, 2 * pi, ellipseSteps)
v = np.linspace(0, pi, ellipseSteps)
# Cartesian coordinates that correspond to the spherical angles:
# (this is the equation of an ellipsoid):
ex = rx * np.outer(cos(u), sin(v))
ey = ry * np.outer(sin(u), sin(v))
ez = rz * np.outer(np.ones_like(u), cos(v))
# Plot:
ax.plot_surface(ex, ey, ez, rstride=4, cstride=4, color='blue')
plt.show()
from scipy.linalg import block_diag
from timeit import timeit
def rot_euler_better(v, xyz):
TD = np.multiply.outer(np.exp(1j * np.asanyarray(xyz)), [[1], [1j]]).view(float)
x, y, z = (block_diag(1, TD[i])[np.ix_(*2*(np.arange(-i, 3-i),))] for i in range(3))
return v @ (x @ y @ z)
# example
xyz = np.pi * np.array((1/6, -2/3, 1/4))
print("Same result:",
np.allclose(rot_euler(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz),
rot_euler_better(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz))
print("OP: ", timeit(lambda: rot_euler(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz), number=1000), "ms")
print("optimized:", timeit(lambda: rot_euler_better(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz), number=1000), "ms")
ex, ey, ez = map(np.reshape, rot_euler_better(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz).T, map(np.shape, (ex, ey, ez)))
Same result: True
OP: 2.1019406360574067 ms
optimized: 0.3485010238364339 ms