Published
Edited
Jul 7, 2021
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
glproj = `
if (x * x + 4. * y * y < pi * pi + 1e-12) {
float x1 = x, y1 = y, sinx, sinx_2, cosx_2, siny, cosy, sin_2y, sin2y, cos2y, sin2x_2, c, e, f, fx, fy, dxdx, dxdy, dydx, dydy, z, dx, dy;

for (int i = 0; i < 25; i++) {
sinx = sin(x1),
sinx_2 = sin(x1 / 2.),
cosx_2 = cos(x1 / 2.),
siny = sin(y1),
cosy = cos(y1),
sin_2y = sin(2. * y1),
sin2y = siny * siny,
cos2y = cosy * cosy,
sin2x_2 = sinx_2 * sinx_2,
c = 1. - cos2y * cosx_2 * cosx_2;
if (c == 0.0) c = 1e-12;
e = acos(cosy * cosx_2) * sqrt(f = 1. / c),
fx = 2. * e * cosy * sinx_2 - x,
fy = e * siny - y,
dxdx = f * (cos2y * sin2x_2 + e * cosy * cosx_2 * sin2y),
dxdy = f * (0.5 * sinx * sin_2y - e * 2. * siny * sinx_2),
dydx = f * 0.25 * (sin_2y * sinx_2 - e * siny * cos2y * sinx),
dydy = f * (sin2y * cosx_2 + e * sin2x_2 * cosy),
z = dxdy * dydx - dydy * dxdx;
if (z == 0.0) z = 1e-12;
dx = (fy * dxdy - fx * dydy) / z,
dy = (fx * dydx - fy * dxdx) / z;
x1 -= dx, y1 -= dy;
}
lambda = x1;
phi = y1;
} else {
transparent = true;
}
`
Insert cell
projection = d3.geoAitoff().fitSize([width, height], { type: "Sphere" })
Insert cell
function stabWernerRaw(ratio, max) {
/*
* simplified Bonne, with phi0 = halfPi ;
* https://github.com/d3/d3-geo-projection/blob/master/src/bonne.js
*/
function r(lambda, phi) {
const rho = halfPi - phi,
e = rho ? (lambda * cos(phi)) / rho : rho;
return [rho * sin(e), -rho * cos(e)];
}
r.invert = function(x, y) {
var rho = sqrt(x ** 2 + y ** 2),
phi = halfPi - rho;
return [(rho / cos(phi)) * atan2(x, -y), phi];
};

/* azimuthal equidistant for the pole part */
const az = d3
.geoAzimuthalEquidistant()
.rotate([0, -90])
.translate([0, 0])
.scale(1);

/* mix */
function forward(lambda, phi) {
if (phi < max * radians) {
lambda *= ratio;
return r(lambda, phi);
} else {
const p = az([lambda * degrees, phi * degrees]);
return [p[0], -p[1]];
}
}

function invert(x, y) {
let i = az.invert([x, -y]);
if (i[1] < max) {
i = r.invert(x, y);
i[0] /= ratio;
} else {
i[0] *= radians;
i[1] *= radians;
}
return [i[0], i[1]];
}

forward.invert = invert;

return forward;
}
Insert cell
// Ancient Earth Images by Christopher Scotese. https://www.earthbyte.org/paleomap-paleoatlas-for-gplates/
image = d3
.image(
`https://raw.githubusercontent.com/typpo/ancient-earth/master/images/scrape/${period}.jpg`,
{
crossOrigin: "anonymous"
}
)
.then(d => Object.assign(d, { style: "max-height:100px" }))
Insert cell
height = width >> 1
Insert cell
import { reglCanvas, createDrawCommand, regl } with {
width,
height,
projection,
glproj,
image
} from "@fil/phytoplankton"
Insert cell
d3 = require("d3@7", "d3-geo-projection@3", "d3-geo-polygon@1")
Insert cell
import { checkbox, radio, select } from "@jashkenas/inputs"
Insert cell
import { atan2, cos, degrees, halfPi, radians, sin, sqrt } from "@fil/math"
Insert cell
import { drag } from "@d3/versor-dragging"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more