block by tophtucker 0387ae2d06220b23e215

Earth orbit

Full Screen

Click to fast-forward. Based on the math here. No guarantees of accuracy, this is not legal advice. Made in honor of Pi Day — which I think is borderline numerology, a random and arbitrary mapping, but I respect the ability to create meaning in life ex nihilo.

script.js

// ALL GOOD STUFF ADAPTED FROM THIS WONDERFUL OLD SITE:
// http://www.stargazing.net/kepler/ellipse.html

// angles are in degrees
// distances are in a.u.

////////////////////////////////////////////

// dates
var dayToMs = 24*60*60*1000;
var msToDay = 1/dayToMs;

// trig
var degToRad = (2*Math.PI)/360;
var radToDeg = 1/degToRad;
function sin(x) { return Math.sin(x * degToRad); }
function cos(x) { return Math.cos(x * degToRad); }

// "Osculating Elements"

var abbrevs = {
  "i": "Inclination",
  "o": "Longitude of the Ascending Node",
  "p": "Longitude of Perihelion",
  "a": "Mean distance",
  "n": "Daily motion",
  "e": "Eccentricity",
  "L": "Mean Longitude",
  "JD": "Julian Date"
}

var earth = {
  "i": 0.00041,
  "o": 349.2,
  "p": 102.8517,
  "a": 1.0000200,
  "n": 0.9855796,
  "e": 0.0166967,
  "L": 328.40353,
  "JD": 2450680.5,
  "datetime": new Date("August 20, 1997 00:00:00"),
  "radius": 0.000042563739
};

var mars = {
  "i": 1.84992,
  "o": 49.5664,
  "p": 336.0882,
  "a": 1.5236365,
  "n": 0.5240613,
  "e": 0.0934231,
  "L": 262.42784,
  "JD": 2450680.5,
  "datetime": new Date("August 20, 1997 00:00:00"),
  "radius": 0.00002263
};

var sun = {
  "radius": 0.004649
}

// MATH

function meanAnomaly(satellite, time) {
  var days = (time-satellite.datetime)*msToDay;
  return ((satellite.n * days + satellite.L - satellite.p) % 360 + 360) % 360;
}

function trueAnomaly(satellite, time) {
  var M = meanAnomaly(satellite, time);
  return M + (180/Math.PI) * 
    (
      (2 * satellite.e - Math.pow(satellite.e, 3)/4) * Math.sin(degToRad*M) +
      (5/4 * Math.pow(satellite.e, 2)) * Math.sin(degToRad*M*2) +
      (13/12 * Math.pow(satellite.e, 3)) * Math.sin(degToRad*M*3)
    );
}

function radius(satellite, time) {
  return satellite.a * (1 - Math.pow(satellite.e, 2)) / (1 + satellite.e * Math.cos(trueAnomaly(satellite, time)*degToRad));
}

function coordinates(satellite, time) {
	var r = radius(satellite, time);
  var v = trueAnomaly(satellite, time);
  var o = satellite.o;
  var p = satellite.p;
  var i = satellite.i;
  
  var X = r * (cos(o) * cos(v+p-o) - sin(o) * sin(v+p-o) * cos(i));
  var Y = r * (sin(o) * cos(v+p-o) + cos(o) * sin(v+p-o) * cos(i));
  var Z = r * (sin(v+p-o) * sin(i));
  
  return [X,Y,Z];
}

// au to pixels
var minPx = Math.min(window.innerHeight, window.innerWidth);
var auScale = d3.scale.linear().domain([0,2.2]).range([0,minPx]);

var sunSel = d3.select("#ecliptic").append("div")
    .classed('celestial-body', true)
		.attr('id', 'sun')
		.style('left', '0')
		.style('top', '0')
		.style('width', (auScale(sun.radius)*2)+'px')
		.style('height', (auScale(sun.radius)*2)+'px');

var earthSel = d3.select("#ecliptic").append("div")
    .classed('celestial-body', true)
		.attr('id', 'earth')
		.style('width', (auScale(earth.radius)*2)+'px')
		.style('height', (auScale(earth.radius)*2)+'px');

function render(time) {
  var earthRadius = radius(earth, time);
  var earthTrueAnomaly = trueAnomaly(earth, time);
  var earthCoords = coordinates(earth, time);
  console.log(earthCoords);
  
  d3.select("#date").text(time);
  d3.select("#radius").text(earthRadius);
  d3.select("#true-anomaly").text(earthTrueAnomaly);
  d3.select("#true-anomaly-pi").text(earthTrueAnomaly*degToRad/Math.PI);
  
  earthSel
    .style('left', auScale(earthCoords[0]) + 'px')
    .style('top', auScale(earthCoords[1]) + 'px')
}
render(new Date());

var realtime = setInterval(function() { render(new Date()); }, 1000);
var fastForward;
window.onclick = function() {
  clearInterval(realtime);
  clearInterval(fastForward);
  var t = 0;
  fastForward = setInterval(function() {
    var newTime = new Date(+new Date() + t*dayToMs);
    render(newTime);
    t++;
  }, 50);
}

index.html

<link rel="stylesheet" href="style.css">

<div id="ecliptic"></div>

<p>Date: <span id="date"></span><p>
<p>Distance from sun: <span id="radius"></span> AU</p>
<p>True anomaly: <span id="true-anomaly"></span>°</p>
<p>True anomaly: <span id="true-anomaly-pi"></span>π</p>

<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="script.js" charset="utf-8"></script>

style.css

html, body {
  margin: 0;
  padding: 0;
  background: black;
  width: 100%;
  height: 100%;
  min-width: 500px;
  min-height: 500px;
  color: #333;
  font-family: courier;
  font-size: 10px;
}

p { margin: 0; }

#ecliptic {
  top: 50%;
  left: 50%;
  width: 1px;
  height: 1px;
  transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  position: relative;
}

.celestial-body {
  border: 1px solid rgba(255,255,255,.5);
  border-radius: 100px;
  position: absolute;
  -webkit-transform:  translate(-50%, -50%);
  -moz-transform:     translate(-50%, -50%);
  transform:          translate(-50%, -50%);
  -webkit-box-shadow: 0px 0px 3px 0px rgba(255, 255, 255, 0.75);
  -moz-box-shadow:    0px 0px 3px 0px rgba(255, 255, 255, 0.75);
  box-shadow:         0px 0px 3px 0px rgba(255, 255, 255, 0.75);
}

#sun {
  background: yellow;
}

#earth {
  background: lightblue;
}