Анимация 3D-вектора с помощью matplotlib

Мне нужно анимировать как величину, так и положение векторной стрелки в трехмерной фигуре с помощью matplotlib. Насколько я могу судить, я не могу анимировать положение векторов с помощью Axes3D.quiver, и для трехмерной фигуры нет matplotlib.pyplot.arrow. Есть ли способ сделать это или мне нужно посмотреть другие варианты?

Я не могу сказать, чего вы пытаетесь добиться своим вопросом. Можете ли вы разместить соответствующий код и (если возможно) изображения того, что вы пытаетесь выполнить?

Jack Moody 14.03.2019 19:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
3 787
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете построить свою собственную стрелку, как это делает Axes3D.quiver, и соответствующим образом изменить положение линии. Вот идея, как это могло бы работать:

from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt
import numpy as np

def move_arrow(pos, dir, trunk_plt, head_plt, length=1, arrow_length_ratio=0.3, normalize=False, arrow_angle=15):
    pos = np.asarray(pos)
    dir = np.asarray(dir)
    dir_norm = dir / np.linalg.norm(dir)
    if normalize:
        dir = dir_norm
    shift = dir * length
    end = pos + shift
    # Make rotation matrix for arrow direction
    head_x = -dir_norm
    head_y = np.cross(head_x, np.arange(3) == head_x.argmin())
    head_z = np.cross(head_x, head_y)
    rot_ref = np.stack([head_x, head_y, head_z], axis=1)
    # Make rotation matrix for head tips
    arrow_rad = np.deg2rad(arrow_angle)
    s, c = np.sin(arrow_rad), np.cos(arrow_rad)
    rot_arrow = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]])
    # Compute head tips
    head_length = np.linalg.norm(shift) * arrow_length_ratio
    head_1 = end + rot_ref @ rot_arrow @ [head_length, 0, 0]
    head_2 = end + rot_ref @ rot_arrow.T @ [head_length, 0, 0]
    # Set line data
    trunk_plt.set_data([pos[0], end[0]], [pos[1], end[1]])
    trunk_plt.set_3d_properties([pos[2], end[2]])
    head_plt.set_data([head_1[0], end[0], head_2[0]], [head_1[1], end[1], head_2[1]])
    head_plt.set_3d_properties([head_1[2], end[2], head_2[2]])

fig = plt.figure()
ax = fig.gca(projection='3d')
pos = [.2, .4, .1]
dir = [.5, .0, .3]
trunk_plt = ax.plot3D([], [], [], c='b')[0]
head_plt = ax.plot3D([], [], [], c='b')[0]
move_arrow(pos, dir, trunk_plt, head_plt)
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

def anim_frame(i):
    dir_shift = 0.1 * np.array([np.sin(0.01 * i + 1), np.sin(0.02 * i + 2), np.sin(0.03 * i + 3)])
    move_arrow(pos, dir + dir_shift, trunk_plt, head_plt)
    return [trunk_plt, head_plt]

anim = mplanim.FuncAnimation(fig, anim_frame, range(1000), interval=1. / 30., repeat=False, blit=True)
anim.save('arrow.avi')

Результат:

Arrow animation

Ответ принят как подходящий

quiver не имеет функции обновления, но вы можете легко удалить старый колчан и рисовать новый в каждом кадре.

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots(subplot_kw=dict(projection = "3d"))

def get_arrow(theta):
    x = np.cos(theta)
    y = np.sin(theta)
    z = 0
    u = np.sin(2*theta)
    v = np.sin(3*theta)
    w = np.cos(3*theta)
    return x,y,z,u,v,w

quiver = ax.quiver(*get_arrow(0))

ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
ax.set_zlim(-2, 2)

def update(theta):
    global quiver
    quiver.remove()
    quiver = ax.quiver(*get_arrow(theta))

ani = FuncAnimation(fig, update, frames=np.linspace(0,2*np.pi,200), interval=50)
plt.show()

quiver animation

Другие вопросы по теме