Khan Academy での学習
Forces
学習元 Forces
var Mover = function() { // 簡単にするため質量は 1 とする this.mass = 1; this.position = new processing.PVector(30, 30); this.velocity = new processing.PVector(0, 0); this.acceleration = new processing.PVector(0, 0); }; // ニュートンの第2法則をシミュレートする // force を受取り, 質量で割り, 加速度に加える Mover.prototype.applyForce = function(force) { var f = processing.PVector.div(force, this.mass); this.acceleration.add(f); }; Mover.prototype.update = function() { // Vectorsの最初の例でシミュレートする this.velocity.add(this.acceleration); this.position.add(this.velocity); // 毎回加速度をクリア this.acceleration.mult(0); }; Mover.prototype.display = function() { processing.stroke(0); processing.strokeWeight(2); processing.fill(255, 255, 255, 127); // 質量により、サイズを変更する processing.ellipse(this.position.x, this.position.y, this.mass*30, this.mass*30); }; // mover をエッジでバウンドさせるため、速度を変えています Mover.prototype.checkEdges = function() { if (this.position.x > width) { this.position.x = width; this.velocity.x *= -1; } else if (this.position.x < 0) { this.velocity.x *= -1; this.position.x = 0; } if (this.position.y > height) { this.velocity.y *= -1; this.position.y = height; } }; // setup processing.setup = function(){ // canvas size processing.size(width,height); }; // mover生成 var m = new Mover(); processing.draw = function() { processing.background(66, 66, 66); //風と重力 var wind = new processing.PVector(0.01, 0); var gravity = new processing.PVector(0, 0.1); m.applyForce(wind); m.applyForce(gravity); m.update(); m.display(); m.checkEdges(); };
Many objects
var Mover = function(m, x, y) { this.mass = m; this.position = new processing.PVector(x, y); this.velocity = new processing.PVector(0, 0); this.acceleration = new processing.PVector(0, 0); }; ..... Mover.prototype.display = function() { processing.stroke(0); processing.strokeWeight(2); processing.fill(255, 255, 255, 127); processing.ellipse(this.position.x, this.position.y, this.mass*30, tmass*30); }; .... var m = []; for (var i = 0; i < 20; i++) { m[i] = new Mover(processing.random(0.1, 5), 0, 0); }; .....
Acceleration
Many objects 2
Mover.prototype.calculateWallForce = function() { var fx = 0; var fy = 0; if (this.position.x > width) { fx = -1; } else if (this.position.x < 0) { fx =1; } if (this.position.y > height) { fy = -1; } else if (this.position.y < 0) { fy = 1; } return new processing.PVector(fx,fy); }; .... processing.draw = function() { processing.background(66, 66, 66); for (var i = 0; i < m.length; i++) { var wind = new processing.PVector(0.01, 0); var gravity = new processing.PVector(0, 0.1); m[i].applyForce(wind); m[i].applyForce(gravity); m[i].applyForce(m[i].calculateWallForce()); m[i].update(); m[i].display(); }; };
Modeling gravity and friction
gravity
processing.draw = function() { processing.background(66, 66, 66); for (var i = 0; i < m.length; i++) { var wind = new processing.PVector(0.01, 0); var gravity = new processing.PVector(0, 0.1 * m[i].mass); m[i].applyForce(wind); m[i].applyForce(gravity); m[i].update(); m[i].display(); m[i].checkEdges(); }; };
friction
for (var i = 0; i < movers.length; i++) { var wind = new processing.PVector(0.01, 0); var gravity = new processing.PVector(0, 0.1*movers[i].mass); var c = 0.01; // 摩擦係数 var normal = 1; // 垂直抗力 var frictionMag = c * normal; // 抗力 var friction = movers[i].velocity.get(); // 速度の取得 friction.mult(-1); // 速度の向きを反転 friction.normalize(); // 単位ベクトル化 friction.mult(frictionMag); // 摩擦力の大きさ movers[i].applyForce(friction); // 摩擦力を適用 movers[i].applyForce(wind); // 風力を適用 movers[i].applyForce(gravity); // 重力を適用 movers[i].update(); movers[i].display(); movers[i].checkEdges(); }
Air and fluid resistance
$$F_{d} = -\frac{1}{2}\rho v^{2}AC_{d}\hat{v}$$ $$F_{d} : Drag \quad force(抗力)$$ $$-\frac{1}{2} : 定数$$ $$\rho : 流体の密度$$ $$v^2 : v は物体のスピードで、速度ベクトルの大きさ -- velocity.mag()$$ $$A : 流体を押す物体の正面の面積$$ $$C_{d} : 抗力係数$$ $$_hat{v} : 速度の単位ベクトル -- velocity.normalize()$$
// Calculate drag force Liquid.prototype.calculateDrag = function(m) { // Magnitude is coefficient * speed squared var speed = m.velocity.mag(); var dragMagnitude = this.c * speed * speed; // Direction is inverse of velocity var dragForce = m.velocity.get(); dragForce.mult(-1); // Scale according to magnitude // dragForce.setMag(dragMagnitude); dragForce.normalize(); dragForce.mult(dragMagnitude); return dragForce; }; .... for (var i = 0; i < movers.length; i++) { // Is the Mover in the liquid? if (liquid.contains(movers[i])) { // Calculate drag force var dragForce = liquid.calculateDrag(movers[i]); // Apply drag force to Mover movers[i].applyForce(dragForce); } ....
Gravitational attraction
$$F=G\frac{m_{1} \dot m_{2}}{r^2}\hat{r}$$ $$F:引力$$ $$G:万有引力定数=6.67408x10^{-11}m^{3}kg^{-1}s^{-2}$$ $$m_{1},m_{2}:物体の質量$$ $$r:物体間の距離$$ $$\hat{r}:距離の単位ベクトル$$
Attractor.prototype.calculateAttraction = function(mover) { // Calculate direction of force var force = processing.PVector.sub(this.position, mover.position); // Distance between objects var distance = force.mag(); // Limiting the distance to eliminate "extreme" results // for very close or very far objects distance = processing.constrain(distance, 5, 25); // Normalize vector force.normalize(); // Calculate gravitional force magnitude var strength = (this.G * this.mass * mover.mass) / (distance * distance); // Get force vector --> magnitude * direction force.mult(strength); return force; };
Gravitational attraction
Mutual attraction
Mover.prototype.calculateAttraction = function(m, i) { // Calculate direction of force var force = processing.PVector.sub(this.position, m.position); // Distance between objects var distance = force.mag(); // Limiting the distance to eliminate "extreme" results for very closevery far objects distance = processing.constrain(distance, 5.0, 25.0); // Normalize vector (distance doesn't matter here, we just want tvector for direction force.normalize(); // Calculate gravitional force magnitude var strength = (G * this.mass * m.mass) / (distance * distance); // Get force vector --> magnitude * direction force.mult(strength); return force; }; ... processing.draw = function() { processing.background(50, 50, 50); for (var i = 0; i < movers.length; i++) { for (var j = 0; j < movers.length; j++) { if (i !== j) { var force = movers[j].calculateAttraction(movers[i]); movers[i].applyForce(force); } } movers[i].update(); movers[i].display(); } };