「The Nature of Code」から単振動について取り上げます。ここでは、単振動の出力値を振り子の座標に適用します。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。
本記事の参考書籍は以下です。
用語の整理:振幅と周期
- 振幅(Amplitude)
- 振動の幅の半分の長さを振幅という。振動は、グラフの一番下と一番上の幅のこと。
- 周期(Period)
- 1サイクルの運動にかかる時間
y=sinθのグラフの読み取り方
図のグラフを見ると、振幅が1で周期が2πであることが分かります。正弦の出力は、1を上回ったり-1を下回ったりすることはありません。2πラジアン(360度)ごとに波のパターンが繰り返されます。
振幅と周期をコードに落とし込む
振幅と周期が何なのか分かってもコード化できなければウィンドウに描画できません。ここからは、コードに落とし込んでいきます。
振幅
振幅は幅なので、ウィンドウのピクセルに当てはめることができます。例えば、幅が200ピクセルのウィンドウの場合、中央から右に100ピクセル、左に100ピクセル振動すると考えます。つまり、x座標に対応します。
周期
Processingの世界での時間の尺度は、フレーム数です。繰り返しの周期を何フレームにするのか決めます。例えば、30フレーム、100フレーム毎に繰り返すようにすれば良いです。フレーム数は、好きなように決められます。
単振動の例(1):振幅と周期
以下は、単振動のグラフ(y=cosθ)を振り子の動きに適用する参考例です。振幅50ピクセル、周期120フレームで左右に振動します。
//Simple Harmonic Motion float amplitude = 50; //振幅 float period = 120; //周期 void setup() { size(200, 200); } void draw() { background(255); //単振動を使った水平位置の計算 float x = amplitude * cos(TWO_PI * frameCount / period); stroke(0); strokeWeight(2); fill(127); translate(width/2, height/2); line(0, 0, x, 0); ellipse(x, 0, 24, 24); }
プログラムの解説
以下は、x座標を求めるコードです。
//単振動を使った水平位置の計算 float x = amplitude * cos(TWO_PI * frameCount / period);
上記の式は初見だとよく分からないので、変数が取る値を表にして見てみます。 見る変数はframeCount、frameCount / period、TWO_PI * frameCount / periodです。
frameCount | frameCount / period | TWO_PI * frameCount / period |
---|---|---|
0 | 0 | 0 |
60 | 0.5 | PI |
120 | 1 | TWO_PI |
240 | 2 | 2 * TWO_PI(or 4 * PI) |
表から「frameCountが120のときに2πになり、1サイクルを完了する」ことが分かります。この例では、周期を120フレームにしているので矛盾していません。
単振動の例(2):振幅と角速度
以下は、単振動のグラフ(y=cosθ)を振り子の動きに適用する参考例です。振幅100ピクセル、周期120フレームで左右に振動します。
例1との違いは、周期の代わりに角速度を使って座標を計算している点です。
//Simple Harmonic MotionII float angle = 0; //角度 float aVelocity = 0.05; //角速度 float amplitude = 100; //振幅 void setup() { size(200, 200); } void draw() { background(255); //単振動を使った水平位置の計算 float x = amplitude * cos(angle); angle += aVelocity; stroke(0); strokeWeight(2); fill(127); translate(width/2, height/2); line(0, 0, x, 0); ellipse(x, 0, 24, 24); }
単振動の例1のプログラムと同じように動作します。
プログラムの解説
以下は、x座標を求めるコードです。
//単振動を使った水平位置の計算 float x = amplitude * cos(angle); angle += aVelocity;
cos(angle)のangleはラジアンです。上記のコードでは、angleにそれらしい値を入れて計算しています。3行目でangleに角速度を加えて、angleの値を更新します。
2つのプログラムの違い
2つのプログラムで異なるところは、cos(θ)を計算するところです。
//単振動の例1:振幅と周期 float x = amplitude * cos(TWO_PI * frameCount / period);
//単振動の例2:振幅と角度 float x = amplitude * cos(angle); angle += aVelocity;
例1は丁寧な書き方で、例2は単純化した書き方だと思ってもらえれば良いです。
まとめ
「The Nature of Code」から単振動について取り上げました。今回は、単振動の出力値を振り子の座標に適用しました。引き続き、「The Nature of Code」の内容を勉強します。
参考書籍
※Javaの勉強にもなるので一石二鳥です。