# makizushi-06.py 2023.03.25 by Kero
# 最終目標は「巻きずしを作る3Dアニメ」です。
# 6.「巻きずし」アニメの3D化(その1:輪郭)(makizushi-06.py)
# 巻きずしの幅を、z=0からz=10の10とします。
# z=0平面でらせんを描き、一筆書きで、z=10平面で逆順でらせんを描き、
# 最後にz=0平面のスタート点に戻ります。
# 前回のソースコードの解説(コメント文)を消し、今回の解説をします。
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D # 3D処理のモジュールを追加。
pi = np.pi
imgs = []
# らせんの計算
maki = 4 # 巻数を4に変更。
r0 = 1
a = 2
kaku0 = 2 * pi * r0 / a
ara = 72 # 粗さを72に変更。
pon = maki * ara + 1
kaku = np.linspace(0, 2 * pi * maki, pon)
kakut = kaku + kaku0
r = a * kakut / (2 * pi)
x = r * np.cos(kakut)
y = r * np.sin(kakut)
# z座標を追加。pon+1は、らせん後の巻き余りの1点を追加するため。
z0 = np.zeros(pon+1) # z=0のxy平面上にらせんを描くため。
z1 = np.ones(pon+1) * 10 # z=10のxy平面上にらせんを描くため。
# グラフ化
fig = plt.figure(figsize=(6,6)) # figとaxを分けて設定。
ax = fig.add_subplot(111,projection='3d') # 3D表示を宣言。
ax.set_aspect('auto') # 軸設定はとりあえず自動。
ax.grid()
ax.set_xlim(-5,140) # x軸をさらに延長。
ax.set_ylim(-5,140) # x,y目盛の比率は設定できないのでxに合わせる。
ax.set_zlim(-5,15) # z軸の目盛は、0と10が入るように適当に。
ax.scatter(0,0,0, c='r') # zの値を加えて原点表示。
sld = 0
for i in range(1,pon+1):
rkak = -kakut[i-1] - pi/2
xr = x[:i] * np.cos(rkak) - y[:i] * np.sin(rkak)
yr = x[:i] * np.sin(rkak) + y[:i] * np.cos(rkak)
xr0 = xr - xr[i-1]
yr0 = yr - yr[i-1]
sld += np.sqrt(xr0[i-2]**2 + yr0[i-2]**2)
xr0 = xr0 + sld
xr0 = np.append(xr0, 135) # らせん最外端の点と(135,0)を結ぶ。
yr0 = np.append(yr0, 0) # 同上。どちらも配列後端に要素を追加。
zr0 = z0[0:i+1] # 巻き余りの1点を追加したのでi+1まで作る。
xr1 = np.flipud(xr0) # z=10平面のらせんは逆順で描く。
yr1 = np.flipud(yr0) # 同上。
zr1 = z1[0:i+1] # zの値はすべて10。
xrt = np.append(xr0,xr1) # z=0平面のらせんとz=10平面のらせんをつなぐ。
yrt = np.append(yr0,yr1) # 同上。
zrt = np.append(zr0,zr1) # 同上。
xrt = np.append(xrt,xr0[0]) # 最後に、最初のスタート点を追加。
yrt = np.append(yrt,yr0[0]) # 同上。
zrt = np.append(zrt,zr0[0]) # 同上。
img =ax.plot(xrt, yrt, zrt, c='b') # z値の配列を追加。
imgs.append(img)
anime = animation.ArtistAnimation(fig, imgs, interval=5) # 5ミリ秒間隔に変更。
plt.show()
plt.close()
sys.exit()