Files
astronomy/demo/browser/barycenter.html
Mateo Tibaquira 44a96f8c21 JS: Improve the documentation of FlexibleDateTime
Also moved the NPM commands to the package.json
so the makedoc scripts execute them in a central place.

Installed a jsdoc theme to improve the html output.
2021-02-07 20:42:05 -05:00

159 lines
7.4 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Solar System Barycenter</title>
<link rel="stylesheet" href="barycenter.css">
<script src="astronomy.browser.js"></script>
<script>
window.onload = function() {
const ReservedPixelsBottom = 70;
const graph = document.getElementById('GraphCanvas');
const context = graph.getContext('2d');
const timeSlider = document.getElementById('TimeSlider');
let animating = true;
let prevAnimationTime = null;
const PlanetOrbitScale = 33.0; // radius in AU that corresponds to graph size.
const SunOrbitScale = 0.3;
const SimSpeed = 0.5; // days of simulated time per millisecond of animation time
const SunRadiusAU = 0.00465047;
const SunMass = 333054.25318;
const JupiterMass = 317.84997;
const SaturnMass = 95.16745;
const UranusMass = 14.53617;
const NeptuneMass = 17.14886;
function ResizeGraph() {
// Make the canvas fit the available space inside the browser window.
// Reserve some space below the graph for sliders.
graph.width = window.innerWidth;
graph.height = window.innerHeight - ReservedPixelsBottom;
// Resize the sliders to fit in the reserved space beneath the graph.
const yspace = 10; // pixels of vertical "cushion" for sliders
const sliderWidth = (graph.width - 20).toFixed() + 'px';
const sliderHeight = (ReservedPixelsBottom - yspace).toFixed() + 'px';
timeSlider.style.width = sliderWidth;
timeSlider.style.height = sliderHeight;
}
function PlotPlanet(planet, symbol, radius) {
const pixels = Math.min(graph.width, graph.height) / 2;
const px = (graph.width/2) + (planet.x/PlanetOrbitScale)*pixels;
const py = (graph.height/2) - (planet.y/PlanetOrbitScale)*pixels;
context.beginPath();
context.arc(px, py, radius, 0, 2*Math.PI);
context.style = 'rgb(0,0,0)';
context.fillStyle = 'rgb(180,180,128)';
context.fill();
context.font = '16px monospace';
context.fillStyle = 'rgb(0,180,128)';
context.fillText(symbol, px-5, py+radius+15);
}
function PlotSun(ssb) {
const cx = graph.width / 2;
const cy = graph.height / 2;
const pixels = Math.min(graph.width, graph.height);
// Draw the Sun's position at a larger scale, to make its movement around the SSB visible.
const SunPlotRadius = (SunRadiusAU/SunOrbitScale)*pixels;
const bx = (graph.width/2) + (-ssb.x/SunOrbitScale)*pixels;
const by = (graph.height/2) - (-ssb.y/SunOrbitScale)*pixels;
context.beginPath();
context.arc(bx, by, SunPlotRadius, 0, 2*Math.PI);
context.fillStyle = 'rgb(255,255,0)';
context.fill();
// Draw a cross at the SSB location.
const crossPixels = 8;
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(cx - crossPixels, cy);
context.lineTo(cx + crossPixels, cy);
context.moveTo(cx, cy - crossPixels);
context.lineTo(cx, cy + crossPixels);
context.stroke();
}
function AdjustBarycenter(ssb, planet, pmass) {
const shift = pmass / (pmass + SunMass);
ssb.x += shift * planet.x;
ssb.y += shift * planet.y;
ssb.z += shift * planet.z;
}
function Render() {
context.fillStyle = 'rgb(0,0,0)';
context.fillRect(0, 0, graph.width, graph.height);
const ut = parseFloat(timeSlider.value);
const time = Astronomy.MakeTime(ut);
// Calculate positions of the major planets.
const jupiter = Astronomy.HelioVector('Jupiter', time);
const saturn = Astronomy.HelioVector('Saturn', time);
const uranus = Astronomy.HelioVector('Uranus', time);
const neptune = Astronomy.HelioVector('Neptune', time);
// Calculate the location of the Solar System Barycenter (SSB).
let ssb = { x:0, y:0, z:0 };
AdjustBarycenter(ssb, jupiter, JupiterMass);
AdjustBarycenter(ssb, saturn, SaturnMass);
AdjustBarycenter(ssb, uranus, UranusMass);
AdjustBarycenter(ssb, neptune, NeptuneMass);
// Convert heliocentric coordinates to barycentric coordinates.
jupiter.x -= ssb.x; jupiter.y -= ssb.y;
saturn.x -= ssb.x; saturn.y -= ssb.y;
uranus.x -= ssb.x; uranus.y -= ssb.y;
neptune.x -= ssb.x; neptune.y -= ssb.y;
PlotPlanet(jupiter, 'J', 5);
PlotPlanet(saturn, 'S', 3);
PlotPlanet(uranus, 'U', 2);
PlotPlanet(neptune, 'N', 2);
PlotSun(ssb);
// Draw the date corresponding to the slider position.
context.font = '16px monospace';
context.fillStyle = 'rgb(0,255,0)';
const dateText = time.toString().substr(0, 10);
context.fillText(dateText, 10, graph.height-8);
}
function OnAnimationFrame(time) {
if (animating && prevAnimationTime !== null) {
let ut = parseFloat(timeSlider.value);
ut += (time - prevAnimationTime) * SimSpeed;
if (ut > 40000) ut = -40000; // start over
timeSlider.value = ut.toFixed(8);
Render();
}
prevAnimationTime = time;
requestAnimationFrame(OnAnimationFrame);
}
ResizeGraph();
window.addEventListener('resize', ResizeGraph);
timeSlider.addEventListener('input', Render);
timeSlider.addEventListener('mouseover', function() {
animating = false;
});
timeSlider.addEventListener('mouseout', function() {
animating = true;
});
Render();
requestAnimationFrame(OnAnimationFrame);
}
</script>
</head>
<body>
<div>
<canvas id="GraphCanvas" class="PlotCanvas"></canvas>
</div>
<div>
<input id="TimeSlider" type="range" min="-40000" max="40000" value="7305" step="any">
</div>
</body>
</html>