元Webデザイナー兼コーダーの備忘録

ウェブデザインやプログラミング、ブログのカスタマイズなどについてアウトプットしています。

 メニュー

» HTML入門のまとめはこちらです。

Proccesing:ばね

「The Nature of Code」からばねについて取り上げます。ばねにかかる力を計算して、ばねをシミュレーションします。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。

ばねの描き方

フックの法則に従い、力を計算します。ばねの力は、ばねの伸びに正比例します。

ばねのシミュレーション

以下は、ばねの参考例です。

//A Spring connection
Bob bob;
Spring spring;
 
void setup() {
  size(200,200);
  //バネの起点の座標とバネの自然長
  spring = new Spring(width/2, 10, 100);
  //球の座標
  bob = new Bob(width/2, 100);
}
 
void draw() {
  background(255);
  
  //重力を適用する
  PVector gravity = new PVector(0, 2);
  bob.applyForce(gravity);
  
  //球をバネに接続する(バネの力を計算する)
  spring.connect(bob);
  //バネの長さを制限する
  spring.constrainLength(bob, 30, 200);
 
  bob.update();
  bob.drag(mouseX, mouseY);
  
  //図形の描画:バネの起点、バネ、球
  spring.displayLine(bob);
  bob.display();
  spring.display();
  
  fill(0);
  text("click on bob to drag", 10, height-5);
}

//マウスをクリックしたとき
void mousePressed(){
  bob.clicked(mouseX, mouseY);
}

//マウスを離したとき
void mouseReleased(){
  bob.stopDragging();
}
class Bob {
  PVector position;
  PVector velocity;
  PVector acceleration;
  float mass = 24;  //質量

  float damping = 0.98;  //速度の減衰量
  
  //マウス操作用
  PVector dragOffset;
  boolean dragging = false;

  //コンストラクタ
  Bob(float x, float y) {
    position = new PVector(x, y);
    velocity = new PVector();
    acceleration = new PVector();
    dragOffset = new PVector();
  }

  //値の更新
  void update() {
    velocity.add(acceleration);
    velocity.mult(damping);
    position.add(velocity);
    acceleration.mult(0);
  }
  
  //力を適用する
  void applyForce(PVector force){
    PVector f = force.copy();
    f.div(mass);
    acceleration.add(f);
  }

  //球の描画
  void display() {
    stroke(0);
    strokeWeight(2);
    fill(175);
    if(dragging){
      fill(50);
    }
    ellipse(position.x, position.y, mass*2, mass*2);
  }
  
  //以下、マウス操作
  //球がクリックされたか確認する
  void clicked(int mx, int my){
    float d = dist(mx, my, position.x, position.y);
    if(d < mass){
      dragging = true;
      dragOffset.x = position.x - mx;
      dragOffset.y = position.y - my;
    }
  }
  
  void stopDragging(){
    dragging = false;
  }
  
  //ドラッグ
  void drag(int mx, int my){
    if(dragging){
      position.x = mx + dragOffset.x;
      position.y = my + dragOffset.y;
    }
  }
}
class Spring{
  PVector anchor;  //バネの起点の座標
  float len;  //バネの自然長の長さ
  float k = 0.2;  //バネ定数
  
  //コンストラクタ
  Spring(float x, float y, int l){
    anchor = new PVector(x, y);
    len = l;
  }
  
  //バネの力の計算
  void connect(Bob b){
    PVector force = PVector.sub(b.position, anchor);
    float dist = force.mag();
    float stretch = dist - len;  //現在のバネの伸びと自然長の差
    
    //フックの法則より力を計算する
    //F = k * stretch
    force.normalize();
    force.mult(-1 * k * stretch);
    b.applyForce(force);
  }
  
  //球とアンカーとの距離を制限する
  void constrainLength(Bob b, float minlen, float maxlen){
    PVector dir = PVector.sub(b.position, anchor);
    float d = dir.mag();
    
    //短すぎる場合
    if(d < minlen){
      dir.normalize();
      dir.mult(minlen);
      //位置をリセットして移動を停止(現実的な物理ではない)
      b.position = PVector.add(anchor, dir);
      b.velocity.mult(0);
    }else if(d > maxlen){  //長過ぎる場合
      dir.normalize();
      dir.mult(maxlen);
      //位置をリセットして移動を停止(現実的な物理ではない)
      b.position = PVector.add(anchor, dir);
      b.velocity.mult(0);
    }
  }
  
  //バネの起点の描画
  void display(){
    stroke(0);
    fill(175);
    strokeWeight(2);
    rectMode(CENTER);
    rect(anchor.x, anchor.y, 10, 10);
  }
  
  //バネの描画
  void displayLine(Bob b){
    strokeWeight(2);
    stroke(0);
    line(b.position.x, b.position.y, anchor.x, anchor.y);
  } 
}

まとめ

「The Nature of Code」からばねについて取り上げました。ばねにかかる力を計算して、ばねをシミュレーションしました。引き続き、「The Nature of Code」の内容を勉強します。

参考書籍

Javaの勉強にもなるので一石二鳥です。

» HTML入門のまとめはこちらです。