プログラミングの備忘録

プログラムをつくる過程を残すもの

processingでフラクタル -木-

こんばんは。今回から「フラクタル」を描くプログラムをprocessingでつくっていこうと思います。
フラクタルは、その図形の一部と全体が相似になっているような図形のことです。

初回は「木」です。
木といわれてもパッとはわからないと思いますが、こんなやつです。

f:id:taq2777:20211010042422p:plain
木のフラクタル

まずは幹となる部分を描いてみましょう。

void setup(){
    size(500, 500);
    background(255);
}

void draw(){
    line(width/2, height, width/2, height-100);
}

さて、フラクタル図形のプログラムをつくるうえで、本ブログでは「再帰」の処理を使っていきます。
再帰は、ある関数の中でその関数を参照するという形でつくります。
先の画像で、幹から出た枝を枝1、そこから出た枝を枝2とすると、枝1を幹と考えればそこから出た枝2は枝1と考えることができます。
画像で言えばこんな感じです。赤枠の中が全体と同じ形になっていることがわかると思います。
(実際は無限に続くものなので、有限の繰り返しでは完全に同じとはいえませんが・・・)
f:id:taq2777:20211218093016p:plain ややこしいことを言ってますが、この繰り返しが再帰であり、これでフラクタルを表すことができます。

まずは右側の枝だけ描いてみます。

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();
    }
}

これで基本の形はできました。
あとは、角度を変えてみたり、繰り返しを増やしてみたりすると、見たことのある木のフラクタルの形になると思います。
いろいろ変えて遊んでみてください。


おまけ
何もかもランダムにすると、本物の木っぽい形をつくることもできます。
クリックで描き直せます。