#python #python-3.x #matplotlib #matplotlib-animation
#python #python-3.x #matplotlib #matplotlib-анимация
Вопрос:
У меня есть 3 списка, которые содержат координаты x, координаты y и координаты z соответственно. Я пытаюсь отследить положение в 3D-пространстве. Я использую приведенный ниже код:
fig = plt.figure()
ax = p3.Axes3D(fig)
def update(num, data, line):
line.set_data(data[:2, :num])
line.set_3d_properties(data[2, :num])
N = 4000
d3d=np.array([xdata,ydata,zdata])
line, = ax.plot(d3d[0, 0:1], d3d[1, 0:1], d3d[2, 0:1], color='blue')
ax.set_xlim3d([2.0, -2.0])
ax.set_xlabel('X')
ax.set_ylim3d([2.0, -2.0])
ax.set_ylabel('Y')
ax.set_zlim3d([0.0, 4.0])
ax.set_zlabel('Z')
ani = animation.FuncAnimation(fig, update, N, fargs=(d3d, line), interval=10000/N, blit=False)
plt.show()
Благодаря этому я могу успешно видеть траекторию в синем цвете. Тем не менее, я хочу видеть обновленную траекторию синим цветом и хочу выделить серым цветом предыдущую:
Я попытался использовать приведенную ниже функцию обновления, чтобы выделить серым цветом предыдущую строку:
def update(num, data, line):
line.set_data(data[:2, :num])
line.set_3d_properties(data[2, :num])
if line is not None:
line.set_color('gray')
но это просто выделяет серым цветом всю траекторию. Любая помощь будет оценена.
Комментарии:
1. Я думаю, вам нужно было бы создать две линии: одну для старой серой линии и одну для новой синей линии, а затем продолжать обновлять их обе с течением времени. Один
line3D
экземпляр не может иметь несколько цветов в matplotlib
Ответ №1:
Мы можем отслеживать нанесенные линии и просто изменять их цвет.
import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np
fig = plt.figure()
ax = fig.gca(projection="3d")
#random data
np.random.seed(12345)
d3d = np.random.random((3, 12))
line_list = []
#number of line segments to retain in blue before greying them out
line_delay = 4
def init():
ax.clear()
#you can omit the fixed scales, then they will be automatically updated
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 1)
def update(i):
#initializing the plot, emptying the line list
if not i:
init()
line_list[:] = []
#set line color to grey if delay number is exceeded
if len(line_list)>=line_delay:
line_list[-line_delay].set_color("grey")
#plot new line segment
newsegm, = ax.plot(*d3d[:, i:i 2], "blue")
line_list.append(newsegm)
ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]), interval = 300, repeat=True)
plt.show()
Преимущество этого подхода в том, что мы можем легко адаптировать его для лучшего представления данных — например, если у нас много данных, мы можем сделать их более плавными и удалить все невидимые линии:
import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np
fig = plt.figure()
ax = fig.gca(projection="3d")
#random data
np.random.seed(12345)
d3d = np.random.random((3, 40))
#defines the number of disappearing line segments
max_length = 20
line_list = []
def init():
ax.clear()
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 1)
def update(i):
if not i:
init()
line_list[:] = []
else:
#if not the first line segment, change color to grey,
line_list[-1].set_color("grey")
#then reduce gradually the alpha value for all line segments
diff2max = max(0, max_length-len(line_list))
[x.set_alpha((j diff2max)/max_length) for j, x in enumerate(line_list)]
#delete line segments that we don't see anymore to declutter the space
if len(line_list)>max_length:
del_line = line_list.pop(0)
del_line.remove()
#plot new segment and append it to the list
newsegm, = ax.plot(*d3d[:, i:i 2], "blue")
line_list.append(newsegm)
ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]), interval = 300, repeat=True)
plt.show()