¿Cómo configurar la "posición de la cámara" para trazados 3D usando python / matplotlib?

134

Estoy aprendiendo a usar mplot3d para producir buenas parcelas de datos en 3D y estoy muy feliz hasta ahora. Lo que estoy tratando de hacer en este momento es una pequeña animación de una superficie giratoria. Para ese propósito, necesito establecer una posición de cámara para la proyección 3D. Supongo que esto debe ser posible ya que una superficie se puede girar con el mouse cuando se usa matplotlib de forma interactiva. Pero, ¿cómo puedo hacer esto desde un script? Encontré muchas transformaciones en mpl_toolkits.mplot3d.proj3d pero no pude encontrar cómo usarlas para mi propósito y no encontré ningún ejemplo de lo que estoy tratando de hacer.

Andreas Bleuler
fuente
2
Nota al margen para los que se preguntan cómo rotar interactivamente en el cuaderno jupyter: puede usar%matplotlib notebook
YvesgereY
También arrastrar mientras mantiene presionado el botón derecho del mouse cambia la distancia de la cámara.
LoMaPh
Para este tipo de visualizaciones, probaría mayavi.
Tactopoda

Respuestas:

158

Por "posición de cámara", parece que desea ajustar la elevación y el ángulo de acimut que utiliza para ver el diagrama 3D. Puedes configurar esto con ax.view_init. Utilicé el siguiente script para crear primero la trama, luego determiné una buena elevación, o elevdesde la cual ver mi trama. Luego ajusté el ángulo de acimut o azim, para variar los 360 grados completos alrededor de mi gráfico, guardando la figura en cada caso (y observando qué ángulo de acimut guardaba el gráfico). Para una panorámica de cámara más complicada, puede ajustar tanto la elevación como el ángulo para lograr el efecto deseado.

    from mpl_toolkits.mplot3d import Axes3D
    ax = Axes3D(fig)
    ax.scatter(xx,yy,zz, marker='o', s=20, c="goldenrod", alpha=0.6)
    for ii in xrange(0,360,1):
        ax.view_init(elev=10., azim=ii)
        savefig("movie%d.png" % ii)
cosmosis
fuente
26
¡Golpéame! En una nota al margen, estos están disponibles como las propiedades ax.elevy ax.azim. También podría haber escrito ax.azim = iio incluso ax.azim += 1lograr el mismo efecto.
Joe Kington
1
Lo siento, te gané pero puntos justos por todas partes. Esto también es solo un extracto de codificación mío, había más dentro de ese bucle for que simplemente view_init y savefig. =)
cosmosis
44
Gracias cosmosis y Joe, eso era exactamente lo que estaba buscando. Como ahora sabía qué buscar, también encontré ax.dist que, junto con ax.azim y ax.elev, permite establecer la posición de la cámara en coordenadas polares.
Andreas Bleuler
Si esta es la respuesta, ¿podría marcarla? Gracias.
cosmosis
12
También puede establecer la distancia entre la cámara y el punto del objeto mediante ax.dist = 15 (el valor predeterminado es 10)
Tim
14

Lo que sería útil sería aplicar la posición de la cámara a una nueva trama. Así que trazo, luego muevo la trama con el mouse cambiando la distancia. Luego intente replicar la vista, incluida la distancia en otra parcela. Me parece que axx.ax.get_axes () me da un objeto con los viejos .azim y .elev.

EN PITÓN ...

axx=ax1.get_axes()
azm=axx.azim
ele=axx.elev
dst=axx.dist       # ALWAYS GIVES 10
#dst=ax1.axes.dist # ALWAYS GIVES 10
#dst=ax1.dist      # ALWAYS GIVES 10

Más tarde gráfico 3d ...

ax2.view_init(elev=ele, azim=azm) #Works!
ax2.dist=dst                       # works but always 10 from axx

EDITAR 1 ... OK, la posición de la cámara es la forma incorrecta de pensar con respecto al valor .dist. Se monta sobre todo como una especie de multiplicador escalar hackey para todo el gráfico.

Esto funciona para la ampliación / zoom de la vista:

xlm=ax1.get_xlim3d() #These are two tupples
ylm=ax1.get_ylim3d() #we use them in the next
zlm=ax1.get_zlim3d() #graph to reproduce the magnification from mousing
axx=ax1.get_axes()
azm=axx.azim
ele=axx.elev

Gráfico posterior ...

ax2.view_init(elev=ele, azim=azm) #Reproduce view
ax2.set_xlim3d(xlm[0],xlm[1])     #Reproduce magnification
ax2.set_ylim3d(ylm[0],ylm[1])     #...
ax2.set_zlim3d(zlm[0],zlm[1])     #...
usuario1469620
fuente
+1 por llamar a la multiplicación escalar hacky. Es muy molesto si esperabas una perspectiva.
user5920660