Pythonで らせんを描く その3

画面の両側からくるくる巻く動画です。スムーズに動きます。右側のうずは中心から原点への直線が伸びていますが、消す方法を検討中です。動画とPython ソースコードを示します。Python 開発環境でお試しください。入力項目「巻き密度」は150、「離れ具合」は12程度が妥当です。

# CS-1 螺旋部分2次元アニメ基礎検討その3   2023.02.16 by Kero
# 両側から巻いていきます。
# 今回は、行列演算(アフィン変換)を利用して、「吹き出し」風にした。
# 回転角に比例してらせん中心からの距離が長くなる「等差らせん」を作る。
# 接線の傾きをらせんの回転角とする。
# 各i点における傾きは点i-1から点iへの傾きとする。

import sys
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation

# 描画画面設定。
fig, ax = plt.subplots(figsize=(10.0, 4.0))
ax.set_aspect('equal') # 正方形の方眼紙。
artists = [] # パラパラ漫画設定。最初は白紙。

n = input("巻き密度(100〜): ")
n = int(n)
m = input("離れ具合(  0〜): ")
m = int(m)

# 回転のマトリックス設定。座標の列ベクトル群に左から掛けると回転。
def A(rd):
    Am = np.array([[np.cos(rd), -np.sin(rd), 0],
                  [np.sin(rd),  np.cos(rd), 0],
                  [0., 0., 1.]])
    return Am

# y軸対称のマトリックス設定。
Dm = np.array([[-1, 0, 0],
               [ 0, 1, 0],
               [ 0, 0, 1]])

# 各点の回転角度を予め計算しておく。【重要】
# 右端(x=100)の点は、x=99を中心にπ/2(=1.570)回転。
do = [0] * (n + 1)  # for文でiは100から1までだけど、なぜか101個必要。
ri = 0
for i in range(n, 0, -1):
    do[i] = np.pi/2 - np.arctan2(ri, 1.)
    ri = np.sqrt(np.square(ri) + 1.)
dp = np.array(do)

sf = np.array([[1],[0],[0]]) # 図形を右に1移動するため。
ad = np.array([[0],[0],[1]]) # 図形に点(0,0)を追加するため。

# 図形(座標の列ベクトル)の最初は原点。
zu = np.array([[0],[0],[1]])

# ここかららせん作成。
for i in range(n, m,-1):
    zu = zu + sf # 図形を右に1移動。
    zu = np.append(zu, ad, axis=1) # 図形に原点を追加。
    Am = A(dp[i]) # 図形の回転マトリックスを作る。
    zu = np.dot(Am, zu) # かいてーん!!
    sf2 = np.array([[i],[0],[1]])
    zu2 = zu + sf2
    zu2 = np.append(zu2, ad, axis=1)
    zu3 = np.dot(Dm, zu2)
    zu4 = np.append(zu3, zu2, axis=1)
    artist= ax.plot(zu4[0], zu4[1], c='b') # グラフ表示。
    artists.append(artist) # 一コマをパラパラ漫画の1ページに収録。

anim = ArtistAnimation(fig, artists, interval=100, repeat=True)
anim.save('rasen-230216.gif', writer='pillow')
        
plt.show()
plt.close()