書名:代碼本色:用編程模擬自然系統(tǒng)
作者:Daniel Shiffman
譯者:周晗彬
ISBN:978-7-115-36947-5
目錄
2.8 空氣和流體阻力
??
5、Mover對象如何與流體對象交互?
我們想達到這樣的效果:
- 運動者穿過流體對象時會受到阻力的作用。
用Processing實現(xiàn)起來是這樣的(假設(shè)我們用索引i遍歷整個Mover對象數(shù)組):
if (movers[i].isInside(liquid)) {
movers[i].drag(liquid); 如果Mover對象位于流體內(nèi)部,流體阻力將作用在物體上
}
從這段代碼可以看出,我們需要在Mover類中加入兩個額外的函數(shù):
- isInside()函數(shù)
用于判斷Mover對象是否在流體對象內(nèi)部, - drag()函數(shù)
計算并將流體阻力作用在Mover對象上。
6、isInside()函數(shù)的實現(xiàn)
- isInside()函數(shù)的實現(xiàn)很簡單,我們只需要加一個條件判斷語句,判斷Mover對象的位置是否在流體的矩形區(qū)域內(nèi)部。
boolean isInside(Liquid l) {
if (location.x>l.x && location.x<l.x+l.w && location.y>l.y && location.y<l.y+l.h) {
return true;
}
else {
return false;
}
}
7、drag()函數(shù)
drag()函數(shù)就稍顯復(fù)雜,但前面我們已經(jīng)實現(xiàn)過類似的邏輯,它只是流體阻力公式的實現(xiàn):阻力的大小等于阻力系數(shù)乘以Mover對象速度的平方,方向與Mover對象的速度方向相反。
// 流體阻力公式的實現(xiàn)
void drag(Liquid l) {
float speed = velocity.mag();
float dragMagnitude = l.c * speed * speed; // 力的大小
PVector drag = velocity.get();
drag.mult(-1);
drag.normalize(); // 力的方向:與速度相反
drag.mult(dragMagnitude); // 最終確定力:大小和方向
applyForce(drag); // 應(yīng)用力
}
8、示例代碼2-5
示例代碼2-5 流體阻力
Mover[] movers = new Mover[9];
// Liquid
Liquid liquid;
void setup() {
size(640, 360);
reset();
// Create liquid object
liquid = new Liquid(0, height/2, width, height/2, 0.1);
}
void draw() {
background(255);
// Draw water
liquid.display();
for (int i = 0; i < movers.length; i++) {
// Is the Mover in the liquid?
if (liquid.contains(movers[i])) {
// Calculate drag force
PVector dragForce = liquid.drag(movers[i]);
// Apply drag force to Mover
movers[i].applyForce(dragForce);
}
// Gravity is scaled by mass here!
PVector gravity = new PVector(0, 0.1*movers[i].mass);
// Apply gravity
movers[i].applyForce(gravity);
// Update and display
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
fill(0);
text("click mouse to reset", 10, 30);
}
void mousePressed() {
reset();
}
// Restart all the Mover objects randomly
void reset() {
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover(random(0.5, 3), 40+i*70, 0);
}
}
Liquid.pde
class Liquid {
// Liquid is a rectangle
float x, y, w, h;
// Coefficient of drag
float c;
Liquid(float x_, float y_, float w_, float h_, float c_) {
x = x_;
y = y_;
w = w_;
h = h_;
c = c_;
}
// Is the Mover in the Liquid?
boolean contains(Mover m) {
PVector l = m.position;
return l.x > x && l.x < x + w && l.y > y && l.y < y + h;
}
// Calculate drag force
PVector drag(Mover m) {
// Magnitude is coefficient * speed squared
float speed = m.velocity.mag();
float dragMagnitude = c * speed * speed;
// Direction is inverse of velocity
PVector dragForce = m.velocity.get();
dragForce.mult(-1);
// Scale according to magnitude
// dragForce.setMag(dragMagnitude);
dragForce.normalize();
dragForce.mult(dragMagnitude);
return dragForce;
}
void display() {
noStroke();
fill(50);
rect(x, y, w, h);
}
}
Mover.pde(略)

運行結(jié)果
- 運行這段代碼,你會發(fā)現(xiàn)它模擬的是物體掉入水中的效果。物體穿過窗口底部的灰色區(qū)域(代表流體)時,會減速。你還會發(fā)現(xiàn)物體越小,速度減小地越快。
- 回想牛頓第二運動定律, ,加速度等于力除以質(zhì)量。在同一個力的作用下,物體的質(zhì)量越大,加速度就越小。
- 在本例中,阻力產(chǎn)生的反向加速度有減速的效果。因此物體的質(zhì)量越小,減速越快。