Traces the path of N bodies with gravity.
Log in to post a comment.
Canvas.setpenopacity(-0.5);
const turtle = new Turtle();
const MAX_MASS = 25;
const INITIAL_SPEED = 5;
const SUN = true;
const SUN_FIXED = true;
const SUN_MASS = 400;
const STEPS = 1000;
const STEPS_BEFORE_DRAWING = 100; //let the simulation for a while before drawing trejectories
const CIRCLE_STEPS = 10; //The number of simulation steps between each circle is drawn
const DT = 0.01; //Simulation time step constant
const G = 400; //Gravitational constant
const N = 10; //Number of objects not including sun
function cbody(mass,x,y,vx,vy){
this.mass = mass;
this.x = x;
this.y = y;
this.prevx = x-vx;
this.prevy = y-vy;
this.fx = 0
this.fy = 0
}
cbody.prototype.move = function(){
const nx = 2 * this.x-this.prevx + this.fx/this.mass*DT;
const ny = 2 * this.y-this.prevy + this.fy/this.mass*DT;
this.prevx = this.x;
this.prevy = this.y;
this.x = nx;
this.y = ny;
this.fx=0;
this.fy=0;
}
cbody.prototype.addForce = function(fx,fy){
if(this.fixed){
return;
}
this.fx += fx;
this.fy += fy;
}
function gravity(body1,body2){
const dx = body2.x-body1.x;
const dy = body2.y-body1.y;
const distsq = dx*dx + dy*dy;
const dist = Math.sqrt(distsq)
if(distsq == 0){
return [0,0]
}
const Gm = G*body1.mass*body2.mass/(distsq*dist)
return [dx*Gm,dy*Gm]
}
function forEachPairIn(collection,func){
for(i = 0; i < collection.length; i++){
for(j = i+1; j<collection.length; j++){
func(collection[i], collection[j]);
}
}
}
function smallCircle(x,y,r){
turtle.radians();
const steps=30;
turtle.seth(0);
turtle.pu();
turtle.goto(x,y);
turtle.forward(r);
turtle.pd();
turtle.rt(Math.PI/2);
for(i = 0; i<steps; i++){
turtle.forward(r*Math.PI*2.0/steps);
turtle.rt(Math.PI*2.0/steps);
}
}
let bodies = [];
for(i = 0; i < N; i++){
let m = 1+Math.random()*MAX_MASS
let r = 50+Math.random()*25;
let ang = Math.random()*2*Math.PI;
let x = r*Math.cos(ang);
let y = r*Math.sin(ang);
let vx = -INITIAL_SPEED*Math.sin(ang);
let vy = INITIAL_SPEED*Math.cos(ang);
bodies.push(new cbody(m,x,
y,
vx,
vy,));
}
if(SUN){
sun = new cbody(SUN_MASS,0,0,0,0);
sun.fixed = SUN_FIXED;
bodies.push(sun);
}
function walk(i) {
forEachPairIn(bodies,(body1,body2)=>{
const [fx,fy] = gravity(body1,body2);
//console.log("fx: "+fx+",fy: "+fy)
body1.addForce(fx,fy);
body2.addForce(-fx,-fy);
});
for(b of bodies){
b.move()
if(i > STEPS_BEFORE_DRAWING){
turtle.pu()
turtle.goto(b.prevx,b.prevy)
turtle.pd()
turtle.goto(b.x,b.y)
if (i%CIRCLE_STEPS == 0){
smallCircle(b.x,b.y,Math.sqrt(b.mass))
}
}
}
return i < STEPS;
}