diff --git a/src/marks/delaunay.js b/src/marks/delaunay.js index cf8c696c01..57a927d22e 100644 --- a/src/marks/delaunay.js +++ b/src/marks/delaunay.js @@ -1,16 +1,16 @@ import {group, pathRound as path, select, Delaunay} from "d3"; import {create} from "../context.js"; import {maybeCurve} from "../curve.js"; +import {defined} from "../defined.js"; import {Mark} from "../mark.js"; import {markers, applyMarkers} from "../marker.js"; import {constant, maybeTuple, maybeZ} from "../options.js"; -import { - applyChannelStyles, - applyDirectStyles, - applyFrameAnchor, - applyIndirectStyles, - applyTransform -} from "../style.js"; +import {applyPosition} from "../projection.js"; +import {applyFrameAnchor, applyTransform} from "../style.js"; +import {applyChannelStyles, applyDirectStyles, applyIndirectStyles} from "../style.js"; +import {basic, initializer} from "../transforms/basic.js"; +import {exclusiveFacets} from "../transforms/exclusiveFacets.js"; +import {maybeGroup} from "../transforms/group.js"; const delaunayLinkDefaults = { ariaLabel: "delaunay link", @@ -221,45 +221,45 @@ class Voronoi extends Mark { y: {value: y, scale: "y", optional: true}, z: {value: z, optional: true} }, - options, + initializer(options, function (data, facets, channels, scales, dimensions, context) { + let {x: X, y: Y, z: Z} = channels; + ({x: X, y: Y} = applyPosition(channels, scales, context)); + Z = Z?.value; + const C = new Array((X ?? Y).length).fill(null); + const [cx, cy] = applyFrameAnchor(this, dimensions); + const xi = X ? (i) => X[i] : constant(cx); + const yi = Y ? (i) => Y[i] : constant(cy); + for (let I of facets) { + if (X) I = I.filter((i) => defined(xi(i))); + if (Y) I = I.filter((i) => defined(yi(i))); + for (const [, J] of maybeGroup(I, Z)) { + const delaunay = Delaunay.from(J, xi, yi); + const voronoi = voronoiof(delaunay, dimensions); + for (let i = 0, n = J.length; i < n; ++i) { + C[J[i]] = voronoi.renderCell(i); + } + } + } + return {data, facets, channels: {cells: {value: C}}}; + }), voronoiDefaults ); } render(index, scales, channels, dimensions, context) { const {x, y} = scales; - const {x: X, y: Y, z: Z} = channels; - const [cx, cy] = applyFrameAnchor(this, dimensions); - const xi = X ? (i) => X[i] : constant(cx); - const yi = Y ? (i) => Y[i] : constant(cy); - const mark = this; - - function cells(index) { - const delaunay = Delaunay.from(index, xi, yi); - const voronoi = voronoiof(delaunay, dimensions); - select(this) - .selectAll() - .data(index) - .enter() - .append("path") - .call(applyDirectStyles, mark) - .attr("d", (_, i) => voronoi.renderCell(i)) - .call(applyChannelStyles, mark, channels); - } - + const {x: X, y: Y, cells: C} = channels; return create("svg:g", context) .call(applyIndirectStyles, this, dimensions, context) .call(applyTransform, this, {x: X && x, y: Y && y}) - .call( - Z - ? (g) => - g - .selectAll() - .data(group(index, (i) => Z[i]).values()) - .enter() - .append("g") - .each(cells) - : (g) => g.datum(index).each(cells) - ) + .call((g) => { + g.selectAll() + .data(index) + .enter() + .append("path") + .call(applyDirectStyles, this) + .attr("d", (i) => C[i]) + .call(applyChannelStyles, this, channels); + }) .node(); } } @@ -296,8 +296,8 @@ export function hull(data, options) { return delaunayMark(Hull, data, options); } -export function voronoi(data, options) { - return delaunayMark(Voronoi, data, options); +export function voronoi(data, {x, y, initializer, ...options} = {}) { + return delaunayMark(Voronoi, data, {...basic({...options, x, y}, exclusiveFacets), initializer}); } export function voronoiMesh(data, options) { diff --git a/src/style.js b/src/style.js index 53601f3f62..deeb66346f 100644 --- a/src/style.js +++ b/src/style.js @@ -297,6 +297,7 @@ export function* groupIndex(I, position, mark, channels) { } } +// TODO avoid creating a new clip-path each time? // Note: may mutate selection.node! function applyClip(selection, mark, dimensions, context) { let clipUrl; diff --git a/test/output/penguinCulmenVoronoi.svg b/test/output/penguinCulmenVoronoi.svg index d5be80710c..633d3c10dd 100644 --- a/test/output/penguinCulmenVoronoi.svg +++ b/test/output/penguinCulmenVoronoi.svg @@ -465,7 +465,6 @@ - @@ -517,7 +516,6 @@ - @@ -654,7 +652,6 @@ - @@ -677,7 +674,6 @@ - @@ -757,4 +753,5 @@ + \ No newline at end of file diff --git a/test/output/penguinCulmenVoronoiExclude.svg b/test/output/penguinCulmenVoronoiExclude.svg new file mode 100644 index 0000000000..5db2c7a863 --- /dev/null +++ b/test/output/penguinCulmenVoronoiExclude.svg @@ -0,0 +1,1161 @@ + + + + + Adelie + + + Chinstrap + + + Gentoo + + + + species + + + + + 34 + 36 + 38 + 40 + 42 + 44 + 46 + 48 + 50 + 52 + 54 + 56 + 58 + + + + ↑ culmen_length_mm + + + + + 15 + 20 + + + 15 + 20 + + + 15 + 20 + + + + culmen_depth_mm → + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/penguinCulmenVoronoiExcludeHex.svg b/test/output/penguinCulmenVoronoiExcludeHex.svg new file mode 100644 index 0000000000..c58a662cb4 --- /dev/null +++ b/test/output/penguinCulmenVoronoiExcludeHex.svg @@ -0,0 +1,315 @@ + + + + + Adelie + + + Chinstrap + + + Gentoo + + + + species + + + + + 34 + 36 + 38 + 40 + 42 + 44 + 46 + 48 + 50 + 52 + 54 + 56 + 58 + + + + ↑ culmen_length_mm + + + + + 15 + 20 + + + 15 + 20 + + + 15 + 20 + + + + culmen_depth_mm → + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/penguinVoronoi1D.svg b/test/output/penguinVoronoi1D.svg index 23bf873942..564a4f0268 100644 --- a/test/output/penguinVoronoi1D.svg +++ b/test/output/penguinVoronoi1D.svg @@ -37,51 +37,12 @@ Adelie (MALE) Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen Adelie (FEMALE) Torgersen Adelie (MALE) Torgersen - - Adelie (null) - Torgersen - - Adelie (null) - Torgersen - - Adelie (null) - Torgersen - - Adelie (null) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (FEMALE) - Torgersen Adelie (MALE) Torgersen @@ -91,270 +52,75 @@ Adelie (MALE) Torgersen - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe - - Adelie (MALE) - Biscoe - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Biscoe - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Dream - - Adelie (MALE) - Dream Adelie (FEMALE) Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream Adelie (FEMALE) Dream - - Adelie (MALE) - Dream Adelie (FEMALE) Dream - - Adelie (MALE) - Dream Adelie (MALE) Dream Adelie (null) Dream - - Adelie (FEMALE) - Dream Adelie (MALE) Dream - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Biscoe - - Adelie (MALE) - Biscoe - - Adelie (FEMALE) - Biscoe Adelie (MALE) Biscoe - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Biscoe - - Adelie (MALE) - Biscoe - - Adelie (FEMALE) - Biscoe Adelie (MALE) Biscoe - - Adelie (FEMALE) - Torgersen Adelie (MALE) Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen Adelie (MALE) Torgersen - - Adelie (FEMALE) - Torgersen Adelie (MALE) Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen Adelie (FEMALE) Dream Adelie (MALE) Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream Adelie (MALE) Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Biscoe Adelie (MALE) Biscoe Adelie (FEMALE) Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Biscoe - - Adelie (MALE) - Biscoe - - Adelie (FEMALE) - Biscoe - - Adelie (MALE) - Biscoe Adelie (FEMALE) Biscoe @@ -364,384 +130,93 @@ Adelie (FEMALE) Biscoe - - Adelie (MALE) - Biscoe - - Adelie (FEMALE) - Biscoe Adelie (MALE) Biscoe - - Adelie (FEMALE) - Biscoe Adelie (MALE) Biscoe - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen Adelie (MALE) Torgersen Adelie (FEMALE) Torgersen - - Adelie (MALE) - Torgersen Adelie (FEMALE) Torgersen Adelie (MALE) Torgersen - - Adelie (FEMALE) - Torgersen - - Adelie (MALE) - Torgersen - - Adelie (FEMALE) - Torgersen Adelie (MALE) Torgersen - - Adelie (FEMALE) - Dream Adelie (MALE) Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream Adelie (MALE) Dream - - Adelie (FEMALE) - Dream Adelie (MALE) Dream - - Adelie (FEMALE) - Dream Adelie (MALE) Dream - - Adelie (FEMALE) - Dream Adelie (MALE) Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Adelie (FEMALE) - Dream - - Adelie (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (MALE) Dream - - Chinstrap (MALE) - Dream Chinstrap (FEMALE) Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream Chinstrap (FEMALE) Dream - - Chinstrap (MALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (MALE) Dream Chinstrap (FEMALE) Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (MALE) Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (FEMALE) Dream - - Chinstrap (MALE) - Dream Chinstrap (FEMALE) Dream - - Chinstrap (MALE) - Dream Chinstrap (MALE) Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (FEMALE) Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (MALE) Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (FEMALE) Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream Chinstrap (MALE) Dream - - Chinstrap (MALE) - Dream - - Chinstrap (FEMALE) - Dream - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe @@ -751,42 +226,9 @@ Gentoo (MALE) Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (null) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (FEMALE) Biscoe @@ -799,267 +241,81 @@ Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (null) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (FEMALE) Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe Gentoo (MALE) Biscoe - - Gentoo (null) - Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe Gentoo (MALE) Biscoe - - Gentoo (FEMALE) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe - - Gentoo (null) - Biscoe - - Gentoo (MALE) - Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (FEMALE) - Biscoe Gentoo (MALE) Biscoe Gentoo (FEMALE) Biscoe - - Gentoo (MALE) - Biscoe diff --git a/test/output/usCountyVoronoi.svg b/test/output/usCountyVoronoi.svg new file mode 100644 index 0000000000..73b71aae02 --- /dev/null +++ b/test/output/usCountyVoronoi.svg @@ -0,0 +1,6234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/usCountyVoronoiMesh.svg b/test/output/usCountyVoronoiMesh.svg new file mode 100644 index 0000000000..98767d5a97 --- /dev/null +++ b/test/output/usCountyVoronoiMesh.svg @@ -0,0 +1,22 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/output/usStateCapitalsVoronoi.svg b/test/output/usStateCapitalsVoronoi.svg index 25ecb0ebcf..c34eef764b 100644 --- a/test/output/usStateCapitalsVoronoi.svg +++ b/test/output/usStateCapitalsVoronoi.svg @@ -66,58 +66,16 @@ - + - Alabama - Arizona - Arkansas - California - Colorado - Connecticut - Delaware - Florida - Georgia - Idaho - Illinois - Indiana - Iowa - Kansas - Kentucky - Louisiana - Maine - Maryland - Massachusetts - Michigan - Minnesota - Mississippi - Missouri - Montana - Nebraska - Nevada - New Hampshire - New Jersey - New Mexico - North Carolina - North Dakota - New York - Ohio - Oklahoma - Oregon - Pennsylvania - Rhode Island - South Carolina - South Dakota - Tennessee - Texas - Utah - Vermont - Virginia - Washington - West Virginia - Wisconsin - Wyoming + + + + + + diff --git a/test/output/usStateCentroidVoronoi.svg b/test/output/usStateCentroidVoronoi.svg new file mode 100644 index 0000000000..cc0ca4df88 --- /dev/null +++ b/test/output/usStateCentroidVoronoi.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/usStateGeoCentroidVoronoi.svg b/test/output/usStateGeoCentroidVoronoi.svg new file mode 100644 index 0000000000..2ad229543d --- /dev/null +++ b/test/output/usStateGeoCentroidVoronoi.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plots/index.ts b/test/plots/index.ts index 6b4742539e..a5d272dc46 100644 --- a/test/plots/index.ts +++ b/test/plots/index.ts @@ -322,6 +322,7 @@ export * from "./us-congress-age-symbol-explicit.js"; export * from "./us-congress-age.js"; export * from "./us-county-choropleth.js"; export * from "./us-county-spikes.js"; +export * from "./us-county-voronoi.js"; export * from "./us-population-state-age-dots.js"; export * from "./us-population-state-age.js"; export * from "./us-president-favorability-dots.js"; diff --git a/test/plots/penguin-culmen-voronoi.ts b/test/plots/penguin-culmen-voronoi.ts index 07d2d7f96c..ecb99cf817 100644 --- a/test/plots/penguin-culmen-voronoi.ts +++ b/test/plots/penguin-culmen-voronoi.ts @@ -6,7 +6,49 @@ export async function penguinCulmenVoronoi() { return Plot.plot({ marks: [ Plot.dot(penguins, {x: "culmen_depth_mm", y: "culmen_length_mm", fill: "currentColor", r: 1.5}), - Plot.voronoi(penguins, {x: "culmen_depth_mm", y: "culmen_length_mm", stroke: "species"}) + Plot.voronoi(penguins, {x: "culmen_depth_mm", y: "culmen_length_mm", stroke: "species", tip: true}) + ] + }); +} + +export async function penguinCulmenVoronoiExclude() { + const penguins = await d3.csv("data/penguins.csv", d3.autoType); + const xy = {fx: "species", x: "culmen_depth_mm", y: "culmen_length_mm"}; + return Plot.plot({ + inset: 10, + marks: [ + Plot.frame(), + Plot.dot(penguins, {...xy, facet: "exclude", fill: "currentColor", r: 1.5}), + Plot.dot(penguins, {...xy, facet: "include", fillOpacity: 0.25, fill: "currentColor", r: 1.5}), + Plot.voronoiMesh(penguins, {...xy, facet: "exclude"}), + Plot.voronoi( + penguins, + Plot.pointer({ + ...xy, + facet: "exclude", + stroke: "species", + fill: "species", + fillOpacity: 0.2, + maxRadius: Infinity + }) + ) + ] + }); +} + +export async function penguinCulmenVoronoiExcludeHex() { + const penguins = await d3.csv("data/penguins.csv", d3.autoType); + const xy = {fx: "species", x: "culmen_depth_mm", y: "culmen_length_mm"}; + return Plot.plot({ + inset: 20, + marks: [ + Plot.frame(), + Plot.dot(penguins, Plot.hexbin({}, {...xy, facet: "exclude", stroke: "species", fill: "species"})), + Plot.voronoiMesh(penguins, Plot.hexbin({}, {...xy, facet: "exclude", strokeOpacity: 1})), + Plot.voronoi( + penguins, + Plot.pointer(Plot.hexbin({}, {...xy, facet: "exclude", strokeWidth: 2, maxRadius: Infinity})) + ) ] }); } diff --git a/test/plots/us-county-voronoi.ts b/test/plots/us-county-voronoi.ts new file mode 100644 index 0000000000..d721f0777c --- /dev/null +++ b/test/plots/us-county-voronoi.ts @@ -0,0 +1,31 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; +import {feature} from "topojson-client"; + +const transform = (data, facets) => ({data, facets: facets.map((I) => I.slice(1))}); + +export async function usCountyVoronoi() { + const counties = await d3 + .json("data/us-counties-10m.json") + .then((us) => feature(us, us.objects.counties).features); + return Plot.plot({ + projection: "albers", + marks: [ + Plot.voronoi(counties, Plot.geoCentroid({transform, stroke: "red"})), + Plot.voronoi(counties, Plot.centroid({transform, stroke: "blue", mixBlendMode: "multiply"})) + ] + }); +} + +export async function usCountyVoronoiMesh() { + const counties = await d3 + .json("data/us-counties-10m.json") + .then((us) => feature(us, us.objects.counties).features); + return Plot.plot({ + projection: "albers", + marks: [ + Plot.voronoiMesh(counties, Plot.geoCentroid({transform, stroke: "red", strokeOpacity: 1})), + Plot.voronoiMesh(counties, Plot.centroid({transform, stroke: "blue", strokeOpacity: 1, mixBlendMode: "multiply"})) + ] + }); +} diff --git a/test/plots/us-state-capitals-voronoi.ts b/test/plots/us-state-capitals-voronoi.ts index c89d09e5e5..a2481cfa07 100644 --- a/test/plots/us-state-capitals-voronoi.ts +++ b/test/plots/us-state-capitals-voronoi.ts @@ -16,8 +16,65 @@ export async function usStateCapitalsVoronoi() { marks: [ Plot.geo(nation, {fill: "currentColor", fillOpacity: 0.2}), Plot.dot(capitals, {x: "longitude", y: "latitude", r: 2.5, fill: "currentColor"}), - Plot.voronoi(capitals, {x: "longitude", y: "latitude", clip: "sphere", title: "state", pointerEvents: "all"}), + Plot.voronoiMesh(capitals, {x: "longitude", y: "latitude", clip: "sphere"}), + Plot.voronoi( + capitals, + Plot.pointer({ + x: "longitude", + y: "latitude", + clip: "sphere", + title: "state", + stroke: "red", + fill: "red", + fillOpacity: 0.4, + pointerEvents: "all", + maxRadius: Infinity + }) + ), Plot.sphere({strokeWidth: 2}) ] }); } + +async function voronoiMap(centroid) { + const [nation, states] = await d3 + .json("data/us-counties-10m.json") + .then((us) => [feature(us, us.objects.nation), feature(us, us.objects.states)]); + return Plot.plot({ + width: 640, + height: 640, + margin: 1, + projection: ({width, height}) => + d3.geoAzimuthalEqualArea().rotate([96, -40]).clipAngle(24).fitSize([width, height], {type: "Sphere"}), + marks: [ + Plot.geo(nation, {fill: "currentColor", fillOpacity: 0.2}), + Plot.dot(states.features, centroid({r: 2.5, fill: "currentColor"})), + Plot.voronoiMesh(states.features, centroid({clip: "sphere"})), + Plot.voronoi( + states.features, + Plot.pointer( + centroid({ + x: "longitude", + y: "latitude", + clip: "sphere", + title: "state", + stroke: "red", + fill: "red", + fillOpacity: 0.4, + pointerEvents: "all", + maxRadius: Infinity + }) + ) + ), + Plot.sphere({strokeWidth: 2}) + ] + }); +} + +export async function usStateCentroidVoronoi() { + return voronoiMap(Plot.centroid); +} + +export async function usStateGeoCentroidVoronoi() { + return voronoiMap(Plot.geoCentroid); +}