Skip to content

Instantly share code, notes, and snippets.

@realmonster
Last active October 20, 2016 15:50
Show Gist options
  • Select an option

  • Save realmonster/90b95af838b06ed7efa94432549d9cf9 to your computer and use it in GitHub Desktop.

Select an option

Save realmonster/90b95af838b06ed7efa94432549d9cf9 to your computer and use it in GitHub Desktop.
Moon trajectory visualization
license: mit

##Visualisation of Moon trajectory for myths exorcism.

###Assumptions:

  1. Earth and Moon moving by circles around Sun and Earth respectively.
  2. All objects moving in same plane.
  3. All shapes using sizes with correct proportions, but not correct absolute scale, including vectors.
  4. All rotations are uniform: no speedups, no slowdowns.

###Myths being destroyed:

  1. Moon has bigger attraction force to Earth than to Sun.
  2. Moon making many loops around Earth.
  3. Moon has sine alike trajectory.
  4. Moon does not rotating around Sun.

###Features

  1. Pan & Scan + Zoom. Everyone likes zoom.
  2. Force vectors. Yellow, blue, gray - Sun, Earth, summary respectively.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.circle {
fill-opacity: .5;
}
.ring {
fill: none;
stroke: #000;
pointer-events: none;
}
.ring-inner {
stroke-width: 5px;
stroke-opacity: .25;
}
.moon {
stroke-width: 1px;
stroke: #444;
fill: none;
}
.earth {
stroke-width: 1px;
stroke: blue;
fill: none;
}
.vector {
stroke-width: 2px;
fill: none;
}
</style>
<svg width="960" height="500"></svg>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
var sun_dist = 149.6e9;
var moon_dist = 370.3e6;
var sun_r = 696.342e6
var earth_r = 6.371e6;
var moon_r = 1.737e6;
var sun_mass = 1.989e30;
var earth_mass = 5.972e24;
var moon_mass = 7.36e22;
var c1 = {x: 480, y: 250, r: sun_r/3e7, color: "orange"},
c2 = {x: 600, y: 100, r: earth_r/3e7, color: "blue"},
c3 = {x: 600, y: 300, r: moon_r/3e7, color: "#444"};
var a_scale = 0.5;
var v1 = {x1: 0, y1: 0, x2: 0, y2: 0, color: "orange"};
v2 = {x1: 0, y1: 0, x2: 0, y2: 0, color: "blue"};
v3 = {x1: 0, y1: 0, x2: 0, y2: 0, color: "#444"};
function update_pos(t)
{
c2.x = c1.x + sun_dist/1e9 * Math.cos(t);
c2.y = c1.y - sun_dist/1e9 * Math.sin(t);
c3.x = c2.x + moon_dist/1e9 * Math.cos(t * 13);
c3.y = c2.y - moon_dist/1e9 * Math.sin(t * 13);
var dx = c1.x - c3.x;
var dy = c1.y - c3.y;
var len = Math.sqrt(dx*dx + dy*dy);
v1.x1 = c3.x;
v1.y1 = c3.y;
v1.x2 = v1.x1 + dx*sun_mass/1e25/(len*len*len);
v1.y2 = v1.y1 + dy*sun_mass/1e25/(len*len*len);
dx = c2.x - c3.x;
dy = c2.y - c3.y;
len = Math.sqrt(dx*dx + dy*dy);
v2.x1 = c3.x;
v2.y1 = c3.y;
v2.x2 = v2.x1 + dx*earth_mass/1e25/(len*len*len);
v2.y2 = v2.y1 + dy*earth_mass/1e25/(len*len*len);
v3.x1 = c3.x;
v3.y1 = c3.y;
v3.x2 = v3.x1 + v1.x2 - v1.x1 + v2.x2 - v2.x1;
v3.y2 = v3.y1 + v1.y2 - v1.y1 + v2.y2 - v2.y1;
}
var color = d3.scale.category10();
var svg = d3.select("svg");
svg.style("pointer-events", "all");
svg = svg.append("g")
.call(d3.behavior.zoom().scaleExtent([1, 40]).on("zoom", zoom))
.append("g");
var earth = svg.append("circle").attr("class", "earth")
.attr("r", sun_dist/1e9)
.attr("cx", c1.x)
.attr("cy", c1.y);
svg.append("path").attr("class", "moon")
.attr("d", function () {
var path = ["M0,0"];
for (var i=0; i < 201; ++i) {
var t1 = i*2*Math.PI/200;
update_pos(t1);
path.push((i?"L":"M"), c3.x, ",", c3.y);
}
return path.join("");
});
var vectors = svg.selectAll(".vector")
.data([v1, v2, v3]).enter()
.append("path")
.attr("class", "vector")
.style("stroke", function (d) { return d.color; });
function zoom() {
svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
svg.select("path").style("stroke-width", 1/d3.event.scale);
earth.style("stroke-width", 1/d3.event.scale);
vectors.style("stroke-width", 2/d3.event.scale);
a_scale = Math.min(5/d3.event.scale, 0.5);
}
var circles = svg.selectAll(".circle")
.data([c1, c2, c3]);
var circle = circles
.enter().append("g")
.attr("class", "circle")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.style("fill", function(d) { return d.color; });
circle.append("circle")
.attr("r", function(d) { return d.r; });
function vectorP(v)
{
var path = ["M", v.x1, ",", v.y1];
path.push("L", v.x2, ",", v.y2);
var dx = v.x2 - v.x1;
var dy = v.y2 - v.y1;
var len = dx*dx + dy*dy;
if (Math.abs(len) > 1e-7)
{
len = Math.sqrt(len);
dx /= len;
dy /= len;
path.push("L", v.x2 - dy * a_scale - dx * a_scale, ",", v.y2 + dx * a_scale - dy * a_scale);
path.push("L", v.x2 + dy * a_scale - dx * a_scale, ",", v.y2 - dx * a_scale - dy * a_scale);
path.push("L", v.x2, ",", v.y2);
path.push("Z");
}
return path.join("");
}
function update() {
vectors.each(function(d) {
d3.select(this).attr("d", vectorP(d));
});
}
var start = Date.now();
d3.timer( function (){
var t1 = (Date.now() - start)/20000;
update_pos(t1);
circles.each(function (d) {
d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")");
});
update();
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment