Skip to content

Instantly share code, notes, and snippets.

@Fil
Last active Mar 28, 2021
Embed
What would you like to do?
A conformal Airocean
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://unpkg.com/d3-geo-polygon@1.12.1"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
function geoConformalAirocean() {
const {acos} = Math;
const degrees = 180 / Math.PI;
const sqrt3_4 = Math.sqrt(3) / 4;
const rotate = [115, acos(1 / 3) * .5 * degrees - 90, 180]
const rawLee = d3.geoTetrahedralLee()
.rotate(rotate)
.fitExtent([[-4, -1.5 / sqrt3_4], [4, 1.5 / sqrt3_4]], {
type: "Sphere"
});
const forward = (l, p) => {
let [x, y] = rawLee([l * degrees, p * degrees]);
y = -y;
if (x < -2.1 || y < -2.73) {
x = -x - 4;
y = -y;
}
if (x < -4) {
x = -x - 8;
y = 6.93 - y; // 6.93 is a visual approximation—haven't figured out the exact value yet (please help!)
}
return [x, y];
};
forward.invert = (x, y) => {
y = -y;
const a =
rawLee.invert([x, y]) ||
rawLee.invert([-x - 4, -y]) ||
rawLee.invert([-x - 8, 6.93 - y]) ||
rawLee.invert([-(-x - 8) - 4, 6.93 + y]);
if (a) return [a[0] * radians, a[1] * radians];
};
const clipPolygon = {
type: "Polygon", coordinates: [[
[-20, 0],
[-27, 14],
[-27, 18],
[-20, 37],
[-30, 37],
[-35, -40],
[-30, -70],
[40, -50],
[70, -40],
[120, -60],
[150, -60],
[180, -60],
[-150, -50],
[-110, -40],
[-110, -30],
[-170, 10],
[160, 40],
[150, 40],
[150, 30],
[-170, 0],
[-150, -10],
[-140, -30],
[-170, -50],
[120, -50],
[90, -30],
[60, -25],
[30, -38],
[10, -38],
[-20, 0]
].map(d => [d[0] - .01, d[1] - .01])]
};
return d3.geoProjection(forward)
.preclip(d3.geoClipPolygon(clipPolygon))
.angle(57 - 180)
.fitExtent([[0,0], [960, 500]], {type: "Sphere"});
}
const projection = geoConformalAirocean();
const path = d3.geoPath(projection);
const svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
const land = svg.append("path");
d3.json("https://unpkg.com/visionscarto-world-atlas@0.0.6/world/110m_land.geojson")
.then(geo => land.datum(geo).attr("d", path));
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment