Как установить «положение камеры» для 3D-графиков, используя python / matplotlib?

134

Я учусь использовать mplot3d для создания хороших графиков 3D-данных, и я до сих пор очень счастлив. На данный момент я пытаюсь сделать небольшую анимацию вращающейся поверхности. Для этого мне нужно установить положение камеры для 3D-проекции. Я предполагаю, что это должно быть возможно, так как поверхность может вращаться с помощью мыши при интерактивном использовании matplotlib. Но как я могу сделать это из сценария? Я нашел много преобразований в mpl_toolkits.mplot3d.proj3d, но не смог выяснить, как использовать их для своих целей, и я не нашел ни одного примера того, что я пытаюсь сделать.

Андреас Блеулер
источник
2
Примечание для тех, кто интересуется интерактивным вращением в блокноте Jupyter: вы можете использовать%matplotlib notebook
YvesgereY
Также перетаскивание, удерживая правую кнопку мыши, изменяет расстояние до камеры.
LoMaPh
Для такого рода визуализаций я бы попробовал Майяви.
Тактопода

Ответы:

158

«Положение камеры» звучит так, как будто вы хотите настроить высоту и угол азимута, которые вы используете для просмотра 3D-графика. Вы можете установить это с ax.view_init. Я использовал приведенный ниже сценарий, чтобы сначала создать график, затем я определил хорошую высоту или elev, из которой можно просмотреть мой график. Затем я отрегулировал угол азимута или azim, чтобы изменить все 360 градусов вокруг моего графика, сохраняя фигуру в каждом случае (и отмечая, какой угол азимута при сохранении графика). Для более сложного панорамирования камеры вы можете отрегулировать высоту и угол наклона для достижения желаемого эффекта.

    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
источник
26
Обыграй меня! На заметку, они доступны как ax.elevи ax.azimсвойства. Вы также можете просто написать ax.azim = iiили даже ax.azim += 1достичь того же эффекта.
Джо Кингтон
1
Извините, что побил вас, но все вокруг справедливо. Это также мой фрагмент кода, в этом цикле for было больше, чем просто view_init и savefig. =)
Космос
4
Спасибо Космос и Джо, это именно то, что я искал. Так как теперь я знал, что искать, я также нашел ax.dist, который - вместе с ax.azim и ax.elev - позволяет установить положение камеры в полярных координатах.
Андреас Блеулер
Если это ответ - не могли бы вы поставить галочку? Спасибо.
Космос
12
Вы также можете установить расстояние между камерой и точкой объекта, используя ax.dist = 15 (по умолчанию 10)
Тим
14

Было бы удобно применить положение камеры к новому графику. Поэтому я строю график, затем перемещаю график с помощью мыши, меняющей расстояние. Затем попробуйте скопировать вид, включая расстояние на другом участке. Я обнаружил, что axx.ax.get_axes () возвращает мне объект со старыми .azim и .elev.

В ПИТОНЕ ...

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

Позже 3d график ...

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

РЕДАКТИРОВАТЬ 1 ... ОК. Положение камеры - неправильное представление о значении .dist. Он работает поверх всего прочего как своего рода хакейский скалярный множитель для всего графа.

Это работает для увеличения / увеличения вида:

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

Позже График ...

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
источник
+1 за вызов хакерского скалярного умножения. Это очень раздражает, если вы надеялись на перспективу.
user5920660