-
Notifications
You must be signed in to change notification settings - Fork 199
/
wagner.js
98 lines (86 loc) · 3.02 KB
/
wagner.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import {geoProjectionMutator as projectionMutator} from "d3-geo";
import {acos, asin, atan2, cos, degrees, epsilon, halfPi, max, min, pi, radians, sin, sqrt, tan} from "./math.js";
function wagnerFormula(cx, cy, m1, m2, n) {
function forward(lambda, phi) {
var s = m1 * sin(m2 * phi),
c0 = sqrt(1 - s * s),
c1 = sqrt(2 / (1 + c0 * cos(lambda *= n)));
return [
cx * c0 * c1 * sin(lambda),
cy * s * c1
];
}
forward.invert = function(x, y) {
var t1 = x / cx,
t2 = y / cy,
p = sqrt(t1 * t1 + t2 * t2),
c = 2 * asin(p / 2);
return [
atan2(x * tan(c), cx * p) / n,
p && asin(y * sin(c) / (cy * m1 * p)) / m2
];
};
return forward;
}
export function wagnerRaw(poleline, parallels, inflation, ratio) {
// 60 is always used as reference parallel
var phi1 = pi / 3;
// sanitizing the input values
// poleline and parallels may approximate but never equal 0
poleline = max(poleline, epsilon);
parallels = max(parallels, epsilon);
// poleline must be <= 90; parallels may approximate but never equal 180
poleline = min(poleline, halfPi);
parallels = min(parallels, pi - epsilon);
// 0 <= inflation <= 99.999
inflation = max(inflation, 0);
inflation = min(inflation, 100 - epsilon);
// ratio > 0.
// sensible values, i.e. something that renders a map which still can be
// recognized as world map, are e.g. 20 <= ratio <= 1000.
ratio = max(ratio, epsilon);
// convert values from boehm notation
// areal inflation e.g. from 0 to 1 or 20 to 1.2:
var vinflation = inflation/100 + 1;
// axial ratio e.g. from 200 to 2:
var vratio = ratio / 100;
// the other ones are a bit more complicated...
var m2 = acos(vinflation * cos(phi1)) / phi1,
m1 = sin(poleline) / sin(m2 * halfPi),
n = parallels / pi,
k = sqrt(vratio * sin(poleline / 2) / sin(parallels / 2)),
cx = k / sqrt(n * m1 * m2),
cy = 1 / (k * sqrt(n * m1 * m2));
return wagnerFormula(cx, cy, m1, m2, n);
}
export default function wagner() {
// default values generate wagner8
var poleline = 65 * radians,
parallels = 60 * radians,
inflation = 20,
ratio = 200,
mutate = projectionMutator(wagnerRaw),
projection = mutate(poleline, parallels, inflation, ratio);
projection.poleline = function(_) {
return arguments.length ? mutate(poleline = +_ * radians, parallels, inflation, ratio) : poleline * degrees;
};
projection.parallels = function(_) {
return arguments.length ? mutate(poleline, parallels = +_ * radians, inflation, ratio) : parallels * degrees;
};
projection.inflation = function(_) {
return arguments.length ? mutate(poleline, parallels, inflation = +_, ratio) : inflation;
};
projection.ratio = function(_) {
return arguments.length ? mutate(poleline, parallels, inflation, ratio = +_) : ratio;
};
return projection
.scale(163.775);
}
export function wagner7() {
return wagner()
.poleline(65)
.parallels(60)
.inflation(0)
.ratio(200)
.scale(172.633);
}