2023.02.23
らせんにハマってしまいました。原点から「らせん」を吹き出すことを考えます。一定長の直線を吹き出すごとに所定の角度だけ曲げます。曲率は、入力項目「曲率増減率?」で加減しています。サンプル図における曲率増減率は、左図: 50、中央図: 1、右図: 0.5 です。左図は「対数らせん」、中央図は「代数らせん」、右図は「放物らせん」になっています。一般的な教科書では、各らせんは別々の公式が示されていますが、ここでは一つの式で、パラメータを変えるだけで、各らせんを描いています。
ソースコードは Python 開発環境でお試しください。
# coil-basic-2.py
# CS-1 螺旋部分2次元アニメ基礎検討その4 2023.02.23 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()
ax.set_aspect('equal') # 正方形の方眼紙。
artists = [] # パラパラ漫画設定。最初は白紙。
n = input("グレード(100〜): ")
n = int(n)
dex = input("曲率増減率?: ")
ax.set_title("Curve change rate = " + dex)
dex = float(dex)
# 回転のマトリックス設定。座標の列ベクトル群に左から掛けると回転。
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
# 各点の回転角度を予め計算しておく。【重要】
# 右端(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]])
ad = np.array([[0],[0],[1]]) # 図形に点(0,0)を追加するため。
# 図形(座標の列ベクトル)の最初は原点。
zu = np.array([[0],[0],[1]])
# ここかららせん作成。
for i in range(n, 0,-1):
sf = np.array([[(1-dex)*i/n+dex],[0],[0]]) # ⊿x幅をdexへ漸増漸減。
zu = zu + sf # 図形を右に移動。
zu = np.append(zu, ad, axis=1) # 図形に原点を追加。
Am = A(dp[i]) # 図形の回転マトリックスを作る。
zu = np.dot(Am, zu) # かいてーん!!
artist= ax.plot(zu[0], zu[1], c='b') # グラフ表示。
artists.append(artist) # 一コマをパラパラ漫画の1ページに収録。
anim = ArtistAnimation(fig, artists, interval=100, repeat=True)
anim.save('coil-basic-2.gif', writer='pillow')
plt.show()
plt.close()