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; }