jak ustawić „pozycję kamery” dla wykresów 3D za pomocą python / matplotlib?

134

Uczę się, jak używać mplot3d do tworzenia ładnych wykresów danych 3D i do tej pory jestem całkiem zadowolony. W tej chwili próbuję zrobić małą animację obracającej się powierzchni. W tym celu muszę ustawić położenie kamery do projekcji 3D. Wydaje mi się, że to musi być możliwe, ponieważ powierzchnię można obracać za pomocą myszy podczas interaktywnego korzystania z matplotlib. Ale jak mogę to zrobić ze skryptu? Znalazłem wiele transformacji w mpl_toolkits.mplot3d.proj3d, ale nie mogłem się dowiedzieć, jak je wykorzystać do swoich celów i nie znalazłem żadnego przykładu na to, co próbuję zrobić.

Andreas Bleuler
źródło
2
Uwaga dodatkowa dla tych, którzy zastanawiają się, jak interaktywnie obracać w notatniku Jupyter: możesz użyć%matplotlib notebook
YvesgereY
Również przeciąganie z wciśniętym prawym przyciskiem myszy zmienia odległość kamery.
LoMaPh
W przypadku tego rodzaju wizualizacji spróbuję.
Tactopoda

Odpowiedzi:

158

„Położenie kamery” oznacza, że ​​chcesz dopasować elewację i kąt azymutu, których używasz do oglądania wykresu 3D. Możesz to ustawić za pomocą ax.view_init. Użyłem poniższego skryptu, aby najpierw utworzyć działkę, a następnie określiłem dobrą elewację lub elevz której wyświetlić moją działkę. Następnie dostosowałem kąt azymutu lub azimzmieniłem pełne 360 ​​stopni wokół wykresu, zapisując figurę w każdym wystąpieniu (i notując, który kąt azymutu, zapisując wykres). Aby uzyskać bardziej skomplikowaną panoramę kamery, możesz dostosować zarówno wysokość, jak i kąt, aby uzyskać pożądany efekt.

    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)
kosmoza
źródło
26
Pokonaj mnie! Na marginesie, są one dostępne jako właściwości ax.elevi ax.azim. Mogłeś też po prostu napisać ax.azim = iilub nawet ax.azim += 1osiągnąć ten sam efekt.
Joe Kington,
1
Przepraszam, że cię pokonałem, ale uczciwe punkty. To także jest tylko mój fragment kodu, w tej pętli for było więcej niż tylko view_init i savefig. =)
kosmoza
4
Dzięki kosmozie i Joe, właśnie tego szukałem. Skoro już wiedziałem czego szukać, znalazłem również ax.dist, który - razem z ax.azim i ax.elev - pozwala ustawić położenie kamery we współrzędnych biegunowych.
Andreas Bleuler,
Jeśli to jest odpowiedź - czy mógłbyś ją zaznaczyć? Dzięki.
kosmoza
12
Możesz także ustawić odległość między kamerą a punktem obiektu przez ax.dist = 15 (domyślnie 10)
Tim
14

Przydatne byłoby zastosowanie pozycji kamery do nowego wykresu. Więc kreślę, a potem przesuwam wykres za pomocą myszy, zmieniając odległość. Następnie spróbuj odtworzyć widok z uwzględnieniem odległości na innym wykresie. Uważam, że axx.ax.get_axes () pobiera mi obiekt ze starymi plikami .azim i .elev.

W 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

Później wykres 3d ...

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

EDYCJA 1 ... OK, położenie kamery to niewłaściwy sposób myślenia o wartości .dist. Jeździ na szczycie wszystkiego jako rodzaj hackey skalarny mnożnik dla całego wykresu.

Działa to w przypadku powiększania / powiększania widoku:

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

Późniejszy wykres ...

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
źródło
+1 za wywołanie zepsutego mnożenia przez skalar. To bardzo irytujące, jeśli liczysz na perspektywę.
user5920660