記事「リサージュ図形の回転に関する考察」において、\(\sin, \ \ \cos\)関数の引数がパラメータ\(t\)の線形関数ではなく、非線形になるようなものを考え、これを拡張されたリサージュ図形として考えてはどうかと示唆しました。ここでは、この拡張されたリサージュ図形を描いてみます。
楕円トーラス型コイル
記事「トーラス型コイル」では、主軌道として円を選び、その周りを副軌道となる楕円が螺旋状に巻いていくような形を描きました。今回は、同様にトーラス型コイルのようなものを作成しますが、主軌道が円ではなく、楕円にとっています。結果は以下のような図形になります。
描き方
この楕円トーラス型コイルは、記事「トーラス型コイル」で解説した描き方とほぼ同じです。主軌道が円から楕円(下図の赤色の楕円)に変わるだけです。
まず、\(N=2\)のリサージュ曲線\[ x(t) = A_1 \cos ( \omega_{x,1} t + \theta_{x,1})+A_2 \cos ( \omega_{x,2} t + \theta_{x,2}) , \\ y(t) = B_1 \sin ( \omega_{y,1} t + \theta_{y,1})+ B_2 \sin ( \omega_{y,2} t + \theta_{y,2}) \]に対してパラメータを以下のようにとります。\[ A_1 = B_1 = R = 120, \ \ A_2=B_2=r=40, \\ \omega_{x,1}=\omega_{y,1}=\Omega=1, \ \ \omega_{x,2}=\omega_{y,2}=\omega=120, \\ \theta_{x,1} =0, \ \ \theta_{y,1}=\Theta = 30, \ \ \theta_{x,2} = 0, \ \ \theta_{y,2} = \theta= 75 \]\( \theta_{y,1} \)を\(30\)にとることで、主軌道が楕円となります。では、この\(N=2\)のリサージュ図形をそのまま描いてみます。
やはり、45°傾いた楕円状の図形が楕円形に並べられたものになります。
楕円を放射線状に傾ける
副軌道の楕円を主軌道の楕円に沿って放射線状に傾ける方法は、記事「リサージュ図形の回転に関する考察」で解説しています。
主軌道上の座標を\( (R \cos \Omega t, R \sin (\Omega t + \Theta )) \)とすると、主軌道の接線方向は、主軌道上の座標をパラメータ\(t\)で微分した\( (-R \Omega \sin \Omega t, R \Omega \cos ( \Omega t + \Theta ) ) \)で表されます。この接線のベクトルから、主軌道の接線方向の\(x\)軸の正方向からの角度\( \varphi(t) \)を\[ \varphi (t) = \arctan \left( -\frac{\cos ( \Omega t + \Theta ) }{\sin \Omega t} \right) \]で求めることができます。
主軌道が円の場合\( \Theta =0 \)で\[ \varphi (t) = \Omega t +90 \]というパラメータ\(t\)の線形関数の形になりましたが、今回主軌道が楕円で\( \Theta \neq 0 \)となるので、\( \varphi (t) \)は非線形関数のまま残ります。そのため、本来のリサージュ図形の形で表すことはできませんが、今回はこれを線形から非線形に「拡張された」と考え、拡張されたリサージュ図形と呼ぶことにしました。
あとは、副軌道となる楕円上の点をその楕円の中心回りに時計回りに\( \varphi (t) -135 \)だけ回転させていくだけです。\[ \begin{pmatrix} \cos ( \varphi (t) -135 ) & -\sin ( \varphi (t) -135 ) \\ \sin ( \varphi (t) -135 ) & \cos ( \varphi (t) -135 ) \end{pmatrix} \begin{pmatrix} r \cos \omega t \\ r \sin (\omega t + \theta ) \end{pmatrix} = \begin{pmatrix} r \cos \omega t \cos ( \varphi (t) -135 ) – r \sin ( \omega t + \theta ) \sin ( \varphi (t) -135 ) \\ r \cos \omega t \sin ( \varphi (t) -135 ) + r \sin (\omega t + \theta ) \cos ( \varphi (t) -135 ) \end{pmatrix} \]これをもう少し整理すると、\[ r \cos \omega t \to \frac{r}{2} \cos ( \varphi (t) + \omega t -135 ) + \frac{r}{2} \cos ( \varphi (t) – \omega t -135 ) + \frac{r}{2} \cos ( \varphi (t) + \omega t + \theta -135 ) – \frac{r}{2} \cos ( \varphi (t) – \omega t – \theta -135 ) \\ r \sin ( \omega t + \theta ) \to \frac{r}{2} \sin ( \varphi (t) + \omega t -135 ) + \frac{r}{2} \sin ( \varphi (t) – \omega t -135 ) + \frac{r}{2} \sin ( \varphi (t) + \omega t + \theta -135 ) – \frac{r}{2} \sin ( \varphi (t) – \omega t – \theta -135 ) \]のように座標変換することで実現することができますので、これを主軌道の座標に加えることで、副軌道が主軌道と垂直に交わるような図形を描くことができます。
ソースコード
最後に、今回の「楕円トーラス型コイル」を描いたプログラムのソースコードを示しておきます。
void setup(){
size(500,500);
translate(width/2.0, height/2.0);
noFill();
int N = 2; // 項数
// y方向の位相を変化させる
float[] r_x = {120.0, 40.0};
float[] omega_x = {1.0, 120.0};
float[] theta_x = {0.0, 0.0};
float[] r_y = {120.0, 40.0};
float[] omega_y = {1.0, 120.0};
float[] theta_y = {30.0, 75.0};
N = 5;
float[] r2_x = {r_x[0], r_x[1]/2.0, r_x[1]/2.0, r_y[1]/2.0, -r_y[1]/2.0};
float[] omega2_x = {omega_x[0], omega_x[1], - omega_x[1], omega_y[1], - omega_y[1]};
float[] theta2_x = {theta_x[0], theta_x[1], - theta_x[1], theta_y[1], - theta_y[1]};
float[] r2_y = {r_y[0], r_x[1]/2.0, r_x[1]/2.0, r_y[1]/2.0, -r_y[1]/2.0};
float[] omega2_y = {omega_y[0], omega_x[1], - omega_x[1], omega_y[1], - omega_y[1]};
float[] theta2_y = {theta_y[0], theta_x[1], - theta_x[1], theta_y[1], - theta_y[1]};
drawLissajous(5, r2_x, omega2_x, theta2_x, r2_y, omega2_y, theta2_y);
}
// リサージュ曲線を描く関数
void drawLissajous(
int N, // 項数
float[] r_x, // x方向の振幅に関する配列
float[] omega_x, // x方向の周波数に関する配列
float[] theta_x, // x方向の位相に関する配列
float[] r_y, // y方向の振幅に関する配列
float[] omega_y, // y方向の周波数に関する配列
float[] theta_y // y方向の位相に関する配列
){
float t, x, y, phi;
int num = 10000;
beginShape();
for(int i=0; i<num; i++){
t = radians(i*360.0/num);
phi = atan2(cos(omega_x[0] * t + radians(theta_y[0])), -sin(omega_x[0] * t ) );
x = r_x[0] * cos( omega_x[0] * t + radians(theta_x[0]) );
y = r_x[0] * sin( omega_y[0] * t + radians(theta_y[0]) );
for(int j=1; j<N; j++){
x += r_x[j] * cos( phi + omega_x[j] * t + radians(theta_x[j]-135.0) );
y += r_y[j] * sin( phi + omega_y[j] * t + radians(theta_y[j]-135.0) );
}
vertex(x,y);
}
endShape();
}