2012年8月16日木曜日

[ドリトル] サイクロイド曲線

サイクロイド (cycloid) とは、円がある規則にしたがって回転するときの円上の定点が描く軌跡として得られる平面曲線の総称である。

-- by ウィキペディア

ということなのだが、見方を変えると周回する点にX方向のオフセットを与えたものと見なすこともできる。
これならドリトルで簡単に描けそうなのでやってみよう。
forward による周回移動と水平移動の2段階移動になるため、移動後位置算出用の不可視タートルと描画用のタートルの2つ組を用意する。

STEPNUM = 360.
STEPSIZE = 1.
tHidden = Turtle ! create.
tHidden ! hide -180 direction  -200 0 moveto.

t1 = Turtle ! create penup.
t1 ! (tHidden!xPosition?) (tHidden!yPosition?) moveTo pendown.
[
  tHidden ! (STEPSIZE) forward (360/STEPNUM) rightturn.
  tHidden ! (STEPSIZE) 0 moveBy.
  t1 ! (tHidden!xPosition?) (tHidden!yPosition?) moveTo.
] ! (STEPNUM) repeat.
t1 ! makeFigure.
t1 ! hide.

サイクロイドは媒介変数表示では
  • x = rm * (θ - sinθ)
  • y = rm * ( 1 - cosθ)
となるとのことだが (by Wikipedia)、ドリトルだと三角関数を一切使わないでも簡単に描画できてしまうところが素晴らしい。

水平移動はそのままにして周回動作の大きさを変化させるとさまざまなサイクロイドが描画できる。
転がる円の大きさを一定にして描画点の円中心からの位置を変化させた操作に相当する。
上の例では1回転だがさびしいので今度は2回転分描画する。

STEPNUM = 360.
STEPSIZE = 1.
R = STEPSIZE*STEPNUM/PI/2.

t1 = Turtle ! create.
t1:cycloid = [ | rate ; tHidden | 
  tHidden = Turtle ! create.
  tHidden ! hide (! xPosition?) (! yPosition?) moveTo -180 direction.
  ! pendown.
  [
    tHidden ! (STEPSIZE * rate) forward (360/STEPNUM) rightturn.
    tHidden ! (STEPSIZE) 0 moveBy.
    ! (tHidden!xPosition?) (tHidden!yPosition?) moveTo.
  ] ! (STEPNUM*2) repeat.
].
Screen ! (black) paint.

t1 ! penup -400 (-0.5 * R) moveTo pendown.
t1 ! (red) linecolor.
t1 ! 0.5 cycloid.
t1 ! makeFigure.

t1 ! penup -400 (-1.0*R) moveTo pendown.
t1 ! (blue) linecolor.
t1 ! 1.0 cycloid.
t1 ! makeFigure.

t1 ! penup -400 (-1.5*R) moveTo pendown.
t1 ! (green) linecolor.
t1 ! 1.5 cycloid.
t1 ! makeFigure.

t1 ! penup -400 (-2.0*R) moveTo pendown.
t1 ! (cyan) linecolor.
t1 ! 2.0 cycloid.
t1 ! makeFigure.

t1 ! hide.

せっかくなのでアニメ化してみよう。

STEPNUM = 180.
STEPSIZE = 2.
R = STEPSIZE*STEPNUM/PI/2.
INITIAL_X = -400.

// サイクロイド描画用タートルのプロトタイプ定義

turtles = Array ! create.
t0 = Turtle ! create hide.
t0:prepare = [ | ; create | 
  tHidden = Turtle ! create.
  tHidden ! hide (! xPosition?) (! yPosition?) moveTo -180 direction.
  ! show pendown 0.7 scale.
].
t0:step = [
  tHidden ! (STEPSIZE * stepRate) forward (360/STEPNUM) rightturn.
  tHidden ! (STEPSIZE) 0 moveBy.
  ! (tHidden!xPosition?) (tHidden!yPosition?) moveTo.
  ! (tHidden!direction?) direction.
].

// サイクロイド描画用のタートルを作成する

t1 = t0 ! create (red) lineColor.
t1:stepRate = 0.5.
t1 ! penup (INITIAL_X) (-0.5 * R) moveTo prepare.
turtles ! (t1) add.

t2 = t0 ! create (blue) lineColor.
t2:stepRate = 1.0.
t2 ! penup (INITIAL_X) (-1.0*R) moveTo prepare.
turtles ! (t2) add.

t3 = t0 ! create (green) lineColor.
t3:stepRate = 1.5.
t3 ! penup (INITIAL_X) (-1.5*R) moveTo prepare.
turtles ! (t3) add.

t4 = t0 ! create (cyan) lineColor.
t4:stepRate = 2.0.
t4 ! penup (INITIAL_X) (-2.0*R) moveTo prepare.
turtles ! (t4) add.

Screen ! (black) paint.

// 円を描画する
tCircle = Turtle ! create (white) linecolor 1 lineWidth.
tCircle ! penup (INITIAL_X) (0) moveto.
tCircle ! pendown 0 (-2*R) moveby.
tCircle ! penup 0 (3*R) moveby pendown (R) circle.
circle = tCircle ! makeFigure.
tCircle ! hide.

// 円を移動しながらサイクロイド群を描画する。
timer1 = Timer ! create 0.05 interval (STEPNUM*2) times.
timer1 ! [
  turtles ! [ | turtle | turtle ! step ] foreach.
  circle ! (STEPSIZE) 0 moveby.
  circle ! (360/STEPNUM) rightturn.
] execute.

動きをわかりやすくするために円も一緒に動かしてみた。

今回は、元の円が直線上を転がる場合のサイクロイドを描画してみたが、 サイクロイドは他の円の上など直線以外の上を転がる円に対しても定義することができる。 次回は円上を転がる場合のサイクロイドを描いてみよう。



0 件のコメント:

コメントを投稿