This repository has been archived by the owner on Nov 7, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 685
/
berghaus.js
76 lines (66 loc) · 2.22 KB
/
berghaus.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import "projection";
var berghausAzimuthalEquidistant = d3.geo.azimuthalEquidistant.raw;
function berghaus(n) {
var k = 2 * π / n;
function forward(λ, φ) {
var p = berghausAzimuthalEquidistant(λ, φ);
if (Math.abs(λ) > π / 2) { // back hemisphere
var θ = Math.atan2(p[1], p[0]),
r = Math.sqrt(p[0] * p[0] + p[1] * p[1]),
θ0 = k * Math.round((θ - π / 2) / k) + π / 2,
α = Math.atan2(Math.sin(θ -= θ0), 2 - Math.cos(θ)); // angle relative to lobe end
θ = θ0 + asin(π / r * Math.sin(α)) - α;
p[0] = r * Math.cos(θ);
p[1] = r * Math.sin(θ);
}
return p;
}
forward.invert = function(x, y) {
var r = Math.sqrt(x * x + y * y);
if (r > π / 2) {
var θ = Math.atan2(y, x),
θ0 = k * Math.round((θ - π / 2) / k) + π / 2,
s = θ > θ0 ? -1 : 1,
A = r * Math.cos(θ0 - θ)
cotα = 1 / Math.tan(s * Math.acos((A - π) / Math.sqrt(π * (π - 2 * A) + r * r)));
θ = θ0 + 2 * Math.atan((cotα + s * Math.sqrt(cotα * cotα - 3)) / 3);
x = r * Math.cos(θ), y = r * Math.sin(θ);
}
return berghausAzimuthalEquidistant.invert(x, y);
};
return forward;
}
function berghausProjection() {
var n = 5,
m = projectionMutator(berghaus),
p = m(n),
stream_ = p.stream;
p.lobes = function(_) {
if (!arguments.length) return n;
return m(n = +_);
};
p.stream = function(stream) {
var rotate = p.rotate(),
rotateStream = stream_(stream),
sphereStream = (p.rotate([0, 0]), stream_(stream));
p.rotate(rotate);
rotateStream.sphere = function() {
sphereStream.polygonStart(), sphereStream.lineStart();
var ε = 1e-2;
for (var i = 0, δ = 360 / n, φ = 90 - 180 / n; i < n; ++i, φ -= δ) {
sphereStream.point(180, 0);
if (φ < -90) {
sphereStream.point(-90, 180 - φ - ε);
sphereStream.point(-90, 180 - φ + ε);
} else {
sphereStream.point(90, φ + ε);
sphereStream.point(90, φ - ε);
}
}
sphereStream.lineEnd(), sphereStream.polygonEnd();
};
return rotateStream;
};
return p;
}
(d3.geo.berghaus = berghausProjection).raw = berghaus;