サイクロイド(cycloid)、あえて日本語に訳すなら、「転がってる感じ」というところでしょうか。
円をコロコロ転がしてできる図形です。
1.1. サイクロイドの式
図1のように、半径rの円(動円)を、X軸に沿って転がすことを考えます。
サイクロイドとは、この動円の円周上の一点Pが描く軌跡です。
図1では、最初に原点にある点Pが、動円が転がることによって描く軌跡を示しています。
1.1.1. θ
ここでは、図1のように「動円が回転した角度」を θ とします。
点Pは、 θ=0° の時に原点からスタートし、 θ=180°で頂点に達し、 θ=360° で一周してX軸上に戻ってきます。
サイクロイドの式は、このθをパラメータとして、つまり、θを0°から増やしていく形で、考えていきます。
1.1.2. 中心C
θをパラメータにしたので、回転角がθの時の中心Cの座標を考えます。
まず、Y座標は、θに関係なく常に r です。
次に、X座標に関しては、図1に緑で示したように、転がった長さ、つまりは中心角θに対する弧の長さ rθ になります。
というわけで、
となります(θはラジアンで計算します)。
1.1.3. 中心Cから見た点Pの座標
中心Cを基準として、そこから点Pの座標をどう表せるかを、図1aを眺めながら考えます。
まずX座標は、中心Cの座標から r sinθ を引いた値になります。
次にY座標は、中心Cの座標から r cosθ を引いた値になります。
θ=0°,90°,180° 等の時を当てはめてみれば、確認できます。
よって、中心Cから見た点Pの座標は、
となります。
1.2. サイクロイドを描く
1.2.1. とりあえず描く
とりあえず、サイクロイドを描いてみます。
! ! サイクロイドを描く ! Copyright(c) カイン Cain 2006 ! LET r = 1 ! 半径 WHEN EXCEPTION IN INPUT r USE END WHEN LET r = ABS( r ) LET rounds = 1.7 ! 周回数 WHEN EXCEPTION IN INPUT rounds USE END WHEN LET rounds = ABS( rounds ) ! SET WINDOW -r * 1.2, r * ( 2 * PI * rounds + 1.2 ), & & r - ( 2 * PI * rounds + 2.4 ) / 2, r + ( 2 * PI * rounds + 2.4 ) / 2 DRAW grid ! ! サイクロイド描画 ! 関数定義 DEF xp(t) = r * ( t - SIN( t ) ) DEF yp(t) = r * ( 1 - COS( t ) ) ! LET div = 36 ! 360°を分割する数 ! FOR t = 0 TO 2 * PI * rounds STEP 2 * PI / div PLOT LINES : xp(t), yp(t); NEXT t END
実行すると、まず半径 r
の入力を求められ(初期値1)、続いて周回数 rounds
の入力も求められます(初期値1.7)。
周回数は、 θ=0°~360°を一周と考えて、何周分描くか、を指定します。
グラフィックスウィンドウの大きさを、 SET WINDOW
で、 r
と rounds
を元に軌跡がウィンドウ内に収まるように設定するので、あまり rounds
を大きくしない方がいいでしょう。…どうせ同じ曲線の繰り返しですし。
デフォルト値のままで描くと、次のような軌跡が描かれます。
r
とrounds
の入力-
r
とrounds
の入力については、前回やった通り、初期値を設定し、例外も受け止め、絶対値を取っています。 - 行継続
-
JIS Full BASICでは、基本的には一行一命令なのですが、命令文を複数の行に分けることもできます。
リスト1では、SET WINDOW
文が長くなったので二行にわけ、その行末と行頭をアンド記号(&
)でつないでいます。
今回は、ブラウザ上で表示するために行継続を使いましたが、普段は特に使う必要はありません。 - 括弧
-
JIS Full BASICでは、数学と同様、括弧(
(
~)
)で括った部分が先に計算されます。
r * ( 2 * PI * rounds + 1.2 )
は、まず先に2 * PI * rounds + 1.2
が計算され、それにr
が掛けられます。
ただし、数学では丸括弧( () )の外側では波括弧( {} )で括ったりしますが、JIS Full BASICでは丸括弧のみが使われ、丸括弧の外側でも丸括弧で括ります。 - 関数
-
JIS Full BASICでは、関数(function)を次のように定義します。
DEF 関数名(引数1,引数2,…) = 式
こうして定義した関数は、組み込み関数のSIN
、COS
、ABS
等と同じ感覚で使うことができます。
リスト1では、式(3)を元に、点 P の座標(xP(θ),yP(θ))をDEF xp(t) = r * ( t - SIN( t ) ) DEF yp(t) = r * ( 1 - COS( t ) )
と定義しています。
この時、半径を表す変数r
は、メインプログラムの変数r
がそのまま使われますが、引数として受け取っている、回転角θを表す変数t
の方は、関数定義内でのみ使えるローカル変数になります。
変数r
は、プログラムの前半で設定されて以降は値が変わらないために、このような形で関数xp
、yp
を定義しています。
そして、θである変数 t
を0から2π×(周回数)まで変化させ、 関数 xp(t)
、 yp(t)
によって点 P の座標を得て、サイクロイドを描いています。
1.2.2. ゆっくり描く
軌跡が描かれた結果だけではなく、軌跡が描かれる経過を表現することを考えます。
…
LET div = 36 ! 360°を分割する数
LET round_time = 2 ! t=0~2π を描くのにウェイトをかける秒数
!
FOR t = 0 TO 2 * PI * rounds STEP 2 * PI / div
PLOT LINES : xp(t), yp(t);
WAIT DELAY round_time / div
NEXT t
END
実行すると、リスト1と同じ軌跡がゆっくり描かれます。
- ウェイト
-
WAIT DELAY 待ち時間
とWAIT DELAY
文を使うことで、指定した時間(秒単位、小数可)だけウェイト(=待ち時間)を入れることが出来ます((仮称)十進BASIC独自の拡張)。
リスト2では、線を一つ引くごとにround_time/div
秒のウェイトを入れています。
つまり、リスト2の実行時間は、リスト1に比べて (round_time
/div
) ×div
×rounds
秒ほど余計にかかります。
ウェイトを入れることで、描画の様子をアニメーションさせるための下準備ができました。
1.3. サイクロイドの描画アニメーション
ここまでは点Pの軌跡だけを描いてきましたが、動円が回転する様子も描くことを考えます。
1.3.1. 動円を描く
まずは動円を描きます。
!
! サイクロイドを描く
! Copyright(c) カイン Cain 2006
!
DECLARE EXTERNAL PICTURE circle
!
LET r = 1 ! 半径
…
LET round_time = 2 ! t=0~2π を描くのにウェイトをかける秒数
!
LET prev_xp = xp(0) ! 1つ前の点
LET prev_yp = yp(0)
!
FOR t = 0 TO 2 * PI * rounds STEP 2 * PI / div
! 軌跡描画
SET LINE COLOR 4
PLOT LINES : prev_xp, prev_yp ; xp(t), yp(t)
LET prev_xp = xp(t)
LET prev_yp = yp(t)
! 動円描画
SET DRAW MODE NOTXOR
SET LINE COLOR 2
DRAW circle( r * t, r, r )
WAIT DELAY round_time / div
DRAW circle( r * t, r, r )
SET DRAW MODE OVERWRITE
NEXT t
END
!
! (擬似)円描画ルーチン
!
EXTERNAL PICTURE circle( xc, yc, r )
LET div = 90
!
FOR t=0 TO 2 * PI STEP 2 * PI / div
PLOT LINES : xc + r * COS( t ), yc + r * SIN( t );
NEXT t
END PICTURE
(擬似)円描画ルーチンは、第1回のリスト6からコピーしています。
実行すると、次のように描画途中の動円も描かれます。
prev_x
とprev_y
-
第1回のリスト4でしたように、軌跡を描く際に、一つ前の点の座標を
prev_x
とprev_y
に記憶して線を引いています。
これは、軌跡を描く途中に動円を描くと、PLOT LINES X座標, Y座標;
と末尾にセミコロンを置いても、動円を描く(擬似)円描画ルーチン中にもPLOT LINES
文があって、線がつながらないためです。
こういう場合、一つ前の点の座標を記憶するやり方の方が応用が利きます。 - 線の色
-
SET LINE COLOR 色番号
とすることで、描かれる線の色を変えることができます。
カラーインデックスは、0が白、1が黒、2が青、3が緑、4が赤…と、255まで使えます。
リスト3では、軌跡を色番号4の赤、動円を色番号2の青で描いています。より細かい色の指定もできますが、今回は取り上げません。 - 描画モード
-
アニメーションするためには、一度描いた動円を消す必要があります。
しかし、動円を消す時に、既に描いた点Pの軌跡まで消えてしまっては困ります。
そんな時、描画モードNOTXORを使います。
なぜNOTXORなのかは、一応コラムに書いておきました。
NOTXORモードへは、SET DRAW MODE NOTXOR
で移行します。
NOTXORモードでは、次のような動作をします。- 白地には、描こうとする色そのままの色で描かれる。
- 白地以外のところには、描こうとする色とは異なる色で描かれる。
- 白地であっても白地でなくても、同じ色で二度描けば、そこの色は元に戻る=消える。
これにより、アニメーションが実現できます。
リスト3では、DRAW circle(...)
で動円を描く。WAIT DELAY ...
でちょっと待つ。DRAW circle(...)
で動円を描く=消す。
通常の上書きモードへは、SET DRAW MODE OVERWRITE
で戻ります。
動円を動かすことで、サイクロイドがより実感できるようになりました。
なぜNOTXORだと二度描いたら消えるのか、について、ざっと書いておきます。
ただ、これを理解するためには論理演算を理解しておく必要があるのですが、それをここで一から書くのは難しいので、論理演算の基礎を前提として書きます。
別に、分からなくても困ることはありません。
以下、話は0と1のみの場合で進めていきます。
論理演算NOT XOR
NOT XOR、つまり排他的論理和(exclusive or)の否定は、次のようになります。
X | Y | X NOT XOR Y |
---|---|---|
0 | 0 | 1 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
真っ白な背景に描くとそのままの色になる
背景色Bは、白の時1であるとします。
白い背景色B=1に、ある色CでNOT XORで描くと、次のようになります。
B | C | B NOT XOR C=C' |
---|---|---|
1 | 0 | 0 |
1 | 1 | 1 |
実際に描かれた色をC'としています。
NOTXORで色Cで描くと、白い背景には色Cがそのまま出ていますね。
真っ白な背景でない時は?
背景色B=0の時は、次のようになります。
B | C | B NOT XOR C=C' |
---|---|---|
0 | 0 | 1 |
0 | 1 | 0 |
Cとは異なる色で描かれます。
赤い点Pの軌跡と青い動円が交差するところを拡大すると、色が緑になっています。
もう一度NOT XORで描くと…
Bに一度色CでNOT XORで描いてC'になったところに、もう一度色CでNOT XORで描くと、次のようになります。
B | C | B NOT XOR C=C' | C | C' NOT XOR C |
---|---|---|---|---|
1 | 0 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
0 | 0 | 1 | 0 | 0 |
0 | 1 | 0 | 1 | 0 |
C' NOT XOR C=Bになりました。
つまり、NOT XORで白地に色Cで描くと色Cになり、もう一度NOT XORで色Cで描くと、白地でもそうでなくても、元の色に戻る=消せる、ということです。
これにより、「アニメーションのための一時的な描画」が実現できます。
1.3.2. 点Pも描く
点Pの位置を、もう少し分かりやすく描きたいと思います。
… LET prev_yp = yp(0) ! SET POINT STYLE 5 ! 描画ポイントを示す SET POINT COLOR 2 ! FOR t = 0 TO 2 * PI * rounds STEP 2 * PI / div … DRAW circle( r * t, r, r ) PLOT LINES : r * t, r ; xp(t), yp(t) PLOT POINTS: xp(t), yp(t) WAIT DELAY round_time / div PLOT POINTS: xp(t), yp(t) PLOT LINES : r * t, r ; xp(t), yp(t) DRAW circle( r * t, r, r ) SET DRAW MODE OVERWRITE NEXT t …
実行すると、次のように、中心Cと点Pをつなぐ半径と、分かりにくいですが点Pのところに一応点を打っています。
- 点のスタイルと色
-
線の色は
SET LINE COLOR
で変えましたが、同じように点のスタイルと色は、SET POINT STYLE スタイル番号 SET POINT COLOR 色番号
で変えます。
点のスタイルというのは、打つ点の形で、JIS Full BASICでは、1:・、2:+、3:*、4:○、5:×、となります(初期値3)。
たぶん、グラフに印をつけるような用途を想定しているために、記号で点を打つ仕様になっているのだと思われます。
色の方は、線の時と同じように色番号で指定しますが、線の描画色とは別に管理されます。
つまり、点の色を変えても線の色は変わりません。 - 中心の座標
-
リスト4では、
PLOT LINES : r * t, r ; xp(t), yp(t)
として、中心Cから点Pに線を引いています。
r*t,r
というのは、式(1)の (rθ,r) です。
アニメーションさせることで、描かれ方がだいぶ分かりやすくなりましたが、直線上を転がすだけのサイクロイドでは、さほど変化のある図形は描けませんね。