You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
1.7 KiB
73 lines
1.7 KiB
import {geoProjectionMutator as projectionMutator} from "d3-geo";
|
|
import {abs, asin, pi, pow, sign, sin} from "./math.js";
|
|
import {integrate} from "./integrate.js";
|
|
|
|
export function hyperellipticalRaw(alpha, k, gamma) {
|
|
|
|
function elliptic (f) {
|
|
return alpha + (1 - alpha) * pow(1 - pow(f, k), 1 / k);
|
|
}
|
|
|
|
function z(f) {
|
|
return integrate(elliptic, 0, f, 1e-4);
|
|
}
|
|
|
|
var G = 1 / z(1),
|
|
n = 1000,
|
|
m = (1 + 1e-8) * G,
|
|
approx = [];
|
|
for (var i = 0; i <= n; i++)
|
|
approx.push(z(i / n) * m);
|
|
|
|
function Y(sinphi) {
|
|
var rmin = 0, rmax = n, r = n >> 1;
|
|
do {
|
|
if (approx[r] > sinphi) rmax = r; else rmin = r;
|
|
r = (rmin + rmax) >> 1;
|
|
} while (r > rmin);
|
|
var u = approx[r + 1] - approx[r];
|
|
if (u) u = (sinphi - approx[r + 1]) / u;
|
|
return (r + 1 + u) / n;
|
|
}
|
|
|
|
var ratio = 2 * Y(1) / pi * G / gamma;
|
|
|
|
var forward = function(lambda, phi) {
|
|
var y = Y(abs(sin(phi))),
|
|
x = elliptic(y) * lambda;
|
|
y /= ratio;
|
|
return [ x, (phi >= 0) ? y : -y ];
|
|
};
|
|
|
|
forward.invert = function(x, y) {
|
|
var phi;
|
|
y *= ratio;
|
|
if (abs(y) < 1) phi = sign(y) * asin(z(abs(y)) * G);
|
|
return [ x / elliptic(abs(y)), phi ];
|
|
};
|
|
|
|
return forward;
|
|
}
|
|
|
|
export default function() {
|
|
var alpha = 0,
|
|
k = 2.5,
|
|
gamma = 1.183136, // affine = sqrt(2 * gamma / pi) = 0.8679
|
|
m = projectionMutator(hyperellipticalRaw),
|
|
p = m(alpha, k, gamma);
|
|
|
|
p.alpha = function(_) {
|
|
return arguments.length ? m(alpha = +_, k, gamma) : alpha;
|
|
};
|
|
|
|
p.k = function(_) {
|
|
return arguments.length ? m(alpha, k = +_, gamma) : k;
|
|
};
|
|
|
|
p.gamma = function(_) {
|
|
return arguments.length ? m(alpha, k, gamma = +_) : gamma;
|
|
};
|
|
|
|
return p
|
|
.scale(152.63);
|
|
}
|
|
|