Lunar Craters

Astronomy
Mapping
Code
chart = {
  const width = fullWidth,
        height = fullHeight;

  const window = d3.create("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("viewBox", `0 0 ${fullWidth} ${fullHeight}`)
    .attr("preserveAspectRatio", "xMidYMid meet");

  const svg = window.append("g")
    .attr("class", "moon");

  const graticule = d3.geoGraticule();

  const projection = d3.geoOrthographic()
    .rotate([0, 0])
    .translate([width / 2, height / 2])
    .scale(200)
    .clipAngle(90);

  const path = d3.geoPath()
    .projection(projection);

  const circle = d3.geoCircle()
    .center(d => [d.lon, d.lat])
    .radius(d => d.d / 2 / 1737 * 180 / Math.PI)
    .precision(20);

  svg.append("rect")
    .attr("width", width)
    .attr("height", height)
    .attr("fill", "#000000");

  svg.append("path")
    .datum(graticule.outline())
    .attr("fill", "#bdbdbd")
    .attr("d", path);

  svg.append("path")
    .datum(graticule())
    .attr("class", "geo-path")
    .attr("fill", "none")
    .attr("stroke", "#252525")
    .attr("stroke-width", 0.5)
    .attr("stroke-opacity", 0.2)
    .attr("d", path);

  svg.selectAll(".crater")
    .data(craters.map(d => circle(d)))
    .join("path")
      .attr("class", "crater geo-path")
      .attr("fill", "#969696")
      .attr("stroke", "#737373")
      .attr("fill-opacity", 0.5)
      .attr("d", path);

  function render() {
    d3.selectAll(".geo-path")
      .attr("d", path);
  }

  function tick() {
    const origin = projection.rotate();
    origin[0] += 0.1;
    projection.rotate(origin);
    render();
  }

  function start() {
    return d3.interval(tick, 20);
  }

  let timer = start();

  let v0, r0, q0, v1, r1, q1;
  const drag = d3.drag();

  drag.on("start", function(event) {
    timer.stop();
    v0 = versor.cartesian(
      projection.invert(d3.pointer(event, this)));
    r0 = projection.rotate();
    q0 = versor(r0);
  });

  drag.on("drag", function(event) {
    v1 = versor.cartesian(
      projection.rotate(r0).invert(d3.pointer(event, this)));
    q1 = versor.multiply(q0, versor.delta(v0, v1));
    r1 = versor.rotation(q1);
    projection.rotate(r1);
    render();
  });

  drag.on("end", function() {
    timer = start();
  });

  svg.call(drag);

  invalidation.then(() => {
    timer.stop();
  });

  return window.node();
}

Shown on this moon globe are all large lunar craters (with diameters greater than 50 km).

Resources

Data