block by Fil 6244cd213f08d5d16774

Bottomley projection

Full Screen

See d3-geo-projection/pull/26

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  background: #fcfcfa;
}

.stroke {
  fill: none;
  stroke: #000;
  stroke-width: 3px;
}

.fill {
  fill: #fff;
}

.graticule {
  fill: none;
  stroke: #777;
  stroke-width: .5px;
  stroke-opacity: .5;
}

.land {
  fill: #222;
}

.boundary {
  fill: none;
  stroke: #fff;
  stroke-width: .5px;
}

</style>
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/d3-geo-projection.v2.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>

  
var width = 960,
    height = 500;

var projection = d3.geoBottomley()
    .scale(155)
    .translate([width / 2, height / 2])
    .precision(.1);

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

var graticule = d3.geoGraticule();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

svg.append("defs").append("path")
    .datum({type: "Sphere"})
    .attr("id", "sphere")
    .attr("d", path);

svg.append("use")
    .attr("class", "stroke")
    .attr("xlink:href", "#sphere");

svg.append("use")
    .attr("class", "fill")
    .attr("xlink:href", "#sphere");

svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);

d3.json("https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/world-50m.json", function(error, world) {
  if (error) throw error;

  svg.insert("path", ".graticule")
      .datum(topojson.feature(world, world.objects.land))
      .attr("class", "land")
      .attr("d", path);

  svg.insert("path", ".graticule")
      .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
      .attr("class", "boundary")
      .attr("d", path);
});


</script>

bottomley.js

var π = Math.PI, halfπ=π/2;
function bottomleyRaw(ψ) {
  function forward(λ, φ) {
    var ρ = halfπ - φ,
        η = ρ ? λ * Math.sin(ψ) * Math.sin(ρ) / ρ : ρ;
    return [
      ρ * Math.sin(η) / Math.sin(ψ),
      halfπ - ρ * Math.cos(η)
    ];
  }

  forward.invert = function(x, y) {
    var x1 = x * Math.sin(ψ),
      y1 = halfπ - y;
    var ρ = Math.sqrt( x1 * x1 + y1 * y1 ),
      η = Math.atan( x1 / y1 );

    return [
      (ρ ? ρ / Math.sin(ρ) : 1) * η / Math.sin(ψ),
      halfπ - ρ
    ];
  };

  return forward;
}

(d3.geo.bottomley = function() {
  var ψ = π/6,
    mutate = d3.geo.projectionMutator(bottomleyRaw),
    projection = mutate(ψ);

  projection.variant = function(_) {
    if (!arguments.length) return ψ;
    return mutate(ψ = _);
  };

  return projection;
}).raw = bottomleyRaw;