Skip to content

Commit da061c1

Browse files
committed
curve: "geodesic" for Plot.line
closes #1146
1 parent fc75219 commit da061c1

File tree

7 files changed

+708
-3
lines changed

7 files changed

+708
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2826,6 +2826,7 @@ The following named curve methods are supported:
28262826
* *step* - a piecewise constant function where *y* changes at the midpoint of *x*
28272827
* *step-after* - a piecewise constant function where *y* changes after *x*
28282828
* *step-before* - a piecewise constant function where *x* changes after *y*
2829+
* *geodesic* - a curve for spherical data along the geodesic (available only for the line mark, associated with a spherical projection)
28292830
28302831
If *curve* is a function, it will be invoked with a given *context* in the same fashion as a [D3 curve factory](https://github.com/d3/d3-shape/blob/main/README.md#custom-curves).
28312832

src/marks/line.js

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {line as shapeLine} from "d3";
1+
import {geoPath, line as shapeLine} from "d3";
22
import {create} from "../context.js";
33
import {Curve} from "../curve.js";
44
import {indexOf, identity, maybeTuple, maybeZ} from "../options.js";
@@ -72,9 +72,11 @@ export class Line extends Mark {
7272

7373
/** @jsdoc line */
7474
export function line(data, options = {}) {
75-
let {x, y, ...remainingOptions} = options;
75+
let {x, y, curve, ...remainingOptions} = options;
7676
[x, y] = maybeTuple(x, y);
77-
return new Line(data, {...remainingOptions, x, y});
77+
return curve === "geodesic"
78+
? new LineGeodesic(data, {...remainingOptions, x, y})
79+
: new Line(data, {...remainingOptions, curve, x, y});
7880
}
7981

8082
/** @jsdoc lineX */
@@ -88,3 +90,50 @@ export function lineY(data, options = {}) {
8890
const {x = indexOf, y = identity, ...remainingOptions} = options;
8991
return new Line(data, maybeDenseIntervalX({...remainingOptions, x, y}));
9092
}
93+
94+
export class LineGeodesic extends Mark {
95+
constructor(data, options = {}) {
96+
const {x, y, z} = options;
97+
super(
98+
data,
99+
{
100+
x: {value: x},
101+
y: {value: y},
102+
z: {value: maybeZ(options), optional: true}
103+
},
104+
options,
105+
defaults
106+
);
107+
this.z = z;
108+
markers(this, options);
109+
}
110+
filter(index) {
111+
return index;
112+
}
113+
render(index, scales, channels, dimensions, context) {
114+
const {x: X, y: Y} = channels;
115+
const {projection} = context;
116+
if (projection === undefined) throw new Error("A projection is needed for geodesic curves");
117+
const path = geoPath(projection);
118+
return create("svg:g", context)
119+
.call(applyIndirectStyles, this, scales, dimensions, context)
120+
.call(applyTransform, this, scales)
121+
.call((g) =>
122+
g
123+
.selectAll()
124+
.data(groupIndex(index, [X, Y], this, channels))
125+
.enter()
126+
.append("path")
127+
.call(applyDirectStyles, this)
128+
.call(applyGroupedChannelStyles, this, channels)
129+
.call(applyGroupedMarkers, this, channels)
130+
.attr("d", (I) =>
131+
path({
132+
type: "LineString",
133+
coordinates: Array.from(I, (i) => [+X[i], +Y[i]]).filter(([x, y]) => !isNaN(x + y))
134+
})
135+
)
136+
)
137+
.node();
138+
}
139+
}

test/data/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ https://www.flother.is/2017/olympic-games-data/
1919
## barley.csv
2020
http://search.r-project.org/R/library/lattice/html/barley.html
2121

22+
## beagle.csv
23+
https://observablehq.com/@bmschmidt/data-driven-projections-darwins-world
24+
2225
## bls-metro-unemployment.csv
2326
Bureau of Labor Statistics
2427
https://www.bls.gov/

test/data/beagle.csv

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
-4.17,50.37
2+
-7.01,47.88
3+
-8.75,46.24
4+
-9.69,45.34
5+
-10.75,44.27
6+
-11.6,43.42
7+
-15.05,38.4
8+
-15.53,37.48
9+
-16.54,34.36
10+
-21.27,20.48
11+
-23.4,15.05
12+
-23.5,14.9
13+
-24.29,14.22
14+
-25.08,13.55
15+
-25.32,13.28
16+
-26.57,11.87
17+
-38.42,-13.48
18+
-36.32,-17.2
19+
-38.67,-17.96
20+
-43.13,-22.9
21+
-38.75,-16.92
22+
-38.52,-20.17
23+
-40.52,-23.07
24+
-42.68,-23.08
25+
-43.13,-22.9
26+
-43.13,-22.9
27+
-45.73,-27.13
28+
-48.09,-30.17
29+
-50.3,-33.35
30+
-53.32,-34.98
31+
-58.36,-34.59
32+
-56.6,-36.38
33+
-56.64,-36.51
34+
-57.96,-38.6
35+
-58.79,-38.77
36+
-61.06,-39.23
37+
-60.91,-39.27
38+
-60.81,-39.29
39+
-60.67,-39.32
40+
-60.6,-39.34
41+
-60.43,-39.38
42+
-60.39,-39.39
43+
-60.29,-39.41
44+
-60.28,-39.41
45+
-60.21,-39.43
46+
-60.07,-39.46
47+
-59.94,-39.5
48+
-59.87,-39.51
49+
-59.52,-39.53
50+
-58.92,-39.41
51+
-57.17,-38.85
52+
-57.75,-34.68
53+
-56.58,-35.13
54+
-56.18,-34.87
55+
-58.01,-39.19
56+
-58.17,-39.33
57+
-59.72,-40.05
58+
-62.1,-40.8
59+
-61.49,-42.15
60+
-61.37,-43.57
61+
-63.37,-46.28
62+
-68.16,-56.48
63+
-69.31,-57.01
64+
-69.4,-56.26
65+
-69.38,-56.25
66+
-71.15,-56.73
67+
-69.4,-56.12
68+
-69.21,-56.29
69+
-68.74,-55.98
70+
-63.33,-53.3
71+
-62.88,-53.3
72+
-59.36,-50.12
73+
-59.92,-49.07
74+
-61.6,-47.2
75+
-62.33,-43.02
76+
-62.62,-41.13
77+
-62.66,-41.15
78+
-60.17,-40.48
79+
-55.54,-37.01
80+
-55.5,-37.06
81+
-54.95,-34.9
82+
-55.78,-34.9
83+
-54.87,-34.9
84+
-53.28,-35.23
85+
-58.07,-38.15
86+
-59.29,-40.13
87+
-59.14,-38.31
88+
-58.88,-38.09
89+
-61.97,-41.67
90+
-56.2,-34.9
91+
-54.95,-34.9
92+
-56.24,-35.18
93+
-56.97,-37.77
94+
-55.81,-34.9
95+
-56.45,-37.18
96+
-57.02,-37.82
97+
-58.4,-41.25
98+
-58.82,-42.53
99+
-60.19,-43.53
100+
-60.77,-44.2
101+
-64.43,-46.79
102+
-65.48,-47.63
103+
-66.37,-48.77
104+
-67.4,-49
105+
-66.01,-49.31
106+
-70.55,-53.11
107+
-70.71,-53.34
108+
-70.79,-53.43
109+
-70.91,-53.63
110+
-70.53,-53.59
111+
-70.51,-53.58
112+
-70.11,-53.54
113+
-68.93,-53.41
114+
-68.36,-53.34
115+
-68.23,-53.33
116+
-69.78,-52.81
117+
-70.11,-54.02
118+
-72.78,-52.38
119+
-72.6,-52.51
120+
-67.01,-55.24
121+
-66.64,-55.15
122+
-65.81,-54.83
123+
-60.8,-49.44
124+
-64.15,-50.17
125+
-65.08,-49.77
126+
-66.63,-50.95
127+
-66.76,-52.47
128+
-66.71,-52.28
129+
-66.71,-52.46
130+
-70.69,-53.3
131+
-70.93,-53.63
132+
-72.06,-54.13
133+
-72.91,-54.5
134+
-74.99,-54.78
135+
-76.23,-44.45
136+
-74.14,-43.29
137+
-73.87,-43.18
138+
-75.08,-42.69
139+
-74.96,-42.23
140+
-75.01,-42.19
141+
-75.44,-41.83
142+
-73.75,-35.95
143+
-73.18,-34.6
144+
-72.89,-34.17
145+
-71.95,-33.27
146+
-71.85,-33.19
147+
-78.03,-39.85
148+
-76.35,-41.48
149+
-76.28,-41.53
150+
-77.34,-43.72
151+
-76.75,-44.3
152+
-76.3,-44.44
153+
-74.54,-44.44
154+
-73.9,-43.54
155+
-74.09,-44
156+
-74.34,-45.03
157+
-74.6,-45.3
158+
-75.05,-45.9
159+
-75.56,-46.58
160+
-74.33,-44.57
161+
-74.05,-43.81
162+
-73.5,-39.83
163+
-73.53,-39.72
164+
-73.6,-38.95
165+
-73.77,-38.95
166+
-73.91,-38.3
167+
-73.08,-36.83
168+
-72.86,-35.55
169+
-72.82,-35.28
170+
-72.43,-33.75
171+
-72.27,-33.61
172+
-79.05,-34.18
173+
-81.16,-35.03
174+
-76.25,-35.63
175+
-73.04,-36.64
176+
-71.6,-33
177+
-71.59,-32.69
178+
-71.54,-32.39
179+
-71.28,-31.58
180+
-71.68,-30.22
181+
-71.43,-29.97
182+
-74.41,-31.44
183+
-71.65,-27.68
184+
-71.48,-25.53
185+
-70.32,-20.29
186+
-72.32,-18.78
187+
-72.78,-18.47
188+
-83.32,-6.87
189+
-89.95,-0.84
190+
-91.2,-1.09
191+
-91.33,-0.55
192+
-91.24,-0.36
193+
-90.66,0.52
194+
-90.67,0.26
195+
-91.29,-0.57
196+
-90.85,0.16
197+
-90.84,0.22
198+
-92.41,1.38
199+
-99.48,-0.92
200+
-104.57,-4.9
201+
-105.44,-5.48
202+
-107,-6.53
203+
-126.11,-11.71
204+
-142.07,-15.39
205+
-146.09,-16.09
206+
-147.83,-16.79
207+
-148.52,-17.08
208+
-148.67,-17.15
209+
-149.26,-17.4
210+
-152.63,-17.33
211+
-153.93,-17.58
212+
-155,-17.9
213+
-160.64,-19.3
214+
-165.21,-21.14
215+
-167,-22.03
216+
-169.98,-23.1
217+
-172.81,-24.23
218+
-179.87,-28.13
219+
179.93,-28.36
220+
179.67,-28.66
221+
174.28,-35.28
222+
174,-35.98
223+
164.88,-34.33
224+
163.97,-34.35
225+
159.9,-35.1
226+
150.44,-39.11
227+
149.93,-42.8
228+
148.24,-42.86
229+
147.96,-42.87
230+
145.23,-44.12
231+
133.38,-41.66
232+
132.35,-41.43
233+
129.02,-40.57
234+
125.48,-39.63
235+
123.3,-38.02
236+
123.2,-37.92
237+
122.76,-37.58
238+
117.29,-35.03
239+
113.89,-34.87
240+
112.97,-32.72
241+
109.52,-28.13
242+
105.73,-22.96
243+
104.26,-20.76
244+
97.54,-12.42
245+
97.38,-12.34
246+
97.36,-12.33
247+
97.07,-12.17
248+
44.99,-26.58
249+
42.67,-27.52
250+
42.55,-27.52
251+
42.13,-27.51
252+
37.87,-27.83
253+
36.97,-27.97
254+
22.76,-34.79
255+
21.92,-35.46
256+
21.05,-35.2
257+
20.37,-35.08
258+
19.97,-34.87
259+
20.03,-35.18
260+
19.85,-35.19
261+
17.13,-34.95
262+
17.06,-34.95
263+
16.92,-34.95
264+
16.91,-31.68
265+
15.48,-30.48
266+
5.22,-23.07
267+
3.27,-21
268+
-0.53,-18.87
269+
-3.72,-17.88
270+
-6.49,-15.29
271+
-8.21,-13.94
272+
-22.72,-11.28
273+
-23.87,-11.44
274+
-38.51,-12.98
275+
-38.25,-13.03
276+
-36.28,-11.5
277+
-35.31,-9.68
278+
-35.1,-7.97
279+
-34.86,-8.06
280+
-34.83,-7.96
281+
-34.42,-6.67
282+
-29.5,2.3
283+
-24.3,9.95
284+
-23.42,12.86
285+
-23.27,13.9
286+
-25.35,14.4
287+
-30.61,19.05
288+
-32.42,23.12
289+
-32.6,23.33
290+
-34.57,25.68
291+
-35.78,27.87
292+
-34.5,32.68
293+
-32.37,35.25
294+
-28.86,37.25
295+
-27.55,38.18
296+
-27.09,38.76
297+
-26.14,38.07
298+
-24.5,39.33
299+
-23.7,39.92
300+
-13.93,45.63
301+
-8.97,48.25
302+
-5.05,50.14
303+
-4.17,50.37

0 commit comments

Comments
 (0)