原因
昨天在学习时发现缺少一些关键内容,所以就去找了作者提供的原始代码,看看是如何实现的。
代码
ParticleSystem ps;
Repeller repeller;
void setup() {
size(800,200);
smooth();
ps = new ParticleSystem(new PVector(width/2,50));
repeller = new Repeller(width/2-20,height/2);
}
void draw() {
background(255);
ps.addParticle();
// Apply gravity force to all Particles
PVector gravity = new PVector(0,0.1);
ps.applyForce(gravity);
*********关键部分************
ps.applyRepeller(repeller);
repeller.display();
ps.run();
}
// Simple Particle System
// Daniel Shiffman <http://www.shiffman.net>
// A simple Particle class
class Particle {
PVector location;
PVector velocity;
PVector acceleration;
float lifespan;
float mass = 1; // Let's do something better here!
Particle(PVector l) {
acceleration = new PVector(0,0);
velocity = new PVector(random(-1,1),random(-2,0));
location = l.get();
lifespan = 255.0;
}
void run() {
update();
display();
}
void applyForce(PVector force) {
PVector f = force.get();
f.div(mass);
acceleration.add(f);
}
// Method to update location
void update() {
velocity.add(acceleration);
location.add(velocity);
acceleration.mult(0);
lifespan -= 2.0;
}
// Method to display
void display() {
stroke(0,lifespan);
strokeWeight(2);
fill(127,lifespan);
ellipse(location.x,location.y,12,12);
}
// Is the particle still useful?
boolean isDead() {
if (lifespan < 0.0) {
return true;
} else {
return false;
}
}
}
import java.util.Iterator;
class ParticleSystem {
ArrayList<Particle> particles;
PVector origin;
ParticleSystem(PVector location) {
origin = location.get();
particles = new ArrayList<Particle>();
}
void addParticle() {
particles.add(new Particle(origin));
}
// A function to apply a force to all Particles
void applyForce(PVector f) {
for (Particle p: particles) {
p.applyForce(f);
}
}
**********关键部分*************
void applyRepeller(Repeller r) {
for (Particle p: particles) {
PVector force = r.repel(p);
p.applyForce(force);
}
}
void run() {
Iterator<Particle> it = particles.iterator();
while (it.hasNext()) {
Particle p = it.next();
p.run();
if (p.isDead()) {
it.remove();
}
}
}
}
经过分析后发现,这种排斥力依然是通过力施加方法实现的,不过这里的力需要通过专门计算获得。也就是排斥物中的repel方法。这种实现非常巧妙的,避免了重复代码。
// Particles + Forces
// Daniel Shiffman <http://www.shiffman.net>
// A very basic Repeller class
class Repeller {
// Gravitational Constant
float G = 100;
// Location
PVector location;
float r = 10;
Repeller(float x, float y) {
location = new PVector(x,y);
}
void display() {
stroke(0);
strokeWeight(2);
fill(175);
ellipse(location.x,location.y,48,48);
}
// Calculate a force to push particle away from repeller
PVector repel(Particle p) {
PVector dir = PVector.sub(location,p.location); // Calculate direction of force
float d = dir.mag(); // Distance between objects
dir.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
d = constrain(d,5,100); // Keep distance within a reasonable range
float force = -1 * G / (d * d); // Repelling force is inversely proportional to distance
dir.mult(force); // Get force vector --> magnitude * direction
return dir;
}
}
具体来看repel函数,使用数学符号表示这一过程。
于是就获得了排斥力的表达形式,依然是距离的平方反比规律,不过方向掉转了。其中还有一个约束,限制了距离的最小和最大值,可能是一种截断函数。
总结
不局限于此,可以考虑很多种形式的势场和势场所生成的力场,这个在量子力学的习题中见过不少,求给定势场下的粒子的波函数形式。
如果将一切都视为参数索引的物理量,那么还可以给出更多自由度,f(t,x,y,z),依赖于时间和位置的力函数,当然还有很多其他的实现,比如空间非平坦,那么距离的计算就需要考虑空间曲率。
动画就是时间依赖参数的更新与绘制,在每一帧中更新所需参数。
网友评论