• これは、Pascalまたは、Delphiによるプログラム講座です。Visitor No. - : - : -

sin cosを使って桜を描いてみよう。

  • 児童養護施設勤務時代に女子高生から三角関数やって何が面白いのか質問されました。「おしり」の絵(NTTのマークに似てる)が描けるとその場で説明しながらBasicで記述して、runで実行。えらく感心してました。そのSwitch-on-Basic機種は、CASIO FP-1100って超ド級のマイナーもの。自宅はShop BrandのAT互換機のWin3.1にして、職場に持ち込んで仕事に使っていました。なお、Pascalは、Cと似ています。若干の書き換えで使えると思います。

(1) 最初に「まる」を描かせる。

  • といっても、「まる」を描く命令で描いてはいけません。あくまでも三角関数を使って描きます。拡大してもきれいに描くなら、平方根を使いますが、ここは、最終目標の都合です。なお、通常、グラフィックの座標は、左上が(x,y)=(0,0)になっています。
  • delphiを起動したら、まず、Image(200x200くらい)とButtonそれぞれ1個を準備してください。そしたら、Button1をW-clickして次のように記述しましょう。
  • ところで、piは予約語です。3.1415…のことです。
  • コピーして貼付ければ早いんですが、ここは練習のため地道に入力しましょう。入力したら、コンパイル、ボタンをクリック!…って何も出ません。かと思えば、左上の隅に黒い点が出ていませんか? sinとcosは-1から1の間を行き来する関数ですから、半径1の円です。見えません!という訳で、半径を100くらいに設定してやりましょう。
  • って、round( )の中で100倍しましょう。もう一回、実行。Button1をクリック。今度は、描けたけれど、4分の1しかありません。先にも書いたようにsin,cosは、-1~1を移動するので、-100~100になります。つまり、左上が原点(0,0)で右下に向かって+方向なので、中心点を(0,0)ではなく、(100,100)にもってきましょう。
  • それから、クリック!、多分丸が描けたのではないかと思います。ところで…半径の100なんですが、このままでは、何かと不便です。中心点は、たまたまxyの両座標が100なんですが、半径は同じものです。そこで、変数の実数のところにrとして追加しましょう。
  • その上で
  • てな具合に、100倍した半径のところをrという変数で表現しましょう。これで、「まる」を描くプログラムは完成です。いきなり桜じゃ面白くないので…少し寄り道して、例の「おしり」の絵でも描いてみましょう。
  • このグラフはどうやって描いているかというと、たとえば、時計の針が一回りするときに中心からの距離がr=100で針の先の座標を、xとyで表しています。ということは、rの値を何かに連動して動くものに変えてやるわけです。たとえば、r:=100; の部分を r:=i; としてみましょう。iは、0から360まで変化しますから、途中ではみ出して、髪の毛のようなものが描かれたと思います。100に収めるには、r:=i/360*100; で実行すると、オウム貝みたいなものが描かれたと思います。
  • それでは、いよいよですが、おしりに移ってみましょう。まず、360度の設定がしてあります。π(パイ)でいえば1週は、2π、cosなら、0→1→0→-1→0に戻るまでの動きをします。1じゃ目立たないので100倍したものを入れてみましょう。
    • r:=sin(th)*100;
  • 小さな丸が1つしか出ません。0→1→0→-1→0から考えれば2回大きな丸の中心点を行き来しているはずです。これは、同じ場所に2回描いているからです。絶対値をとれば、0→1→0→1→0と変化し、丸は2つになります。
    • r:=abs(sin(th)*100);
  • なりましたか? もう少し遊んでみましょう。今度は、100倍するのではなく、50倍して、外に50を足してみましょう。
    • r:=abs(sin(th)*50)+50;
  • 双眼鏡の映像っぽいものがでたのではないでしょうか。
  • お尻の絵(NTTマークの中のワッカがないもの)を描くには、前のように2山あるのではなく、1山にしないといけません。そこで、0→360変化する間にその半分になるようにするには…ということになります。ラジアンなら2πになるところを、半分の1πにするわけですから、次のようになります。
    • r:=abs(sin(th/2)*100);
  • もっとも、この場合、0→1→0と変化するだけなのでABS()の絶対値は不要になります。しかし、都合もあるのでそのまま、残しておいて、/2の部分を*1ならワッカが2個*2なら…実験してみてください。さらに半径長さを*100ではなく、*50)+50の方でも同様に、*2, *3を実験してみてください。また、括弧の中と外の数字を足して100になるパターンもいくつか実験すると楽しいかもしれません。
    • r:=abs(sin(th*2.5)*30)+70;
  • このあたりで、なんとなく、梅の花でしょうか…1,2,3,4とすれば、その2倍の花弁ができますから、奇数にするには、もとが0.5単位になればOKですね。

(2) それでは、桜へ…

  • さて、梅まできたところで、ちょっと花びらがまるっこいんで桜には向かない形ですね。実は、よくある桜のような花びらは、y=x/2のような、直線の式でいいのです。実際には、r=thの式で表すことになります。問題は、直線の式ですから一度行ったら戻ってこない!ことが問題です。
  • 0から360度の1回転の間にMの字を5回描けば桜です。1回描くのに、360/5=72で1回Mを描くことになります。つまり、0から71度、72度で中心からの距離が0度と同じになればOK。
  • さっきの梅の花で変動する幅は30です。というわけで、
    • 00-30 r:=(i mod 72)+70;
    • 31-36 r:=-(i mod 72)+100+31;
    • 37-42 r:=(i mod 72)+???????????考えるのが面倒
  • ということで、前回比較で作業を進めましょう。
    • var i,x,y,f:integer; th,r:real;
    • f(符号)変数を設定。
    • r:=70; f:=1;
    • for loopの前に初期値設定する。
  • その上で、for loopで以下のようにする。
    • if (i mod 72=0) or (i mod 72=36) then f:=1;
    • if (i mod 72=30) or (i mod 72=42) then f:=-1;
    • r:=r+1*f;
  • しかし、これだと、
    • case i mod 72 of 0,36: f:=1; 30,42: f:=-1; end;
    • が楽です。
    • ということで、こんなんができました。




最終更新:2009年10月30日 23:11