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