walnutpedia / notes

1 stars 0 forks source link

Processing学习笔记 03 - NoC forces #5

Open walnutpedia opened 8 years ago

walnutpedia commented 8 years ago

这章开始讲力的模拟了。

力与牛顿定律

牛顿第一定律(惯性定律): 除非有不平衡的力施加在物体上,否则物体运动状态不变。 牛顿第二定律: 力 = 质量 x 加速度。 F = ma. 显示情况下, F m a 都是有单位的。 模拟的时候可以先不考虑单位,只计算数字。

向量

上章向量里讲了, 物体的速度 Velocity 是由 Acceleration 决定的。那 Acceleration 由谁决定呢?根据牛二定律,Acceleration = F/m; 也就是说加速度由力与质量的比来决定。所以在模拟物体的运动和位置的时候,决定链是:

force -> acceleration -> velocity -> location

向量 acceleration 是所有向量 force 的和, 向量 velocity 是原速度和 acceleration 的和, 向量 location 又是原 location 和 velocity 的和。到这里,一个物体运动的状态就能用四组向量的运算表达出来了。但这个向量 force 是有很多组不同的力的和(力的累加)。

重力加速度

物体的质量与其重力(地球对其产生的引力)成正比。地球上从同一高度开始自由下落的物体,不管质量如何,他们的重力加速度是一样的,落到地面的时间也是一样的。 所以在模拟重力的时候,需要用 f/m 来将不同重量的物体的重力加速度设置为一样的。

摩擦力

主要考虑运动摩擦力。公式为:

image

-1 代表方向与物体运动方向相反。μ 是摩擦系数;N 是物体间的反作用力(Normal Force)。如果物体是水平运动的,那这个力就等于重力,如果运动方向是斜上或者斜下的话,还需要根据计算来得出N。

空气与液体阻力

viscous force, drag force, fluid resistace. 说的是一个东西。公式跟上面的摩擦力不一样。如下:

image

看起来很麻烦。

Fd : drag force -1/2 : 一个常量,也就是0.5。 据说模拟的时候这个可以修改。负值同样是说跟物体运动方向相反。 ρ : 液体密度。据说模拟的时候可以先不考虑,直接简化为 1。 v : 物体的运动速度的值。 A: 物体运动时前面与液体或空气接触的面积。 Cd : drag force 系数。意义同上面摩擦力里的摩擦系数。

模拟液体的时候,写一个液体Class. 它有自己的坐标。 Mover类需要有个方法来判断自身坐标是不是已经在液体里面了。如果是的话,就执行另一个方法,把液体阻力计算进去。

万有引力

两个物体间的引力。 公式:

image

F: gravitational force G: 万有引力常数,牛顿常数。 这个值是不变的。但编程模拟的时候可以根据需要来修改……Orz。据说简化成1也没什么太大不了的。 m1 和 m2 : 是两个物体的质量。据说也可以忽略,简化为1(因为屏幕上的物体显然没有质量)。当然也可以不忽略,按需求来模拟。 r : 物体1指向物体2的单位向量。 可以用两个物体的坐标计算出来。 r^2: 连个物体距离的平方。物体距离越远,引力越小。and vise versa.

总结

这章其实还算可以…… 写代码的时候得想一下怎样模拟公式出来。接下来就是练了。这章里有几个练习可以试试。

walnutpedia commented 8 years ago

Exercise 2.1

// Declare Mover object.
Mover mover;
PVector wind;
PVector gravity;
PVector buoyancy;

void setup() {
  size(640,640);
  // Create Mover object.
  mover = new Mover();
}

void draw() {
  background(255);

  //[full] Call functions on Mover object.
  mover.update();
  mover.display();
  //[end]
}

class Mover {

  //[full] Our object has two PVectors: location and velocity.
  PVector location;
  PVector velocity;
  PVector acceleration;
  float time = 10000;
  PVector gravity = new PVector(0, 1);
  PVector buoyancy = new PVector(0, -2);
  //[end]

  Mover() {
    location = new PVector(width/2, height);
    velocity = new PVector(0,0);
    acceleration = new PVector(0, 0);
    velocity.limit(10);
  }

  void update() {
    time++;
    float windXForce = map(noise(time),0,1,-5,5);
    wind = new PVector(windXForce, 0);

    applyForce(wind);
    applyForce(gravity);
    applyForce(buoyancy);

    velocity.add(acceleration);
    location.add(velocity);

    acceleration.mult(0);
  }

  void display() {
    stroke(0);
    fill(175);
    ellipse(location.x,location.y,50,50);
    velocity.mult(0);
  }

  void applyForce(PVector force){
    acceleration.add(force);
  }
}