在用编程模拟自然系统的过程中,很基本的就是对现实世界力的模拟,本篇整理通过代码实现对现实世界力的模拟。
1. 力与牛顿运动定律
在开始模拟力之前,我们先了解力在现实中的概念。从经典的牛顿三大定律开始。
牛顿第一定律
牛顿在《自然哲学的数学原理》中的原始表述是:任何物体都要保持匀速直线运动或静止状态,直到外力迫使它改变运动状态为止。
在Processing中,我们可以将其表述为,在平衡状态下,对象的运动速度(PVector对象)始终是常量。
牛顿第三定律
牛顿第三定律表述:相互作用的两个物体之间的作用力和反作用力总是大小相等,方向相反,作用在同一条直线上。
在Processing中,我们可以将其表述为,如果我们要计算一个由A施加在B上的作用力f(PVector对象),必须额外施加一个由B作用在A上的反作用力(对象PVector.mult(f,-1))。
但是在用Processing编程模拟时,我们不一定要遵循上面的说法。比如说,在模拟风力的效果时,我们就不需要计算物体作用在空气上的反作用力,因为我们根本不会去模拟空气。
牛顿第二定律
牛顿第二运动定律的简单表述为:合力等于质量乘以加速度。
在Processing中,通常我们关注力主要是为了计算加速度,而计算加速度为了获取速度,进而获取对象的位置信息。
此部分内容代码实现:
// 应用力
void applyForce(PVector force) {
// 加速度 = 力 / 质量
PVector a = PVector.div(force, mass);
acceleration.add(a);
}
void update() {
// 速度 = 速度 + 加速度
velocity.add(acceleration);
// 位置 = 位置 + 速度
position.add(velocity);
//在每一帧对加速度清零,避免加速度的累加
acceleration.mult(0);
}
2. 风力模拟
PVector wind()
{
// 模拟一个向右的风力
PVector winds = new PVector(0.01, 0);
return winds;
}
3. 重力模拟
PVector gravity()
{
float m = mass;
// 假设重力加速度为0.1
PVector gravitys = new PVector(0, m*0.1);
return gravitys;
}
4. 摩檫力模拟
摩檫力是一种耗散力。
耗散力:在运动中使系统总能量减少的力。
比如说,开车时,脚踩刹车板会让车通过摩檫力使轮胎减速,它们之间就有摩擦力。
摩檫力分为静摩擦力和动摩檫力。以下只讨论动摩擦力。
摩檫力的确定分为两个部分:
- 力的大小
- 力的方向
PVector friction()
{
// 摩擦力的大小
float u = 0.01;
float N = 1;
float frictionMag = u * N; // 计算摩擦力的大小(一个随意确定的常量)
// 摩檫力的方向
PVector frictions = velocity;
frictions.normalize();
frictions.mult(-1); // 摩檫力方向与对象运动方向相反
// 摩檫力
frictions.mult(frictionMag);
return frictions;
}
5. 流体阻力模拟
流体阻力公式:
processing模拟该力时关注点:
-、 Fd代表阻力,是我们最终要计算的量。
- -1/2是一个常量,对于模拟该力来说,这个数值大小并没有多少意义,代这个量必须是负数。
- ρ表示流体密度,是常量,不用关注它。
- v是对象的运动速度
- A表示物体前端推动流体流动部分的面积,下述代码中也忽略此量。
- Cd表示流体阻力,为常数。我们可以根据阻力的强弱确定它的大小。
- 最后一个参数为力的方向
//判断是否处于流体内
boolean isInSide()
{
// movers为运动对象
if ((movers.location.x > liquid.x) &&( movers.location.x<liquid.x+liquid.w) && (movers.location.y>liquid.y )&& (movers.location.y<liquid.y+liquid.h))
{//这个条件判断语句可以判断对象的位置是否位于流体的矩形内
return true;
}
else {
return false;
}
}
//浮力
PVector drag()
{
float c = 0.01;
float speed = movers.velocity.mag();
float dragMagnitude = c*speed*speed;
PVector drags = movers.velocity.get();
drags.mult(-1);
drags.normalize();
if(isInSide()) {
drags.mult(dragMagnitude);
}
else {
drags.mult(0);
}
return drags;
}
6. 引力模拟
processing模拟该力时关注点:
- F代表引力,是我们最终计算的量。
- G是万有引力常量,它的大小不重要。
- m1和m2代表两个物体的质量。
- r2表示物体距离的平方。
PVector attract()
{
float G = 0.4;
PVector attractors = PVector.sub(a.location, b.location);
// 对象a与对象b的距离
float distance = attractors.mag();
// 计算力的方向
attractors.normalize();
//符号确定引力或斥力
float strength = - G * a.mass * b.mass/(distance*distance);
attractors.mult(strength);
return attractors;
}
7. 弹力模拟
胡克定律:F = -kx``
/**
* a 枢纽点
* b
* len 弹簧静止长度
* k 弹力系数
**/
PVector spring(PVector a,PVector b,float len,float k)
{
PVector springs = PVector.sub(a,b);
float d = springs.mag();
float stretch = d - len;
springs.normalize();
springs.mult(-1*k*stretch);
return springs;
}