forked from d3/d3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclip-antimeridian.js
More file actions
95 lines (90 loc) · 2.81 KB
/
Copy pathclip-antimeridian.js
File metadata and controls
95 lines (90 loc) · 2.81 KB
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
import "../core/true";
import "../math/abs";
import "../math/trigonometry";
import "clip";
var d3_geo_clipAntimeridian = d3_geo_clip(
d3_true,
d3_geo_clipAntimeridianLine,
d3_geo_clipAntimeridianInterpolate,
[-π, -π / 2]);
// Takes a line and cuts into visible segments. Return values:
// 0: there were intersections or the line was empty.
// 1: no intersections.
// 2: there were intersections, and the first and last segments should be
// rejoined.
function d3_geo_clipAntimeridianLine(listener) {
var λ0 = NaN,
φ0 = NaN,
sλ0 = NaN,
clean; // no intersections
return {
lineStart: function() {
listener.lineStart();
clean = 1;
},
point: function(λ1, φ1) {
var sλ1 = λ1 > 0 ? π : -π,
dλ = abs(λ1 - λ0);
if (abs(dλ - π) < ε) { // line crosses a pole
listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
listener.point(sλ0, φ0);
listener.lineEnd();
listener.lineStart();
listener.point(sλ1, φ0);
listener.point(λ1, φ0);
clean = 0;
} else if (sλ0 !== sλ1 && dλ >= π) { // line crosses antimeridian
// handle degeneracies
if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
listener.point(sλ0, φ0);
listener.lineEnd();
listener.lineStart();
listener.point(sλ1, φ0);
clean = 0;
}
listener.point(λ0 = λ1, φ0 = φ1);
sλ0 = sλ1;
},
lineEnd: function() {
listener.lineEnd();
λ0 = φ0 = NaN;
},
// if there are intersections, we always rejoin the first and last segments.
clean: function() { return 2 - clean; }
};
}
function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
var cosφ0,
cosφ1,
sinλ0_λ1 = Math.sin(λ0 - λ1);
return abs(sinλ0_λ1) > ε
? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1)
- Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0))
/ (cosφ0 * cosφ1 * sinλ0_λ1))
: (φ0 + φ1) / 2;
}
function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
var φ;
if (from == null) {
φ = direction * halfπ;
listener.point(-π, φ);
listener.point( 0, φ);
listener.point( π, φ);
listener.point( π, 0);
listener.point( π, -φ);
listener.point( 0, -φ);
listener.point(-π, -φ);
listener.point(-π, 0);
listener.point(-π, φ);
} else if (abs(from[0] - to[0]) > ε) {
var s = from[0] < to[0] ? π : -π;
φ = direction * s / 2;
listener.point(-s, φ);
listener.point( 0, φ);
listener.point( s, φ);
} else {
listener.point(to[0], to[1]);
}
}