2012-09-09 33 views
5

Me refiero a que el cono o disco se está moviendo o rotando con su eje de simetría. Para ser exactos, estoy creando este eje, que está en constante cambio con el tiempo:creando un cono 3D o disco y seguir actualizando su eje de simetría con matplotlib

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

necesito la cara del cono o un círculo siempre perpendicular a dicho eje. Probé una simple primero mediante la creación de un círculo 2D y luego levantarla hasta la posición que quiero:

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

pero eso no va a hacer que la cara del círculo perpendicular al eje de movimiento. Me pregunto si hay alguna función en matplotlib que pueda usar para rotar esa cara del cono/círculo.

Si, comencé de otra manera creando un objeto 3D, como un elipsoide, el problema persiste: cómo dejo que el objeto se mueva con su eje de simetría como un cuerpo rígido (se adhiere a su eje) en lugar de un linterna colgando allí (unido a un punto fijo solamente)?

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") 
+0

Puede youy proporcionar un ejemplo de trabajo? –

Respuesta

2
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) 

Para ello se utilizará un cono alrededor de la línea que apunta en la dirección del eje z después de la rotación a través de la Euler anglesphi, theta, psi. (en este caso, psi no tendrá ningún efecto ya que el cono es axi simétrico alrededor del eje z) Ver también rotation matrix.

Para dibujar un solo círculo desplazado a lo largo de la normal por 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) 

Se deja como ejercicio para obtener los ángulos de Euler de un vector dado.

euler_rot en un gist

Cuestiones relacionadas