|
1 | 1 | import {group, pathRound as path, select, Delaunay} from "d3";
|
2 | 2 | import {create} from "../context.js";
|
3 | 3 | import {maybeCurve} from "../curve.js";
|
| 4 | +import {defined} from "../defined.js"; |
4 | 5 | import {Mark} from "../mark.js";
|
5 | 6 | import {markers, applyMarkers} from "../marker.js";
|
6 | 7 | import {constant, maybeTuple, maybeZ} from "../options.js";
|
7 |
| -import { |
8 |
| - applyChannelStyles, |
9 |
| - applyDirectStyles, |
10 |
| - applyFrameAnchor, |
11 |
| - applyIndirectStyles, |
12 |
| - applyTransform |
13 |
| -} from "../style.js"; |
| 8 | +import {applyPosition} from "../projection.js"; |
| 9 | +import {applyFrameAnchor, applyTransform} from "../style.js"; |
| 10 | +import {applyChannelStyles, applyDirectStyles, applyIndirectStyles} from "../style.js"; |
| 11 | +import {basic, initializer} from "../transforms/basic.js"; |
| 12 | +import {exclusiveFacets} from "../transforms/exclusiveFacets.js"; |
| 13 | +import {maybeGroup} from "../transforms/group.js"; |
14 | 14 |
|
15 | 15 | const delaunayLinkDefaults = {
|
16 | 16 | ariaLabel: "delaunay link",
|
@@ -221,45 +221,45 @@ class Voronoi extends Mark {
|
221 | 221 | y: {value: y, scale: "y", optional: true},
|
222 | 222 | z: {value: z, optional: true}
|
223 | 223 | },
|
224 |
| - options, |
| 224 | + initializer(options, function (data, facets, channels, scales, dimensions, context) { |
| 225 | + let {x: X, y: Y, z: Z} = channels; |
| 226 | + ({x: X, y: Y} = applyPosition(channels, scales, context)); |
| 227 | + Z = Z?.value; |
| 228 | + const C = new Array((X ?? Y).length).fill(null); |
| 229 | + const [cx, cy] = applyFrameAnchor(this, dimensions); |
| 230 | + const xi = X ? (i) => X[i] : constant(cx); |
| 231 | + const yi = Y ? (i) => Y[i] : constant(cy); |
| 232 | + for (let I of facets) { |
| 233 | + if (X) I = I.filter((i) => defined(xi(i))); |
| 234 | + if (Y) I = I.filter((i) => defined(yi(i))); |
| 235 | + for (const [, J] of maybeGroup(I, Z)) { |
| 236 | + const delaunay = Delaunay.from(J, xi, yi); |
| 237 | + const voronoi = voronoiof(delaunay, dimensions); |
| 238 | + for (let i = 0, n = J.length; i < n; ++i) { |
| 239 | + C[J[i]] = voronoi.renderCell(i); |
| 240 | + } |
| 241 | + } |
| 242 | + } |
| 243 | + return {data, facets, channels: {cells: {value: C}}}; |
| 244 | + }), |
225 | 245 | voronoiDefaults
|
226 | 246 | );
|
227 | 247 | }
|
228 | 248 | render(index, scales, channels, dimensions, context) {
|
229 | 249 | const {x, y} = scales;
|
230 |
| - const {x: X, y: Y, z: Z} = channels; |
231 |
| - const [cx, cy] = applyFrameAnchor(this, dimensions); |
232 |
| - const xi = X ? (i) => X[i] : constant(cx); |
233 |
| - const yi = Y ? (i) => Y[i] : constant(cy); |
234 |
| - const mark = this; |
235 |
| - |
236 |
| - function cells(index) { |
237 |
| - const delaunay = Delaunay.from(index, xi, yi); |
238 |
| - const voronoi = voronoiof(delaunay, dimensions); |
239 |
| - select(this) |
240 |
| - .selectAll() |
241 |
| - .data(index) |
242 |
| - .enter() |
243 |
| - .append("path") |
244 |
| - .call(applyDirectStyles, mark) |
245 |
| - .attr("d", (_, i) => voronoi.renderCell(i)) |
246 |
| - .call(applyChannelStyles, mark, channels); |
247 |
| - } |
248 |
| - |
| 250 | + const {x: X, y: Y, cells: C} = channels; |
249 | 251 | return create("svg:g", context)
|
250 | 252 | .call(applyIndirectStyles, this, dimensions, context)
|
251 | 253 | .call(applyTransform, this, {x: X && x, y: Y && y})
|
252 |
| - .call( |
253 |
| - Z |
254 |
| - ? (g) => |
255 |
| - g |
256 |
| - .selectAll() |
257 |
| - .data(group(index, (i) => Z[i]).values()) |
258 |
| - .enter() |
259 |
| - .append("g") |
260 |
| - .each(cells) |
261 |
| - : (g) => g.datum(index).each(cells) |
262 |
| - ) |
| 254 | + .call((g) => { |
| 255 | + g.selectAll() |
| 256 | + .data(index) |
| 257 | + .enter() |
| 258 | + .append("path") |
| 259 | + .call(applyDirectStyles, this) |
| 260 | + .attr("d", (i) => C[i]) |
| 261 | + .call(applyChannelStyles, this, channels); |
| 262 | + }) |
263 | 263 | .node();
|
264 | 264 | }
|
265 | 265 | }
|
@@ -296,8 +296,8 @@ export function hull(data, options) {
|
296 | 296 | return delaunayMark(Hull, data, options);
|
297 | 297 | }
|
298 | 298 |
|
299 |
| -export function voronoi(data, options) { |
300 |
| - return delaunayMark(Voronoi, data, options); |
| 299 | +export function voronoi(data, {x, y, initializer, ...options} = {}) { |
| 300 | + return delaunayMark(Voronoi, data, {...basic({...options, x, y}, exclusiveFacets), initializer}); |
301 | 301 | }
|
302 | 302 |
|
303 | 303 | export function voronoiMesh(data, options) {
|
|
0 commit comments