kerry-s
6/6/2017 - 11:59 AM

A basic simulation & visualization for the three body problem.

A basic simulation & visualization for the three body problem.

<html>
    <head>
        <style>
            #universe{
                position: absolute;
                left: 0;
                top: 0;
            }
        </style>
    </head>
    <body>
        <canvas id='universe'></canvas>
        <script>
            {
                const canvas=document.getElementById("universe");
                const ctx=canvas.getContext('2d');
                const G=100;
                const Mass=1;//kg
                const Time=1;//s
                const scale=1;//m
                canvas.width=document.body.clientWidth;
                canvas.height=document.body.clientHeight;
                function sqrDis(a,b){
                    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
                }
                function Body(color){
                    this.color=color;
                    this.x=((Math.random()-0.5)*(canvas.width/3)+canvas.width/2)*scale;
                    this.y=((Math.random()-0.5)*(canvas.height/3)+canvas.height/2)*scale;
                    this.radius=2;
                    this.vx=Math.random()-0.5;
                    this.vy=Math.random()-0.5;
                    this.ax=this.ay=0;
                    this.drawnTo=(body)=>{
                        var dis2=sqrDis(this,body);
                        var dis=Math.sqrt(dis2);
                        var ex=(body.x-this.x)/dis,ey=(body.y-this.y)/dis;
                        var ac=G*Mass/dis2;
                        this.ax+=ac*ex,this.ay+=ac*ey;
                    };
                    this.move=()=>{//time set to 1
                        this.x+=this.vx*Time+this.ax*Time*Time/2;
                        this.y+=this.vy*Time+this.ay*Time*Time/2;
                        this.vx+=this.ax*Time;
                        this.vy+=this.ay*Time;
                        this.ax=this.ay=0;/*
                        if (this.y > canvas.height || this.y < 0) {
                            this.vy = -this.vy;
                        }
                        if (this.x > canvas.width || this.x < 0) {
                            this.vx = -this.vx;
                        }*/
                    };
                    this.draw=()=>{
                        ctx.beginPath();
                        ctx.arc(this.x/scale, this.y/scale, this.radius, 0, Math.PI * 2, true);
                        ctx.closePath();
                        ctx.fillStyle = this.color;
                        ctx.fill();
                    }
                }
                const objs=[new Body('blue'),new Body('red'),new Body('green')];
                objs[2].vx=-objs[0].vx-objs[1].vx;
                objs[2].vy=-objs[0].vy-objs[1].vy;
                function getEp(){
                    var ans=0;
                    objs.forEach((i)=>{
                        objs.forEach((j)=>{
                            if(i!==j){
                                ans+=G/Math.sqrt(sqrDis(i,j));
                            }
                        });
                    });
                    return -ans*Mass/2;
                }
                function getEk(){
                    var ans=0;
                    objs.forEach((i)=>{
                        ans+=i.vx*i.vx+i.vy*i.vy;
                    });
                    return ans*Mass/2;
                }
                var E=getEp()+getEk();
                function update(){
                    ctx.fillStyle = 'rgba(255, 255, 255, 0.01)';
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                    objs.forEach((i)=>{
                        objs.forEach((j)=>{
                            if(i!==j){
                                i.drawnTo(j);
                            }
                        });
                    });
                    objs.forEach((i)=>{
                        i.move(),i.draw();
                    });
                    objs[2].vx=-objs[0].vx-objs[1].vx;
                    objs[2].vy=-objs[0].vy-objs[1].vy;
                    var k=Math.sqrt((E-getEp())/getEk());
                    objs.forEach((i)=>{
                        i.vx*=k;
                        i.vy*=k;
                    });
                    window.requestAnimationFrame(update);
                }
                update();
            }
        </script>
    </body>
</html>