home processing download documents tutorial python tutorial gallery source about
 チュートリアル (トピック一覧へ戻る)

物理シミュレーションとスウォーム・アルゴリズム例

     パーティクル・エージェント・アルゴリズム例

以下の例ではアトラクタ―で作られた力の場をつくることによって、 パーティクル・エージェントの軌跡を制御します。

import processing.opengl.*;
import igeo.*;

void setup(){
  size(480,360,IG.GL);
  IG.duration(360);
  int num=200;
  for(int i=0; i < num; i++){
    IVec pos = IG.v(100,0,0).rot(2*PI*i/num);
    IVec vel = IG.v(-40,0,0).rot(2*PI*i/num);
    new MyParticle(pos, vel).fric(0.012).hsb(1.0/num*i,1,1);
  }
  for(int i=0; i < 8; i++){
    new Attractor(IRand.pt(-120,-120,0,80,80,0)).clr(1.0,0,0);
  }
}

class Attractor extends IPointAgent{
  final double threshold = 100;
  final double gravity = 300.0;
  final double minDist = 1.0;

  Attractor(IVec v){ super(v); }
  
  void interact(ArrayList agents){
    for(int i=0; i < agents.size(); i++){
      if(agents.get(i) instanceof MyParticle){
        MyParticle agent = (MyParticle)agents.get(i);
        IVec dif = pos().dif(agent.pos());
        double dist = dif.len();
        if(dist < threshold){
          if(dist < minDist){ dist = minDist; }
          double strength = gravity/dist; //the closer the larger
          IVec force = dif.len(strength);
          agent.push(force);
        }
      }
    }
  }
}

class MyParticle extends IParticle{
  IVec prevPos;
  
  MyParticle(IVec p, IVec v){ super(p,v); }

  void update(){
    IVec curPos = pos().cp();
    if(prevPos!=null){
      new ICurve(prevPos, curPos).clr(clr());
    }
    prevPos = curPos;
  }
}

次のコードではMyParticleクラスにインタラクト・メソッドを追加し、 アトラクタ―だけでなく、パーティクル・エージェント自身にもお互いを引っ張り合う引力を定義しています。

import processing.opengl.*;
import igeo.*;

void setup(){
  size(480,360,IG.GL);
  IG.duration(450);
  int num=100;
  for(int i=0; i < num; i++){
    if(IRand.pct(97)){
      IVec pos = IG.v(100,0,0).rot(2*PI*i/num);
      IVec vel = IG.v(-20,0,0).rot(2*PI*i/num);
      new MyParticle(pos, vel).fric(0.001).hsb(1.0/num*i,1,1);
    }
  }
  for(int i=0; i < 3; i++){
    new Attractor(IRand.pt(-120,-120,0,80,80,0)).clr(1.0,0,0);
  }
}

class Attractor extends IPointAgent{
  final double threshold = 100;
  final double gravity = 300.0;
  final double minDist = 1.0;

  Attractor(IVec v){ super(v); }
  
  void interact(ArrayList agents){
    for(int i=0; i < agents.size(); i++){
      if(agents.get(i) instanceof MyParticle){
        MyParticle agent = (MyParticle)agents.get(i);
        IVec dif = pos().dif(agent.pos());
        double dist = dif.len();
        if(dist < threshold){
          if(dist < minDist){ dist = minDist; }
          double strength = gravity/dist; //the closer the larger
          IVec force = dif.len(strength);
          agent.push(force);
        }
      }
    }
  }
}

class MyParticle extends IParticle{
  final double threshold = 30;
  final double gravity = 2.0;
  IVec prevPos;
  
  MyParticle(IVec p, IVec v){ super(p,v); }
  
  void interact(ArrayList < IDynamics > agents){
    IVec center=null;
    int num=0;
    for(int i=0; i < agents.size(); i++){
      if(agents.get(i) instanceof MyParticle){
        MyParticle a = (MyParticle)agents.get(i);
        if(a != this){
          if(a.pos().dist(pos()) < threshold){
            if(center==null) center = a.pos().dup();
            else{ center.add(a.pos()); }
            num++;
          }
        }
      }
    }
    if(num > 0){
      center.div(num);
      IVec force = center.dif(pos()).mul(gravity);
      push(force);
    }
  }

  void update(){
    IVec curPos = pos().cp();
    if(prevPos!=null){
      new ICurve(prevPos, curPos).clr(clr());
    }
    prevPos = curPos;
  }
}

以下のコードではアトラクタ―などの外部の力の場の影響は無しに、 エージェント自身の引力だけで軌跡に影響を及ぼします。 軌跡は出発点や出発速度、他のエージェントとの間隔などの初期条件で 大きく変わります。この例では上下一列に並んだ状態から上下方向へ向けて 出発します。

import processing.opengl.*;
import igeo.*;

void setup(){
  size(480,360,IG.GL);
  IG.duration(250);
  int num=100;
  for(int i=0; i < num; i++){
    for(int j=0; j < 2; j++){
      if(IRand.pct(70)){
        IVec pos = IG.v(i, j*100, 0);
        IVec vel = IG.v(0, (30-j*55), 0);
        new MyParticle(pos, vel).fric(0.008).clr(IRand.clr());
      }
    }
  }
}

class MyParticle extends IParticle{
  final double threshold = 15;
  final double gravity = 25.0;
  IVec prevPos;
  
  MyParticle(IVec p, IVec v){ super(p,v); }
  
  void interact(ArrayList < IDynamics > agents){
    IVec center=null;
    int num=0;
    for(int i=0; i < agents.size(); i++){
      if(agents.get(i) instanceof MyParticle){
        MyParticle a = (MyParticle)agents.get(i);
        if(a != this){
          if(a.pos().dist(pos()) < threshold){
            if(center==null) center = a.pos().dup();
            else{ center.add(a.pos()); }
            num++;
          }
        }
      }
    }
    if(num > 0){
      center.div(num);
      IVec force = center.dif(pos()).mul(gravity);
      push(force);
    }
  }

  void update(){
    IVec curPos = pos().cp();
    if(prevPos!=null){
      new ICurve(prevPos, curPos).clr(clr());
    }
    prevPos = curPos;
  }
}


(トピック一覧へ戻る)

HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java / Python)
GALLERY
SOURCE CODE(GitHub)
PRIVACY POLICY
ABOUT/CONTACT