como definir a “posição da câmera” para gráficos 3D usando python / matplotlib?

134

Estou aprendendo a usar o mplot3d para produzir bons gráficos de dados 3D e até agora estou muito feliz. O que estou tentando fazer no momento é uma pequena animação de uma superfície rotativa. Para isso, preciso definir uma posição de câmera para a projeção em 3D. Eu acho que isso deve ser possível, pois uma superfície pode ser girada usando o mouse ao usar o matplotlib interativamente. Mas como posso fazer isso a partir de um script? Encontrei muitas transformações em mpl_toolkits.mplot3d.proj3d, mas não consegui descobrir como usá-las para o meu propósito e não encontrei nenhum exemplo para o que estou tentando fazer.

Andreas Bleuler
fonte
2
Nota lateral para aqueles que querem saber como rodar interativamente no caderno jupyter: você pode usar%matplotlib notebook
YvesgereY
Também arrastar enquanto mantém pressionado o botão direito do mouse altera a distância da câmera.
LoMaPh
Para esse tipo de visualização, eu daria uma chance ao mayavi.
Tactopoda

Respostas:

158

Por "posição da câmera", parece que você deseja ajustar a elevação e o ângulo de azimute que você usa para visualizar o gráfico 3D. Você pode definir isso com ax.view_init. Eu usei o script abaixo para criar o enredo primeiro, depois determinei uma boa elevação, ou elev, a partir da qual visualizar o enredo. Em seguida, ajustei o ângulo do azimute, ou azim, para variar 360 graus ao redor da plotagem, salvando a figura em cada instância (e observando qual ângulo de azimute salvei a plotagem). Para uma panorâmica da câmera mais complicada, você pode ajustar a elevação e o ângulo para obter o efeito desejado.

    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
fonte
26
Bata-me para isso! Em uma nota lateral, eles estão disponíveis como propriedades ax.eleve ax.azim. Você também pode ter escrito ax.azim = iiou até mesmo ax.azim += 1para obter o mesmo efeito.
9788 Joe O'Donton
1
Desculpe por ter batido em você, mas com pontos justos por toda parte. Este também é apenas um trecho de codificação meu, havia mais nesse loop for do que apenas view_init e savefig. =)
cosmosis
4
Obrigado cosmosis e Joe, era exatamente o que eu estava procurando. Como agora eu sabia o que procurar, também encontrei ax.dist que, junto com ax.azim e ax.elev - permite definir a posição da câmera em coordenadas polares.
Andreas Bleuler
Se esta é a resposta - você pode marcar? Obrigado.
Cosmosis
12
Você também pode definir a distância entre a câmera eo objeto ponto por ax.dist = 15 (default a ser 10)
Tim
14

O que seria útil seria aplicar a posição da câmera a um novo gráfico. Então, traço, movo a trama com o mouse alterando a distância. Em seguida, tente replicar a vista, incluindo a distância em outro gráfico. Acho que axx.ax.get_axes () me fornece um objeto com o antigo .azim e .elev.

EM PYTHON ...

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

Mais tarde gráfico 3d ...

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

EDIT 1 ... OK, a posição da câmera é a maneira errada de pensar em relação ao valor .dist. Ele roda em cima de tudo como uma espécie de multiplicador escalar de hackey para todo o gráfico.

Isso funciona para a ampliação / zoom da visualização:

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])     #...
user1469620
fonte
+1 por chamar a multiplicação escalar hacky. É muito chato se você estava esperando uma perspectiva.
user5920660