Pertanyaan membuat 3D Cone atau disk dan terus memperbarui poros simetri dengan matplotlib


Maksud saya kerucut atau cakram bergerak atau berputar dengan poros simetrinya. Tepatnya, saya membuat sumbu ini, yang terus berubah seiring waktu:

line = ax.plot([x,0],[y,0],[z,z- n_o],color='#000066', marker= 'o')

Saya perlu wajah kerucut atau lingkaran selalu tegak lurus terhadap sumbu itu. Saya mencoba yang lebih sederhana terlebih dahulu dengan membuat lingkaran 2D lalu mengangkatnya ke posisi yang saya inginkan:

circle = Circle((0, 0), .3, color='r')
ax.add_patch(circle)
art3d.pathpatch_2d_to_3d(circle, z=1)

tetapi itu tidak akan membuat wajah lingkaran tegak lurus dengan poros yang bergerak. Saya bertanya-tanya apakah ada fungsi di matplotlib yang dapat saya gunakan untuk memutar wajah kerucut / lingkaran itu?

Jika, saya mulai dari cara lain dengan membuat objek 3D, seperti ellipsoid, masalahnya tetap: bagaimana saya membiarkan objek bergerak dengan poros simetrinya seperti tubuh yang kaku (tetap dengan porosnya) daripada lentera tergantung di sana ( melekat pada titik tetap saja)?

u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x=np.cos(u)*np.sin(v)
y=np.sin(u)*np.sin(v)
z=.3*np.cos(v)
ax.plot_wireframe(x, y, z, color="r")

5
2017-09-09 17:16


asal


Jawaban:


from mpl_toolkits.mplot3d import Axes3D



def euler_rot(XYZ,phi,theta,psi):
    '''Returns the points XYZ rotated by the given euler angles'''


    ERot = np.array([[np.cos(theta)*np.cos(psi), 
                      -np.cos(phi)*np.sin(psi) + np.sin(phi)*np.sin(theta)*np.cos(psi), 
                      np.sin(phi)*np.sin(psi) + np.cos(phi)*np.sin(theta)*np.cos(psi)],
                     [np.cos(theta)*np.sin(psi), 
                      np.cos(phi)*np.cos(psi) + np.sin(phi)*np.sin(theta)*np.sin(psi),
                      -np.sin(phi)*np.cos(psi) + np.cos(phi)*np.sin(theta)*np.sin(psi)],
                     [-np.sin(theta),
                      np.sin(phi)*np.cos(theta),
                      np.cos(phi)*np.cos(theta)]])

    return ERot.dot(XYZ)


u = np.linspace(0,2*np.pi,50)
num_levels = 10

r0 = 1 # maximum radius of cone
h0 = 5 # height of cone

phi = .5 # aka alpha
theta = .25 # aka beta
psi = 0 # aka gamma



norm = np.array([0,0,h0]).reshape(3,1)
normp = euler_rot(norm,phi,theta,psi)


fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot([0,normp[0]],[0,normp[1]],zs= [0,normp[2]])

x = np.hstack([r0*(1-h)*np.cos(u) for h in linspace(0,1,num_levels)])
y = np.hstack([r0*(1-h)*np.sin(u) for h in linspace(0,1,num_levels)])
z = np.hstack([np.ones(len(u))*h*h0 for h in linspace(0,1,num_levels)])
XYZ = np.vstack([x,y,z])

xp,yp,zp = euler_rot(XYZ,phi,theta,psi) 
ax.plot_wireframe(xp,yp,zp)

Ini akan menarik kerucut di sekitar garis yang menunjuk sepanjang arah sumbu-z setelah rotasi melalui Sudut Euler  phi,theta,psi. (pada kasus ini psi tidak akan berpengaruh karena kerucut adalah axi-simetris di sekitar sumbu-z) Juga lihat matriks rotasi.

Untuk menggambar satu lingkaran bergeser sepanjang normal oleh h0:

x=r0*np.cos(u)
y=r0*np.sin(u)
z=h0*np.ones(len(x))
XYZ = np.vstack([x,y,z])    
xp,yp,zp = euler_rot(XYZ,phi,theta,psi) 
ax.plot(xp,yp,zs=zp)

Ini dibiarkan sebagai latihan untuk mendapatkan sudut euler dari vektor yang diberikan.

euler_rot di sebuah inti


2
2017-10-29 01:27