大学生の雑記

色々なものを書いています 旧:旧帝大生の雑記ブログ

Processingでセルオートマトン③:BZ反応をシミュレーションする


スポンサードリンク

ごった煮マシンというものを用いてBZ反応をシミュレーションします。ごった煮マシンとはBZ反応のような反応拡散系をセルオートマトンでシミュレーションするために作られたモデルです。

実際に動かしたものがこちらになります。
youtu.be

後半の部分がBZ反応にとても良く似ているかと思います。



ルールやパラメータは以下のpdfの一番下の方に書かれたものを参考にしました。

http://endeavor.eng.toyo.ac.jp/~yoshino/lecture/ex_com_simulation/2010week10.pdf

このpdfの説明を見ればどういうルールなのか理解できると思います。

少し仕様を変えていますがほとんどオリジナルと同じです。

コード

int len;
int col, row;
int[][] c;
boolean pause = false;
int n = 0;

void setup() {
  size(600, 600);
  frameRate(10);
  len = 3;
  col = width/len;
  row = height/len;


  c = new int[col][row];

  //最初の配置
  for (int i = 0; i < col; i ++) {
    for (int j = 0; j < row; j ++) {


      c[i][j] = floor(random(0, 256));

     
    }
  }
}


void draw() {
  background(255);

  //セルの描画
  for (int i = 0; i < col; i ++) {
    for (int j = 0; j < row; j ++) {
      noStroke();
      fill(c[i][j]);

      rect(i*len, j*len, len, len);
    }
  }


  //次のステップでの生命の配置を計算
  if (pause == false) { //描画が動いているとき

    int[][] next = new int[col][row];
    for (int i = 1; i < col+1; i ++) { 
    for (int j = 1; j < row+1; j ++) {
   

        int a = 0; //隣接する感染したセル数
        int b = 0; //隣接する病気のセル数

        for (int k = 0; k <= 2; k ++) {
        for (int l = 0; l <= 2; l ++) {


            if (c[(i+k-1) % col][(j+l-1) % col] > 0 && c[(i+k-1) % col][(j+l-1) % col] <255 ) {
              a += 1;
            }
            if (c[(i+k-1) % col][(j+l-1) % col] == 255 ) {
              b += 1;
            }



            int s =     c[(i-1) % col][(j-1) % col] + c[(i) % col][(j-1) % col] + c[(i+1) % col][(j-1) % col]
                      + c[(i-1) % col][(j) % col]   + c[(i) % col][(j) % col]   + c[(i+1) % col][(j) % col]
                      + c[(i-1) % col][(j+1) % col] + c[(i) % col][(j+1) % col] + c[(i+1) % col][(j+1) % col];

           
            
            if (c[(i) % col][(j) % col] < 0) {
              c[(i) % col][(j) % col] = 0;
            }
            
            if (c[(i) % col][(j) % col] == 0) {
              float k_1 = 0.09;
              float k_2 = 0.01; 

              next[(i) % col][(j) % col] = floor(a/k_1) + floor(b/k_2);
            } 
            if (c[(i) % col][(j) % col] > 0 && c[(i) % col][(j) % col] < 255) {
              float g = -0.01;
              next[(i) % col][(j) % col] = floor(s/(a + b + 1) + g);
            } 
            if (c[(i) % col][(j) % col] >= 255) {
              next[(i) % col][(j) % col] = 0;
            }
          }
        }
      }
    }
    c = next; //次のステップの配置を適用
  }
  }



void keyPressed() {
  //「s」キーでポーズする
  if (key == 's') pause = true;

  //「c」キーで画面の初期化
  if (key == 'c') {
    for (int i = 0; i < col; i ++) {
      for (int j = 0; j < row; j ++) {
        c[i][j] = 0;
      }
    }
  }
}

void keyReleased() {
  //「s」キーが離されたらポーズを解除
  if (key == 's') pause = false;
}