2012年7月26日木曜日

[ドリトル] リサージュ図形を描く(三角関数禁止)

ドリトルのサンプルにリサージュ図形 を描くものがある。
これはこれで楽しいのだが、三角関数は子供に説明できないので三角関数を使わずに書いてみることにしよう。
forward 命令と leftturn 命令でタートルに円運動をさせてそこから X 座標と Y 座標を取得するようにする。


サインカーブ

まずは手始めにサインカーブを描いてみよう。


t1 = Turtle ! create.
t2 = turtle ! create.

// draw axes
t1 ! 1 linewidth (blue) linecolor.
t1 ! penup 0 -100 moveto pendown 0 100 moveto. 
t1 ! penup 0 0 moveto pendown 360 0 moveto penup makeFigure. 
t1 ! 2 linewidth (black) linecolor movetocenter pendown.

// draw circle and sin-curve
t1 ! penup -50 0 moveto 90 direction pendown.
t2 ! (red) linecolor.
[ | n |
  t1 ! 1 forward 1 leftturn.
  t2 ! (n) (t1 ! yPosition?) moveto.
] ! 360 repeat.


リサージュ図形を描く


次はリサージュ図形を描く。
単純に描くだけではつまらないので、Timer で 2つのタートルをゆっくり円運動させて、それぞれの座標を使ってリサージュ図形が作成される様子がわかるようにしてみる。

tcx = turtle ! create.
tcx:step = [
  self ! (2 * self:freq) forward  (1*self:freq) leftturn.
].
tcy = tcx ! create.
 
// draw circles
tcx ! penup 250 -150 moveto 90 direction pendown.
tcy ! penup -150 30 moveto pendown.
[ tcx ! 2 forward 1 leftturn ] ! 360 repeat. 
[ tcy ! 2 forward 1 leftturn ] ! 360 repeat. 
tcx ! penup.
tcy ! penup.

// draw cross-hair 
t1 = Turtle ! create (blue) linecolor 1 linewidth.
xCross = t1 ! penup -1000 -1000 moveto pendown 1000 -1000 moveto penup makeFigure.
yCross = t1 ! penup -1000 -1000 moveto pendown -1000  1000 moveto penup makeFigure.
t1 ! hide.

// prepare GUI
Label ! "X周波数 " create -250 -50 moveto.
fieldX = TextField ! "2" create 50 36 size.
Label ! "Y周波数 " create -250 -100 moveto.
fieldY = TextField ! "3" create 50 36 size.
Label ! "位相差  " create -250 -150 moveto.
fieldPhase = TextField ! "30" create 50 36 size.
tLissajous = Turtle ! create 2 lineWidth (red) lineColor penup "" setShape.
bgnGo = Button ! "実行" create -250 -200 moveto.

// execute
bgnGo:action = [ 
  // reset timer & turtles.
  [timer1 != undef ] ! then [timer1!stop] execute.
  tcx:freq = fieldX ! get.
  tcy:freq = fieldY ! get.
  tcx ! 250 -150 moveto 90 direction.
  tcy ! -150 30 moveto -0 direction.
  [ tcy ! 2 forward 1 leftturn ] ! (fieldPhase!get) repeat. 
  tLissajous ! penup makeFigure hide.

  timer1 = Timer ! create.
  timer1 ! 0.05 interval 6000 times.
  timer1 ! [
    tcx ! step.
    tcy ! step.
    tLissajous ! ( tcx ! xPosition?) (tcy ! yPosition?) moveto pendown.
    yCross ! ( tcx ! xPosition?) -1000 moveto.
    xCross ! -1000 ( tcy ! yPosition?) moveto.
  ] execute.
].

いい感じになったかも。
位相差0の時に図形が直線になるようにしたので、位相差0を指定すると X、Y 両タートルは 90°ずれたところからスタートすることになるがそれは仕様。
X、Y それぞれの周波数は 10 くらいまでが限度でそれを超えるとずれてきたりする。
あと位相差は負値は無視されるので正値で指定する。



0 件のコメント:

コメントを投稿