Published
Edited
May 5, 2021
1 star
Insert cell
Insert cell
map(projection.rotate([-11.023, 0]))
Insert cell
cupola = {
// the projection is based on a center at <11.023°,0°>
// hence the 0.5253 * v - 0.1010612291 to compensate…
// todo: simplify; see https://github.com/mbloch/mapshaper-proj/blob/master/src/projections/cupola.js
const deltaV = (11.023 / 180) * Math.PI;
const cupola = (v, u) => {
v += deltaV;
return [
1.6188566 *
sqrt(
2 /
(1 +
0.530815 * sin(asin(0.7264 * sin(u) + 0.2587011)) +
0.8474875 *
cos(asin(0.7264 * sin(u) + 0.2587011)) *
cos(0.5253 * v - 0.1010612291))
) *
cos(asin(0.7264 * sin(u) + 0.2587011)) *
sin(0.5253 * v - 0.1010612291) *
0.9701,
(1.6188566 *
sqrt(
2 /
(1 +
0.530815 * sin(asin(0.7264 * sin(u) + 0.2587011)) +
0.8474875 *
cos(asin(0.7264 * sin(u) + 0.2587011)) *
cos(0.5253 * v - 0.1010612291))
) *
(0.8474875 * sin(asin(0.7264 * sin(u) + 0.2587011)) -
0.530815 *
cos(asin(0.7264 * sin(u) + 0.2587011)) *
cos(0.5253 * v - 0.1010612291))) /
0.9701
];
};

// todo: convergence on the whole domain
cupola.invert = solve2d(cupola);

return cupola;
}
Insert cell
projection = d3.geoProjection(cupola)
Insert cell
d3 = require("d3@6")
Insert cell
import { map } from "@fil/base-map"
Insert cell
import { abs, asin, cos, epsilon2, sin, sqrt } from "@fil/math"
Insert cell
// Approximate Newton-Raphson in 2D
// Solve f(a,b) = [x,y]
function solve2d(f, MAX_ITERATIONS, eps) {
if (MAX_ITERATIONS === undefined) MAX_ITERATIONS = 40;
if (eps === undefined) eps = epsilon2;
return function(x, y, a, b) {
var err2, da, db;
a = a === undefined ? 0 : +a;
b = b === undefined ? 0 : +b;
for (var i = 0; i < MAX_ITERATIONS; i++) {
var p = f(a, b),
// diffs
tx = p[0] - x,
ty = p[1] - y;
if (abs(tx) < eps && abs(ty) < eps) break; // we're there!

// backtrack if we overshot
var h = tx * tx + ty * ty;
if (h > err2) {
a -= da /= 2;
b -= db /= 2;
continue;
}
err2 = h;

// partial derivatives
var ea = (a > 0 ? -1 : 1) * eps,
eb = (b > 0 ? -1 : 1) * eps,
pa = f(a + ea, b),
pb = f(a, b + eb),
dxa = (pa[0] - p[0]) / ea,
dya = (pa[1] - p[1]) / ea,
dxb = (pb[0] - p[0]) / eb,
dyb = (pb[1] - p[1]) / eb,
// determinant
D = dyb * dxa - dya * dxb,
// newton step — or half-step for small D
l = (abs(D) < 0.5 ? 0.5 : 1) / D;
da = (ty * dxb - tx * dyb) * l;
db = (tx * dya - ty * dxa) * l;
a += da;
b += db;
if (abs(da) < eps && abs(db) < eps) break; // we're crawling
}
return [a, b];
};
}
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