// imports var atan = Math.atan, sqrt1_2 = Math.sqrt(1/2), π = Math.PI, degrees = 180 / π, θ = atan(sqrt1_2) * degrees; var d3Geo = d3, polyhedral = d3.geoPolyhedral; var width = 900, height = 400, rotate = [30, 0, 0]; var vertices = [ [0, θ], [90, θ], [180, θ], [-90, θ], [0, -θ], [90, -θ], [180, -θ], [-90, -θ] ]; var polyhedron = [ [0, 3, 2, 1], // N [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7], [4, 5, 6, 7] // S ].map(function(face) { return face.map(function(i) { return vertices[i]; }); }); var furuti1 = function(faceProjection) { faceProjection = faceProjection || function(face) { var c = d3Geo.geoCentroid({type: "MultiPoint", coordinates: face}); return d3Geo.geoGnomonic().scale(1).translate([0, 0]).rotate([-c[0], -c[1]]); }; var faces = polyhedron.map(function(face) { var polygon = face.slice(); polygon.push(polygon[0]); return { face: face, contains: function(lambda, phi) { return d3Geo.geoContains({ type: "Polygon", coordinates: [ polygon ] }, [lambda * degrees, phi * degrees]); }, project: faceProjection(face) }; }); // Connect each face to a parent face. [-1, 4, 5, 2, 0, 1].forEach(function (d, i) { var node = faces[d]; node && (node.children || (node.children = [])).push(faces[i]); }); // Polyhedral projection var proj = polyhedral(faces[0], function(lambda, phi) { for (var i = 0; i < faces.length; i++) { if (faces[i].contains(lambda, phi)) return faces[i]; } }, π/2 // rotation of the root face in the projected (pixel) space ) .rotate(rotate) .clipAngle(1) // no antimeridian clipping on the Sphere .fitExtent([[20,20], [width - 20, height - 20]], {type:"Sphere"}); proj.faces = faces; return proj; } d3.geoPolyhedralFuruti1 = furuti1; // map in a cube. var projection = d3.geoPolyhedralFuruti1(); var path = d3.geoPath().projection(projection); var graticule = d3.geoGraticule(); var svg = d3.select("#map").append("svg") .attr("width", width) .attr("height", height); svg.append("path") .datum({type: "Sphere"}) .attr("class", "background") .attr("d", path); svg.append("path") .datum(graticule) .attr("class", "graticule") .attr("d", path); svg.append("path") .datum({type: "Sphere"}) .attr("class", "outline") .attr("d", path); d3.json("Mystara_2017.topojson", function(error, mystara) { if (error) return console.error(error); svg.insert("path", ".graticule") .datum(topojson.feature(mystara, mystara.objects.Mystara_2017_unprojected)) .attr("class", "land") .attr("d", path); }); d3.select(self.frameElement).style("height", height + "px");