Skip to content

Commit

Permalink
geo + tip: true
Browse files Browse the repository at this point in the history
- fix collapsing bug (#1742)
- compute a centroid if there is a geometry channel but no x and y channels (#1743)
  • Loading branch information
Fil committed Jul 10, 2023
1 parent e44dd3d commit 2a7a899
Show file tree
Hide file tree
Showing 4 changed files with 3,208 additions and 12 deletions.
15 changes: 13 additions & 2 deletions src/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {innerDimensions, outerDimensions} from "./scales.js";
import {position, registry as scaleRegistry} from "./scales/index.js";
import {applyInlineStyles, maybeClassName} from "./style.js";
import {initializer} from "./transforms/basic.js";
import {centroidChannels} from "./transforms/centroid.js";
import {consumeWarnings, warn} from "./warnings.js";

export function plot(options = {}) {
Expand Down Expand Up @@ -502,8 +503,18 @@ function maybeMarkFacet(mark, topFacetState, options) {
}

function derive(mark, options = {}) {
return initializer({...options, x: null, y: null}, (data, facets, channels, scales, dimensions, context) => {
return context.getMarkState(mark);
return initializer({...options, x: null, y: null}, (da, f, c, s, di, context) => {
let {
data,
facets,
channels: {geometry, x, y, ...channels}
} = context.getMarkState(mark);
if (geometry && !x && !y) {
const {projection} = context;
({x, y} = centroidChannels(data, (d) => d, projection));
if (projection == null) (x.scale = "x"), (y.scale = "y");
}
return {data, facets, channels: {...channels, ...(x && {x}), ...(y && {y})}};
});
}

Expand Down
26 changes: 16 additions & 10 deletions src/transforms/centroid.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ import {geoCentroid as GeoCentroid, geoPath} from "d3";
import {identity, valueof} from "../options.js";
import {initializer} from "./basic.js";

export function centroid({geometry = identity, ...options} = {}) {
export function centroid({geometry, ...options} = {}) {
// Suppress defaults for x and y since they will be computed by the initializer.
return initializer({...options, x: null, y: null}, (data, facets, channels, scales, dimensions, {projection}) => {
const G = valueof(data, geometry);
const n = G.length;
const X = new Float64Array(n);
const Y = new Float64Array(n);
const path = geoPath(projection);
for (let i = 0; i < n; ++i) [X[i], Y[i]] = path.centroid(G[i]);
return {data, facets, channels: {x: {value: X, source: null}, y: {value: Y, source: null}}};
});
return initializer({...options, x: null, y: null}, (data, facets, channels, scales, dimensions, {projection}) => ({
data,
facets,
channels: {...channels, ...centroidChannels(data, geometry, projection)}
}));
}

export function centroidChannels(data, geometry = identity, projection) {
const G = valueof(data, geometry);
const n = G.length;
const X = new Float64Array(n);
const Y = new Float64Array(n);
const path = geoPath(projection);
for (let i = 0; i < n; ++i) [X[i], Y[i]] = path.centroid(G[i]);
return {x: {value: X, source: null}, y: {value: Y, source: null}};
}

export function geoCentroid({geometry = identity, ...options} = {}) {
Expand Down
Loading

0 comments on commit 2a7a899

Please sign in to comment.