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.
83 lines
2.8 KiB
83 lines
2.8 KiB
import {geoProjectionMutator as projectionMutator} from "d3-geo";
|
|
import {abs, atan2, cos, degrees, epsilon, radians, sin, tan} from "./math.js";
|
|
|
|
export function armadilloRaw(phi0) {
|
|
var sinPhi0 = sin(phi0),
|
|
cosPhi0 = cos(phi0),
|
|
sPhi0 = phi0 >= 0 ? 1 : -1,
|
|
tanPhi0 = tan(sPhi0 * phi0),
|
|
k = (1 + sinPhi0 - cosPhi0) / 2;
|
|
|
|
function forward(lambda, phi) {
|
|
var cosPhi = cos(phi),
|
|
cosLambda = cos(lambda /= 2);
|
|
return [
|
|
(1 + cosPhi) * sin(lambda),
|
|
(sPhi0 * phi > -atan2(cosLambda, tanPhi0) - 1e-3 ? 0 : -sPhi0 * 10) + k + sin(phi) * cosPhi0 - (1 + cosPhi) * sinPhi0 * cosLambda // TODO D3 core should allow null or [NaN, NaN] to be returned.
|
|
];
|
|
}
|
|
|
|
forward.invert = function(x, y) {
|
|
var lambda = 0,
|
|
phi = 0,
|
|
i = 50;
|
|
do {
|
|
var cosLambda = cos(lambda),
|
|
sinLambda = sin(lambda),
|
|
cosPhi = cos(phi),
|
|
sinPhi = sin(phi),
|
|
A = 1 + cosPhi,
|
|
fx = A * sinLambda - x,
|
|
fy = k + sinPhi * cosPhi0 - A * sinPhi0 * cosLambda - y,
|
|
dxdLambda = A * cosLambda / 2,
|
|
dxdPhi = -sinLambda * sinPhi,
|
|
dydLambda = sinPhi0 * A * sinLambda / 2,
|
|
dydPhi = cosPhi0 * cosPhi + sinPhi0 * cosLambda * sinPhi,
|
|
denominator = dxdPhi * dydLambda - dydPhi * dxdLambda,
|
|
dLambda = (fy * dxdPhi - fx * dydPhi) / denominator / 2,
|
|
dPhi = (fx * dydLambda - fy * dxdLambda) / denominator;
|
|
if (abs(dPhi) > 2) dPhi /= 2;
|
|
lambda -= dLambda, phi -= dPhi;
|
|
} while ((abs(dLambda) > epsilon || abs(dPhi) > epsilon) && --i > 0);
|
|
return sPhi0 * phi > -atan2(cos(lambda), tanPhi0) - 1e-3 ? [lambda * 2, phi] : null;
|
|
};
|
|
|
|
return forward;
|
|
}
|
|
|
|
export default function() {
|
|
var phi0 = 20 * radians,
|
|
sPhi0 = phi0 >= 0 ? 1 : -1,
|
|
tanPhi0 = tan(sPhi0 * phi0),
|
|
m = projectionMutator(armadilloRaw),
|
|
p = m(phi0),
|
|
stream_ = p.stream;
|
|
|
|
p.parallel = function(_) {
|
|
if (!arguments.length) return phi0 * degrees;
|
|
tanPhi0 = tan((sPhi0 = (phi0 = _ * radians) >= 0 ? 1 : -1) * phi0);
|
|
return m(phi0);
|
|
};
|
|
|
|
p.stream = function(stream) {
|
|
var rotate = p.rotate(),
|
|
rotateStream = stream_(stream),
|
|
sphereStream = (p.rotate([0, 0]), stream_(stream)),
|
|
precision = p.precision();
|
|
p.rotate(rotate);
|
|
rotateStream.sphere = function() {
|
|
sphereStream.polygonStart(), sphereStream.lineStart();
|
|
for (var lambda = sPhi0 * -180; sPhi0 * lambda < 180; lambda += sPhi0 * 90)
|
|
sphereStream.point(lambda, sPhi0 * 90);
|
|
if (phi0) while (sPhi0 * (lambda -= 3 * sPhi0 * precision) >= -180) {
|
|
sphereStream.point(lambda, sPhi0 * -atan2(cos(lambda * radians / 2), tanPhi0) * degrees);
|
|
}
|
|
sphereStream.lineEnd(), sphereStream.polygonEnd();
|
|
};
|
|
return rotateStream;
|
|
};
|
|
|
|
return p
|
|
.scale(218.695)
|
|
.center([0, 28.0974]);
|
|
}
|
|
|