概要

拡散律速凝集(Diffusion-limited aggregation;DLA)は、ブラウン運動する粒子が、核となる粒子に結合することで粒子の集合体(クラスタ)が成長する過程のことです。雪の結晶や雷の成長などに見られます。以下のプログラムではブラウン運動する粒子(ここでは水分子)を白色、核となる粒子を色付きとしました。

プログラムを見ればわかると思いますが、白い粒子が集合体にくっ付くと、自分もその集合体に取り込まれています(取り込まれるようにしたというのが正しいですが)。なお、取り込まれた時間が分かりやすいように、何番目に取り込まれたかで色相を変化させました。

粒子の個数を5000個に増やしてみたのが以下の図です。

実装

int edge=5;
int NUM=2000;
int speed=2;
float[] x=new float[NUM];
float[] y=new float[NUM];
float[] r=new float[NUM];
float[] theta=new float[NUM];
float[] fixed_x=new float[NUM];
float[] fixed_y=new float[NUM];
float[] fixed_hue=new float[NUM];
int nan=1000;
float hue=0;

void setup(){
  size(400,400);
  colorMode(HSB);
  for(int i=0;i<NUM;i++){
  r[i]=random(50,200);
  theta[i]=random(0,2*PI);
  x[i]=int(width/2+r[i]*cos(theta[i]));
  y[i]=int(width/2+r[i]*sin(theta[i]));
  }
  fixed_hue[0]=hue;
  fixed_x[0]=width/2;
  fixed_y[0]=height/2;
  for(int i=1;i<NUM;i++){
    fixed_x[i]=nan;
    fixed_y[i]=nan;
  }
  noStroke();
}

void draw(){
  background(0);
  Disp_Move_Molecular();
  Disp_Fixed_Molecular();
  CheckHit();
}

void Disp_Move_Molecular(){
  fill(255);
  for(int i=0;i<NUM;i++){
   if(x[i]!=nan){
    theta[i]=random(0,2*PI);
    x[i]+= speed*cos(theta[i]);
    y[i]+= speed*sin(theta[i]);
      ellipse(x[i],y[i],edge,edge);
    }
  }
}

void Disp_Fixed_Molecular(){
   for(int i=0;i<NUM;i++){
     if(fixed_x[i]!=nan){
       fill(fixed_hue[i],255,255);
       ellipse(fixed_x[i],fixed_y[i],edge,edge);
     }

  }
}

void CheckHit(){
   for(int i=0;i<NUM;i++){
     if(x[i]!=nan){
       for(int j=0;j<NUM;j++){
         if(fixed_x[j]!=nan){
           if(distance(i,j)<=edge){
             fixed_x[i]=x[i];
             fixed_y[i]=y[i];
             x[i]=nan;
             y[i]=nan;
             hue+=0.1;
             if(hue>255){
               hue=0;
             }
             fixed_hue[i]=hue;
           }
         }
       }
     }
  }
}

float distance(int i,int j){
  float d;
  d=sq(x[i]-fixed_x[j])+sq(y[i]-fixed_y[j]);
  return sqrt(d);
}