2015年10月2日金曜日

フラクタル図形を描いてみる[Processing]

 図書館に『初めてのフラクタル 数学とプログラミング』という本を見つけた。Processingなら描けるかなと思って借りてみました。とりあえず幾つか描いてみます。

※フラクタルの次元などの理論的な小難しい話は割愛します(そもそも理解していない)。

1.Hフラクタルのプログラム

百聞は一見にしかず。とりあえず見てみればわかると思う。

 Hという文字が沢山くっついているのがわかると思う。一部を拡大すればまたHが出てきて,さらにそれを拡大すれば……となっている。

 まぁプログラムはこちら。

/* stepを呼び出す関数 */
int N = 5;

void setup() {
  size(512,512);
}

void draw() {
  /* 背景を黒で塗りつぶす */
  background(0);
  /* 線の色を緑に指定 */
  stroke(0,255,0);
  
  /* 再帰関数を呼び出す */
  step(width/2,height/2,0);
}

/**
 * @fn
 * H-フラクタルを描くプログラム
 * @param (x) 'H'の文字の中心x座標
 * @param (y) 'H'の文字の中心y座標
 * @param (n) 呼び出された回数(深さ)
 */
void step(float x, float y, int n) {
  if ( n >= N )
    return;

  /* Hの各辺の長さの半分の長さ */
  float len = width / 4 * pow(0.5, n);

  /* 中心の横棒を描く */
  line(x-len, y, x+len, y);
  /* 左の縦棒を描く */
  line(x-len, y-len, x-len, y+len);
  /* 右の縦棒を描く */
  line(x+len, y-len, x+len, y+len);

  /* Hの右上・右下・左上・左下の点から新たに'H'を描く */
  step(x-len, y-len, n+1);
  step(x-len, y+len, n+1);
  step(x+len, y-len, n+1);
  step(x+len, y+len, n+1);
}

再帰関数の練習にはなったかな。

2.シェルピンスキーのふるいを描く

シェルピンスキーのギャスケットとも言うらしい。本の絵を見て作ったから間違ってるかもしれ無いけれど。
 図形はこんなの

 プログラムはこんな感じ。
/* stepを呼び出す回数 */
int N = 7;

void setup() {
  size(512, 512);
}

void draw() {
  /* 背景を黒で塗りつぶす */
  background(0);
  /* 線の色を緑に指定 */
  stroke(0, 255, 0);

  /* 原点を中心に持ってくる */
  translate(width/2, height/2);
  /* 画面を適当な角度だけ回転する */
  rotate(PI/6);

  /* 再帰関数を呼び出す */
  step(0, 0, 0);
}

/**
 * @fn
 * シェルピンスキーのふるいを描くプログラム
 * @param (x) 三角形の中心x座標
 * @param (y) 三角形の中心y座標
 * @param (n) 呼び出された回数(深さ)
 */
void step(float x, float y, int n) {
  if ( n >= N )
    return;

  float len = width / 3 * pow(0.5, n);
  /* 3分の2 * PI [rad]つまり120度 */
  float theta = 2.0/3.0*PI;
  float x0, x1, y0, y1;

  /* 三角形を描く */
  for (int i = 0; i < 3; i++ ) {
    x0 = x+len * cos( i * theta );
    y0 = y+len * sin( i * theta );
    x1 = x+len * cos( (i+1) * theta );
    y1 = y+len * sin( (i+1) * theta );

    line(x0, y0, x1, y1);
  }

  /* もう一つ小さい三角形の中心を指定し呼び出す */
  len = len / 2;
  for (int i = 0; i < 3; i++ ) {
    step(x+len*cos(i*theta), y+len*sin(i*theta), n+1);
  }
}

 まぁsin,cosの勉強にはなったかな。

3.なんかよくわからないもの

なんかいい感じのやつがあったのであげておきます。ただ詳細はよくわからないです。
L,Rの漸化式をランダムで計算するといい感じの図形が得られる。Lは原点中心の1/4回転を,Rは点(1,0)の拡大を行うとのこと。そうするといい感じのやつが描かれるという。
 百聞は一見にしかず,だ。プログラムと画像はこんな感じ。プログラムを実行したらマウスを動かすと上の式のaが変化して図形が変化します。


 
int N = 4096;

void setup() {
  size(512, 512);
}

void draw() {
  /* 背景を黒で塗りつぶす */
  background(0);
  /* 線の色を緑に指定 */
  stroke(0, 255, 0);


  /* 原点を中心に持ってくる */
  translate(width/2, height/2);
  /* 画面を適当な角度だけ回転する */
  rotate(PI);

  float x = 0.0;
  float y = 0.0;  
  float temp, tx, ty;
  /* 定数aを適当に決める */
  float a = 5.0*(mouseX * mouseY ) / ( width*height );

  for (int i = 0; i < N; i++ ) {
    /* x_n,y_nを保存しておく */
    tx = x;
    ty = y;

    /* 漸化式をランダムに変える */
    if ( random(2) < 1 ) {
      x = -ty;
      y = tx;
    } else {
      temp = (tx-1)*(tx-1)+ty*ty+1;
      x = 1 + a * ( x - 1 ) / temp;
      y = a * ty /temp;
    }
    
    /* 点の描画 */
    rect(x*width/2, y*height/2, 1, 1);
  }
}

 何なんだろこれ。でも面白いからいいか.

0 件のコメント:

コメントを投稿