Skip to content

Commit 22e478c

Browse files
committed
density mark
1 parent 1d4da1f commit 22e478c

File tree

6 files changed

+697
-0
lines changed

6 files changed

+697
-0
lines changed

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export {BarX, BarY, barX, barY} from "./marks/bar.js";
55
export {boxX, boxY} from "./marks/box.js";
66
export {Cell, cell, cellX, cellY} from "./marks/cell.js";
77
export {delaunayLink, delaunayMesh, hull, voronoi, voronoiMesh} from "./marks/delaunay.js";
8+
export {Density, density} from "./marks/density.js";
89
export {Dot, dot, dotX, dotY, circle, hexagon} from "./marks/dot.js";
910
export {Frame, frame} from "./marks/frame.js";
1011
export {Hexgrid, hexgrid} from "./marks/hexgrid.js";

src/marks/density.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import {contourDensity, create, geoPath} from "d3";
2+
import {constant, maybeTuple} from "../options.js";
3+
import {Mark} from "../plot.js";
4+
import {applyFrameAnchor, applyIndirectStyles, applyTransform} from "../style.js";
5+
6+
const defaults = {
7+
ariaLabel: "density",
8+
fill: "none",
9+
stroke: "currentColor",
10+
strokeMiterlimit: 1
11+
};
12+
13+
export class Density extends Mark {
14+
constructor(data, options = {}) {
15+
const {x, y, bandwidth = 20, thresholds = 20} = options;
16+
super(
17+
data,
18+
[
19+
{name: "x", value: x, scale: "x", optional: true},
20+
{name: "y", value: y, scale: "y", optional: true}
21+
],
22+
options,
23+
defaults
24+
);
25+
this.bandwidth = +bandwidth;
26+
this.thresholds = +thresholds;
27+
}
28+
render(index, scales, channels, dimensions) {
29+
const {x: X, y: Y} = channels;
30+
const {bandwidth, thresholds} = this;
31+
const [cx, cy] = applyFrameAnchor(this, dimensions);
32+
const {width, height} = dimensions;
33+
return create("svg:g")
34+
.call(applyIndirectStyles, this, scales, dimensions)
35+
.call(applyTransform, this, scales)
36+
.call(g => g.selectAll("path")
37+
.data(contourDensity()
38+
.x(X ? i => X[i] : constant(cx))
39+
.y(Y ? i => Y[i] : constant(cy))
40+
.size([width, height])
41+
.bandwidth(bandwidth)
42+
.thresholds(thresholds)
43+
(index))
44+
.enter()
45+
.append("path")
46+
.attr("d", geoPath()))
47+
.node();
48+
}
49+
}
50+
51+
export function density(data, {x, y, ...options} = {}) {
52+
([x, y] = maybeTuple(x, y));
53+
return new Density(data, {...options, x, y});
54+
}

test/data/faithful.tsv

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
eruptions waiting
2+
3.600 79
3+
1.800 54
4+
3.333 74
5+
2.283 62
6+
4.533 85
7+
2.883 55
8+
4.700 88
9+
3.600 85
10+
1.950 51
11+
4.350 85
12+
1.833 54
13+
3.917 84
14+
4.200 78
15+
1.750 47
16+
4.700 83
17+
2.167 52
18+
1.750 62
19+
4.800 84
20+
1.600 52
21+
4.250 79
22+
1.800 51
23+
1.750 47
24+
3.450 78
25+
3.067 69
26+
4.533 74
27+
3.600 83
28+
1.967 55
29+
4.083 76
30+
3.850 78
31+
4.433 79
32+
4.300 73
33+
4.467 77
34+
3.367 66
35+
4.033 80
36+
3.833 74
37+
2.017 52
38+
1.867 48
39+
4.833 80
40+
1.833 59
41+
4.783 90
42+
4.350 80
43+
1.883 58
44+
4.567 84
45+
1.750 58
46+
4.533 73
47+
3.317 83
48+
3.833 64
49+
2.100 53
50+
4.633 82
51+
2.000 59
52+
4.800 75
53+
4.716 90
54+
1.833 54
55+
4.833 80
56+
1.733 54
57+
4.883 83
58+
3.717 71
59+
1.667 64
60+
4.567 77
61+
4.317 81
62+
2.233 59
63+
4.500 84
64+
1.750 48
65+
4.800 82
66+
1.817 60
67+
4.400 92
68+
4.167 78
69+
4.700 78
70+
2.067 65
71+
4.700 73
72+
4.033 82
73+
1.967 56
74+
4.500 79
75+
4.000 71
76+
1.983 62
77+
5.067 76
78+
2.017 60
79+
4.567 78
80+
3.883 76
81+
3.600 83
82+
4.133 75
83+
4.333 82
84+
4.100 70
85+
2.633 65
86+
4.067 73
87+
4.933 88
88+
3.950 76
89+
4.517 80
90+
2.167 48
91+
4.000 86
92+
2.200 60
93+
4.333 90
94+
1.867 50
95+
4.817 78
96+
1.833 63
97+
4.300 72
98+
4.667 84
99+
3.750 75
100+
1.867 51
101+
4.900 82
102+
2.483 62
103+
4.367 88
104+
2.100 49
105+
4.500 83
106+
4.050 81
107+
1.867 47
108+
4.700 84
109+
1.783 52
110+
4.850 86
111+
3.683 81
112+
4.733 75
113+
2.300 59
114+
4.900 89
115+
4.417 79
116+
1.700 59
117+
4.633 81
118+
2.317 50
119+
4.600 85
120+
1.817 59
121+
4.417 87
122+
2.617 53
123+
4.067 69
124+
4.250 77
125+
1.967 56
126+
4.600 88
127+
3.767 81
128+
1.917 45
129+
4.500 82
130+
2.267 55
131+
4.650 90
132+
1.867 45
133+
4.167 83
134+
2.800 56
135+
4.333 89
136+
1.833 46
137+
4.383 82
138+
1.883 51
139+
4.933 86
140+
2.033 53
141+
3.733 79
142+
4.233 81
143+
2.233 60
144+
4.533 82
145+
4.817 77
146+
4.333 76
147+
1.983 59
148+
4.633 80
149+
2.017 49
150+
5.100 96
151+
1.800 53
152+
5.033 77
153+
4.000 77
154+
2.400 65
155+
4.600 81
156+
3.567 71
157+
4.000 70
158+
4.500 81
159+
4.083 93
160+
1.800 53
161+
3.967 89
162+
2.200 45
163+
4.150 86
164+
2.000 58
165+
3.833 78
166+
3.500 66
167+
4.583 76
168+
2.367 63
169+
5.000 88
170+
1.933 52
171+
4.617 93
172+
1.917 49
173+
2.083 57
174+
4.583 77
175+
3.333 68
176+
4.167 81
177+
4.333 81
178+
4.500 73
179+
2.417 50
180+
4.000 85
181+
4.167 74
182+
1.883 55
183+
4.583 77
184+
4.250 83
185+
3.767 83
186+
2.033 51
187+
4.433 78
188+
4.083 84
189+
1.833 46
190+
4.417 83
191+
2.183 55
192+
4.800 81
193+
1.833 57
194+
4.800 76
195+
4.100 84
196+
3.966 77
197+
4.233 81
198+
3.500 87
199+
4.366 77
200+
2.250 51
201+
4.667 78
202+
2.100 60
203+
4.350 82
204+
4.133 91
205+
1.867 53
206+
4.600 78
207+
1.783 46
208+
4.367 77
209+
3.850 84
210+
1.933 49
211+
4.500 83
212+
2.383 71
213+
4.700 80
214+
1.867 49
215+
3.833 75
216+
3.417 64
217+
4.233 76
218+
2.400 53
219+
4.800 94
220+
2.000 55
221+
4.150 76
222+
1.867 50
223+
4.267 82
224+
1.750 54
225+
4.483 75
226+
4.000 78
227+
4.117 79
228+
4.083 78
229+
4.267 78
230+
3.917 70
231+
4.550 79
232+
4.083 70
233+
2.417 54
234+
4.183 86
235+
2.217 50
236+
4.450 90
237+
1.883 54
238+
1.850 54
239+
4.283 77
240+
3.950 79
241+
2.333 64
242+
4.150 75
243+
2.350 47
244+
4.933 86
245+
2.900 63
246+
4.583 85
247+
3.833 82
248+
2.083 57
249+
4.367 82
250+
2.133 67
251+
4.350 74
252+
2.200 54
253+
4.450 83
254+
3.567 73
255+
4.500 73
256+
4.150 88
257+
3.817 80
258+
3.917 71
259+
4.450 83
260+
2.000 56
261+
4.283 79
262+
4.767 78
263+
4.533 84
264+
1.850 58
265+
4.250 83
266+
1.983 43
267+
2.250 60
268+
4.750 75
269+
4.117 81
270+
2.150 46
271+
4.417 90
272+
1.817 46
273+
4.467 74

test/output/faithfulDensity.svg

Lines changed: 354 additions & 0 deletions
Loading

test/plots/faithful-density.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import * as Plot from "@observablehq/plot";
2+
import * as d3 from "d3";
3+
4+
export default async function() {
5+
const faithful = await d3.tsv("data/faithful.tsv", d3.autoType);
6+
return Plot.plot({
7+
inset: 20,
8+
marks: [
9+
Plot.density(faithful, {x: "waiting", y: "eruptions", stroke: "steelblue", strokeWidth: 0.25}),
10+
Plot.density(faithful, {x: "waiting", y: "eruptions", thresholds: 4, stroke: "steelblue"}),
11+
Plot.dot(faithful, {x: "waiting", y: "eruptions", fill: "currentColor", r: 1.5})
12+
]
13+
});
14+
}

test/plots/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export {default as empty} from "./empty.js";
6262
export {default as emptyLegend} from "./empty-legend.js";
6363
export {default as emptyX} from "./empty-x.js";
6464
export {default as energyProduction} from "./energy-production.js";
65+
export {default as faithfulDensity} from "./faithful-density.js";
6566
export {default as figcaption} from "./figcaption.js";
6667
export {default as figcaptionHtml} from "./figcaption-html.js";
6768
export {default as firstLadies} from "./first-ladies.js";

0 commit comments

Comments
 (0)