Je suis accro à l'animation 3D Sin-Cos-t suivante qui est arrivée sur Twitter il y a 3 jours, je vais donc la résumer. Je voulais dessiner une figure Lisaju plus intéressante avec une colle légère qui semble être une figure Lisaju ordinaire. .. .. J'en étais accro. https://twitter.com/i/status/1302164499139502080 Je voulais dessiner la même image, mais j'ai abandonné sur les points suivants.
・ Animation Axes3D ・ Animation Sin-Cos-t -Appelez la fonction update () directement pour dessiner ・ Décalez l'axe Z ・ Rotation des figures ・ Figurine Lisaju 3D
Au début, même si c'était en 3D, j'ai finalement pensé qu'il serait possible d'aller avec quelque chose comme une référence. 【référence】 [Matplotlib basic] Essayez d'écrire un graphique dynamique ♬ ~ Sortie vidéo; animation Gif En fait, dans sin-cos-t, vous trouverez un code similaire à Gugu: 【référence】 ② [Matplotlib] Visualisation des données 3D
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
#Ajouter une figure
fig = plt.figure(figsize = (8, 8))
#Ajout d'axes 3D
ax = fig.add_subplot(111, projection='3d')
#Définir le titre des axes
ax.set_title("Helix", size = 20)
#Définir l'étiquette de l'axe
ax.set_xlabel("x", size = 14)
ax.set_ylabel("y", size = 14)
ax.set_zlabel("z", size = 14)
#Définir l'échelle de l'axe
ax.set_xticks([-1.0, -0.5, 0.0, 0.5, 1.0])
ax.set_yticks([-1.0, -0.5, 0.0, 0.5, 1.0])
#Définition du rapport de circonférence
pi = np.pi
#Nombre de divisions de paramètres
n = 256
#Créer le paramètre t
t = np.linspace(-6*pi, 6*pi, n)
#Equation en spirale
x = np.cos(t)
y = np.sin(t)
z = t
#Tracez une courbe
ax.plot(x, y, z, color = "red")
plt.show()
Le résultat est le suivant, mais j'ai obtenu un chiffre similaire bien que cela ne fonctionne pas. Après cela, déplacez-le simplement, recherchez l'animation. Un moyen facile de le trouver est sur matplotlib.org Une intrigue animée en 3D., mais j'ai trouvé quelque chose de plus proche ci-dessous.
【référence】 3D animation using matplotlib C'est presque la réponse.
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
def gen(n):
phi = 0
while phi < 2*np.pi:
yield np.array([np.cos(phi), np.sin(phi), phi])
phi += 2*np.pi/n
def update(num, data, line):
line.set_data(data[:2, :num])
line.set_3d_properties(data[2, :num])
N = 100
data = np.array(list(gen(N))).T
line, = ax.plot(data[0, 0:1], data[1, 0:1], data[2, 0:1])
# Setting the axes properties
ax.set_xlim3d([-1.0, 1.0])
ax.set_xlabel('X')
ax.set_ylim3d([-1.0, 1.0])
ax.set_ylabel('Y')
ax.set_zlim3d([0.0, 10.0])
ax.set_zlabel('Z')
ani = animation.FuncAnimation(fig, update, N, fargs=(data, line), interval=10000/N, blit=False)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()
Cependant, lorsque j'essaye de dessiner trois animations, cela ressemble à ceci:
aniy = animation.FuncAnimation(fig, update, N, fargs=(datay, liney), interval=10000/N, blit=False)
anix = animation.FuncAnimation(fig, update, N, fargs=(datax, linex), interval=10000/N, blit=False)
aniz = animation.FuncAnimation(fig, update, N, fargs=(dataxy, linexy), interval=10000/N, blit=False)
Avec cette méthode, vous pouvez obtenir des animations similaires sous forme d'images, mais je ne peux pas penser à un moyen de sauvegarder ces trois animations ensemble.
J'ai décidé de tracer chacun d'eux avec plt.pause (0,001) comme indiqué ci-dessous et d'enregistrer la figure. Finalement, j'ai décidé de générer gif_animation à partir de ces chiffres.
frames =100
s=180
for n in range(frames):
s+=1
num = s%800+200
update(num,datax,linex)
update(num,datay,liney)
update(num,dataz,linez)
plt.pause(0.001)
plt.savefig('./sin_wave/'+str(n)+'.png'.format(elev, azim))
from PIL import Image,ImageFilter
images = []
for n in range(frames):
exec('a'+str(n)+'=Image.open("./sin_wave/'+str(n)+'.png ")')
images.append(eval('a'+str(n)))
images[0].save('./sin_wave/sin_wave_el{}_az{}.gif'.format(elev, azim),
save_all=True,
append_images=images[1:],
duration=100,
loop=0)
Et en limitant la plage de dessin avec line.set_data (data [: 2, num-200: num]) et num = s% 800 + 200 comme dans le code ci-dessous, le résultat est plus proche de ce que vous voulez. ..
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
def genxy(n,fx,fy,fxc=0,fyc=0):
phi = 0
sk = 0
while phi < 360:
yield np.array([fx*np.cos(phi)+fxc, fy*np.sin(phi)+fyc,phi])
phi += 36*5/n
def update(num, data, line):
line.set_data(data[:2,num-200 :num]) #Limiter la section de dessin
line.set_3d_properties(data[2,num-200 :num])
N = 960
datay = np.array(list(genxy(N,fx=0,fy=1,fxc=-2,fyc=0))).T
liney, = ax.plot(datay[0, 0:1], datay[1, 0:1], datay[2, 0:1])
datax = np.array(list(genxy(N,fx=1,fy=0,fxc=0,fyc=2))).T
linex, = ax.plot(datax[0, 0:1], datax[1, 0:1], datax[2, 0:1])
dataz = np.array(list(genxy(N,fx=1,fy=1,fxc=0,fyc=0))).T
linez, = ax.plot(dataz[0, 0:1], dataz[1, 0:1], dataz[2, 0:1])
# Setting the axes properties
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([36.0, 80.])
ax.set_zlabel('Z')
frames =36
s=180
for n in range(frames):
s+=1
num = s%800+200
update(num,datax,linex)
update(num,datay,liney)
update(num,dataz,linez)
plt.pause(0.001)
plt.savefig('./sin_wave/'+str(n)+'.png'.format(0, 0))
from PIL import Image,ImageFilter
images = []
for n in range(frames):
exec('a'+str(n)+'=Image.open("./sin_wave/'+str(n)+'.png ")')
images.append(eval('a'+str(n)))
images[0].save('./sin_wave/sin_wave_el{}_az{}.gif'.format(0, 0),
save_all=True,
append_images=images[1:],
duration=100,
loop=0)
Réécrivons la fonction update () comme suit pour décaler l'axe Z. En conséquence, l'image est dessinée dans la même position le long de l'axe Z. L'affichage de l'axe est également effacé ici.
def update(num, data, line):
line.set_data(data[:2,num-200 :num])
line.set_3d_properties(data[2,num-200 :num])
ax.set_zlim3d([0+data[2,num-200], 34+data[2,num-200]])
ax.set_zticklabels([])
ax.grid(False)
Eh bien, si vous apportez les axes de coordonnées à cet arrangement, il est terminé pour le moment. Cependant, cela a été difficile. Tout d'abord, vous pouvez faire pivoter l'arbre comme suit. Dans ce qui suit, l'image de la valeur initiale est sortie avec l'axe modifié.
for elev in range(0,360,10): #Changement d'élévation
for azim in range(-180,180,5): #Changer l'angle azimutal
ax.view_init(elev, azim) #Ajustez ici l'orientation des axes de coordonnées
frames =1 #34
s=180
for n in range(1): #frames
s+=1
num = s%800+200
update(num,datax,linex)
update(num,datay,liney)
update(num,dataz,linez)
plt.pause(0.001)
plt.savefig('./sin_wave/'+str(n)+'{}{}.png'.format(elev, azim))
En conséquence, cet arrangement n'a pas été obtenu.
Vous n'avez pas assez d'imagination.
Je ne peux penser à rien d'autre que la plage d'angles ci-dessus.
Cependant, j'ai eu l'idée de changer les en-têtes des axes pour X-Y-Z.
yield np.array([phi,fx*np.cos(phi)+fxc, fy*np.sin(phi)+fyc])
C'est dit.
En d'autres termes, si vous changez le cap de l'axe, la spirale se couchera.
Je suis donc arrivé au code suivant.
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
def genxy(n,fx,fy,fxc=0,fyc=0):
phi = 0
while phi < 360:
yield np.array([phi,fx*np.cos(phi)+fxc, fy*np.sin(phi)+fyc])
phi += 36*5/n
def update(num, data, line):
line.set_data(data[:2,num-200 :num])
line.set_3d_properties(data[2,num-200 :num])
ax.set_xlim3d([0+data[0,num-200], 36+data[0,num-200]])
ax.set_xticklabels([])
ax.grid(False)
N = 960
datay = np.array(list(genxy(N,fx=0,fy=1,fxc=-2,fyc=0))).T
liney, = ax.plot(datay[0, 0:1], datay[1, 0:1], datay[2, 0:1])
datax = np.array(list(genxy(N,fx=1,fy=0,fxc=0,fyc=-2))).T
linex, = ax.plot(datax[0, 0:1], datax[1, 0:1], datax[2, 0:1])
dataz = np.array(list(genxy(N,fx=1,fy=1,fxc=0,fyc=0))).T
linez, = ax.plot(dataz[0, 0:1], dataz[1, 0:1], dataz[2, 0:1])
# Setting the axes properties
ax.set_xlim3d([20, 70.0])
ax.set_xlabel('Z')
ax.set_ylim3d([-2.0, 2.0])
ax.set_ylabel('X')
ax.set_zlim3d([-2.0, 2.0])
ax.set_zlabel('Y')
elev=20.
azim=35.
ax.view_init(elev, azim)
frames =100
s=180
for n in range(frames): #frames
s+=1
num = s%800+200
update(num,datax,linex)
update(num,datay,liney)
update(num,dataz,linez)
plt.pause(0.001)
plt.savefig('./sin_wave/'+str(n)+'.png'.format(elev, azim))
from PIL import Image,ImageFilter
images = []
for n in range(frames):
exec('a'+str(n)+'=Image.open("./sin_wave/'+str(n)+'.png ")')
images.append(eval('a'+str(n)))
images[0].save('./sin_wave/sin_wave_el{}_az{}.gif'.format(elev, azim),
save_all=True,
append_images=images[1:],
duration=100,
loop=0)
De cette façon, la première animation 3D publiée a été produite.
Cependant, ce que je voulais à l'origine, c'est une figurine 3D Lisaju, alors je vais en essayer.
Vous pouvez le faire en changeant ce qui suit et en changeant frames = 200
pour que la connexion soit fluide.
yield np.array([phi,fx*np.cos(3*phi/2)+fxc, fy*np.sin(2*phi/3)+fyc])
X : Y = 1 : 2 X : Y = 1/2 : 2/3 X : Y = 3/2 : 2/3
・ J'ai dessiné une animation 3D de Sin-Cos-t ・ Vous pouvez maintenant dessiner une animation 3D ・ J'ai dessiné une figurine de Lisaju en 3D
Version terminée Amélioré pour dessiner la figure de Lisaju à l'origine 3d_animation_Risajyu/3D_animation_risajyu.py
point ajouté
Recommended Posts