1. ホーム
  2. フラクタル
  3. マンデルブロ集合

ここでは、書籍「フラクタルの美 複素力学系のイメージ」のp.191-192に解説されている「実験その2:マンデルブロー集合」を参考にして、初めてのマンデルブロ集合による作品を作ってみました。

マンデルブロ集合

今回描いたマンデルブロ集合による作品は以下の図形となります。

マンデルブロ集合(c=-2.25-1.5i~0.75+1.5i)

よく見かける、マンデルブロ集合のかっこいい図形を描くことができました。

マンデルブロ集合の考え方

マンデルブロ集合とは複素平面上の点の集まりで、 z_0=0 として漸化式

z_{n+1} \mapsto z_n^2 + c \ \ ( n = 0,1,2,\cdots )

で定義される複素数列を考えたときに n \to \infty の極限で無限大に発散しないという条件を満たす複素数cの全体が作る集合を指します。

このマンデルブロ集合をまともに計算することはできません。そのため、マンデルブロ集合を用いた図形を描く場合、

  • |z_n|はある値Mを越えたときに複素数列は発散したとみなす
  • n が適当な上限値 K に達したとき、z_K < Mであれば複素数列は発散しなかったとみなす

として複素数cを分類し、発散したとみなされた場合はそのときのnの値、発散しなかったとみなされた場合は上限値Kに対応させて、複素数c の位置にある画素に色を与えるようにして描いています。

プログラムの流れ

マンデルブロ集合による作品を作る際のプログラムの流れを記載しておきます。

Step 0

  • キャンバスサイズw, hを決めます。
  • 複素数cの範囲をp_\mathrm{min} =-2.25, \ \ q_\mathrm{min} =-1.5, \ \ p_\mathrm{max} =0.75, \ \ q_\mathrm{max} =1.5 、判定条件M=200, \ \ K=256 を決めます。
  • \Delta p = (p_\mathrm{max} – p_\mathrm{min})/w, \ \ \Delta q = (q_\mathrm{max} – q_\mathrm{min})/h とおきます。

以下の処理はキャンバスのすべての画素(n_p, n_q)に対して行います。

Step 1

p=p_\mathrm{min} + n_p \cdot \Delta p, \ \ q=q_\mathrm{min} + n_q \cdot \Delta q, \ \ k=0, \ \ x_0=y_0=0 とおきます。

Step 2(反復ステップ)

(x_k,y_k)をもとにして(x_{k+1},y_{k+1})を漸化式

x_{k+1} = x_k^2-y_k^2+p, \ \ y_{k+1}=2x_k y_k + q

にしたがって計算します。このとき、カウンターkの値に1を加えます。

Step 3(判定ステップ)

r = \sqrt{x_k^2+y_k^2} を計算します。

(i) r>M ならば、kの値に応じてその画素の色を割り当てます。

(ii) k=Kならば、その画素の色に0(黒色)を割り当てます。

(iii) r \leq Mかつk<Kならば、Step 2に行きます。

プログラムコード

最後に、このマンデルブロ集合による作品を描いた際のプログラムコード(Processing)を示しておきます。

void setup(){
  size(1000,1000);
  
  PImage img = createImage(width, height, RGB);
    
  int Kmax = 256;
  float M = 200;
  float pmax = 0.75;
  float pmin = -2.25;
  float qmax = 1.5;
  float qmin = -1.5;

  float delta_p = (pmax - pmin) / width;
  float delta_q = (qmax - qmin) / height;
  
  float x, y, next_x, next_y, r;
  float p, q;
  int k;
  for(int i=0; i<width; i++){
    for(int j=0; j<height; j++){
      p = pmin + i * delta_p;
      q = qmax - j * delta_q;
      x = 0.0;
      y = 0.0;
      r = sqrt(x*x+y*y);
      k=0;
      img.set(i,j,color(0,0,0));
      while(k < Kmax){
        if(r > M){
          img.set(i,j,color(10*k,0,0));
          break;
        }
        next_x = x*x - y*y + p;
        next_y = 2.0 * x * y + q;
        x = next_x;
        y = next_y;
        r = sqrt(x*x+y*y);
        k++;
      }
    }
  }
  
  image(img,0,0,width,height);
}

コメントを残す