こんばんは。今回から「フラクタル」を描くプログラムをprocessingでつくっていこうと思います。
フラクタルは、その図形の一部と全体が相似になっているような図形のことです。
初回は「木」です。
木といわれてもパッとはわからないと思いますが、こんなやつです。
まずは幹となる部分を描いてみましょう。
void setup(){ size(500, 500); background(255); } void draw(){ line(width/2, height, width/2, height-100); }
さて、フラクタル図形のプログラムをつくるうえで、本ブログでは「再帰」の処理を使っていきます。
再帰は、ある関数の中でその関数を参照するという形でつくります。
先の画像で、幹から出た枝を枝1、そこから出た枝を枝2とすると、枝1を幹と考えればそこから出た枝2は枝1と考えることができます。
画像で言えばこんな感じです。赤枠の中が全体と同じ形になっていることがわかると思います。
(実際は無限に続くものなので、有限の繰り返しでは完全に同じとはいえませんが・・・)
ややこしいことを言ってますが、この繰り返しが再帰であり、これでフラクタルを表すことができます。
まずは右側の枝だけ描いてみます。
void setup(){ size(500, 500); background(255); } void draw(){ translate(width/2, height); //根元を画面の下中央に branch(100, 1); //幹の長さ、繰返し回数を指定 } void branch(float length, int n){ //関数をつくる(lengthで幹の長さ、nで繰り返しの回数を指定できるようにした) line(0, 0, 0, -length); //幹を描く translate(0, -length); //幹の先端に原点を移動させる length *= 0.7; //繰り返すに従って枝の長さを短くする if(n > 0){ //nが0より大きいとき pushMatrix(); //今の原点・回転の情報を保存 rotate(PI/4); //全体を45度回転させる line(0, 0, 0, -length); //枝を描く branch(length, n-1); //さらにbranch関数を実行する /* branch(length, n-1)は、以下のコードと同じ意味を持つ line(0, 0, 0, -length); translate(0, -length); length *= 0.7; if(n > 0){ //実際には、始めに指定したnは1であるから、-1したことでn=0となり以下のコードは実行されていない(=ここで繰り返し終わり) pushMatrix(); rotate(PI/3); line(0, 0, 0, -length); branch(length, n-1); popMatrix(); */ popMatrix(); //保存した原点の情報を呼び出す(原点は幹の先端にあり、回転はしていない) } }
似たような形(角度を負で指定するだけ)で左側の枝も描くことができます。
void setup(){ size(500, 500); background(255); } void draw(){ translate(width/2, height); branch(100, 10); } void branch(float length, int n){ line(0, 0, 0, -length); translate(0, -length); length *= 0.7; if(n > 0){ //右側の枝 pushMatrix(); rotate(PI/4); line(0, 0, 0, -length); branch(length, n-1); popMatrix(); //左側の枝 pushMatrix(); rotate(-PI/4); line(0, 0, 0, -length); branch(length, n-1); popMatrix(); } }
これで基本の形はできました。
あとは、角度を変えてみたり、繰り返しを増やしてみたりすると、見たことのある木のフラクタルの形になると思います。
いろいろ変えて遊んでみてください。
おまけ
何もかもランダムにすると、本物の木っぽい形をつくることもできます。
クリックで描き直せます。