Animaciones Canvas: Sistema solar según Kepler

Este ejemplo de sistema planetario es bastante más físico que el otro que tienes en esta sección. Aquí se aplican las leyes de Kepler para mostrar las órbitas elípticas de los planetas en lugar de circulares. Se usa el planeta Tierra con su luna y Marte.

Es algo más realista porque aplica las leyes físicas que describen como las fuerzas de atracción provocan un movimiento de un objeto alrededor de otro. Si no te acuerdas de la física del instituto: son las que explicaron por primera vez el movimiento planetario.

Pues aquí las tienes aplicadas para simular un sistema solar, puedes experimentar con el editor online.

<html>

<head>

<meta charset="utf-8">

<title>Movimiento en elipse</title>

<script>

function astro(cx, cy, rad, color){

lapiz.arc(cx, cy, rad, 0, 2*Math.PI);

lapiz.fillStyle = color;

lapiz.fill();

lapiz.strokeStyle = color;

lapiz.stroke();

}

//Aproximaciones sucesivas por método Newton

//Calcula el ángulo del foco al planeta

//excentricidad, semieje, periodo, tiempo girando

function keplerE(exc, per, dt)

{

let E0, E1, M;

//Realmente es M = (2*pi/periodo como argumento)*dt

M = (0.0001/per)*dt

E1 = M + exc*Math.sin(M);

while (Math.abs(E1-E0) > 0.0000001) {

E0 = E1;

E1 = E0 - ( E0 - M - exc*Math.sin(E0) )/(1-exc*Math.cos(E0));

}

return E1;

}

//Dibuja la posición del planeta o satélite en su órbita

//Parámetros: radio planeta, excentricidad, semieje, tiempo, periodo, color, si lleva satelite

function orbita(rad, exc, semieje, tiempo, per, color, sat)

{

let E = keplerE(exc, per, tiempo)

//coords. X, Y respecto al foco

let cx = semieje*(Math.cos(E)-exc);

let cy = semieje*Math.sqrt(1-exc*exc)*Math.sin(E);

//reinicia lapiz tras cada vuelta

lapiz.beginPath()

astro(cx,cy,rad, color);

//si se quiere dibujar las elipses

//dibOrbita(exec, semije, color);

if (sat){ lapiz.translate(cx,cy) }

}

function mover(time)

{

let dt = Math.round((time-iniAnim))*100;

lapiz.putImageData(fondo,0,0);

//Pongo planeta con satelite es necesario guardar contexto

lapiz.save()

orbita(5, 0.2, 100, dt, 12 , "blue", true);

orbita(2, 0.1, 15, dt, 1 ,"pink", false);

lapiz.restore()

orbita(4, 0.5, 250, dt, 18 ,"red", false);

oAnim = window.requestAnimationFrame(mover)

}

//Si se quieren dibujar las órbitas se usarí esta función

//exc: excentricidad de la orbita,

//eje: semieje mayor de la orbita,

//color: color de la orbita

function dibOrbita(exc, eje, color){

lapiz.beginPath();

lapiz.strokeStyle = color;

let eje2 = eje*Math.sqrt(1-exc*exc);

lapiz.ellipse(-eje*exc, 0, eje, eje2, 0, 0, 2*Math.PI);

lapiz.stroke();

}

//globales (habría que mejorar esto)

var iniAnim, oAnim, lapiz, fondo;

function iniciar()

{

let marco=document.getElementById("marco")

lapiz = marco.getContext("2d");

lapiz.translate(marco.width/1.5, marco.height/2 - 100)

//Poner sol

lapiz.beginPath()

astro(0, 0, 10, "yellow");

fondo = lapiz.getImageData(0,0,marco.width, marco.height);

iniAnim = window.performance.now();

oAnim = window.requestAnimationFrame(mover)

}

</script>

</head>

<body onload="iniciar()">

<canvas id="marco" width="800" height="800" style="background-color: black"></canvas>

</body>

</html>