From dba3a6af287ccab29d19809df8c9bbedf313179f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 9 Jun 2022 18:50:37 +0200 Subject: [PATCH 1/3] delaunay X and Y are optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A complement to https://github.com/observablehq/plot/pull/930 the X and Y channels should be optional in all the voronoi marks—since d3-delaunay can handle collinear points (and it's not just for the sake of it: the resulting voronoi can be useful, as illustrated in the test case). --- src/marks/delaunay.js | 35 +- test/output/penguinVoronoi1D.svg | 1756 ++++++++++++++++++++++++++++++ test/plots/index.js | 1 + test/plots/penguin-voronoi-1d.js | 27 + 4 files changed, 1805 insertions(+), 14 deletions(-) create mode 100644 test/output/penguinVoronoi1D.svg create mode 100644 test/plots/penguin-voronoi-1d.js diff --git a/src/marks/delaunay.js b/src/marks/delaunay.js index 16d4d85287..da41af3720 100644 --- a/src/marks/delaunay.js +++ b/src/marks/delaunay.js @@ -1,6 +1,6 @@ import {create, group, path, select, Delaunay} from "d3"; import {Curve} from "../curve.js"; -import {maybeTuple, maybeZ} from "../options.js"; +import {constant, maybeTuple, maybeZ} from "../options.js"; import {Mark} from "../plot.js"; import {applyChannelStyles, applyDirectStyles, applyIndirectStyles, applyTransform, offset} from "../style.js"; import {markers, applyMarkers} from "./marker.js"; @@ -47,8 +47,8 @@ class DelaunayLink extends Mark { super( data, [ - {name: "x", value: x, scale: "x"}, - {name: "y", value: y, scale: "y"}, + {name: "x", value: x, scale: "x", optional: true}, + {name: "y", value: y, scale: "y", optional: true}, {name: "z", value: z, optional: true} ], options, @@ -59,6 +59,7 @@ class DelaunayLink extends Mark { } render(index, {x, y}, channels, dimensions) { const {x: X, y: Y, z: Z} = channels; + if (!(X || Y)) throw new Error("missing channel values: x or y"); const {dx, dy, curve} = this; const mark = this; @@ -76,14 +77,14 @@ class DelaunayLink extends Mark { ti = index[ti]; tj = index[tj]; newIndex.push(++i); - X1[i] = X[ti]; - Y1[i] = Y[ti]; - X2[i] = X[tj]; - Y2[i] = Y[tj]; + X1[i] = X ? X[ti] : 0; + Y1[i] = Y ? Y[ti] : 0; + X2[i] = X ? X[tj] : 0; + Y2[i] = Y ? Y[tj] : 0; for (const k in channels) newChannels[k].push(channels[k][tj]); } - const {halfedges, hull, triangles} = Delaunay.from(index, i => X[i], i => Y[i]); + const {halfedges, hull, triangles} = diagram(index, X, Y); for (let i = 0; i < halfedges.length; ++i) { // inner edges const j = halfedges[i]; if (j > i) link(triangles[i], triangles[j]); @@ -126,8 +127,8 @@ class AbstractDelaunayMark extends Mark { super( data, [ - {name: "x", value: x, scale: "x"}, - {name: "y", value: y, scale: "y"}, + {name: "x", value: x, scale: "x", optional: true}, + {name: "y", value: y, scale: "y", optional: true}, {name: "z", value: zof(options), optional: true} ], options, @@ -135,11 +136,12 @@ class AbstractDelaunayMark extends Mark { ); } render(index, {x, y}, {x: X, y: Y, z: Z, ...channels}, dimensions) { + if (!(X || Y)) throw new Error("missing channel values: x or y"); const {dx, dy} = this; const mark = this; function mesh(render) { return function(index) { - const delaunay = Delaunay.from(index, i => X[i], i => Y[i]); + const delaunay = diagram(index, X, Y); select(this).append("path") .datum(index[0]) .call(applyDirectStyles, mark) @@ -182,8 +184,8 @@ class Voronoi extends Mark { super( data, [ - {name: "x", value: x, scale: "x"}, - {name: "y", value: y, scale: "y"}, + {name: "x", value: x, scale: "x", optional: true}, + {name: "y", value: y, scale: "y", optional: true}, {name: "z", value: z, optional: true} ], options, @@ -192,10 +194,11 @@ class Voronoi extends Mark { } render(index, {x, y}, channels, dimensions) { const {x: X, y: Y, z: Z} = channels; + if (!(X || Y)) throw new Error("missing channel values: x or y"); const {dx, dy} = this; function cells(index) { - const delaunay = Delaunay.from(index, i => X[i], i => Y[i]); + const delaunay = diagram(index, X, Y); const voronoi = voronoiof(delaunay, dimensions); select(this) .selectAll() @@ -256,3 +259,7 @@ export function voronoi(data, options) { export function voronoiMesh(data, options) { return delaunayMark(VoronoiMesh, data, options); } + +function diagram(index, X, Y) { + return Delaunay.from(index, X ? i => X[i] : constant(0), Y ? i => Y[i] : constant(0)); +} diff --git a/test/output/penguinVoronoi1D.svg b/test/output/penguinVoronoi1D.svg new file mode 100644 index 0000000000..5611022640 --- /dev/null +++ b/test/output/penguinVoronoi1D.svg @@ -0,0 +1,1756 @@ + + + + + 3,000 + + + 3,500 + + + 4,000 + + + 4,500 + + + 5,000 + + + 5,500 + + + 6,000 + body_mass_g → + + + + 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 + + + Adelie (FEMALE) + Torgersen + + + 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 + + + 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 (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 + + + 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 (null) + 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 (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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plots/index.js b/test/plots/index.js index c0665b8749..bc3916270e 100644 --- a/test/plots/index.js +++ b/test/plots/index.js @@ -126,6 +126,7 @@ export {default as penguinCulmenDelaunay} from "./penguin-culmen-delaunay.js"; export {default as penguinCulmenDelaunayMesh} from "./penguin-culmen-delaunay-mesh.js"; export {default as penguinCulmenDelaunaySpecies} from "./penguin-culmen-delaunay-species.js"; export {default as penguinCulmenVoronoi} from "./penguin-culmen-voronoi.js"; +export {default as penguinVoronoi1D} from "./penguin-voronoi-1d.js"; export {default as penguinDodge} from "./penguin-dodge.js"; export {default as penguinDodgeHexbin} from "./penguin-dodge-hexbin.js"; export {default as penguinFacetDodge} from "./penguin-facet-dodge.js"; diff --git a/test/plots/penguin-voronoi-1d.js b/test/plots/penguin-voronoi-1d.js new file mode 100644 index 0000000000..8ee850439f --- /dev/null +++ b/test/plots/penguin-voronoi-1d.js @@ -0,0 +1,27 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function() { + const penguins = await d3.csv("data/penguins.csv", d3.autoType); + return Plot.plot({ + inset: 10, + marks: [ + Plot.voronoi(penguins, { + x: "body_mass_g", + fill: "species", + fillOpacity: 0.5, + title: d => `${d.species} (${d.sex})\n${d.island}` + }), + Plot.dot(penguins, { + x: "body_mass_g", + fill: "currentColor", + r: 1.5, + pointerEvents: "none" + }), + Plot.voronoiMesh(penguins, { + x: "body_mass_g", + pointerEvents: "none" + }) + ] + }); +} From 40e1558937ca228175f47ed64d8ffe18bf75f616 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 10 Jun 2022 09:13:37 -0700 Subject: [PATCH 2/3] adopt applyFrameAnchor --- src/marks/delaunay.js | 35 ++-- test/output/penguinVoronoi1D.svg | 284 +++++++++++++++---------------- 2 files changed, 161 insertions(+), 158 deletions(-) diff --git a/src/marks/delaunay.js b/src/marks/delaunay.js index da41af3720..aa93a51a58 100644 --- a/src/marks/delaunay.js +++ b/src/marks/delaunay.js @@ -2,7 +2,7 @@ import {create, group, path, select, Delaunay} from "d3"; import {Curve} from "../curve.js"; import {constant, maybeTuple, maybeZ} from "../options.js"; import {Mark} from "../plot.js"; -import {applyChannelStyles, applyDirectStyles, applyIndirectStyles, applyTransform, offset} from "../style.js"; +import {applyChannelStyles, applyDirectStyles, applyFrameAnchor, applyIndirectStyles, applyTransform, offset} from "../style.js"; import {markers, applyMarkers} from "./marker.js"; const delaunayLinkDefaults = { @@ -59,8 +59,10 @@ class DelaunayLink extends Mark { } render(index, {x, y}, channels, dimensions) { const {x: X, y: Y, z: Z} = channels; - if (!(X || Y)) throw new Error("missing channel values: x or y"); const {dx, dy, curve} = this; + 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 links(index) { @@ -77,14 +79,14 @@ class DelaunayLink extends Mark { ti = index[ti]; tj = index[tj]; newIndex.push(++i); - X1[i] = X ? X[ti] : 0; - Y1[i] = Y ? Y[ti] : 0; - X2[i] = X ? X[tj] : 0; - Y2[i] = Y ? Y[tj] : 0; + X1[i] = xi(ti); + Y1[i] = yi(ti); + X2[i] = xi(tj); + Y2[i] = yi(tj); for (const k in channels) newChannels[k].push(channels[k][tj]); } - const {halfedges, hull, triangles} = diagram(index, X, Y); + const {halfedges, hull, triangles} = Delaunay.from(index, xi, yi); for (let i = 0; i < halfedges.length; ++i) { // inner edges const j = halfedges[i]; if (j > i) link(triangles[i], triangles[j]); @@ -135,13 +137,16 @@ class AbstractDelaunayMark extends Mark { defaults ); } - render(index, {x, y}, {x: X, y: Y, z: Z, ...channels}, dimensions) { - if (!(X || Y)) throw new Error("missing channel values: x or y"); + render(index, {x, y}, channels, dimensions) { + const {x: X, y: Y, z: Z} = channels; const {dx, dy} = this; + 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 mesh(render) { return function(index) { - const delaunay = diagram(index, X, Y); + const delaunay = Delaunay.from(index, xi, yi); select(this).append("path") .datum(index[0]) .call(applyDirectStyles, mark) @@ -194,11 +199,13 @@ class Voronoi extends Mark { } render(index, {x, y}, channels, dimensions) { const {x: X, y: Y, z: Z} = channels; - if (!(X || Y)) throw new Error("missing channel values: x or y"); const {dx, dy} = this; + const [cx, cy] = applyFrameAnchor(this, dimensions); + const xi = X ? i => X[i] : constant(cx); + const yi = Y ? i => Y[i] : constant(cy); function cells(index) { - const delaunay = diagram(index, X, Y); + const delaunay = Delaunay.from(index, xi, yi); const voronoi = voronoiof(delaunay, dimensions); select(this) .selectAll() @@ -259,7 +266,3 @@ export function voronoi(data, options) { export function voronoiMesh(data, options) { return delaunayMark(VoronoiMesh, data, options); } - -function diagram(index, X, Y) { - return Delaunay.from(index, X ? i => X[i] : constant(0), Y ? i => Y[i] : constant(0)); -} diff --git a/test/output/penguinVoronoi1D.svg b/test/output/penguinVoronoi1D.svg index 5611022640..09eeac6353 100644 --- a/test/output/penguinVoronoi1D.svg +++ b/test/output/penguinVoronoi1D.svg @@ -37,7 +37,7 @@ body_mass_g → - + Adelie (MALE) Torgersen @@ -45,7 +45,7 @@ Adelie (FEMALE) Torgersen - + Adelie (FEMALE) Torgersen @@ -57,11 +57,11 @@ Adelie (MALE) Torgersen - + Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen @@ -69,7 +69,7 @@ Adelie (null) Torgersen - + Adelie (null) Torgersen @@ -97,23 +97,23 @@ Adelie (FEMALE) Torgersen - + Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen - + Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen - + Adelie (FEMALE) Biscoe @@ -137,15 +137,15 @@ Adelie (FEMALE) Biscoe - + Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -153,15 +153,15 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Dream - + Adelie (MALE) Dream - + Adelie (FEMALE) Dream @@ -189,7 +189,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -201,7 +201,7 @@ Adelie (MALE) Dream - + Adelie (FEMALE) Dream @@ -209,7 +209,7 @@ Adelie (MALE) Dream - + Adelie (FEMALE) Dream @@ -217,11 +217,11 @@ Adelie (MALE) Dream - + Adelie (MALE) Dream - + Adelie (null) Dream @@ -229,7 +229,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -241,7 +241,7 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -253,7 +253,7 @@ Adelie (FEMALE) Biscoe - + Adelie (MALE) Biscoe @@ -265,7 +265,7 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -273,7 +273,7 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -281,7 +281,7 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -289,7 +289,7 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -301,7 +301,7 @@ Adelie (FEMALE) Biscoe - + Adelie (MALE) Biscoe @@ -309,11 +309,11 @@ Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen - + Adelie (FEMALE) Torgersen @@ -349,7 +349,7 @@ Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen @@ -357,7 +357,7 @@ Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen @@ -365,15 +365,15 @@ Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen - + Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -413,7 +413,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -421,7 +421,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -437,11 +437,11 @@ Adelie (FEMALE) Biscoe - + Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -449,7 +449,7 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -465,15 +465,15 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe - + Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe @@ -481,11 +481,11 @@ Adelie (MALE) Biscoe - + Adelie (FEMALE) Biscoe - + Adelie (MALE) Biscoe @@ -493,11 +493,11 @@ Adelie (FEMALE) Biscoe - + Adelie (MALE) Biscoe - + Adelie (FEMALE) Torgersen @@ -525,11 +525,11 @@ Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen - + Adelie (FEMALE) Torgersen @@ -537,19 +537,19 @@ Adelie (MALE) Torgersen - + Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen - + Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen @@ -557,7 +557,7 @@ Adelie (FEMALE) Torgersen - + Adelie (MALE) Torgersen @@ -565,7 +565,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -577,11 +577,11 @@ Adelie (MALE) Dream - + Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -589,7 +589,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -597,7 +597,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -605,7 +605,7 @@ Adelie (FEMALE) Dream - + Adelie (MALE) Dream @@ -633,7 +633,7 @@ Adelie (MALE) Dream - + Adelie (FEMALE) Dream @@ -645,19 +645,19 @@ Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream - + Chinstrap (MALE) Dream - + Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream @@ -673,7 +673,7 @@ Chinstrap (MALE) Dream - + Chinstrap (FEMALE) Dream @@ -697,15 +697,15 @@ Chinstrap (MALE) Dream - + Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream - + Chinstrap (MALE) Dream @@ -725,11 +725,11 @@ Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream - + Chinstrap (FEMALE) Dream @@ -749,7 +749,7 @@ Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream @@ -757,7 +757,7 @@ Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream @@ -785,7 +785,7 @@ Chinstrap (FEMALE) Dream - + Chinstrap (FEMALE) Dream @@ -793,7 +793,7 @@ Chinstrap (MALE) Dream - + Chinstrap (FEMALE) Dream @@ -801,7 +801,7 @@ Chinstrap (MALE) Dream - + Chinstrap (MALE) Dream @@ -817,11 +817,11 @@ Chinstrap (FEMALE) Dream - + Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream @@ -853,11 +853,11 @@ Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream - + Chinstrap (FEMALE) Dream @@ -881,7 +881,7 @@ Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream @@ -889,7 +889,7 @@ Chinstrap (FEMALE) Dream - + Chinstrap (FEMALE) Dream @@ -901,7 +901,7 @@ Chinstrap (FEMALE) Dream - + Chinstrap (MALE) Dream @@ -917,7 +917,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -925,7 +925,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -933,7 +933,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -941,7 +941,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -949,7 +949,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -961,11 +961,11 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -973,7 +973,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -981,15 +981,15 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1001,11 +1001,11 @@ Gentoo (FEMALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1017,15 +1017,15 @@ Gentoo (MALE) Biscoe - + Gentoo (null) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1033,7 +1033,7 @@ Gentoo (MALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1041,23 +1041,23 @@ Gentoo (FEMALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1089,7 +1089,7 @@ Gentoo (MALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1109,11 +1109,11 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1121,7 +1121,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1129,7 +1129,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1141,7 +1141,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1157,7 +1157,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1165,7 +1165,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1181,7 +1181,7 @@ Gentoo (null) Biscoe - + Gentoo (MALE) Biscoe @@ -1189,11 +1189,11 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1201,7 +1201,7 @@ Gentoo (MALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1209,11 +1209,11 @@ Gentoo (FEMALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1221,7 +1221,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1237,7 +1237,7 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1253,11 +1253,11 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1265,7 +1265,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1273,7 +1273,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1289,7 +1289,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1305,11 +1305,11 @@ Gentoo (FEMALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1317,19 +1317,19 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (null) Biscoe @@ -1345,7 +1345,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1353,11 +1353,11 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe @@ -1369,7 +1369,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1377,7 +1377,7 @@ Gentoo (MALE) Biscoe - + Gentoo (null) Biscoe @@ -1385,7 +1385,7 @@ Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1393,11 +1393,11 @@ Gentoo (FEMALE) Biscoe - + Gentoo (MALE) Biscoe - + Gentoo (FEMALE) Biscoe @@ -1751,6 +1751,6 @@ - + \ No newline at end of file From 26325a2b2e1f7429ee7d537ab3931146eaabd1ae Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 10 Jun 2022 09:16:30 -0700 Subject: [PATCH 3/3] one fewer closure --- src/marks/delaunay.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/marks/delaunay.js b/src/marks/delaunay.js index aa93a51a58..a373929de2 100644 --- a/src/marks/delaunay.js +++ b/src/marks/delaunay.js @@ -144,22 +144,22 @@ class AbstractDelaunayMark extends Mark { const xi = X ? i => X[i] : constant(cx); const yi = Y ? i => Y[i] : constant(cy); const mark = this; - function mesh(render) { - return function(index) { - const delaunay = Delaunay.from(index, xi, yi); - select(this).append("path") - .datum(index[0]) - .call(applyDirectStyles, mark) - .attr("d", render(delaunay, dimensions)) - .call(applyChannelStyles, mark, channels); - }; + + function mesh(index) { + const delaunay = Delaunay.from(index, xi, yi); + select(this).append("path") + .datum(index[0]) + .call(applyDirectStyles, mark) + .attr("d", mark._render(delaunay, dimensions)) + .call(applyChannelStyles, mark, channels); } + return create("svg:g") .call(applyIndirectStyles, this, dimensions) .call(applyTransform, x, y, offset + dx, offset + dy) .call(Z - ? g => g.selectAll().data(group(index, i => Z[i]).values()).enter().append("g").each(mesh(this._render)) - : g => g.datum(index).each(mesh(this._render))) + ? g => g.selectAll().data(group(index, i => Z[i]).values()).enter().append("g").each(mesh) + : g => g.datum(index).each(mesh)) .node(); } }