@uwdata/mosaic-plot 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mosaic-plot.js +843 -547
- package/dist/mosaic-plot.min.js +14 -14
- package/package.json +4 -4
- package/src/index.js +1 -1
- package/src/marks/ConnectedMark.js +21 -22
- package/src/marks/ContourMark.js +16 -10
- package/src/marks/DenseLineMark.js +8 -13
- package/src/marks/Density1DMark.js +11 -13
- package/src/marks/Density2DMark.js +27 -25
- package/src/marks/Grid2DMark.js +86 -53
- package/src/marks/RasterMark.js +188 -64
- package/src/marks/RasterTileMark.js +54 -100
- package/src/marks/util/arrow.js +25 -0
- package/src/marks/util/bin-expr.js +30 -0
- package/src/marks/util/channel-scale.js +27 -0
- package/src/marks/util/grid.js +90 -19
- package/src/marks/util/raster.js +113 -26
- package/src/marks/util/to-data-array.js +2 -22
- package/src/plot-attributes.js +18 -0
- package/src/transforms/bin.js +18 -20
- package/src/marks/util/bin-field.js +0 -17
- package/src/marks/util/is-arrow-table.js +0 -3
package/dist/mosaic-plot.js
CHANGED
|
@@ -12810,8 +12810,7 @@ var castDouble = (expr) => cast(expr, "DOUBLE");
|
|
|
12810
12810
|
|
|
12811
12811
|
// ../sql/src/datetime.js
|
|
12812
12812
|
var epoch_ms = (expr) => {
|
|
12813
|
-
|
|
12814
|
-
return sql`(1000 * (epoch(${d}) - second(${d})) + millisecond(${d}))::DOUBLE`;
|
|
12813
|
+
return sql`epoch_ms(${asColumn(expr)})`;
|
|
12815
12814
|
};
|
|
12816
12815
|
|
|
12817
12816
|
// ../sql/src/spatial.js
|
|
@@ -13218,6 +13217,89 @@ function isDoubleQuoted(s2) {
|
|
|
13218
13217
|
return s2[0] === '"' && s2[s2.length - 1] === '"';
|
|
13219
13218
|
}
|
|
13220
13219
|
|
|
13220
|
+
// ../sql/src/scales.js
|
|
13221
|
+
var identity = (x3) => x3;
|
|
13222
|
+
function scaleLinear() {
|
|
13223
|
+
return {
|
|
13224
|
+
apply: identity,
|
|
13225
|
+
invert: identity,
|
|
13226
|
+
sqlApply: asColumn,
|
|
13227
|
+
sqlInvert: identity
|
|
13228
|
+
};
|
|
13229
|
+
}
|
|
13230
|
+
function scaleLog({ base } = {}) {
|
|
13231
|
+
if (base == null || base === Math.E) {
|
|
13232
|
+
return {
|
|
13233
|
+
apply: Math.log,
|
|
13234
|
+
invert: Math.exp,
|
|
13235
|
+
sqlApply: (c4) => sql`LN(${asColumn(c4)})`,
|
|
13236
|
+
sqlInvert: (c4) => sql`EXP(${c4})`
|
|
13237
|
+
};
|
|
13238
|
+
} else if (base === 10) {
|
|
13239
|
+
return {
|
|
13240
|
+
apply: Math.log10,
|
|
13241
|
+
invert: (x3) => Math.pow(10, x3),
|
|
13242
|
+
sqlApply: (c4) => sql`LOG(${asColumn(c4)})`,
|
|
13243
|
+
sqlInvert: (c4) => sql`POW(10, ${c4})`
|
|
13244
|
+
};
|
|
13245
|
+
} else {
|
|
13246
|
+
const b = +base;
|
|
13247
|
+
return {
|
|
13248
|
+
apply: (x3) => Math.log(x3) / Math.log(b),
|
|
13249
|
+
invert: (x3) => Math.pow(b, x3),
|
|
13250
|
+
sqlApply: (c4) => sql`LN(${asColumn(c4)}) / LN(${b})`,
|
|
13251
|
+
sqlInvert: (c4) => sql`POW(${b}, ${c4})`
|
|
13252
|
+
};
|
|
13253
|
+
}
|
|
13254
|
+
}
|
|
13255
|
+
function scaleSymlog({ constant: constant2 = 1 } = {}) {
|
|
13256
|
+
const _ = +constant2;
|
|
13257
|
+
return {
|
|
13258
|
+
apply: (x3) => Math.sign(x3) * Math.log1p(Math.abs(x3)),
|
|
13259
|
+
invert: (x3) => Math.sign(x3) * Math.exp(Math.abs(x3) - _),
|
|
13260
|
+
sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * LN(${_} + ABS(${c4}))`),
|
|
13261
|
+
sqlInvert: (c4) => sql`SIGN(${c4}) * (EXP(ABS(${c4})) - ${_})`
|
|
13262
|
+
};
|
|
13263
|
+
}
|
|
13264
|
+
function scaleSqrt() {
|
|
13265
|
+
return {
|
|
13266
|
+
apply: (x3) => Math.sign(x3) * Math.sqrt(Math.abs(x3)),
|
|
13267
|
+
invert: (x3) => Math.sign(x3) * x3 * x3,
|
|
13268
|
+
sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * SQRT(ABS(${c4}))`),
|
|
13269
|
+
sqlInvert: (c4) => sql`SIGN(${c4}) * (${c4}) ** 2`
|
|
13270
|
+
};
|
|
13271
|
+
}
|
|
13272
|
+
function scalePow({ exponent = 1 } = {}) {
|
|
13273
|
+
const e = +exponent;
|
|
13274
|
+
return {
|
|
13275
|
+
apply: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), e),
|
|
13276
|
+
invert: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), 1 / e),
|
|
13277
|
+
sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * POW(ABS(${c4}), ${e})`),
|
|
13278
|
+
sqlInvert: (c4) => sql`SIGN(${c4}) * POW(ABS(${c4}), 1/${e})`
|
|
13279
|
+
};
|
|
13280
|
+
}
|
|
13281
|
+
function scaleTime() {
|
|
13282
|
+
return {
|
|
13283
|
+
apply: (x3) => +x3,
|
|
13284
|
+
invert: (x3) => new Date(x3),
|
|
13285
|
+
sqlApply: (c4) => c4 instanceof Date ? +c4 : epoch_ms(asColumn(c4)),
|
|
13286
|
+
sqlInvert: identity
|
|
13287
|
+
};
|
|
13288
|
+
}
|
|
13289
|
+
var scales = {
|
|
13290
|
+
linear: scaleLinear,
|
|
13291
|
+
log: scaleLog,
|
|
13292
|
+
symlog: scaleSymlog,
|
|
13293
|
+
sqrt: scaleSqrt,
|
|
13294
|
+
pow: scalePow,
|
|
13295
|
+
time: scaleTime,
|
|
13296
|
+
utc: scaleTime
|
|
13297
|
+
};
|
|
13298
|
+
function scaleTransform(options) {
|
|
13299
|
+
const scale3 = scales[options.type];
|
|
13300
|
+
return scale3 ? { ...options, ...scale3(options) } : null;
|
|
13301
|
+
}
|
|
13302
|
+
|
|
13221
13303
|
// ../sql/src/load/create.js
|
|
13222
13304
|
function create(name, query, {
|
|
13223
13305
|
replace = false,
|
|
@@ -13377,7 +13459,6 @@ function fnv_mix(a2) {
|
|
|
13377
13459
|
}
|
|
13378
13460
|
|
|
13379
13461
|
// ../core/src/DataCubeIndexer.js
|
|
13380
|
-
var identity = (x3) => x3;
|
|
13381
13462
|
var DataCubeIndexer = class {
|
|
13382
13463
|
/**
|
|
13383
13464
|
*
|
|
@@ -13470,10 +13551,10 @@ function getActiveView(clause) {
|
|
|
13470
13551
|
let columns = clause.predicate?.columns;
|
|
13471
13552
|
if (!schema || !columns)
|
|
13472
13553
|
return null;
|
|
13473
|
-
const { type: type2, scales, pixelSize = 1 } = schema;
|
|
13554
|
+
const { type: type2, scales: scales2, pixelSize = 1 } = schema;
|
|
13474
13555
|
let predicate;
|
|
13475
|
-
if (type2 === "interval" &&
|
|
13476
|
-
const bins2 =
|
|
13556
|
+
if (type2 === "interval" && scales2) {
|
|
13557
|
+
const bins2 = scales2.map((s2) => binInterval(s2, pixelSize));
|
|
13477
13558
|
if (bins2.some((b) => b == null))
|
|
13478
13559
|
return null;
|
|
13479
13560
|
if (bins2.length === 1) {
|
|
@@ -13486,7 +13567,7 @@ function getActiveView(clause) {
|
|
|
13486
13567
|
);
|
|
13487
13568
|
}
|
|
13488
13569
|
} else if (type2 === "point") {
|
|
13489
|
-
predicate =
|
|
13570
|
+
predicate = (x3) => x3;
|
|
13490
13571
|
columns = Object.fromEntries(columns.map((col) => [col.toString(), col]));
|
|
13491
13572
|
} else {
|
|
13492
13573
|
return null;
|
|
@@ -13494,39 +13575,15 @@ function getActiveView(clause) {
|
|
|
13494
13575
|
return { source, columns, predicate };
|
|
13495
13576
|
}
|
|
13496
13577
|
function binInterval(scale3, pixelSize) {
|
|
13497
|
-
const {
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
lift = Math.log;
|
|
13506
|
-
toSql = (c4) => sql`LN(${asColumn(c4)})`;
|
|
13507
|
-
break;
|
|
13508
|
-
case "symlog":
|
|
13509
|
-
lift = (x3) => Math.sign(x3) * Math.log1p(Math.abs(x3));
|
|
13510
|
-
toSql = (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * LN(1 + ABS(${c4}))`);
|
|
13511
|
-
break;
|
|
13512
|
-
case "sqrt":
|
|
13513
|
-
lift = Math.sqrt;
|
|
13514
|
-
toSql = (c4) => sql`SQRT(${asColumn(c4)})`;
|
|
13515
|
-
break;
|
|
13516
|
-
case "utc":
|
|
13517
|
-
case "time":
|
|
13518
|
-
lift = (x3) => +x3;
|
|
13519
|
-
toSql = (c4) => c4 instanceof Date ? +c4 : epoch_ms(asColumn(c4));
|
|
13520
|
-
break;
|
|
13578
|
+
const { apply: apply2, sqlApply } = scaleTransform(scale3);
|
|
13579
|
+
if (apply2) {
|
|
13580
|
+
const { domain, range: range3 } = scale3;
|
|
13581
|
+
const lo = apply2(Math.min(...domain));
|
|
13582
|
+
const hi = apply2(Math.max(...domain));
|
|
13583
|
+
const a2 = Math.abs(range3[1] - range3[0]) / (hi - lo) / pixelSize;
|
|
13584
|
+
const s2 = pixelSize === 1 ? "" : `${pixelSize}::INTEGER * `;
|
|
13585
|
+
return (value) => sql`${s2}FLOOR(${a2}::DOUBLE * (${sqlApply(value)} - ${lo}::DOUBLE))::INTEGER`;
|
|
13521
13586
|
}
|
|
13522
|
-
return lift ? binFunction(domain, range3, pixelSize, lift, toSql) : null;
|
|
13523
|
-
}
|
|
13524
|
-
function binFunction(domain, range3, pixelSize, lift, toSql) {
|
|
13525
|
-
const lo = lift(Math.min(domain[0], domain[1]));
|
|
13526
|
-
const hi = lift(Math.max(domain[0], domain[1]));
|
|
13527
|
-
const a2 = Math.abs(lift(range3[1]) - lift(range3[0])) / (hi - lo) / pixelSize;
|
|
13528
|
-
const s2 = pixelSize === 1 ? "" : `${pixelSize}::INTEGER * `;
|
|
13529
|
-
return (value) => sql`${s2}FLOOR(${a2}::DOUBLE * (${toSql(value)} - ${lo}::DOUBLE))::INTEGER`;
|
|
13530
13587
|
}
|
|
13531
13588
|
var NO_INDEX = { from: NaN };
|
|
13532
13589
|
function getIndexColumns(client) {
|
|
@@ -29271,10 +29328,10 @@ function createChannels(channels, data) {
|
|
|
29271
29328
|
Object.entries(channels).map(([name, channel]) => [name, createChannel(data, channel, name)])
|
|
29272
29329
|
);
|
|
29273
29330
|
}
|
|
29274
|
-
function valueObject(channels,
|
|
29331
|
+
function valueObject(channels, scales2) {
|
|
29275
29332
|
const values2 = Object.fromEntries(
|
|
29276
29333
|
Object.entries(channels).map(([name, { scale: scaleName, value }]) => {
|
|
29277
|
-
const scale3 = scaleName == null ? null :
|
|
29334
|
+
const scale3 = scaleName == null ? null : scales2[scaleName];
|
|
29278
29335
|
return [name, scale3 == null ? value : map2(value, scale3)];
|
|
29279
29336
|
})
|
|
29280
29337
|
);
|
|
@@ -30076,14 +30133,14 @@ function projectionAspectRatio(projection3) {
|
|
|
30076
30133
|
}
|
|
30077
30134
|
return defaultAspectRatio;
|
|
30078
30135
|
}
|
|
30079
|
-
function applyPosition(channels,
|
|
30136
|
+
function applyPosition(channels, scales2, { projection: projection3 }) {
|
|
30080
30137
|
const { x: x3, y: y3 } = channels;
|
|
30081
30138
|
let position3 = {};
|
|
30082
30139
|
if (x3)
|
|
30083
30140
|
position3.x = x3;
|
|
30084
30141
|
if (y3)
|
|
30085
30142
|
position3.y = y3;
|
|
30086
|
-
position3 = valueObject(position3,
|
|
30143
|
+
position3 = valueObject(position3, scales2);
|
|
30087
30144
|
if (projection3 && x3?.scale === "x" && y3?.scale === "y")
|
|
30088
30145
|
project("x", "y", position3, projection3);
|
|
30089
30146
|
if (x3)
|
|
@@ -30821,7 +30878,7 @@ function createScales(channelsByScale, {
|
|
|
30821
30878
|
facet: { label: facetLabel = globalLabel } = {},
|
|
30822
30879
|
...options
|
|
30823
30880
|
} = {}) {
|
|
30824
|
-
const
|
|
30881
|
+
const scales2 = {};
|
|
30825
30882
|
for (const [key, channels] of channelsByScale) {
|
|
30826
30883
|
const scaleOptions = options[key];
|
|
30827
30884
|
const scale3 = createScale(key, channels, {
|
|
@@ -30864,17 +30921,17 @@ function createScales(channelsByScale, {
|
|
|
30864
30921
|
scale3.insetTop = +insetTop;
|
|
30865
30922
|
scale3.insetBottom = +insetBottom;
|
|
30866
30923
|
}
|
|
30867
|
-
|
|
30924
|
+
scales2[key] = scale3;
|
|
30868
30925
|
}
|
|
30869
30926
|
}
|
|
30870
|
-
return
|
|
30927
|
+
return scales2;
|
|
30871
30928
|
}
|
|
30872
30929
|
function createScaleFunctions(descriptors) {
|
|
30873
|
-
const
|
|
30874
|
-
const scaleFunctions = { scales };
|
|
30930
|
+
const scales2 = {};
|
|
30931
|
+
const scaleFunctions = { scales: scales2 };
|
|
30875
30932
|
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
30876
30933
|
const { scale: scale3, type: type2, interval: interval2, label } = descriptor;
|
|
30877
|
-
|
|
30934
|
+
scales2[key] = exposeScale(descriptor);
|
|
30878
30935
|
scaleFunctions[key] = scale3;
|
|
30879
30936
|
scale3.type = type2;
|
|
30880
30937
|
if (interval2 != null)
|
|
@@ -30884,14 +30941,14 @@ function createScaleFunctions(descriptors) {
|
|
|
30884
30941
|
}
|
|
30885
30942
|
return scaleFunctions;
|
|
30886
30943
|
}
|
|
30887
|
-
function autoScaleRange(
|
|
30888
|
-
const { x: x3, y: y3, fx, fy } =
|
|
30944
|
+
function autoScaleRange(scales2, dimensions) {
|
|
30945
|
+
const { x: x3, y: y3, fx, fy } = scales2;
|
|
30889
30946
|
const superdimensions = fx || fy ? outerDimensions(dimensions) : dimensions;
|
|
30890
30947
|
if (fx)
|
|
30891
30948
|
autoScaleRangeX(fx, superdimensions);
|
|
30892
30949
|
if (fy)
|
|
30893
30950
|
autoScaleRangeY(fy, superdimensions);
|
|
30894
|
-
const subdimensions = fx || fy ? innerDimensions(
|
|
30951
|
+
const subdimensions = fx || fy ? innerDimensions(scales2, dimensions) : dimensions;
|
|
30895
30952
|
if (x3)
|
|
30896
30953
|
autoScaleRangeX(x3, subdimensions);
|
|
30897
30954
|
if (y3)
|
|
@@ -31234,11 +31291,11 @@ function scale2(options = {}) {
|
|
|
31234
31291
|
throw new Error("invalid scale definition; no scale found");
|
|
31235
31292
|
return scale3;
|
|
31236
31293
|
}
|
|
31237
|
-
function exposeScales(
|
|
31294
|
+
function exposeScales(scales2) {
|
|
31238
31295
|
return (key) => {
|
|
31239
31296
|
if (!registry.has(key = `${key}`))
|
|
31240
31297
|
throw new Error(`unknown scale: ${key}`);
|
|
31241
|
-
return
|
|
31298
|
+
return scales2[key];
|
|
31242
31299
|
};
|
|
31243
31300
|
}
|
|
31244
31301
|
function exposeScale({ scale: scale3, type: type2, domain, range: range3, interpolate, interval: interval2, transform: transform3, percent, pivot }) {
|
|
@@ -31278,7 +31335,7 @@ function exposeScale({ scale: scale3, type: type2, domain, range: range3, interp
|
|
|
31278
31335
|
}
|
|
31279
31336
|
|
|
31280
31337
|
// ../../node_modules/@observablehq/plot/src/dimensions.js
|
|
31281
|
-
function createDimensions(
|
|
31338
|
+
function createDimensions(scales2, marks2, options = {}) {
|
|
31282
31339
|
let marginTopDefault = 0.5 - offset, marginRightDefault = 0.5 + offset, marginBottomDefault = 0.5 + offset, marginLeftDefault = 0.5 - offset;
|
|
31283
31340
|
for (const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } of marks2) {
|
|
31284
31341
|
if (marginTop2 > marginTopDefault)
|
|
@@ -31303,7 +31360,7 @@ function createDimensions(scales, marks2, options = {}) {
|
|
|
31303
31360
|
marginLeft = +marginLeft;
|
|
31304
31361
|
let {
|
|
31305
31362
|
width = 640,
|
|
31306
|
-
height = autoHeight(
|
|
31363
|
+
height = autoHeight(scales2, options, {
|
|
31307
31364
|
width,
|
|
31308
31365
|
marginTopDefault,
|
|
31309
31366
|
marginRightDefault,
|
|
@@ -31321,7 +31378,7 @@ function createDimensions(scales, marks2, options = {}) {
|
|
|
31321
31378
|
marginBottom,
|
|
31322
31379
|
marginLeft
|
|
31323
31380
|
};
|
|
31324
|
-
if (
|
|
31381
|
+
if (scales2.fx || scales2.fy) {
|
|
31325
31382
|
let {
|
|
31326
31383
|
margin: facetMargin,
|
|
31327
31384
|
marginTop: facetMarginTop = facetMargin !== void 0 ? facetMargin : marginTop,
|
|
@@ -31667,8 +31724,8 @@ var Mark = class {
|
|
|
31667
31724
|
}
|
|
31668
31725
|
}
|
|
31669
31726
|
}
|
|
31670
|
-
scale(channels,
|
|
31671
|
-
const values2 = valueObject(channels,
|
|
31727
|
+
scale(channels, scales2, context) {
|
|
31728
|
+
const values2 = valueObject(channels, scales2);
|
|
31672
31729
|
if (context.projection)
|
|
31673
31730
|
this.project(channels, values2, context);
|
|
31674
31731
|
return values2;
|
|
@@ -31726,7 +31783,7 @@ function pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, re
|
|
|
31726
31783
|
// Unlike other composed transforms, the render transform must be the
|
|
31727
31784
|
// outermost render function because it will re-render dynamically in
|
|
31728
31785
|
// response to pointer events.
|
|
31729
|
-
render: composeRender(function(index2,
|
|
31786
|
+
render: composeRender(function(index2, scales2, values2, dimensions, context, next) {
|
|
31730
31787
|
context = { ...context, pointerSticky: false };
|
|
31731
31788
|
const svg = context.ownerSVGElement;
|
|
31732
31789
|
const { data } = context.getMarkState(this);
|
|
@@ -31734,7 +31791,7 @@ function pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, re
|
|
|
31734
31791
|
if (!state)
|
|
31735
31792
|
states.set(svg, state = { sticky: false, roots: [], renders: [] });
|
|
31736
31793
|
let renderIndex = state.renders.push(render2) - 1;
|
|
31737
|
-
const { x: x4, y: y4, fx, fy } =
|
|
31794
|
+
const { x: x4, y: y4, fx, fy } = scales2;
|
|
31738
31795
|
let tx = fx ? fx(index2.fx) - dimensions.marginLeft : 0;
|
|
31739
31796
|
let ty = fy ? fy(index2.fy) - dimensions.marginTop : 0;
|
|
31740
31797
|
if (x4?.bandwidth)
|
|
@@ -31790,7 +31847,7 @@ function pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, re
|
|
|
31790
31847
|
const I = i == null ? [] : [i];
|
|
31791
31848
|
if (faceted)
|
|
31792
31849
|
I.fx = index2.fx, I.fy = index2.fy, I.fi = index2.fi;
|
|
31793
|
-
const r = next(I,
|
|
31850
|
+
const r = next(I, scales2, values2, dimensions, context);
|
|
31794
31851
|
if (g) {
|
|
31795
31852
|
if (faceted) {
|
|
31796
31853
|
const p = g.parentNode;
|
|
@@ -32162,8 +32219,8 @@ var RuleX = class extends Mark {
|
|
|
32162
32219
|
this.insetBottom = number5(insetBottom);
|
|
32163
32220
|
markers(this, options);
|
|
32164
32221
|
}
|
|
32165
|
-
render(index2,
|
|
32166
|
-
const { x: x3, y: y3 } =
|
|
32222
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
32223
|
+
const { x: x3, y: y3 } = scales2;
|
|
32167
32224
|
const { x: X3, y1: Y13, y2: Y23 } = channels;
|
|
32168
32225
|
const { width, height, marginTop, marginRight, marginLeft, marginBottom } = dimensions;
|
|
32169
32226
|
const { insetTop, insetBottom } = this;
|
|
@@ -32192,8 +32249,8 @@ var RuleY = class extends Mark {
|
|
|
32192
32249
|
this.insetLeft = number5(insetLeft);
|
|
32193
32250
|
markers(this, options);
|
|
32194
32251
|
}
|
|
32195
|
-
render(index2,
|
|
32196
|
-
const { x: x3, y: y3 } =
|
|
32252
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
32253
|
+
const { x: x3, y: y3 } = scales2;
|
|
32197
32254
|
const { y: Y3, x1: X13, x2: X23 } = channels;
|
|
32198
32255
|
const { width, height, marginTop, marginRight, marginLeft, marginBottom } = dimensions;
|
|
32199
32256
|
const { insetLeft, insetRight } = this;
|
|
@@ -32315,8 +32372,8 @@ var Text = class extends Mark {
|
|
|
32315
32372
|
this.splitLines = splitter2(this);
|
|
32316
32373
|
this.clipLine = clipper(this);
|
|
32317
32374
|
}
|
|
32318
|
-
render(index2,
|
|
32319
|
-
const { x: x3, y: y3 } =
|
|
32375
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
32376
|
+
const { x: x3, y: y3 } = scales2;
|
|
32320
32377
|
const { x: X3, y: Y3, rotate: R, text: T, title: TL, fontSize: FS } = channels;
|
|
32321
32378
|
const { rotate } = this;
|
|
32322
32379
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
@@ -32739,8 +32796,8 @@ var Vector2 = class extends Mark {
|
|
|
32739
32796
|
this.anchor = keyword(anchor, "anchor", ["start", "middle", "end"]);
|
|
32740
32797
|
this.frameAnchor = maybeFrameAnchor(frameAnchor);
|
|
32741
32798
|
}
|
|
32742
|
-
render(index2,
|
|
32743
|
-
const { x: x3, y: y3 } =
|
|
32799
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
32800
|
+
const { x: x3, y: y3 } = scales2;
|
|
32744
32801
|
const { x: X3, y: Y3, length: L, rotate: A5 } = channels;
|
|
32745
32802
|
const { length: length4, rotate, anchor, shape, r } = this;
|
|
32746
32803
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
@@ -32892,8 +32949,8 @@ function axisKy(k2, anchor, data, {
|
|
|
32892
32949
|
}) : null,
|
|
32893
32950
|
!isNoneish(fill) && label !== null ? text(
|
|
32894
32951
|
[],
|
|
32895
|
-
labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels,
|
|
32896
|
-
const scale3 =
|
|
32952
|
+
labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {
|
|
32953
|
+
const scale3 = scales2[k2];
|
|
32897
32954
|
const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = k2 === "y" && dimensions.inset || dimensions;
|
|
32898
32955
|
const cla = labelAnchor ?? (scale3.bandwidth ? "center" : "top");
|
|
32899
32956
|
const clo = labelOffset ?? (anchor === "right" ? marginRight2 : marginLeft2) - 3;
|
|
@@ -32982,8 +33039,8 @@ function axisKx(k2, anchor, data, {
|
|
|
32982
33039
|
}) : null,
|
|
32983
33040
|
!isNoneish(fill) && label !== null ? text(
|
|
32984
33041
|
[],
|
|
32985
|
-
labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels,
|
|
32986
|
-
const scale3 =
|
|
33042
|
+
labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {
|
|
33043
|
+
const scale3 = scales2[k2];
|
|
32987
33044
|
const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = k2 === "x" && dimensions.inset || dimensions;
|
|
32988
33045
|
const cla = labelAnchor ?? (scale3.bandwidth ? "center" : "right");
|
|
32989
33046
|
const clo = labelOffset ?? (anchor === "top" ? marginTop2 : marginBottom2) - 3;
|
|
@@ -33227,9 +33284,9 @@ function labelOptions({
|
|
|
33227
33284
|
}
|
|
33228
33285
|
function axisMark(mark, k2, anchor, ariaLabel, data, options, initialize) {
|
|
33229
33286
|
let channels;
|
|
33230
|
-
function axisInitializer(data2, facets, _channels,
|
|
33287
|
+
function axisInitializer(data2, facets, _channels, scales2, dimensions, context) {
|
|
33231
33288
|
const initializeFacets = data2 == null && (k2 === "fx" || k2 === "fy");
|
|
33232
|
-
const { [k2]: scale3 } =
|
|
33289
|
+
const { [k2]: scale3 } = scales2;
|
|
33233
33290
|
if (!scale3)
|
|
33234
33291
|
throw new Error(`missing scale: ${k2}`);
|
|
33235
33292
|
const domain = scale3.domain();
|
|
@@ -33516,13 +33573,13 @@ function legend(options = {}) {
|
|
|
33516
33573
|
}
|
|
33517
33574
|
throw new Error("unknown legend type; no scale found");
|
|
33518
33575
|
}
|
|
33519
|
-
function exposeLegends(
|
|
33576
|
+
function exposeLegends(scales2, context, defaults23 = {}) {
|
|
33520
33577
|
return (key, options) => {
|
|
33521
33578
|
if (!legendRegistry.has(key))
|
|
33522
33579
|
throw new Error(`unknown legend type: ${key}`);
|
|
33523
|
-
if (!(key in
|
|
33580
|
+
if (!(key in scales2))
|
|
33524
33581
|
return;
|
|
33525
|
-
return legendRegistry.get(key)(
|
|
33582
|
+
return legendRegistry.get(key)(scales2[key], legendOptions(context, defaults23[key], options), (key2) => scales2[key2]);
|
|
33526
33583
|
};
|
|
33527
33584
|
}
|
|
33528
33585
|
function legendOptions({ className, ...context }, { label, ticks: ticks2, tickFormat: tickFormat2 } = {}, options) {
|
|
@@ -33555,12 +33612,12 @@ function interpolateOpacity(color3) {
|
|
|
33555
33612
|
const { r, g, b } = rgb(color3) || rgb(0, 0, 0);
|
|
33556
33613
|
return (t) => `rgba(${r},${g},${b},${t})`;
|
|
33557
33614
|
}
|
|
33558
|
-
function createLegends(
|
|
33615
|
+
function createLegends(scales2, context, options) {
|
|
33559
33616
|
const legends = [];
|
|
33560
33617
|
for (const [key, value] of legendRegistry) {
|
|
33561
33618
|
const o = options[key];
|
|
33562
|
-
if (o?.legend && key in
|
|
33563
|
-
const legend2 = value(
|
|
33619
|
+
if (o?.legend && key in scales2) {
|
|
33620
|
+
const legend2 = value(scales2[key], legendOptions(context, scales2[key], o), (key2) => scales2[key2]);
|
|
33564
33621
|
if (legend2 != null)
|
|
33565
33622
|
legends.push(legend2);
|
|
33566
33623
|
}
|
|
@@ -33603,7 +33660,7 @@ var Frame = class extends Mark {
|
|
|
33603
33660
|
this.rx = number5(rx);
|
|
33604
33661
|
this.ry = number5(ry);
|
|
33605
33662
|
}
|
|
33606
|
-
render(index2,
|
|
33663
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
33607
33664
|
const { marginTop, marginRight, marginBottom, marginLeft, width, height } = dimensions;
|
|
33608
33665
|
const { anchor, insetTop, insetRight, insetBottom, insetLeft, rx, ry } = this;
|
|
33609
33666
|
const x12 = marginLeft + insetLeft;
|
|
@@ -33698,9 +33755,9 @@ var Tip = class extends Mark {
|
|
|
33698
33755
|
this.clipLine = clipper(this);
|
|
33699
33756
|
this.format = { ...format3 };
|
|
33700
33757
|
}
|
|
33701
|
-
render(index2,
|
|
33758
|
+
render(index2, scales2, values2, dimensions, context) {
|
|
33702
33759
|
const mark = this;
|
|
33703
|
-
const { x: x3, y: y3, fx, fy } =
|
|
33760
|
+
const { x: x3, y: y3, fx, fy } = scales2;
|
|
33704
33761
|
const { ownerSVGElement: svg, document: document2 } = context;
|
|
33705
33762
|
const { anchor, monospace, lineHeight, lineWidth } = this;
|
|
33706
33763
|
const { textPadding: r, pointerSize: m, pathFilter } = this;
|
|
@@ -33718,7 +33775,7 @@ var Tip = class extends Mark {
|
|
|
33718
33775
|
sources = values2.channels;
|
|
33719
33776
|
format3 = formatTitle;
|
|
33720
33777
|
} else {
|
|
33721
|
-
sources = getSourceChannels.call(this, values2,
|
|
33778
|
+
sources = getSourceChannels.call(this, values2, scales2);
|
|
33722
33779
|
format3 = formatChannels;
|
|
33723
33780
|
}
|
|
33724
33781
|
const g = create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyIndirectTextStyles, this).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(
|
|
@@ -33728,7 +33785,7 @@ var Tip = class extends Mark {
|
|
|
33728
33785
|
this.setAttribute("fill", "currentColor");
|
|
33729
33786
|
this.setAttribute("fill-opacity", 1);
|
|
33730
33787
|
this.setAttribute("stroke", "none");
|
|
33731
|
-
const lines = format3.call(mark, i, index2, sources,
|
|
33788
|
+
const lines = format3.call(mark, i, index2, sources, scales2, values2);
|
|
33732
33789
|
if (typeof lines === "string") {
|
|
33733
33790
|
for (const line2 of mark.splitLines(lines)) {
|
|
33734
33791
|
renderLine(that, { value: mark.clipLine(line2) });
|
|
@@ -33866,7 +33923,7 @@ function getPath(anchor, m, r, width, height) {
|
|
|
33866
33923
|
return `M0,0l${m / 2},${-m / 2}v${m / 2 - h / 2}h${w}v${h}h${-w}v${m / 2 - h / 2}z`;
|
|
33867
33924
|
}
|
|
33868
33925
|
}
|
|
33869
|
-
function getSourceChannels({ channels },
|
|
33926
|
+
function getSourceChannels({ channels }, scales2) {
|
|
33870
33927
|
const sources = {};
|
|
33871
33928
|
let format3 = this.format;
|
|
33872
33929
|
format3 = maybeExpandPairedFormat(format3, channels, "x");
|
|
@@ -33892,18 +33949,18 @@ function getSourceChannels({ channels }, scales) {
|
|
|
33892
33949
|
sources[key] = source;
|
|
33893
33950
|
}
|
|
33894
33951
|
if (this.facet) {
|
|
33895
|
-
if (
|
|
33952
|
+
if (scales2.fx && !("fx" in format3))
|
|
33896
33953
|
sources.fx = true;
|
|
33897
|
-
if (
|
|
33954
|
+
if (scales2.fy && !("fy" in format3))
|
|
33898
33955
|
sources.fy = true;
|
|
33899
33956
|
}
|
|
33900
33957
|
for (const key in sources) {
|
|
33901
33958
|
const format4 = this.format[key];
|
|
33902
33959
|
if (typeof format4 === "string") {
|
|
33903
|
-
const value = sources[key]?.value ??
|
|
33960
|
+
const value = sources[key]?.value ?? scales2[key]?.domain() ?? [];
|
|
33904
33961
|
this.format[key] = (isTemporal(value) ? utcFormat : format)(format4);
|
|
33905
33962
|
} else if (format4 === void 0 || format4 === true) {
|
|
33906
|
-
const scale3 =
|
|
33963
|
+
const scale3 = scales2[key];
|
|
33907
33964
|
this.format[key] = scale3?.bandwidth ? inferTickFormat(scale3, scale3.domain()) : formatDefault;
|
|
33908
33965
|
}
|
|
33909
33966
|
}
|
|
@@ -33924,11 +33981,11 @@ function maybeExpandPairedFormat(format3, channels, key) {
|
|
|
33924
33981
|
function formatTitle(i, index2, { title }) {
|
|
33925
33982
|
return formatDefault(title.value[i], i);
|
|
33926
33983
|
}
|
|
33927
|
-
function* formatChannels(i, index2, channels,
|
|
33984
|
+
function* formatChannels(i, index2, channels, scales2, values2) {
|
|
33928
33985
|
for (const key in channels) {
|
|
33929
33986
|
if (key === "fx" || key === "fy") {
|
|
33930
33987
|
yield {
|
|
33931
|
-
label: formatLabel(
|
|
33988
|
+
label: formatLabel(scales2, channels, key),
|
|
33932
33989
|
value: this.format[key](index2[key], i)
|
|
33933
33990
|
};
|
|
33934
33991
|
continue;
|
|
@@ -33940,12 +33997,12 @@ function* formatChannels(i, index2, channels, scales, values2) {
|
|
|
33940
33997
|
const channel = channels[key];
|
|
33941
33998
|
if (key === "x2" && "x1" in channels) {
|
|
33942
33999
|
yield {
|
|
33943
|
-
label: formatPairLabel(
|
|
34000
|
+
label: formatPairLabel(scales2, channels, "x"),
|
|
33944
34001
|
value: formatPair(this.format.x2, channels.x1, channel, i)
|
|
33945
34002
|
};
|
|
33946
34003
|
} else if (key === "y2" && "y1" in channels) {
|
|
33947
34004
|
yield {
|
|
33948
|
-
label: formatPairLabel(
|
|
34005
|
+
label: formatPairLabel(scales2, channels, "y"),
|
|
33949
34006
|
value: formatPair(this.format.y2, channels.y1, channel, i)
|
|
33950
34007
|
};
|
|
33951
34008
|
} else {
|
|
@@ -33954,7 +34011,7 @@ function* formatChannels(i, index2, channels, scales, values2) {
|
|
|
33954
34011
|
if (!defined(value) && scale3 == null)
|
|
33955
34012
|
continue;
|
|
33956
34013
|
yield {
|
|
33957
|
-
label: formatLabel(
|
|
34014
|
+
label: formatLabel(scales2, channels, key),
|
|
33958
34015
|
value: this.format[key](value, i),
|
|
33959
34016
|
color: scale3 === "color" ? values2[key][i] : null,
|
|
33960
34017
|
opacity: scale3 === "opacity" ? values2[key][i] : null
|
|
@@ -33965,14 +34022,14 @@ function* formatChannels(i, index2, channels, scales, values2) {
|
|
|
33965
34022
|
function formatPair(formatValue, c1, c22, i) {
|
|
33966
34023
|
return c22.hint?.length ? `${formatValue(c22.value[i] - c1.value[i], i)}` : `${formatValue(c1.value[i], i)}\u2013${formatValue(c22.value[i], i)}`;
|
|
33967
34024
|
}
|
|
33968
|
-
function formatPairLabel(
|
|
33969
|
-
const l1 = formatLabel(
|
|
33970
|
-
const l2 = formatLabel(
|
|
34025
|
+
function formatPairLabel(scales2, channels, key) {
|
|
34026
|
+
const l1 = formatLabel(scales2, channels, `${key}1`, key);
|
|
34027
|
+
const l2 = formatLabel(scales2, channels, `${key}2`, key);
|
|
33971
34028
|
return l1 === l2 ? l1 : `${l1}\u2013${l2}`;
|
|
33972
34029
|
}
|
|
33973
|
-
function formatLabel(
|
|
34030
|
+
function formatLabel(scales2, channels, key, defaultLabel = key) {
|
|
33974
34031
|
const channel = channels[key];
|
|
33975
|
-
const scale3 =
|
|
34032
|
+
const scale3 = scales2[channel?.scale ?? key];
|
|
33976
34033
|
return String(scale3?.label ?? channel?.label ?? defaultLabel);
|
|
33977
34034
|
}
|
|
33978
34035
|
|
|
@@ -34047,10 +34104,10 @@ function plot(options = {}) {
|
|
|
34047
34104
|
const scaleDescriptors = createScales(addScaleChannels(channelsByScale, stateByMark, options), options);
|
|
34048
34105
|
const dimensions = createDimensions(scaleDescriptors, marks2, options);
|
|
34049
34106
|
autoScaleRange(scaleDescriptors, dimensions);
|
|
34050
|
-
const
|
|
34051
|
-
const { fx, fy } =
|
|
34107
|
+
const scales2 = createScaleFunctions(scaleDescriptors);
|
|
34108
|
+
const { fx, fy } = scales2;
|
|
34052
34109
|
const subdimensions = fx || fy ? innerDimensions(scaleDescriptors, dimensions) : dimensions;
|
|
34053
|
-
const superdimensions = fx || fy ? actualDimensions(
|
|
34110
|
+
const superdimensions = fx || fy ? actualDimensions(scales2, dimensions) : dimensions;
|
|
34054
34111
|
const context = createContext(options);
|
|
34055
34112
|
const document2 = context.document;
|
|
34056
34113
|
const svg = creator_default("svg").call(document2.documentElement);
|
|
@@ -34076,7 +34133,7 @@ function plot(options = {}) {
|
|
|
34076
34133
|
for (const [mark, state] of stateByMark) {
|
|
34077
34134
|
if (mark.initializer != null) {
|
|
34078
34135
|
const dimensions2 = mark.facet === "super" ? superdimensions : subdimensions;
|
|
34079
|
-
const update2 = mark.initializer(state.data, state.facets, state.channels,
|
|
34136
|
+
const update2 = mark.initializer(state.data, state.facets, state.channels, scales2, dimensions2, context);
|
|
34080
34137
|
if (update2.data !== void 0) {
|
|
34081
34138
|
state.data = update2.data;
|
|
34082
34139
|
}
|
|
@@ -34106,8 +34163,8 @@ function plot(options = {}) {
|
|
|
34106
34163
|
const newScaleDescriptors = inheritScaleLabels(createScales(newChannelsByScale, options), scaleDescriptors);
|
|
34107
34164
|
const { scales: newExposedScales, ...newScales } = createScaleFunctions(newScaleDescriptors);
|
|
34108
34165
|
Object.assign(scaleDescriptors, newScaleDescriptors);
|
|
34109
|
-
Object.assign(
|
|
34110
|
-
Object.assign(
|
|
34166
|
+
Object.assign(scales2, newScales);
|
|
34167
|
+
Object.assign(scales2.scales, newExposedScales);
|
|
34111
34168
|
}
|
|
34112
34169
|
let facetDomains, facetTranslate;
|
|
34113
34170
|
if (facets !== void 0) {
|
|
@@ -34116,7 +34173,7 @@ function plot(options = {}) {
|
|
|
34116
34173
|
facetTranslate = facetTranslator(fx, fy, dimensions);
|
|
34117
34174
|
}
|
|
34118
34175
|
for (const [mark, state] of stateByMark) {
|
|
34119
|
-
state.values = mark.scale(state.channels,
|
|
34176
|
+
state.values = mark.scale(state.channels, scales2, context);
|
|
34120
34177
|
}
|
|
34121
34178
|
const { width, height } = dimensions;
|
|
34122
34179
|
select_default2(svg).attr("class", className).attr("fill", "currentColor").attr("font-family", "system-ui, sans-serif").attr("font-size", 10).attr("text-anchor", "middle").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("aria-label", ariaLabel).attr("aria-description", ariaDescription).call(
|
|
@@ -34147,7 +34204,7 @@ function plot(options = {}) {
|
|
|
34147
34204
|
if (index2.length === 0)
|
|
34148
34205
|
continue;
|
|
34149
34206
|
}
|
|
34150
|
-
const node = mark.render(index2,
|
|
34207
|
+
const node = mark.render(index2, scales2, values2, superdimensions, context);
|
|
34151
34208
|
if (node == null)
|
|
34152
34209
|
continue;
|
|
34153
34210
|
svg.appendChild(node);
|
|
@@ -34167,7 +34224,7 @@ function plot(options = {}) {
|
|
|
34167
34224
|
index2 = subarray(index2);
|
|
34168
34225
|
index2.fx = f.x, index2.fy = f.y, index2.fi = f.i;
|
|
34169
34226
|
}
|
|
34170
|
-
const node = mark.render(index2,
|
|
34227
|
+
const node = mark.render(index2, scales2, values2, subdimensions, context);
|
|
34171
34228
|
if (node == null)
|
|
34172
34229
|
continue;
|
|
34173
34230
|
(g ??= select_default2(svg).append("g")).append(() => node).datum(f);
|
|
@@ -34195,7 +34252,7 @@ function plot(options = {}) {
|
|
|
34195
34252
|
if (caption != null)
|
|
34196
34253
|
figure.append(createFigcaption(document2, caption));
|
|
34197
34254
|
}
|
|
34198
|
-
figure.scale = exposeScales(
|
|
34255
|
+
figure.scale = exposeScales(scales2.scales);
|
|
34199
34256
|
figure.legend = exposeLegends(scaleDescriptors, context, options);
|
|
34200
34257
|
figure.projection = context.projection;
|
|
34201
34258
|
const w = consumeWarnings();
|
|
@@ -34342,7 +34399,7 @@ function maybeMarkFacet(mark, topFacetState, options) {
|
|
|
34342
34399
|
}
|
|
34343
34400
|
}
|
|
34344
34401
|
function derive(mark, options = {}) {
|
|
34345
|
-
return initializer({ ...options, x: null, y: null }, (data, facets, channels,
|
|
34402
|
+
return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales2, dimensions, context) => {
|
|
34346
34403
|
return context.getMarkState(mark);
|
|
34347
34404
|
});
|
|
34348
34405
|
}
|
|
@@ -34517,10 +34574,10 @@ function hasPositionChannel(k2, marks2) {
|
|
|
34517
34574
|
}
|
|
34518
34575
|
return false;
|
|
34519
34576
|
}
|
|
34520
|
-
function inheritScaleLabels(newScales,
|
|
34577
|
+
function inheritScaleLabels(newScales, scales2) {
|
|
34521
34578
|
for (const key in newScales) {
|
|
34522
34579
|
const newScale = newScales[key];
|
|
34523
|
-
const scale3 =
|
|
34580
|
+
const scale3 = scales2[key];
|
|
34524
34581
|
if (newScale.label === void 0 && scale3) {
|
|
34525
34582
|
newScale.label = scale3.label;
|
|
34526
34583
|
}
|
|
@@ -35408,9 +35465,9 @@ var Area = class extends Mark {
|
|
|
35408
35465
|
filter(index2) {
|
|
35409
35466
|
return index2;
|
|
35410
35467
|
}
|
|
35411
|
-
render(index2,
|
|
35468
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
35412
35469
|
const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;
|
|
35413
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
35470
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2, 0, 0).call(
|
|
35414
35471
|
(g) => g.selectAll().data(groupIndex(index2, [X13, Y13, X23, Y23], this, channels)).enter().append("path").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).attr(
|
|
35415
35472
|
"d",
|
|
35416
35473
|
area_default3().curve(this.curve).defined((i) => i >= 0).x0((i) => X13[i]).y0((i) => Y13[i]).x1((i) => X23[i]).y1((i) => Y23[i])
|
|
@@ -35461,10 +35518,10 @@ var Link = class extends Mark {
|
|
|
35461
35518
|
super.project(channels, values2, context);
|
|
35462
35519
|
}
|
|
35463
35520
|
}
|
|
35464
|
-
render(index2,
|
|
35521
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
35465
35522
|
const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;
|
|
35466
35523
|
const { curve } = this;
|
|
35467
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
35524
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
|
|
35468
35525
|
(g) => g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr(
|
|
35469
35526
|
"d",
|
|
35470
35527
|
curve === curveAuto && context.projection ? sphereLink(context.projection, X13, Y13, X23, Y23) : (i) => {
|
|
@@ -35559,13 +35616,13 @@ var Arrow = class extends Mark {
|
|
|
35559
35616
|
this.insetEnd = +insetEnd;
|
|
35560
35617
|
this.sweep = maybeSweep(sweep);
|
|
35561
35618
|
}
|
|
35562
|
-
render(index2,
|
|
35619
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
35563
35620
|
const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13, SW } = channels;
|
|
35564
35621
|
const { strokeWidth, bend, headAngle, headLength, insetStart, insetEnd } = this;
|
|
35565
35622
|
const sw = SW ? (i) => SW[i] : constant(strokeWidth === void 0 ? 1 : strokeWidth);
|
|
35566
35623
|
const wingAngle = headAngle * radians3 / 2;
|
|
35567
35624
|
const wingScale = headLength / 1.5;
|
|
35568
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
35625
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
|
|
35569
35626
|
(g) => g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr("d", (i) => {
|
|
35570
35627
|
let x12 = X13[i], y12 = Y13[i], x22 = X23[i], y22 = Y23[i];
|
|
35571
35628
|
const lineLength = Math.hypot(x22 - x12, y22 - y12);
|
|
@@ -35654,17 +35711,17 @@ var AbstractBar = class extends Mark {
|
|
|
35654
35711
|
this.rx = impliedString(rx, "auto");
|
|
35655
35712
|
this.ry = impliedString(ry, "auto");
|
|
35656
35713
|
}
|
|
35657
|
-
render(index2,
|
|
35714
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
35658
35715
|
const { rx, ry } = this;
|
|
35659
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this,
|
|
35660
|
-
(g) => g.selectAll().data(index2).enter().append("rect").call(applyDirectStyles, this).attr("x", this._x(
|
|
35716
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(
|
|
35717
|
+
(g) => g.selectAll().data(index2).enter().append("rect").call(applyDirectStyles, this).attr("x", this._x(scales2, channels, dimensions)).attr("width", this._width(scales2, channels, dimensions)).attr("y", this._y(scales2, channels, dimensions)).attr("height", this._height(scales2, channels, dimensions)).call(applyAttr, "rx", rx).call(applyAttr, "ry", ry).call(applyChannelStyles, this, channels)
|
|
35661
35718
|
).node();
|
|
35662
35719
|
}
|
|
35663
|
-
_x(
|
|
35720
|
+
_x(scales2, { x: X3 }, { marginLeft }) {
|
|
35664
35721
|
const { insetLeft } = this;
|
|
35665
35722
|
return X3 ? (i) => X3[i] + insetLeft : marginLeft + insetLeft;
|
|
35666
35723
|
}
|
|
35667
|
-
_y(
|
|
35724
|
+
_y(scales2, { y: Y3 }, { marginTop }) {
|
|
35668
35725
|
const { insetTop } = this;
|
|
35669
35726
|
return Y3 ? (i) => Y3[i] + insetTop : marginTop + insetTop;
|
|
35670
35727
|
}
|
|
@@ -35822,8 +35879,8 @@ var Dot = class extends Mark {
|
|
|
35822
35879
|
};
|
|
35823
35880
|
}
|
|
35824
35881
|
}
|
|
35825
|
-
render(index2,
|
|
35826
|
-
const { x: x3, y: y3 } =
|
|
35882
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
35883
|
+
const { x: x3, y: y3 } = scales2;
|
|
35827
35884
|
const { x: X3, y: Y3, r: R, rotate: A5, symbol: S } = channels;
|
|
35828
35885
|
const { r, rotate, symbol: symbol2 } = this;
|
|
35829
35886
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
@@ -35917,10 +35974,10 @@ var Line = class extends Mark {
|
|
|
35917
35974
|
super.project(channels, values2, context);
|
|
35918
35975
|
}
|
|
35919
35976
|
}
|
|
35920
|
-
render(index2,
|
|
35977
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
35921
35978
|
const { x: X3, y: Y3 } = channels;
|
|
35922
35979
|
const { curve } = this;
|
|
35923
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
35980
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
|
|
35924
35981
|
(g) => g.selectAll().data(groupIndex(index2, [X3, Y3], this, channels)).enter().append("path").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).call(applyGroupedMarkers, this, channels, context).attr(
|
|
35925
35982
|
"d",
|
|
35926
35983
|
curve === curveAuto && context.projection ? sphereLine(context.projection, X3, Y3) : line_default2().curve(curve).defined((i) => i >= 0).x((i) => X3[i]).y((i) => Y3[i])
|
|
@@ -35994,8 +36051,8 @@ var Rect = class extends Mark {
|
|
|
35994
36051
|
this.rx = impliedString(rx, "auto");
|
|
35995
36052
|
this.ry = impliedString(ry, "auto");
|
|
35996
36053
|
}
|
|
35997
|
-
render(index2,
|
|
35998
|
-
const { x: x3, y: y3 } =
|
|
36054
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
36055
|
+
const { x: x3, y: y3 } = scales2;
|
|
35999
36056
|
const { x1: X13, y1: Y13, x2: X23, y2: Y23 } = channels;
|
|
36000
36057
|
const { marginTop, marginRight, marginBottom, marginLeft, width, height } = dimensions;
|
|
36001
36058
|
const { projection: projection3 } = context;
|
|
@@ -36771,9 +36828,9 @@ var AbstractTick = class extends Mark {
|
|
|
36771
36828
|
super(data, channels, options, defaults15);
|
|
36772
36829
|
markers(this, options);
|
|
36773
36830
|
}
|
|
36774
|
-
render(index2,
|
|
36775
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this,
|
|
36776
|
-
(g) => g.selectAll().data(index2).enter().append("line").call(applyDirectStyles, this).attr("x1", this._x1(
|
|
36831
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
36832
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(
|
|
36833
|
+
(g) => g.selectAll().data(index2).enter().append("line").call(applyDirectStyles, this).attr("x1", this._x1(scales2, channels, dimensions)).attr("x2", this._x2(scales2, channels, dimensions)).attr("y1", this._y1(scales2, channels, dimensions)).attr("y2", this._y2(scales2, channels, dimensions)).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)
|
|
36777
36834
|
).node();
|
|
36778
36835
|
}
|
|
36779
36836
|
};
|
|
@@ -36794,10 +36851,10 @@ var TickX = class extends AbstractTick {
|
|
|
36794
36851
|
_transform(selection2, mark, { x: x3 }) {
|
|
36795
36852
|
selection2.call(applyTransform, mark, { x: x3 }, offset, 0);
|
|
36796
36853
|
}
|
|
36797
|
-
_x1(
|
|
36854
|
+
_x1(scales2, { x: X3 }) {
|
|
36798
36855
|
return (i) => X3[i];
|
|
36799
36856
|
}
|
|
36800
|
-
_x2(
|
|
36857
|
+
_x2(scales2, { x: X3 }) {
|
|
36801
36858
|
return (i) => X3[i];
|
|
36802
36859
|
}
|
|
36803
36860
|
_y1({ y: y3 }, { y: Y3 }, { marginTop }) {
|
|
@@ -36834,10 +36891,10 @@ var TickY = class extends AbstractTick {
|
|
|
36834
36891
|
const { insetRight } = this;
|
|
36835
36892
|
return X3 && x3 ? (i) => X3[i] + x3.bandwidth() - insetRight : width - marginRight - insetRight;
|
|
36836
36893
|
}
|
|
36837
|
-
_y1(
|
|
36894
|
+
_y1(scales2, { y: Y3 }) {
|
|
36838
36895
|
return (i) => Y3[i];
|
|
36839
36896
|
}
|
|
36840
|
-
_y2(
|
|
36897
|
+
_y2(scales2, { y: Y3 }) {
|
|
36841
36898
|
return (i) => Y3[i];
|
|
36842
36899
|
}
|
|
36843
36900
|
};
|
|
@@ -36997,11 +37054,11 @@ var Raster = class extends AbstractRaster {
|
|
|
36997
37054
|
this.imageRendering = impliedString(imageRendering, "auto");
|
|
36998
37055
|
}
|
|
36999
37056
|
// Ignore the color scale, so the fill channel is returned unscaled.
|
|
37000
|
-
scale(channels, { color: color3, ...
|
|
37001
|
-
return super.scale(channels,
|
|
37057
|
+
scale(channels, { color: color3, ...scales2 }, context) {
|
|
37058
|
+
return super.scale(channels, scales2, context);
|
|
37002
37059
|
}
|
|
37003
|
-
render(index2,
|
|
37004
|
-
const color3 =
|
|
37060
|
+
render(index2, scales2, values2, dimensions, context) {
|
|
37061
|
+
const color3 = scales2[values2.channels.fill?.scale] ?? ((x3) => x3);
|
|
37005
37062
|
const { x: X3, y: Y3 } = values2;
|
|
37006
37063
|
const { document: document2 } = context;
|
|
37007
37064
|
const [x12, y12, x22, y22] = renderBounds(values2, dimensions, context);
|
|
@@ -37050,7 +37107,7 @@ var Raster = class extends AbstractRaster {
|
|
|
37050
37107
|
if (this.blur > 0)
|
|
37051
37108
|
blurImage(image2, this.blur);
|
|
37052
37109
|
context2d.putImageData(image2, 0, 0);
|
|
37053
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
37110
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
|
|
37054
37111
|
(g2) => g2.append("image").attr("transform", `translate(${x12},${y12}) scale(${Math.sign(x22 - x12)},${Math.sign(y22 - y12)})`).attr("width", Math.abs(dx)).attr("height", Math.abs(dy)).attr("preserveAspectRatio", "none").call(applyAttr, "image-rendering", this.imageRendering).call(applyDirectStyles, this).attr("xlink:href", canvas.toDataURL())
|
|
37055
37112
|
).node();
|
|
37056
37113
|
}
|
|
@@ -37082,7 +37139,7 @@ function renderBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, dimensions, { proj
|
|
|
37082
37139
|
y22 && projection3 == null ? y22[0] : height - marginBottom
|
|
37083
37140
|
];
|
|
37084
37141
|
}
|
|
37085
|
-
function rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 },
|
|
37142
|
+
function rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, scales2, dimensions, context) {
|
|
37086
37143
|
const channels = {};
|
|
37087
37144
|
if (x12)
|
|
37088
37145
|
channels.x1 = x12;
|
|
@@ -37092,19 +37149,19 @@ function rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, scales, dimensions
|
|
|
37092
37149
|
channels.x2 = x22;
|
|
37093
37150
|
if (y22)
|
|
37094
37151
|
channels.y2 = y22;
|
|
37095
|
-
return renderBounds(valueObject(channels,
|
|
37152
|
+
return renderBounds(valueObject(channels, scales2), dimensions, context);
|
|
37096
37153
|
}
|
|
37097
37154
|
function sampler(name, options = {}) {
|
|
37098
37155
|
const { [name]: value } = options;
|
|
37099
37156
|
if (typeof value !== "function")
|
|
37100
37157
|
throw new Error(`invalid ${name}: not a function`);
|
|
37101
|
-
return initializer({ ...options, [name]: void 0 }, function(data, facets, channels,
|
|
37102
|
-
const { x: x3, y: y3 } =
|
|
37158
|
+
return initializer({ ...options, [name]: void 0 }, function(data, facets, channels, scales2, dimensions, context) {
|
|
37159
|
+
const { x: x3, y: y3 } = scales2;
|
|
37103
37160
|
if (!x3)
|
|
37104
37161
|
throw new Error("missing scale: x");
|
|
37105
37162
|
if (!y3)
|
|
37106
37163
|
throw new Error("missing scale: y");
|
|
37107
|
-
const [x12, y12, x22, y22] = rasterBounds(channels,
|
|
37164
|
+
const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);
|
|
37108
37165
|
const dx = x22 - x12;
|
|
37109
37166
|
const dy = y22 - y12;
|
|
37110
37167
|
const { pixelSize: k2 } = this;
|
|
@@ -37414,18 +37471,18 @@ var Contour = class extends AbstractRaster {
|
|
|
37414
37471
|
filter(index2, { x: x3, y: y3, value, ...channels }, values2) {
|
|
37415
37472
|
return super.filter(index2, channels, values2);
|
|
37416
37473
|
}
|
|
37417
|
-
render(index2,
|
|
37474
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
37418
37475
|
const { geometry: G } = channels;
|
|
37419
37476
|
const path2 = path_default();
|
|
37420
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
37477
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {
|
|
37421
37478
|
g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr("d", (i) => path2(G[i])).call(applyChannelStyles, this, channels);
|
|
37422
37479
|
}).node();
|
|
37423
37480
|
}
|
|
37424
37481
|
};
|
|
37425
37482
|
function contourGeometry({ thresholds, interval: interval2, ...options }) {
|
|
37426
37483
|
thresholds = maybeThresholds(thresholds, interval2, thresholdSturges);
|
|
37427
|
-
return initializer(options, function(data, facets, channels,
|
|
37428
|
-
const [x12, y12, x22, y22] = rasterBounds(channels,
|
|
37484
|
+
return initializer(options, function(data, facets, channels, scales2, dimensions, context) {
|
|
37485
|
+
const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);
|
|
37429
37486
|
const dx = x22 - x12;
|
|
37430
37487
|
const dy = y22 - y12;
|
|
37431
37488
|
const { pixelSize: k2, width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = this;
|
|
@@ -37434,7 +37491,7 @@ function contourGeometry({ thresholds, interval: interval2, ...options }) {
|
|
|
37434
37491
|
const V = channels.value.value;
|
|
37435
37492
|
const VV = [];
|
|
37436
37493
|
if (this.interpolate) {
|
|
37437
|
-
const { x: X3, y: Y3 } = applyPosition(channels,
|
|
37494
|
+
const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);
|
|
37438
37495
|
const IX = map2(X3, (x3) => (x3 - x12) * kx2, Float64Array);
|
|
37439
37496
|
const IY = map2(Y3, (y3) => (y3 - y12) * ky2, Float64Array);
|
|
37440
37497
|
const ichannels = [channels.x, channels.y, channels.value];
|
|
@@ -37645,8 +37702,8 @@ var DelaunayLink = class extends Mark {
|
|
|
37645
37702
|
this.curve = maybeCurve(curve, tension);
|
|
37646
37703
|
markers(this, options);
|
|
37647
37704
|
}
|
|
37648
|
-
render(index2,
|
|
37649
|
-
const { x: x3, y: y3 } =
|
|
37705
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
37706
|
+
const { x: x3, y: y3 } = scales2;
|
|
37650
37707
|
const { x: X3, y: Y3, z: Z } = channels;
|
|
37651
37708
|
const { curve } = this;
|
|
37652
37709
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
@@ -37712,8 +37769,8 @@ var AbstractDelaunayMark = class extends Mark {
|
|
|
37712
37769
|
defaults23
|
|
37713
37770
|
);
|
|
37714
37771
|
}
|
|
37715
|
-
render(index2,
|
|
37716
|
-
const { x: x3, y: y3 } =
|
|
37772
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
37773
|
+
const { x: x3, y: y3 } = scales2;
|
|
37717
37774
|
const { x: X3, y: Y3, z: Z } = channels;
|
|
37718
37775
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
37719
37776
|
const xi = X3 ? (i) => X3[i] : constant(cx);
|
|
@@ -37759,8 +37816,8 @@ var Voronoi2 = class extends Mark {
|
|
|
37759
37816
|
voronoiDefaults
|
|
37760
37817
|
);
|
|
37761
37818
|
}
|
|
37762
|
-
render(index2,
|
|
37763
|
-
const { x: x3, y: y3 } =
|
|
37819
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
37820
|
+
const { x: x3, y: y3 } = scales2;
|
|
37764
37821
|
const { x: X3, y: Y3, z: Z } = channels;
|
|
37765
37822
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
37766
37823
|
const xi = X3 ? (i) => X3[i] : constant(cx);
|
|
@@ -37840,7 +37897,7 @@ var Density = class extends Mark {
|
|
|
37840
37897
|
filter(index2) {
|
|
37841
37898
|
return index2;
|
|
37842
37899
|
}
|
|
37843
|
-
render(index2,
|
|
37900
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
37844
37901
|
const { contours } = channels;
|
|
37845
37902
|
const path2 = path_default();
|
|
37846
37903
|
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}).call(
|
|
@@ -37858,13 +37915,13 @@ function densityInitializer(options, fillDensity, strokeDensity) {
|
|
|
37858
37915
|
let { bandwidth, thresholds } = options;
|
|
37859
37916
|
bandwidth = bandwidth === void 0 ? 20 : +bandwidth;
|
|
37860
37917
|
thresholds = thresholds === void 0 ? 20 : typeof thresholds?.[Symbol.iterator] === "function" ? coerceNumbers(thresholds) : +thresholds;
|
|
37861
|
-
return initializer(options, function(data, facets, channels,
|
|
37918
|
+
return initializer(options, function(data, facets, channels, scales2, dimensions, context) {
|
|
37862
37919
|
const W = channels.weight ? coerceNumbers(channels.weight.value) : null;
|
|
37863
37920
|
const Z = channels.z?.value;
|
|
37864
37921
|
const { z } = this;
|
|
37865
37922
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
37866
37923
|
const { width, height } = dimensions;
|
|
37867
|
-
const { x: X3, y: Y3 } = applyPosition(channels,
|
|
37924
|
+
const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);
|
|
37868
37925
|
const newChannels = Object.fromEntries(
|
|
37869
37926
|
Object.entries(channels).filter(([key]) => !dropChannels.has(key)).map(([key, channel]) => [key, { ...channel, value: [] }])
|
|
37870
37927
|
);
|
|
@@ -38024,14 +38081,14 @@ function memo(v2) {
|
|
|
38024
38081
|
return { transform: (data) => V || (V = valueof(data, value)), label };
|
|
38025
38082
|
}
|
|
38026
38083
|
function clipDifferenceY(positive2) {
|
|
38027
|
-
return (index2,
|
|
38084
|
+
return (index2, scales2, channels, dimensions, context, next) => {
|
|
38028
38085
|
const { x1: x12, x2: x22 } = channels;
|
|
38029
38086
|
const { height } = dimensions;
|
|
38030
38087
|
const y12 = new Float32Array(x12.length);
|
|
38031
38088
|
const y22 = new Float32Array(x22.length);
|
|
38032
|
-
(positive2 === inferScaleOrder(
|
|
38033
|
-
const oc = next(index2,
|
|
38034
|
-
const og = next(index2,
|
|
38089
|
+
(positive2 === inferScaleOrder(scales2.y) < 0 ? y12 : y22).fill(height);
|
|
38090
|
+
const oc = next(index2, scales2, { ...channels, x2: x12, y2: y22 }, dimensions, context);
|
|
38091
|
+
const og = next(index2, scales2, { ...channels, x1: x22, y1: y12 }, dimensions, context);
|
|
38035
38092
|
const c4 = oc.querySelector("g") ?? oc;
|
|
38036
38093
|
const g = og.querySelector("g") ?? og;
|
|
38037
38094
|
for (let i = 0; c4.firstChild; i += 2) {
|
|
@@ -38069,15 +38126,15 @@ var Geo = class extends Mark {
|
|
|
38069
38126
|
);
|
|
38070
38127
|
this.r = cr;
|
|
38071
38128
|
}
|
|
38072
|
-
render(index2,
|
|
38129
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
38073
38130
|
const { geometry: G, r: R } = channels;
|
|
38074
|
-
const path2 = path_default(context.projection ?? scaleProjection2(
|
|
38131
|
+
const path2 = path_default(context.projection ?? scaleProjection2(scales2));
|
|
38075
38132
|
const { r } = this;
|
|
38076
38133
|
if (negative(r))
|
|
38077
38134
|
index2 = [];
|
|
38078
38135
|
else if (r !== void 0)
|
|
38079
38136
|
path2.pointRadius(r);
|
|
38080
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
38137
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {
|
|
38081
38138
|
g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr("d", R ? (i) => path2.pointRadius(R[i])(G[i]) : (i) => path2(G[i])).call(applyChannelStyles, this, channels);
|
|
38082
38139
|
}).node();
|
|
38083
38140
|
}
|
|
@@ -38134,13 +38191,13 @@ function hexbin(outputs = { fill: "count" }, { binWidth, ...options } = {}) {
|
|
|
38134
38191
|
options.symbol = "hexagon";
|
|
38135
38192
|
if (options.r === void 0 && !hasOutput(outputs, "r"))
|
|
38136
38193
|
options.r = binWidth / 2;
|
|
38137
|
-
return initializer(options, (data, facets, channels,
|
|
38194
|
+
return initializer(options, (data, facets, channels, scales2, _, context) => {
|
|
38138
38195
|
let { x: X3, y: Y3, z: Z, fill: F, stroke: S, symbol: Q } = channels;
|
|
38139
38196
|
if (X3 === void 0)
|
|
38140
38197
|
throw new Error("missing channel: x");
|
|
38141
38198
|
if (Y3 === void 0)
|
|
38142
38199
|
throw new Error("missing channel: y");
|
|
38143
|
-
({ x: X3, y: Y3 } = applyPosition(channels,
|
|
38200
|
+
({ x: X3, y: Y3 } = applyPosition(channels, scales2, context));
|
|
38144
38201
|
Z = Z ? Z.value : valueof(data, z);
|
|
38145
38202
|
F = F?.value;
|
|
38146
38203
|
S = S?.value;
|
|
@@ -38182,8 +38239,8 @@ function hexbin(outputs = { fill: "count" }, { binWidth, ...options } = {}) {
|
|
|
38182
38239
|
const sx = channels.x.scale;
|
|
38183
38240
|
const sy = channels.y.scale;
|
|
38184
38241
|
const binChannels = {
|
|
38185
|
-
x: { value: BX, source:
|
|
38186
|
-
y: { value: BY, source:
|
|
38242
|
+
x: { value: BX, source: scales2[sx] ? { value: map2(BX, scales2[sx].invert), scale: sx } : null },
|
|
38243
|
+
y: { value: BY, source: scales2[sy] ? { value: map2(BY, scales2[sy].invert), scale: sy } : null },
|
|
38187
38244
|
...Z && { z: { value: GZ } },
|
|
38188
38245
|
...F && { fill: { value: GF, scale: "auto" } },
|
|
38189
38246
|
...S && { stroke: { value: GS, scale: "auto" } },
|
|
@@ -38242,7 +38299,7 @@ var Hexgrid = class extends Mark {
|
|
|
38242
38299
|
super(singleton, void 0, { clip, ...options }, defaults20);
|
|
38243
38300
|
this.binWidth = number5(binWidth);
|
|
38244
38301
|
}
|
|
38245
|
-
render(index2,
|
|
38302
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
38246
38303
|
const { binWidth } = this;
|
|
38247
38304
|
const { marginTop, marginRight, marginBottom, marginLeft, width, height } = dimensions;
|
|
38248
38305
|
const x06 = marginLeft - ox, x12 = width - marginRight - ox, y06 = marginTop - oy, y12 = height - marginBottom - oy, rx = binWidth / 2, ry = rx * sqrt4_3, hy = ry / 2, wx = rx * 2, wy = ry * 1.5, i0 = Math.floor(x06 / wx), i1 = Math.ceil(x12 / wx), j0 = Math.floor((y06 + hy) / wy), j1 = Math.ceil((y12 - hy) / wy) + 1, path2 = `m0,${round(-ry)}l${round(rx)},${round(hy)}v${round(ry)}l${round(-rx)},${round(hy)}`;
|
|
@@ -38314,8 +38371,8 @@ var Image = class extends Mark {
|
|
|
38314
38371
|
this.frameAnchor = maybeFrameAnchor(frameAnchor);
|
|
38315
38372
|
this.imageRendering = impliedString(imageRendering, "auto");
|
|
38316
38373
|
}
|
|
38317
|
-
render(index2,
|
|
38318
|
-
const { x: x3, y: y3 } =
|
|
38374
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
38375
|
+
const { x: x3, y: y3 } = scales2;
|
|
38319
38376
|
const { x: X3, y: Y3, width: W, height: H, r: R, rotate: A5, src: S } = channels;
|
|
38320
38377
|
const { r, width, height, rotate } = this;
|
|
38321
38378
|
const [cx, cy] = applyFrameAnchor(this, dimensions);
|
|
@@ -38485,10 +38542,10 @@ var LinearRegression = class extends Mark {
|
|
|
38485
38542
|
if (!(this.precision > 0))
|
|
38486
38543
|
throw new Error(`invalid precision: ${precision}`);
|
|
38487
38544
|
}
|
|
38488
|
-
render(index2,
|
|
38545
|
+
render(index2, scales2, channels, dimensions, context) {
|
|
38489
38546
|
const { x: X3, y: Y3, z: Z } = channels;
|
|
38490
38547
|
const { ci } = this;
|
|
38491
|
-
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this,
|
|
38548
|
+
return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
|
|
38492
38549
|
(g) => g.selectAll().data(Z ? groupZ2(index2, Z, this.z) : [index2]).enter().call(
|
|
38493
38550
|
(enter) => enter.append("path").attr("fill", "none").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, { ...channels, fill: null, fillOpacity: null }).attr("d", (I) => this._renderLine(I, X3, Y3)).call(
|
|
38494
38551
|
ci && !isNone(this.fill) ? (path2) => path2.select(pathBefore).attr("stroke", "none").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, {
|
|
@@ -39000,7 +39057,7 @@ function cluster(data, options) {
|
|
|
39000
39057
|
|
|
39001
39058
|
// ../../node_modules/@observablehq/plot/src/transforms/centroid.js
|
|
39002
39059
|
function centroid2({ geometry = identity7, ...options } = {}) {
|
|
39003
|
-
return initializer({ ...options, x: null, y: null }, (data, facets, channels,
|
|
39060
|
+
return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales2, dimensions, { projection: projection3 }) => {
|
|
39004
39061
|
const G = valueof(data, geometry);
|
|
39005
39062
|
const n = G.length;
|
|
39006
39063
|
const X3 = new Float64Array(n);
|
|
@@ -39090,14 +39147,14 @@ function dodge(y3, x3, anchor, padding, r, options) {
|
|
|
39090
39147
|
if (sort3 === void 0 && reverse3 === void 0)
|
|
39091
39148
|
options.sort = { channel: "-r" };
|
|
39092
39149
|
}
|
|
39093
|
-
return initializer(options, function(data, facets, channels,
|
|
39150
|
+
return initializer(options, function(data, facets, channels, scales2, dimensions, context) {
|
|
39094
39151
|
let { [x3]: X3, r: R } = channels;
|
|
39095
39152
|
if (!channels[x3])
|
|
39096
39153
|
throw new Error(`missing channel: ${x3}`);
|
|
39097
|
-
({ [x3]: X3 } = applyPosition(channels,
|
|
39154
|
+
({ [x3]: X3 } = applyPosition(channels, scales2, context));
|
|
39098
39155
|
const cr = R ? void 0 : r !== void 0 ? number5(r) : this.r !== void 0 ? this.r : 3;
|
|
39099
39156
|
if (R)
|
|
39100
|
-
R = valueof(R.value,
|
|
39157
|
+
R = valueof(R.value, scales2[R.scale] || identity7, Float64Array);
|
|
39101
39158
|
let [ky2, ty] = anchor(dimensions);
|
|
39102
39159
|
const compare = ky2 ? compareAscending : compareSymmetric;
|
|
39103
39160
|
const Y3 = new Float64Array(X3.length);
|
|
@@ -39427,6 +39484,9 @@ var attributeMap = /* @__PURE__ */ new Map([
|
|
|
39427
39484
|
["xAriaDescription", "x.ariaDescription"],
|
|
39428
39485
|
["xReverse", "x.reverse"],
|
|
39429
39486
|
["xZero", "x.zero"],
|
|
39487
|
+
["xBase", "x.base"],
|
|
39488
|
+
["xExponent", "x.exponent"],
|
|
39489
|
+
["xConstant", "x.constant"],
|
|
39430
39490
|
["yScale", "y.type"],
|
|
39431
39491
|
["yDomain", "y.domain"],
|
|
39432
39492
|
["yRange", "y.range"],
|
|
@@ -39457,6 +39517,9 @@ var attributeMap = /* @__PURE__ */ new Map([
|
|
|
39457
39517
|
["yAriaDescription", "y.ariaDescription"],
|
|
39458
39518
|
["yReverse", "y.reverse"],
|
|
39459
39519
|
["yZero", "y.zero"],
|
|
39520
|
+
["yBase", "y.base"],
|
|
39521
|
+
["yExponent", "y.exponent"],
|
|
39522
|
+
["yConstant", "y.constant"],
|
|
39460
39523
|
["facetMargin", "facet.margin"],
|
|
39461
39524
|
["facetMarginTop", "facet.marginTop"],
|
|
39462
39525
|
["facetMarginBottom", "facet.marginBottom"],
|
|
@@ -39532,6 +39595,9 @@ var attributeMap = /* @__PURE__ */ new Map([
|
|
|
39532
39595
|
["colorReverse", "color.reverse"],
|
|
39533
39596
|
["colorZero", "color.zero"],
|
|
39534
39597
|
["colorTickFormat", "color.tickFormat"],
|
|
39598
|
+
["colorBase", "color.base"],
|
|
39599
|
+
["colorExponent", "color.exponent"],
|
|
39600
|
+
["colorConstant", "color.constant"],
|
|
39535
39601
|
["opacityScale", "opacity.type"],
|
|
39536
39602
|
["opacityDomain", "opacity.domain"],
|
|
39537
39603
|
["opacityRange", "opacity.range"],
|
|
@@ -39541,18 +39607,27 @@ var attributeMap = /* @__PURE__ */ new Map([
|
|
|
39541
39607
|
["opacityReverse", "opacity.reverse"],
|
|
39542
39608
|
["opacityZero", "opacity.zero"],
|
|
39543
39609
|
["opacityTickFormat", "opacity.tickFormat"],
|
|
39610
|
+
["opacityBase", "opacity.base"],
|
|
39611
|
+
["opacityExponent", "opacity.exponent"],
|
|
39612
|
+
["opacityConstant", "opacity.constant"],
|
|
39544
39613
|
["rScale", "r.type"],
|
|
39545
39614
|
["rDomain", "r.domain"],
|
|
39546
39615
|
["rRange", "r.range"],
|
|
39547
39616
|
["rClamp", "r.clamp"],
|
|
39548
39617
|
["rNice", "r.nice"],
|
|
39549
39618
|
["rZero", "r.zero"],
|
|
39619
|
+
["rBase", "r.base"],
|
|
39620
|
+
["rExponent", "r.exponent"],
|
|
39621
|
+
["rConstant", "r.constant"],
|
|
39550
39622
|
["lengthScale", "length.type"],
|
|
39551
39623
|
["lengthDomain", "length.domain"],
|
|
39552
39624
|
["lengthRange", "length.range"],
|
|
39553
39625
|
["lengthClamp", "length.clamp"],
|
|
39554
39626
|
["lengthNice", "length.nice"],
|
|
39555
39627
|
["lengthZero", "length.zero"],
|
|
39628
|
+
["lengthBase", "length.base"],
|
|
39629
|
+
["lengthExponent", "length.exponent"],
|
|
39630
|
+
["lengthConstant", "length.constant"],
|
|
39556
39631
|
["projectionType", "projection.type"],
|
|
39557
39632
|
["projectionParallels", "projection.parallels"],
|
|
39558
39633
|
["projectionPrecision", "projection.precision"],
|
|
@@ -39909,14 +39984,26 @@ function isSymbol2(value) {
|
|
|
39909
39984
|
return symbols2.has(`${value}`.toLowerCase());
|
|
39910
39985
|
}
|
|
39911
39986
|
|
|
39912
|
-
// src/marks/util/
|
|
39987
|
+
// src/marks/util/arrow.js
|
|
39988
|
+
var INTEGER = 2;
|
|
39989
|
+
var FLOAT = 3;
|
|
39990
|
+
var DECIMAL = 7;
|
|
39991
|
+
var TIMESTAMP = 10;
|
|
39913
39992
|
function isArrowTable(values2) {
|
|
39914
39993
|
return typeof values2?.getChild === "function";
|
|
39915
39994
|
}
|
|
39995
|
+
function convertArrow(type2) {
|
|
39996
|
+
const { typeId } = type2;
|
|
39997
|
+
if (typeId === TIMESTAMP) {
|
|
39998
|
+
return (v2) => v2 == null ? v2 : new Date(v2);
|
|
39999
|
+
}
|
|
40000
|
+
if (typeId === INTEGER && type2.bitWidth >= 64) {
|
|
40001
|
+
return (v2) => v2 == null ? v2 : Number(v2);
|
|
40002
|
+
}
|
|
40003
|
+
return (v2) => v2;
|
|
40004
|
+
}
|
|
39916
40005
|
|
|
39917
40006
|
// src/marks/util/to-data-array.js
|
|
39918
|
-
var INTEGER = 2;
|
|
39919
|
-
var TIMESTAMP = 10;
|
|
39920
40007
|
function toDataArray(data) {
|
|
39921
40008
|
return isArrowTable(data) ? arrowToObjects(data) : data;
|
|
39922
40009
|
}
|
|
@@ -39931,7 +40018,7 @@ function arrowToObjects(data) {
|
|
|
39931
40018
|
for (let j = 0; j < numCols; ++j) {
|
|
39932
40019
|
const child = batch.getChildAt(j);
|
|
39933
40020
|
const { name, type: type2 } = schema.fields[j];
|
|
39934
|
-
const valueOf =
|
|
40021
|
+
const valueOf = convertArrow(type2);
|
|
39935
40022
|
for (let o = k2, i = 0; i < numRows; ++i, ++o) {
|
|
39936
40023
|
objects[o][name] = valueOf(child.get(i));
|
|
39937
40024
|
}
|
|
@@ -39940,16 +40027,6 @@ function arrowToObjects(data) {
|
|
|
39940
40027
|
}
|
|
39941
40028
|
return objects;
|
|
39942
40029
|
}
|
|
39943
|
-
function convert(type2) {
|
|
39944
|
-
const { typeId } = type2;
|
|
39945
|
-
if (typeId === TIMESTAMP) {
|
|
39946
|
-
return (v2) => v2 == null ? v2 : new Date(v2);
|
|
39947
|
-
}
|
|
39948
|
-
if (typeId === INTEGER && type2.bitWidth >= 64) {
|
|
39949
|
-
return (v2) => v2 == null ? v2 : Number(v2);
|
|
39950
|
-
}
|
|
39951
|
-
return (v2) => v2;
|
|
39952
|
-
}
|
|
39953
40030
|
|
|
39954
40031
|
// src/marks/Mark.js
|
|
39955
40032
|
var isColorChannel = (channel) => channel === "stroke" || channel === "fill";
|
|
@@ -40126,19 +40203,43 @@ function markQuery(channels, table, skip = []) {
|
|
|
40126
40203
|
return q;
|
|
40127
40204
|
}
|
|
40128
40205
|
|
|
40129
|
-
// src/marks/util/
|
|
40130
|
-
function
|
|
40131
|
-
|
|
40132
|
-
|
|
40206
|
+
// src/marks/util/channel-scale.js
|
|
40207
|
+
function channelScale(mark, channel) {
|
|
40208
|
+
const { plot: plot2 } = mark;
|
|
40209
|
+
let scaleType = plot2.getAttribute(`${channel}Scale`);
|
|
40210
|
+
if (!scaleType) {
|
|
40211
|
+
const { field: field2 } = mark.channelField(channel, `${channel}1`, `${channel}2`);
|
|
40212
|
+
const { type: type2 } = mark.stats[field2.column];
|
|
40213
|
+
scaleType = type2 === "date" ? "time" : "linear";
|
|
40214
|
+
}
|
|
40215
|
+
const options = { type: scaleType };
|
|
40216
|
+
switch (scaleType) {
|
|
40217
|
+
case "log":
|
|
40218
|
+
options.base = plot2.getAttribute(`${channel}Base`) ?? 10;
|
|
40219
|
+
break;
|
|
40220
|
+
case "pow":
|
|
40221
|
+
options.exponent = plot2.getAttribute(`${channel}Exponent`) ?? 1;
|
|
40222
|
+
break;
|
|
40223
|
+
case "symlog":
|
|
40224
|
+
options.constant = plot2.getAttribute(`${channel}Constant`) ?? 1;
|
|
40225
|
+
break;
|
|
40226
|
+
}
|
|
40227
|
+
return scaleTransform(options);
|
|
40228
|
+
}
|
|
40229
|
+
|
|
40230
|
+
// src/marks/util/bin-expr.js
|
|
40231
|
+
function binExpr(mark, channel, n, extent4, pad3 = 1, expr) {
|
|
40133
40232
|
const { field: field2 } = mark.channelField(channel);
|
|
40134
|
-
const { type: type2 } = mark.stats[field2.column];
|
|
40135
40233
|
expr = expr ?? field2;
|
|
40136
|
-
|
|
40137
|
-
}
|
|
40138
|
-
|
|
40139
|
-
const
|
|
40140
|
-
const f =
|
|
40141
|
-
|
|
40234
|
+
const { type: type2, apply: apply2, sqlApply } = channelScale(mark, channel);
|
|
40235
|
+
const reverse3 = !!mark.plot.getAttribute(`${channel}Reverse`);
|
|
40236
|
+
const [lo, hi] = extent4.map((v3) => apply2(v3));
|
|
40237
|
+
const v2 = sqlApply(expr);
|
|
40238
|
+
const f = type2 === "time" || type2 === "utc" ? v2 : expr;
|
|
40239
|
+
const d = hi === lo ? 0 : (n - pad3) / (hi - lo);
|
|
40240
|
+
const s2 = d !== 1 ? ` * ${d}::DOUBLE` : "";
|
|
40241
|
+
const bin3 = reverse3 ? sql`(${hi} - ${v2}::DOUBLE)${s2}` : sql`(${v2}::DOUBLE - ${lo})${s2}`;
|
|
40242
|
+
return [bin3, f];
|
|
40142
40243
|
}
|
|
40143
40244
|
|
|
40144
40245
|
// src/marks/util/extent.js
|
|
@@ -40194,7 +40295,7 @@ function filteredExtent(filter3, column3) {
|
|
|
40194
40295
|
var ConnectedMark = class extends Mark2 {
|
|
40195
40296
|
constructor(type2, source, encodings) {
|
|
40196
40297
|
const dim = type2.endsWith("X") ? "y" : type2.endsWith("Y") ? "x" : null;
|
|
40197
|
-
const req = { [dim]: ["
|
|
40298
|
+
const req = { [dim]: ["min", "max"] };
|
|
40198
40299
|
super(type2, source, encodings, req);
|
|
40199
40300
|
this.dim = dim;
|
|
40200
40301
|
}
|
|
@@ -40202,27 +40303,29 @@ var ConnectedMark = class extends Mark2 {
|
|
|
40202
40303
|
const { plot: plot2, dim, source, stats } = this;
|
|
40203
40304
|
const { optimize = true } = source.options || {};
|
|
40204
40305
|
const q = super.query(filter3);
|
|
40205
|
-
if (
|
|
40206
|
-
|
|
40306
|
+
if (!dim)
|
|
40307
|
+
return q;
|
|
40308
|
+
const ortho = dim === "x" ? "y" : "x";
|
|
40309
|
+
const value = this.channelField(ortho)?.as;
|
|
40310
|
+
const { field: field2, as } = this.channelField(dim);
|
|
40311
|
+
const { type: type2 } = stats[field2.column];
|
|
40312
|
+
const isContinuous = type2 === "date" || type2 === "number";
|
|
40313
|
+
if (optimize && isContinuous && value) {
|
|
40207
40314
|
const { column: column3 } = field2;
|
|
40208
|
-
const {
|
|
40315
|
+
const { max: max4, min: min5 } = stats[column3];
|
|
40209
40316
|
const size = dim === "x" ? plot2.innerWidth() : plot2.innerHeight();
|
|
40210
40317
|
const [lo, hi] = filteredExtent(filter3, column3) || [min5, max4];
|
|
40211
|
-
const
|
|
40212
|
-
|
|
40213
|
-
|
|
40214
|
-
|
|
40215
|
-
|
|
40216
|
-
return m4(q, dd, as, val, lo, hi, size, cols);
|
|
40217
|
-
}
|
|
40218
|
-
q.orderby(as);
|
|
40318
|
+
const [expr] = binExpr(this, dim, size, [lo, hi], 1, as);
|
|
40319
|
+
const cols = q.select().map((c4) => c4.as).filter((c4) => c4 !== as && c4 !== value);
|
|
40320
|
+
return m4(q, expr, as, value, cols);
|
|
40321
|
+
} else {
|
|
40322
|
+
return q.orderby(field2);
|
|
40219
40323
|
}
|
|
40220
|
-
return q;
|
|
40221
40324
|
}
|
|
40222
40325
|
};
|
|
40223
|
-
function m4(input,
|
|
40224
|
-
const
|
|
40225
|
-
const q = (sel) => Query.from(input).select(sel).groupby(
|
|
40326
|
+
function m4(input, bin3, x3, y3, cols = []) {
|
|
40327
|
+
const pixel = sql`FLOOR(${bin3})::INTEGER`;
|
|
40328
|
+
const q = (sel) => Query.from(input).select(sel).groupby(pixel, cols);
|
|
40226
40329
|
return Query.union(
|
|
40227
40330
|
q([{ [x3]: min(x3), [y3]: argmin(y3, x3) }, ...cols]),
|
|
40228
40331
|
q([{ [x3]: max(x3), [y3]: argmax(y3, x3) }, ...cols]),
|
|
@@ -40231,6 +40334,120 @@ function m4(input, bx, x3, y3, lo, hi, width, cols = []) {
|
|
|
40231
40334
|
).orderby(cols, x3);
|
|
40232
40335
|
}
|
|
40233
40336
|
|
|
40337
|
+
// src/marks/util/grid.js
|
|
40338
|
+
function arrayType(values2, name = "density") {
|
|
40339
|
+
if (isArrowTable(values2)) {
|
|
40340
|
+
const type2 = values2.getChild(name).type;
|
|
40341
|
+
switch (type2.typeId) {
|
|
40342
|
+
case INTEGER:
|
|
40343
|
+
case FLOAT:
|
|
40344
|
+
case DECIMAL:
|
|
40345
|
+
return Float64Array;
|
|
40346
|
+
default:
|
|
40347
|
+
return Array;
|
|
40348
|
+
}
|
|
40349
|
+
} else {
|
|
40350
|
+
return typeof values2[0][name] === "number" ? Float64Array : Array;
|
|
40351
|
+
}
|
|
40352
|
+
}
|
|
40353
|
+
function grid1d(n, values2) {
|
|
40354
|
+
const Type3 = arrayType(values2);
|
|
40355
|
+
return valuesToGrid(new Type3(n), values2);
|
|
40356
|
+
}
|
|
40357
|
+
function grid2d(m, n, values2, aggr, groupby = []) {
|
|
40358
|
+
if (groupby.length) {
|
|
40359
|
+
return groupedValuesToGrids(m * n, values2, aggr, groupby);
|
|
40360
|
+
} else {
|
|
40361
|
+
const cell2 = {};
|
|
40362
|
+
aggr.forEach((name) => {
|
|
40363
|
+
const Type3 = arrayType(values2, name);
|
|
40364
|
+
cell2[name] = valuesToGrid(new Type3(m * n), values2, name);
|
|
40365
|
+
});
|
|
40366
|
+
return [cell2];
|
|
40367
|
+
}
|
|
40368
|
+
}
|
|
40369
|
+
function valuesToGrid(grid, values2, name = "density") {
|
|
40370
|
+
if (isArrowTable(values2)) {
|
|
40371
|
+
const numRows = values2.numRows;
|
|
40372
|
+
if (numRows === 0)
|
|
40373
|
+
return grid;
|
|
40374
|
+
const index2 = values2.getChild("index").toArray();
|
|
40375
|
+
const value = values2.getChild(name).toArray();
|
|
40376
|
+
for (let row = 0; row < numRows; ++row) {
|
|
40377
|
+
grid[index2[row]] = value[row];
|
|
40378
|
+
}
|
|
40379
|
+
} else {
|
|
40380
|
+
for (const row of values2) {
|
|
40381
|
+
grid[row.index] = row[name];
|
|
40382
|
+
}
|
|
40383
|
+
}
|
|
40384
|
+
return grid;
|
|
40385
|
+
}
|
|
40386
|
+
function groupedValuesToGrids(size, values2, aggr, groupby) {
|
|
40387
|
+
const Types = aggr.map((name) => arrayType(values2, name));
|
|
40388
|
+
const numAggr = aggr.length;
|
|
40389
|
+
const cellMap = {};
|
|
40390
|
+
const getCell = (key) => {
|
|
40391
|
+
let cell2 = cellMap[key];
|
|
40392
|
+
if (!cell2) {
|
|
40393
|
+
cell2 = cellMap[key] = {};
|
|
40394
|
+
groupby.forEach((name, i) => cell2[name] = key[i]);
|
|
40395
|
+
aggr.forEach((name, i) => cell2[name] = new Types[i](size));
|
|
40396
|
+
}
|
|
40397
|
+
return cell2;
|
|
40398
|
+
};
|
|
40399
|
+
if (isArrowTable(values2)) {
|
|
40400
|
+
const numRows = values2.numRows;
|
|
40401
|
+
if (numRows === 0)
|
|
40402
|
+
return [];
|
|
40403
|
+
const index2 = values2.getChild("index").toArray();
|
|
40404
|
+
const value = aggr.map((name) => values2.getChild(name).toArray());
|
|
40405
|
+
const groups2 = groupby.map((name) => values2.getChild(name));
|
|
40406
|
+
for (let row = 0; row < numRows; ++row) {
|
|
40407
|
+
const key = groups2.map((vec2) => vec2.get(row));
|
|
40408
|
+
const cell2 = getCell(key);
|
|
40409
|
+
for (let i = 0; i < numAggr; ++i) {
|
|
40410
|
+
cell2[aggr[i]][index2[row]] = value[i][row];
|
|
40411
|
+
}
|
|
40412
|
+
}
|
|
40413
|
+
} else {
|
|
40414
|
+
for (const row of values2) {
|
|
40415
|
+
const key = groupby.map((col) => row[col]);
|
|
40416
|
+
const cell2 = getCell(key);
|
|
40417
|
+
for (let i = 0; i < numAggr; ++i) {
|
|
40418
|
+
cell2[aggr[i]][row.index] = row[aggr[i]];
|
|
40419
|
+
}
|
|
40420
|
+
}
|
|
40421
|
+
}
|
|
40422
|
+
return Object.values(cellMap);
|
|
40423
|
+
}
|
|
40424
|
+
function gridDomainContinuous(grids, prop) {
|
|
40425
|
+
let lo = 0, hi = 0;
|
|
40426
|
+
grids.forEach((cell2) => {
|
|
40427
|
+
const grid = cell2[prop];
|
|
40428
|
+
const n = grid.length;
|
|
40429
|
+
for (let i = 0; i < n; ++i) {
|
|
40430
|
+
const v2 = grid[i];
|
|
40431
|
+
if (v2 < lo)
|
|
40432
|
+
lo = v2;
|
|
40433
|
+
if (v2 > hi)
|
|
40434
|
+
hi = v2;
|
|
40435
|
+
}
|
|
40436
|
+
});
|
|
40437
|
+
return lo === 0 && hi === 0 ? [0, 1] : [lo, hi];
|
|
40438
|
+
}
|
|
40439
|
+
function gridDomainDiscrete(grids, prop) {
|
|
40440
|
+
const values2 = new InternSet();
|
|
40441
|
+
grids.forEach((cell2) => {
|
|
40442
|
+
const grid = cell2[prop];
|
|
40443
|
+
const n = grid.length;
|
|
40444
|
+
for (let i = 0; i < n; ++i) {
|
|
40445
|
+
values2.add(grid[i]);
|
|
40446
|
+
}
|
|
40447
|
+
});
|
|
40448
|
+
return Array.from(values2).sort(ascending);
|
|
40449
|
+
}
|
|
40450
|
+
|
|
40234
40451
|
// src/marks/util/handle-param.js
|
|
40235
40452
|
function handleParam(client, key, param, update2) {
|
|
40236
40453
|
if (isParam(param)) {
|
|
@@ -40415,64 +40632,17 @@ function dericheInitZeroPad(dest, src, N, stride, b, p, a2, q, sum5, h) {
|
|
|
40415
40632
|
return;
|
|
40416
40633
|
}
|
|
40417
40634
|
|
|
40418
|
-
// src/marks/util/grid.js
|
|
40419
|
-
function grid1d(n, values2) {
|
|
40420
|
-
return valuesToGrid(new Float64Array(n), values2);
|
|
40421
|
-
}
|
|
40422
|
-
function grid2d(m, n, values2, groupby = []) {
|
|
40423
|
-
return groupby.length ? Object.values(groupedValuesToGrids(m * n, values2, groupby)) : [{ grid: valuesToGrid(new Float64Array(m * n), values2) }];
|
|
40424
|
-
}
|
|
40425
|
-
function valuesToGrid(grid, values2) {
|
|
40426
|
-
if (isArrowTable(values2)) {
|
|
40427
|
-
const numRows = values2.numRows;
|
|
40428
|
-
if (numRows === 0)
|
|
40429
|
-
return grid;
|
|
40430
|
-
const index2 = values2.getChild("index").toArray();
|
|
40431
|
-
const value = values2.getChild("value").toArray();
|
|
40432
|
-
for (let row = 0; row < numRows; ++row) {
|
|
40433
|
-
grid[index2[row]] = value[row];
|
|
40434
|
-
}
|
|
40435
|
-
} else {
|
|
40436
|
-
for (const row of values2) {
|
|
40437
|
-
grid[row.index] = row.value;
|
|
40438
|
-
}
|
|
40439
|
-
}
|
|
40440
|
-
return grid;
|
|
40441
|
-
}
|
|
40442
|
-
function groupedValuesToGrids(size, values2, groupby) {
|
|
40443
|
-
const grids = {};
|
|
40444
|
-
const getGrid = (key) => {
|
|
40445
|
-
const cell2 = grids[key] || (grids[key] = { key, grid: new Float64Array(size) });
|
|
40446
|
-
return cell2.grid;
|
|
40447
|
-
};
|
|
40448
|
-
if (isArrowTable(values2)) {
|
|
40449
|
-
const numRows = values2.numRows;
|
|
40450
|
-
if (numRows === 0)
|
|
40451
|
-
return grids;
|
|
40452
|
-
const index2 = values2.getChild("index").toArray();
|
|
40453
|
-
const value = values2.getChild("value").toArray();
|
|
40454
|
-
const groups2 = groupby.map((name) => values2.getChild(name));
|
|
40455
|
-
for (let row = 0; row < numRows; ++row) {
|
|
40456
|
-
const key = groups2.map((vec2) => vec2.get(row));
|
|
40457
|
-
getGrid(key)[index2[row]] = value[row];
|
|
40458
|
-
}
|
|
40459
|
-
} else {
|
|
40460
|
-
for (const row of values2) {
|
|
40461
|
-
const key = groupby.map((col) => row[col]);
|
|
40462
|
-
getGrid(key)[row.index] = row.value;
|
|
40463
|
-
}
|
|
40464
|
-
}
|
|
40465
|
-
return grids;
|
|
40466
|
-
}
|
|
40467
|
-
|
|
40468
40635
|
// src/marks/Grid2DMark.js
|
|
40636
|
+
var DENSITY = "density";
|
|
40469
40637
|
var Grid2DMark = class extends Mark2 {
|
|
40470
40638
|
constructor(type2, source, options) {
|
|
40471
40639
|
const {
|
|
40472
|
-
bandwidth =
|
|
40473
|
-
|
|
40474
|
-
|
|
40475
|
-
|
|
40640
|
+
bandwidth = 0,
|
|
40641
|
+
interpolate = "none",
|
|
40642
|
+
pixelSize = 1,
|
|
40643
|
+
pad: pad3 = 1,
|
|
40644
|
+
width,
|
|
40645
|
+
height,
|
|
40476
40646
|
...channels
|
|
40477
40647
|
} = options;
|
|
40478
40648
|
const densityMap = createDensityMap(channels);
|
|
@@ -40481,9 +40651,11 @@ var Grid2DMark = class extends Mark2 {
|
|
|
40481
40651
|
handleParam(this, "bandwidth", bandwidth, () => {
|
|
40482
40652
|
return this.grids ? this.convolve().update() : null;
|
|
40483
40653
|
});
|
|
40484
|
-
handleParam(this, "
|
|
40485
|
-
handleParam(this, "
|
|
40486
|
-
handleParam(this, "
|
|
40654
|
+
handleParam(this, "pixelSize", pixelSize);
|
|
40655
|
+
handleParam(this, "interpolate", interpolate);
|
|
40656
|
+
handleParam(this, "pad", pad3);
|
|
40657
|
+
handleParam(this, "width", width);
|
|
40658
|
+
handleParam(this, "height", height);
|
|
40487
40659
|
}
|
|
40488
40660
|
setPlot(plot2, index2) {
|
|
40489
40661
|
const update2 = () => {
|
|
@@ -40500,64 +40672,80 @@ var Grid2DMark = class extends Mark2 {
|
|
|
40500
40672
|
return xdom && ydom && !xdom[Transient] && !ydom[Transient];
|
|
40501
40673
|
}
|
|
40502
40674
|
query(filter3 = []) {
|
|
40503
|
-
const {
|
|
40675
|
+
const { interpolate, pad: pad3, channels, densityMap, source } = this;
|
|
40504
40676
|
const [x06, x12] = this.extentX = extentX(this, filter3);
|
|
40505
40677
|
const [y06, y12] = this.extentY = extentY(this, filter3);
|
|
40506
40678
|
const [nx, ny] = this.bins = this.binDimensions(this);
|
|
40507
|
-
const bx =
|
|
40508
|
-
const by =
|
|
40509
|
-
const
|
|
40510
|
-
const ry = !!plot2.getAttribute("yReverse");
|
|
40511
|
-
const x3 = bin1d2(bx, x06, x12, nx, rx, this.binPad);
|
|
40512
|
-
const y3 = bin1d2(by, y06, y12, ny, ry, this.binPad);
|
|
40513
|
-
const bounds = binPad ? [isBetween(bx, [x06, x12]), isBetween(by, [y06, y12])] : [lte(x06, bx), lt(bx, x12), lte(y06, by), lt(by, y12)];
|
|
40679
|
+
const [x3, bx] = binExpr(this, "x", nx, [x06, x12], pad3);
|
|
40680
|
+
const [y3, by] = binExpr(this, "y", ny, [y06, y12], pad3);
|
|
40681
|
+
const bounds = pad3 ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];
|
|
40514
40682
|
const q = Query.from(source.table).where(filter3.concat(bounds));
|
|
40515
40683
|
const groupby = this.groupby = [];
|
|
40516
|
-
|
|
40684
|
+
const aggrMap = {};
|
|
40517
40685
|
for (const c4 of channels) {
|
|
40518
40686
|
if (Object.hasOwn(c4, "field")) {
|
|
40519
40687
|
const { as, channel, field: field2 } = c4;
|
|
40520
40688
|
if (field2.aggregate) {
|
|
40521
|
-
|
|
40689
|
+
aggrMap[channel] = field2;
|
|
40522
40690
|
densityMap[channel] = true;
|
|
40523
40691
|
} else if (channel === "weight") {
|
|
40524
|
-
|
|
40692
|
+
aggrMap[DENSITY] = sum2(field2);
|
|
40525
40693
|
} else if (channel !== "x" && channel !== "y") {
|
|
40526
40694
|
q.select({ [as]: field2 });
|
|
40527
40695
|
groupby.push(as);
|
|
40528
40696
|
}
|
|
40529
40697
|
}
|
|
40530
40698
|
}
|
|
40531
|
-
|
|
40699
|
+
const aggr = this.aggr = Object.keys(aggrMap);
|
|
40700
|
+
if (aggrMap.density && aggr.length > 1) {
|
|
40701
|
+
throw new Error("Weight option can not be used with custom aggregates.");
|
|
40702
|
+
}
|
|
40703
|
+
if (!aggr.length) {
|
|
40704
|
+
aggr.push(DENSITY);
|
|
40705
|
+
aggrMap.density = count();
|
|
40706
|
+
}
|
|
40707
|
+
if (interpolate === "linear") {
|
|
40708
|
+
if (aggr.length > 1) {
|
|
40709
|
+
throw new Error("Linear binning not applicable to multiple aggregates.");
|
|
40710
|
+
}
|
|
40711
|
+
if (!aggrMap.density) {
|
|
40712
|
+
throw new Error("Linear binning not applicable to custom aggregates.");
|
|
40713
|
+
}
|
|
40714
|
+
return binLinear2d(q, x3, y3, aggrMap[DENSITY], nx, groupby);
|
|
40715
|
+
} else {
|
|
40716
|
+
return bin2d(q, x3, y3, aggrMap, nx, groupby);
|
|
40717
|
+
}
|
|
40532
40718
|
}
|
|
40533
40719
|
binDimensions() {
|
|
40534
|
-
const { plot: plot2,
|
|
40720
|
+
const { plot: plot2, pixelSize, width, height } = this;
|
|
40535
40721
|
return [
|
|
40536
|
-
Math.round(plot2.innerWidth() /
|
|
40537
|
-
Math.round(plot2.innerHeight() /
|
|
40722
|
+
width ?? Math.round(plot2.innerWidth() / pixelSize),
|
|
40723
|
+
height ?? Math.round(plot2.innerHeight() / pixelSize)
|
|
40538
40724
|
];
|
|
40539
40725
|
}
|
|
40540
40726
|
queryResult(data) {
|
|
40541
40727
|
const [nx, ny] = this.bins;
|
|
40542
|
-
this.grids = grid2d(nx, ny, data, this.groupby);
|
|
40728
|
+
this.grids = grid2d(nx, ny, data, this.aggr, this.groupby);
|
|
40543
40729
|
return this.convolve();
|
|
40544
40730
|
}
|
|
40545
40731
|
convolve() {
|
|
40546
|
-
const { bandwidth, bins: bins2, grids, plot: plot2 } = this;
|
|
40547
|
-
|
|
40548
|
-
|
|
40549
|
-
|
|
40550
|
-
|
|
40551
|
-
|
|
40732
|
+
const { aggr, bandwidth, bins: bins2, grids, plot: plot2 } = this;
|
|
40733
|
+
this.kde = this.grids;
|
|
40734
|
+
if (bandwidth > 0) {
|
|
40735
|
+
const gridProp = aggr.length === 1 ? aggr[0] : aggr.includes(DENSITY) ? DENSITY : null;
|
|
40736
|
+
if (!gridProp) {
|
|
40737
|
+
console.warn("No compatible grid found for smoothing.");
|
|
40738
|
+
return this;
|
|
40739
|
+
}
|
|
40552
40740
|
const w = plot2.innerWidth();
|
|
40553
40741
|
const h = plot2.innerHeight();
|
|
40554
40742
|
const [nx, ny] = bins2;
|
|
40555
|
-
const neg = grids.some((
|
|
40743
|
+
const neg = grids.some((cell2) => cell2[gridProp].some((v2) => v2 < 0));
|
|
40556
40744
|
const configX = dericheConfig(bandwidth * (nx - 1) / w, neg);
|
|
40557
40745
|
const configY = dericheConfig(bandwidth * (ny - 1) / h, neg);
|
|
40558
|
-
this.kde = this.grids.map((
|
|
40559
|
-
const
|
|
40560
|
-
return
|
|
40746
|
+
this.kde = this.grids.map((grid) => {
|
|
40747
|
+
const density2 = dericheConv2d(configX, configY, grid[gridProp], bins2);
|
|
40748
|
+
return { ...grid, [gridProp]: density2 };
|
|
40561
40749
|
});
|
|
40562
40750
|
}
|
|
40563
40751
|
return this;
|
|
@@ -40576,19 +40764,14 @@ function createDensityMap(channels) {
|
|
|
40576
40764
|
}
|
|
40577
40765
|
return densityMap;
|
|
40578
40766
|
}
|
|
40579
|
-
function
|
|
40580
|
-
const d = (n - pad3) / (x12 - x06);
|
|
40581
|
-
const f = d !== 1 ? ` * ${d}::DOUBLE` : "";
|
|
40582
|
-
return reverse3 ? sql`(${x12} - ${x3}::DOUBLE)${f}` : sql`(${x3}::DOUBLE - ${x06})${f}`;
|
|
40583
|
-
}
|
|
40584
|
-
function bin2d(q, xp, yp, value, xn, groupby) {
|
|
40767
|
+
function bin2d(q, xp, yp, aggs, xn, groupby) {
|
|
40585
40768
|
return q.select({
|
|
40586
40769
|
index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,
|
|
40587
|
-
|
|
40770
|
+
...aggs
|
|
40588
40771
|
}).groupby("index", groupby);
|
|
40589
40772
|
}
|
|
40590
|
-
function binLinear2d(q, xp, yp,
|
|
40591
|
-
const w =
|
|
40773
|
+
function binLinear2d(q, xp, yp, density2, xn, groupby) {
|
|
40774
|
+
const w = density2?.column ? `* ${density2.column}` : "";
|
|
40592
40775
|
const subq = (i, w2) => q.clone().select({ xp, yp, i, w: w2 });
|
|
40593
40776
|
const a2 = subq(
|
|
40594
40777
|
sql`FLOOR(xp)::INTEGER + FLOOR(yp)::INTEGER * ${xn}`,
|
|
@@ -40606,14 +40789,19 @@ function binLinear2d(q, xp, yp, value, xn, groupby) {
|
|
|
40606
40789
|
sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,
|
|
40607
40790
|
sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`
|
|
40608
40791
|
);
|
|
40609
|
-
return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i",
|
|
40792
|
+
return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i", density: sum2("w") }, groupby).groupby("index", groupby).having(neq("density", 0));
|
|
40610
40793
|
}
|
|
40611
40794
|
|
|
40612
40795
|
// src/marks/ContourMark.js
|
|
40613
40796
|
var ContourMark = class extends Grid2DMark {
|
|
40614
40797
|
constructor(source, options) {
|
|
40615
40798
|
const { thresholds = 10, ...channels } = options;
|
|
40616
|
-
super("geo", source,
|
|
40799
|
+
super("geo", source, {
|
|
40800
|
+
bandwidth: 20,
|
|
40801
|
+
interpolate: "linear",
|
|
40802
|
+
pixelSize: 2,
|
|
40803
|
+
...channels
|
|
40804
|
+
});
|
|
40617
40805
|
handleParam(this, "thresholds", thresholds, () => {
|
|
40618
40806
|
return this.grids ? this.contours().update() : null;
|
|
40619
40807
|
});
|
|
@@ -40622,11 +40810,11 @@ var ContourMark = class extends Grid2DMark {
|
|
|
40622
40810
|
return super.convolve().contours();
|
|
40623
40811
|
}
|
|
40624
40812
|
contours() {
|
|
40625
|
-
const { bins: bins2, densityMap, kde, thresholds,
|
|
40813
|
+
const { bins: bins2, densityMap, kde, thresholds, plot: plot2 } = this;
|
|
40626
40814
|
let tz = thresholds;
|
|
40627
40815
|
if (!Array.isArray(tz)) {
|
|
40628
|
-
const
|
|
40629
|
-
tz = Array.from({ length: tz - 1 }, (_, i) =>
|
|
40816
|
+
const [, hi] = gridDomainContinuous(kde, "density");
|
|
40817
|
+
tz = Array.from({ length: tz - 1 }, (_, i) => hi * (i + 1) / tz);
|
|
40630
40818
|
}
|
|
40631
40819
|
if (densityMap.fill || densityMap.stroke) {
|
|
40632
40820
|
if (this.plot.getAttribute("colorScale") !== "log") {
|
|
@@ -40643,11 +40831,11 @@ var ContourMark = class extends Grid2DMark {
|
|
|
40643
40831
|
const x3 = (v2) => xo + v2 * sx;
|
|
40644
40832
|
const y3 = (v2) => yo + v2 * sy;
|
|
40645
40833
|
const contour2 = contours_default().size(bins2);
|
|
40646
|
-
this.data = kde.flatMap((
|
|
40647
|
-
|
|
40648
|
-
|
|
40649
|
-
|
|
40650
|
-
|
|
40834
|
+
this.data = kde.flatMap((cell2) => tz.map((t) => {
|
|
40835
|
+
return Object.assign(
|
|
40836
|
+
transform2(contour2.contour(cell2.density, t), x3, y3),
|
|
40837
|
+
{ ...cell2, density: t }
|
|
40838
|
+
);
|
|
40651
40839
|
}));
|
|
40652
40840
|
return this;
|
|
40653
40841
|
}
|
|
@@ -40683,23 +40871,95 @@ function transform2(geometry, x3, y3) {
|
|
|
40683
40871
|
}
|
|
40684
40872
|
|
|
40685
40873
|
// src/marks/util/raster.js
|
|
40686
|
-
function
|
|
40687
|
-
|
|
40688
|
-
|
|
40689
|
-
|
|
40690
|
-
|
|
40691
|
-
|
|
40692
|
-
data[k2 + 1] = scheme28[c4 + 1];
|
|
40693
|
-
data[k2 + 2] = scheme28[c4 + 2];
|
|
40694
|
-
data[k2 + 3] = scheme28[c4 + 3];
|
|
40695
|
-
}
|
|
40874
|
+
function createCanvas(w, h) {
|
|
40875
|
+
if (typeof document !== "undefined") {
|
|
40876
|
+
const c4 = document.createElement("canvas");
|
|
40877
|
+
c4.setAttribute("width", w);
|
|
40878
|
+
c4.setAttribute("height", h);
|
|
40879
|
+
return c4;
|
|
40696
40880
|
}
|
|
40881
|
+
throw new Error("Can not create a canvas instance.");
|
|
40882
|
+
}
|
|
40883
|
+
function alphaConstant(v2 = 1) {
|
|
40884
|
+
const a2 = 255 * v2 | 0;
|
|
40885
|
+
return (data, w, h) => {
|
|
40886
|
+
for (let j = 0, k2 = 0; j < h; ++j) {
|
|
40887
|
+
for (let i = 0; i < w; ++i, k2 += 4) {
|
|
40888
|
+
data[k2 + 3] = a2;
|
|
40889
|
+
}
|
|
40890
|
+
}
|
|
40891
|
+
};
|
|
40892
|
+
}
|
|
40893
|
+
function alphaScheme(scale3) {
|
|
40894
|
+
const { apply: apply2 } = scale3;
|
|
40895
|
+
return (data, w, h, grid) => {
|
|
40896
|
+
for (let j = 0, k2 = 0; j < h; ++j) {
|
|
40897
|
+
for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {
|
|
40898
|
+
data[k2 + 3] = 255 * apply2(grid[i + row]) | 0;
|
|
40899
|
+
}
|
|
40900
|
+
}
|
|
40901
|
+
};
|
|
40902
|
+
}
|
|
40903
|
+
function colorConstant(v2 = {}) {
|
|
40904
|
+
const { r = 0, g = 0, b = 0, opacity: opacity2 = 1 } = typeof v2 === "string" ? rgb(v2) : v2;
|
|
40905
|
+
const c4 = new Uint8ClampedArray([r, g, b, 255 * opacity2 | 0]);
|
|
40906
|
+
return (data, w, h) => {
|
|
40907
|
+
for (let j = 0, k2 = 0; j < h; ++j) {
|
|
40908
|
+
for (let i = 0; i < w; ++i, k2 += 4) {
|
|
40909
|
+
data[k2 + 0] = c4[0];
|
|
40910
|
+
data[k2 + 1] = c4[1];
|
|
40911
|
+
data[k2 + 2] = c4[2];
|
|
40912
|
+
data[k2 + 3] = c4[3];
|
|
40913
|
+
}
|
|
40914
|
+
}
|
|
40915
|
+
};
|
|
40697
40916
|
}
|
|
40698
|
-
function
|
|
40917
|
+
function colorCategory(scale3) {
|
|
40918
|
+
const { domain, range: range3 } = scale3;
|
|
40919
|
+
const idx = /* @__PURE__ */ Object.create(null);
|
|
40920
|
+
const p = new Uint8ClampedArray(4 * domain.length);
|
|
40921
|
+
const n = domain.length - 1;
|
|
40922
|
+
const m = range3.length;
|
|
40923
|
+
for (let i = 0; i <= n; ++i) {
|
|
40924
|
+
const v2 = range3[i % m];
|
|
40925
|
+
const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === "string" ? rgb(v2) : v2;
|
|
40926
|
+
const k2 = i << 2;
|
|
40927
|
+
p[k2 + 0] = r;
|
|
40928
|
+
p[k2 + 1] = g;
|
|
40929
|
+
p[k2 + 2] = b;
|
|
40930
|
+
p[k2 + 3] = 255 * opacity2 | 0;
|
|
40931
|
+
idx[domain[i]] = k2;
|
|
40932
|
+
}
|
|
40933
|
+
return (data, w, h, grid) => {
|
|
40934
|
+
if (grid.map) {
|
|
40935
|
+
for (let j = 0, k2 = 0; j < h; ++j) {
|
|
40936
|
+
for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {
|
|
40937
|
+
const c4 = idx[grid[i + row]];
|
|
40938
|
+
data[k2 + 0] = p[c4 + 0];
|
|
40939
|
+
data[k2 + 1] = p[c4 + 1];
|
|
40940
|
+
data[k2 + 2] = p[c4 + 2];
|
|
40941
|
+
data[k2 + 3] = p[c4 + 3];
|
|
40942
|
+
}
|
|
40943
|
+
}
|
|
40944
|
+
} else {
|
|
40945
|
+
const c4 = idx[grid];
|
|
40946
|
+
for (let j = 0, k2 = 0; j < h; ++j) {
|
|
40947
|
+
for (let i = 0; i < w; ++i, k2 += 4) {
|
|
40948
|
+
data[k2 + 0] = p[c4 + 0];
|
|
40949
|
+
data[k2 + 1] = p[c4 + 1];
|
|
40950
|
+
data[k2 + 2] = p[c4 + 2];
|
|
40951
|
+
data[k2 + 3] = p[c4 + 3];
|
|
40952
|
+
}
|
|
40953
|
+
}
|
|
40954
|
+
}
|
|
40955
|
+
};
|
|
40956
|
+
}
|
|
40957
|
+
function colorScheme(size, scale3, frac) {
|
|
40958
|
+
const { interpolate } = scale3;
|
|
40699
40959
|
const p = new Uint8ClampedArray(4 * size);
|
|
40700
40960
|
const n = size - 1;
|
|
40701
40961
|
for (let i = 0; i <= n; ++i) {
|
|
40702
|
-
const v2 =
|
|
40962
|
+
const v2 = interpolate(i / n);
|
|
40703
40963
|
const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === "string" ? rgb(v2) : v2;
|
|
40704
40964
|
const k2 = i << 2;
|
|
40705
40965
|
p[k2 + 0] = r;
|
|
@@ -40707,20 +40967,17 @@ function palette(size, interp) {
|
|
|
40707
40967
|
p[k2 + 2] = b;
|
|
40708
40968
|
p[k2 + 3] = 255 * opacity2 | 0;
|
|
40709
40969
|
}
|
|
40710
|
-
return
|
|
40711
|
-
|
|
40712
|
-
|
|
40713
|
-
|
|
40714
|
-
|
|
40715
|
-
|
|
40716
|
-
|
|
40717
|
-
|
|
40718
|
-
|
|
40719
|
-
|
|
40720
|
-
}
|
|
40721
|
-
function opacityMap(color3 = "black") {
|
|
40722
|
-
const { r, g, b } = rgb(color3);
|
|
40723
|
-
return (opacity2) => ({ r, g, b, opacity: opacity2 });
|
|
40970
|
+
return (data, w, h, grid) => {
|
|
40971
|
+
for (let j = 0, k2 = 0; j < h; ++j) {
|
|
40972
|
+
for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {
|
|
40973
|
+
const c4 = n * frac(grid[i + row]) << 2;
|
|
40974
|
+
data[k2 + 0] = p[c4 + 0];
|
|
40975
|
+
data[k2 + 1] = p[c4 + 1];
|
|
40976
|
+
data[k2 + 2] = p[c4 + 2];
|
|
40977
|
+
data[k2 + 3] = p[c4 + 3];
|
|
40978
|
+
}
|
|
40979
|
+
}
|
|
40980
|
+
};
|
|
40724
40981
|
}
|
|
40725
40982
|
|
|
40726
40983
|
// src/marks/RasterMark.js
|
|
@@ -40740,15 +40997,13 @@ var RasterMark = class extends Grid2DMark {
|
|
|
40740
40997
|
return super.convolve().rasterize();
|
|
40741
40998
|
}
|
|
40742
40999
|
rasterize() {
|
|
40743
|
-
const { bins: bins2, kde
|
|
41000
|
+
const { bins: bins2, kde } = this;
|
|
40744
41001
|
const [w, h] = bins2;
|
|
40745
41002
|
const { canvas, ctx, img } = imageData(this, w, h);
|
|
40746
|
-
const
|
|
40747
|
-
|
|
40748
|
-
|
|
40749
|
-
|
|
40750
|
-
const palette2 = imagePalette(this, domain, grid.key?.[idx]);
|
|
40751
|
-
raster2(grid, img.data, w, h, s2, palette2);
|
|
41003
|
+
const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);
|
|
41004
|
+
this.data = kde.map((cell2) => {
|
|
41005
|
+
color3?.(img.data, w, h, cell2[colorProp]);
|
|
41006
|
+
alpha?.(img.data, w, h, cell2[alphaProp]);
|
|
40752
41007
|
ctx.putImageData(img, 0, 0);
|
|
40753
41008
|
return { src: canvas.toDataURL() };
|
|
40754
41009
|
});
|
|
@@ -40767,6 +41022,128 @@ var RasterMark = class extends Grid2DMark {
|
|
|
40767
41022
|
return [{ type: type2, data, options }];
|
|
40768
41023
|
}
|
|
40769
41024
|
};
|
|
41025
|
+
var HeatmapMark = class extends RasterMark {
|
|
41026
|
+
constructor(source, options) {
|
|
41027
|
+
super(source, {
|
|
41028
|
+
bandwidth: 20,
|
|
41029
|
+
interpolate: "linear",
|
|
41030
|
+
pixelSize: 2,
|
|
41031
|
+
...options
|
|
41032
|
+
});
|
|
41033
|
+
}
|
|
41034
|
+
};
|
|
41035
|
+
function rasterEncoding(mark) {
|
|
41036
|
+
const { aggr, densityMap, groupby, plot: plot2 } = mark;
|
|
41037
|
+
const hasDensity = aggr.includes(DENSITY);
|
|
41038
|
+
const hasFillOpacity = aggr.includes("fillOpacity");
|
|
41039
|
+
const fillEntry = mark.channel("fill");
|
|
41040
|
+
const opacEntry = mark.channel("fillOpacity");
|
|
41041
|
+
if (aggr.length > 2 || hasDensity && hasFillOpacity) {
|
|
41042
|
+
throw new Error("Invalid raster encodings. Try dropping an aggregate?");
|
|
41043
|
+
}
|
|
41044
|
+
if (groupby.includes(opacEntry?.as)) {
|
|
41045
|
+
throw new Error("Raster fillOpacity must be an aggregate or constant.");
|
|
41046
|
+
}
|
|
41047
|
+
const fill = densityMap.fill || aggr.includes("fill") ? "grid" : groupby.includes(fillEntry?.as) ? "group" : isColor2(fillEntry?.value) ? fillEntry.value : hasDensity && plot2.getAttribute("colorScheme") ? "grid" : void 0;
|
|
41048
|
+
const opac = densityMap.fillOpacity || aggr.includes("fillOpacity") ? "grid" : typeof opacEntry?.value === "number" ? opacEntry.value : hasDensity && fill !== "grid" ? "grid" : void 0;
|
|
41049
|
+
if (fill !== "grid" && opac !== "grid") {
|
|
41050
|
+
throw new Error("Raster mark missing density values.");
|
|
41051
|
+
}
|
|
41052
|
+
const colorProp = fillEntry?.as ?? (fill === "grid" ? DENSITY : null);
|
|
41053
|
+
const alphaProp = opacEntry?.as ?? (opac === "grid" ? DENSITY : null);
|
|
41054
|
+
const color3 = fill !== "grid" && fill !== "group" ? colorConstant(fill) : colorScale(mark, colorProp);
|
|
41055
|
+
const alpha = opac !== "grid" ? alphaConstant(opac) : alphaScale(mark, alphaProp);
|
|
41056
|
+
return { alphaProp, colorProp, alpha, color: color3 };
|
|
41057
|
+
}
|
|
41058
|
+
function alphaScale(mark, prop) {
|
|
41059
|
+
const { plot: plot2, kde: grids } = mark;
|
|
41060
|
+
const domainAttr = plot2.getAttribute("opacityDomain");
|
|
41061
|
+
const domainFixed = domainAttr === Fixed;
|
|
41062
|
+
const domainTransient = domainAttr?.[Transient];
|
|
41063
|
+
const domain = !domainFixed && !domainTransient && domainAttr || gridDomainContinuous(grids, prop);
|
|
41064
|
+
if (domainFixed || domainTransient) {
|
|
41065
|
+
if (domainTransient)
|
|
41066
|
+
domain[Transient] = true;
|
|
41067
|
+
plot2.setAttribute("colorDomain", domain);
|
|
41068
|
+
}
|
|
41069
|
+
const s2 = scale2({
|
|
41070
|
+
opacity: {
|
|
41071
|
+
type: plot2.getAttribute("opacityScale"),
|
|
41072
|
+
domain,
|
|
41073
|
+
clamp: plot2.getAttribute("opacityClamp"),
|
|
41074
|
+
nice: plot2.getAttribute("opacityNice"),
|
|
41075
|
+
reverse: plot2.getAttribute("opacityReverse"),
|
|
41076
|
+
zero: plot2.getAttribute("opacityZero"),
|
|
41077
|
+
base: plot2.getAttribute("opacityBase"),
|
|
41078
|
+
exponent: plot2.getAttribute("opacityExponent"),
|
|
41079
|
+
constant: plot2.getAttribute("opacityConstant")
|
|
41080
|
+
}
|
|
41081
|
+
});
|
|
41082
|
+
return alphaScheme(s2);
|
|
41083
|
+
}
|
|
41084
|
+
function colorScale(mark, prop) {
|
|
41085
|
+
const { plot: plot2, kde: grids } = mark;
|
|
41086
|
+
const flat = !grids[0][prop]?.map;
|
|
41087
|
+
const discrete = flat || Array.isArray(grids[0][prop]);
|
|
41088
|
+
const domainAttr = plot2.getAttribute("colorDomain");
|
|
41089
|
+
const domainFixed = domainAttr === Fixed;
|
|
41090
|
+
const domainTransient = domainAttr?.[Transient];
|
|
41091
|
+
const domain = !domainFixed && !domainTransient && domainAttr || (flat ? grids.map((cell2) => cell2[prop]).sort(ascending) : discrete ? gridDomainDiscrete(grids, prop) : gridDomainContinuous(grids, prop));
|
|
41092
|
+
if (domainFixed || domainTransient) {
|
|
41093
|
+
if (domainTransient)
|
|
41094
|
+
domain[Transient] = true;
|
|
41095
|
+
plot2.setAttribute("colorDomain", domain);
|
|
41096
|
+
}
|
|
41097
|
+
const s2 = scale2({
|
|
41098
|
+
color: {
|
|
41099
|
+
type: plot2.getAttribute("colorScale"),
|
|
41100
|
+
domain,
|
|
41101
|
+
range: plot2.getAttribute("colorRange"),
|
|
41102
|
+
clamp: plot2.getAttribute("colorClamp"),
|
|
41103
|
+
n: plot2.getAttribute("colorN"),
|
|
41104
|
+
nice: plot2.getAttribute("colorNice"),
|
|
41105
|
+
reverse: plot2.getAttribute("colorReverse"),
|
|
41106
|
+
scheme: plot2.getAttribute("colorScheme"),
|
|
41107
|
+
interpolate: plot2.getAttribute("colorInterpolate"),
|
|
41108
|
+
pivot: plot2.getAttribute("colorPivot"),
|
|
41109
|
+
symmetric: plot2.getAttribute("colorSymmetric"),
|
|
41110
|
+
zero: plot2.getAttribute("colorZero"),
|
|
41111
|
+
base: plot2.getAttribute("colorBase"),
|
|
41112
|
+
exponent: plot2.getAttribute("colorExponent"),
|
|
41113
|
+
constant: plot2.getAttribute("colorConstant")
|
|
41114
|
+
}
|
|
41115
|
+
});
|
|
41116
|
+
if (discrete) {
|
|
41117
|
+
return colorCategory(s2);
|
|
41118
|
+
} else {
|
|
41119
|
+
const frac = scale2({
|
|
41120
|
+
x: {
|
|
41121
|
+
type: inferScaleType2(s2.type),
|
|
41122
|
+
domain: s2.domain,
|
|
41123
|
+
reverse: s2.reverse,
|
|
41124
|
+
range: [0, 1],
|
|
41125
|
+
clamp: s2.clamp,
|
|
41126
|
+
base: s2.base,
|
|
41127
|
+
exponent: s2.exponent,
|
|
41128
|
+
constant: s2.constant
|
|
41129
|
+
}
|
|
41130
|
+
});
|
|
41131
|
+
return colorScheme(1024, s2, frac.apply);
|
|
41132
|
+
}
|
|
41133
|
+
}
|
|
41134
|
+
function inferScaleType2(type2) {
|
|
41135
|
+
if (type2.endsWith("symlog"))
|
|
41136
|
+
return "symlog";
|
|
41137
|
+
if (type2.endsWith("log"))
|
|
41138
|
+
return "log";
|
|
41139
|
+
if (type2.endsWith("pow"))
|
|
41140
|
+
return "pow";
|
|
41141
|
+
if (type2.endsWith("sqrt"))
|
|
41142
|
+
return "sqrt";
|
|
41143
|
+
if (type2 === "diverging")
|
|
41144
|
+
return "linear";
|
|
41145
|
+
return type2;
|
|
41146
|
+
}
|
|
40770
41147
|
function imageData(mark, w, h) {
|
|
40771
41148
|
if (!mark.image || mark.image.w !== w || mark.image.h !== h) {
|
|
40772
41149
|
const canvas = createCanvas(w, h);
|
|
@@ -40776,71 +41153,21 @@ function imageData(mark, w, h) {
|
|
|
40776
41153
|
}
|
|
40777
41154
|
return mark.image;
|
|
40778
41155
|
}
|
|
40779
|
-
function imageScale(mark) {
|
|
40780
|
-
const { densityMap, kde, plot: plot2 } = mark;
|
|
40781
|
-
let domain = densityMap.fill && plot2.getAttribute("colorDomain");
|
|
40782
|
-
if (!domain) {
|
|
40783
|
-
let lo = 0, hi = 0;
|
|
40784
|
-
kde.forEach((grid) => {
|
|
40785
|
-
for (const v2 of grid) {
|
|
40786
|
-
if (v2 < lo)
|
|
40787
|
-
lo = v2;
|
|
40788
|
-
if (v2 > hi)
|
|
40789
|
-
hi = v2;
|
|
40790
|
-
}
|
|
40791
|
-
});
|
|
40792
|
-
domain = lo === 0 && hi === 0 ? [0, 1] : [lo, hi];
|
|
40793
|
-
}
|
|
40794
|
-
const type2 = plot2.getAttribute("colorScale");
|
|
40795
|
-
return scale2({ x: { type: type2, domain, range: [0, 1] } }).apply;
|
|
40796
|
-
}
|
|
40797
|
-
function imagePalette(mark, domain, value, steps = 1024) {
|
|
40798
|
-
const { densityMap, plot: plot2 } = mark;
|
|
40799
|
-
const scheme28 = plot2.getAttribute("colorScheme");
|
|
40800
|
-
const fill = mark.channel("fill");
|
|
40801
|
-
let color3 = isColor2(fill?.value) ? fill.value : void 0;
|
|
40802
|
-
if (densityMap.fill || scheme28 && !color3) {
|
|
40803
|
-
if (scheme28) {
|
|
40804
|
-
try {
|
|
40805
|
-
return palette(
|
|
40806
|
-
steps,
|
|
40807
|
-
scale2({ color: { scheme: scheme28, domain: [0, 1] } }).interpolate
|
|
40808
|
-
);
|
|
40809
|
-
} catch (err) {
|
|
40810
|
-
console.warn(err);
|
|
40811
|
-
}
|
|
40812
|
-
}
|
|
40813
|
-
} else if (domain.length) {
|
|
40814
|
-
const range3 = plot2.getAttribute("colorRange");
|
|
40815
|
-
const spec = {
|
|
40816
|
-
domain,
|
|
40817
|
-
range: range3,
|
|
40818
|
-
scheme: scheme28 || (range3 ? void 0 : "tableau10")
|
|
40819
|
-
};
|
|
40820
|
-
color3 = scale2({ color: spec }).apply(value);
|
|
40821
|
-
}
|
|
40822
|
-
return palette(steps, opacityMap(color3));
|
|
40823
|
-
}
|
|
40824
41156
|
|
|
40825
41157
|
// src/marks/DenseLineMark.js
|
|
40826
41158
|
var DenseLineMark = class extends RasterMark {
|
|
40827
41159
|
constructor(source, options) {
|
|
40828
41160
|
const { normalize: normalize4 = true, ...rest } = options;
|
|
40829
|
-
super(source,
|
|
41161
|
+
super(source, rest);
|
|
40830
41162
|
handleParam(this, "normalize", normalize4);
|
|
40831
41163
|
}
|
|
40832
41164
|
query(filter3 = []) {
|
|
40833
|
-
const {
|
|
40834
|
-
const [x06, x12] = extentX(this, filter3);
|
|
40835
|
-
const [y06, y12] = extentY(this, filter3);
|
|
41165
|
+
const { channels, normalize: normalize4, source, binPad } = this;
|
|
40836
41166
|
const [nx, ny] = this.bins = this.binDimensions(this);
|
|
40837
|
-
const
|
|
40838
|
-
const
|
|
40839
|
-
const rx = !!plot2.getAttribute("xReverse");
|
|
40840
|
-
const ry = !!plot2.getAttribute("yReverse");
|
|
40841
|
-
const x3 = bin1d(bx, x06, x12, nx, rx, this.binPad);
|
|
40842
|
-
const y3 = bin1d(by, y06, y12, ny, ry, this.binPad);
|
|
41167
|
+
const [x3] = binExpr(this, "x", nx, extentX(this, filter3), binPad);
|
|
41168
|
+
const [y3] = binExpr(this, "y", ny, extentY(this, filter3), binPad);
|
|
40843
41169
|
const q = Query.from(source.table).where(stripXY(this, filter3));
|
|
41170
|
+
this.aggr = ["density"];
|
|
40844
41171
|
const groupby = this.groupby = [];
|
|
40845
41172
|
const z = [];
|
|
40846
41173
|
for (const c4 of channels) {
|
|
@@ -40887,7 +41214,7 @@ function lineDensity(q, x3, y3, z, xn, yn, groupby = [], normalize4 = true) {
|
|
|
40887
41214
|
));
|
|
40888
41215
|
const num = Query.select({ x: sql`GREATEST(MAX(ABS(dx)), MAX(ABS(dy)))` }).from("pairs");
|
|
40889
41216
|
const indices = Query.select({ i: sql`UNNEST(range((${num})))::INTEGER` });
|
|
40890
|
-
const
|
|
41217
|
+
const raster2 = Query.unionAll(
|
|
40891
41218
|
Query.select(groups2, {
|
|
40892
41219
|
x: sql`x0 + i`,
|
|
40893
41220
|
y: sql`y0 + ROUND(i * dy / dx::FLOAT)::INTEGER`
|
|
@@ -40904,10 +41231,10 @@ function lineDensity(q, x3, y3, z, xn, yn, groupby = [], normalize4 = true) {
|
|
|
40904
41231
|
"x",
|
|
40905
41232
|
"y",
|
|
40906
41233
|
normalize4 ? { w: sql`1.0 / COUNT(*) OVER (PARTITION BY ${pointPart})` } : null
|
|
40907
|
-
).where(and(isBetween("x", [0, xn]), isBetween("y", [0, yn])));
|
|
40908
|
-
return Query.with({ pairs: pairs2, indices, raster:
|
|
41234
|
+
).where(and(isBetween("x", [0, xn], true), isBetween("y", [0, yn], true)));
|
|
41235
|
+
return Query.with({ pairs: pairs2, indices, raster: raster2, points: points2 }).from("points").select(groupby, {
|
|
40909
41236
|
index: sql`x + y * ${xn}::INTEGER`,
|
|
40910
|
-
|
|
41237
|
+
density: normalize4 ? sum2("w") : count()
|
|
40911
41238
|
}).groupby("index", groupby);
|
|
40912
41239
|
}
|
|
40913
41240
|
|
|
@@ -40932,13 +41259,11 @@ var Density1DMark = class extends Mark2 {
|
|
|
40932
41259
|
if (this.hasOwnData())
|
|
40933
41260
|
throw new Error("Density1DMark requires a data source");
|
|
40934
41261
|
const { bins: bins2, channels, dim, source: { table } } = this;
|
|
40935
|
-
const
|
|
40936
|
-
const bx =
|
|
40937
|
-
|
|
40938
|
-
|
|
40939
|
-
|
|
40940
|
-
this.channelField("weight") ? "weight" : null
|
|
40941
|
-
);
|
|
41262
|
+
const extent4 = this.extent = (dim === "x" ? extentX : extentY)(this, filter3);
|
|
41263
|
+
const [x3, bx] = binExpr(this, dim, bins2, extent4);
|
|
41264
|
+
const q = markQuery(channels, table, [dim]).where(filter3.concat(isBetween(bx, extent4)));
|
|
41265
|
+
const v2 = this.channelField("weight") ? "weight" : null;
|
|
41266
|
+
return binLinear1d(q, x3, v2);
|
|
40942
41267
|
}
|
|
40943
41268
|
queryResult(data) {
|
|
40944
41269
|
this.grid = grid1d(this.bins, data);
|
|
@@ -40973,8 +41298,8 @@ var Density1DMark = class extends Mark2 {
|
|
|
40973
41298
|
return [{ type: type2, data, options }];
|
|
40974
41299
|
}
|
|
40975
41300
|
};
|
|
40976
|
-
function binLinear1d(q, p,
|
|
40977
|
-
const w =
|
|
41301
|
+
function binLinear1d(q, p, density2) {
|
|
41302
|
+
const w = density2 ? `* ${density2}` : "";
|
|
40978
41303
|
const u4 = q.clone().select({
|
|
40979
41304
|
p,
|
|
40980
41305
|
i: sql`FLOOR(p)::INTEGER`,
|
|
@@ -40985,37 +41310,45 @@ function binLinear1d(q, p, value) {
|
|
|
40985
41310
|
i: sql`FLOOR(p)::INTEGER + 1`,
|
|
40986
41311
|
w: sql`(p - FLOOR(p))${w}`
|
|
40987
41312
|
});
|
|
40988
|
-
return Query.from(Query.unionAll(u4, v2)).select({ index: "i",
|
|
41313
|
+
return Query.from(Query.unionAll(u4, v2)).select({ index: "i", density: sum2("w") }).groupby("index").having(gt("density", 0));
|
|
40989
41314
|
}
|
|
40990
41315
|
|
|
40991
41316
|
// src/marks/Density2DMark.js
|
|
40992
41317
|
var Density2DMark = class extends Grid2DMark {
|
|
40993
41318
|
constructor(source, options) {
|
|
40994
|
-
const { type: type2 = "dot",
|
|
40995
|
-
|
|
40996
|
-
|
|
40997
|
-
|
|
40998
|
-
|
|
41319
|
+
const { type: type2 = "dot", ...channels } = options;
|
|
41320
|
+
super(type2, source, {
|
|
41321
|
+
bandwidth: 20,
|
|
41322
|
+
interpolate: "linear",
|
|
41323
|
+
pad: 0,
|
|
41324
|
+
pixelSize: 2,
|
|
41325
|
+
...channels
|
|
41326
|
+
});
|
|
40999
41327
|
}
|
|
41000
41328
|
convolve() {
|
|
41001
41329
|
super.convolve();
|
|
41002
|
-
const { bins: bins2,
|
|
41330
|
+
const { bins: bins2, pad: pad3, extentX: extentX2, extentY: extentY2 } = this;
|
|
41003
41331
|
const [nx, ny] = bins2;
|
|
41004
|
-
const
|
|
41005
|
-
const
|
|
41006
|
-
const
|
|
41007
|
-
const
|
|
41008
|
-
const
|
|
41009
|
-
|
|
41332
|
+
const scaleX = channelScale(this, "x");
|
|
41333
|
+
const scaleY = channelScale(this, "y");
|
|
41334
|
+
const [x06, x12] = extentX2.map((v2) => scaleX.apply(v2));
|
|
41335
|
+
const [y06, y12] = extentY2.map((v2) => scaleY.apply(v2));
|
|
41336
|
+
const deltaX = (x12 - x06) / (nx - pad3);
|
|
41337
|
+
const deltaY = (y12 - y06) / (ny - pad3);
|
|
41338
|
+
const offset2 = pad3 ? 0 : 0.5;
|
|
41339
|
+
this.data = points(
|
|
41340
|
+
this.kde,
|
|
41341
|
+
bins2,
|
|
41342
|
+
x06,
|
|
41343
|
+
y06,
|
|
41344
|
+
deltaX,
|
|
41345
|
+
deltaY,
|
|
41346
|
+
scaleX.invert,
|
|
41347
|
+
scaleY.invert,
|
|
41348
|
+
offset2
|
|
41349
|
+
);
|
|
41010
41350
|
return this;
|
|
41011
41351
|
}
|
|
41012
|
-
binDimensions() {
|
|
41013
|
-
const { plot: plot2, binWidth, binsX, binsY } = this;
|
|
41014
|
-
return [
|
|
41015
|
-
binsX ?? Math.round(plot2.innerWidth() / binWidth),
|
|
41016
|
-
binsY ?? Math.round(plot2.innerHeight() / binWidth)
|
|
41017
|
-
];
|
|
41018
|
-
}
|
|
41019
41352
|
plotSpecs() {
|
|
41020
41353
|
const { type: type2, channels, densityMap, data } = this;
|
|
41021
41354
|
const options = {};
|
|
@@ -41031,16 +41364,18 @@ var Density2DMark = class extends Grid2DMark {
|
|
|
41031
41364
|
return [{ type: type2, data, options }];
|
|
41032
41365
|
}
|
|
41033
41366
|
};
|
|
41034
|
-
function points(kde, bins2, x06, y06, deltaX, deltaY, offset2) {
|
|
41367
|
+
function points(kde, bins2, x06, y06, deltaX, deltaY, invertX, invertY, offset2) {
|
|
41035
41368
|
const scale3 = 1 / (deltaX * deltaY);
|
|
41036
41369
|
const [nx, ny] = bins2;
|
|
41037
41370
|
const data = [];
|
|
41038
|
-
for (const
|
|
41371
|
+
for (const cell2 of kde) {
|
|
41372
|
+
const grid = cell2.density;
|
|
41039
41373
|
for (let k2 = 0, j = 0; j < ny; ++j) {
|
|
41040
41374
|
for (let i = 0; i < nx; ++i, ++k2) {
|
|
41041
41375
|
data.push({
|
|
41042
|
-
|
|
41043
|
-
|
|
41376
|
+
...cell2,
|
|
41377
|
+
x: invertX(x06 + (i + offset2) * deltaX),
|
|
41378
|
+
y: invertY(y06 + (j + offset2) * deltaY),
|
|
41044
41379
|
density: grid[k2] * scale3
|
|
41045
41380
|
});
|
|
41046
41381
|
}
|
|
@@ -41158,34 +41493,48 @@ var RasterTileMark = class extends Grid2DMark {
|
|
|
41158
41493
|
return null;
|
|
41159
41494
|
}
|
|
41160
41495
|
tileQuery(extent4) {
|
|
41161
|
-
const {
|
|
41496
|
+
const { binType, binPad, channels, densityMap, source } = this;
|
|
41162
41497
|
const [[x06, x12], [y06, y12]] = extent4;
|
|
41163
41498
|
const [nx, ny] = this.bins;
|
|
41164
|
-
const bx =
|
|
41165
|
-
const by =
|
|
41166
|
-
const
|
|
41167
|
-
const ry = !!plot2.getAttribute("yReverse");
|
|
41168
|
-
const x3 = bin1d3(bx, x06, x12, nx, rx, binPad);
|
|
41169
|
-
const y3 = bin1d3(by, y06, y12, ny, ry, binPad);
|
|
41170
|
-
const bounds = binPad ? [isBetween(bx, [x06, x12]), isBetween(by, [y06, y12])] : [lte(x06, bx), lt(bx, x12), lte(y06, by), lt(by, y12)];
|
|
41499
|
+
const [x3, bx] = binExpr(this, "x", nx, [x06, x12], binPad);
|
|
41500
|
+
const [y3, by] = binExpr(this, "y", ny, [y06, y12], binPad);
|
|
41501
|
+
const bounds = binPad ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];
|
|
41171
41502
|
const q = Query.from(source.table).where(bounds);
|
|
41172
41503
|
const groupby = this.groupby = [];
|
|
41173
|
-
|
|
41504
|
+
const aggrMap = {};
|
|
41174
41505
|
for (const c4 of channels) {
|
|
41175
41506
|
if (Object.hasOwn(c4, "field")) {
|
|
41176
|
-
const { channel, field: field2 } = c4;
|
|
41507
|
+
const { as, channel, field: field2 } = c4;
|
|
41177
41508
|
if (field2.aggregate) {
|
|
41178
|
-
|
|
41509
|
+
aggrMap[channel] = field2;
|
|
41179
41510
|
densityMap[channel] = true;
|
|
41180
41511
|
} else if (channel === "weight") {
|
|
41181
|
-
|
|
41512
|
+
aggrMap.density = sum2(field2);
|
|
41182
41513
|
} else if (channel !== "x" && channel !== "y") {
|
|
41183
|
-
q.select({ [
|
|
41184
|
-
groupby.push(
|
|
41514
|
+
q.select({ [as]: field2 });
|
|
41515
|
+
groupby.push(as);
|
|
41185
41516
|
}
|
|
41186
41517
|
}
|
|
41187
41518
|
}
|
|
41188
|
-
|
|
41519
|
+
const aggr = this.aggr = Object.keys(aggrMap);
|
|
41520
|
+
if (aggrMap.density && aggr.length > 1) {
|
|
41521
|
+
throw new Error("Weight option can not be used with custom aggregates.");
|
|
41522
|
+
}
|
|
41523
|
+
if (!aggr.length) {
|
|
41524
|
+
aggr.push("density");
|
|
41525
|
+
aggrMap.density = count();
|
|
41526
|
+
}
|
|
41527
|
+
if (binType === "linear") {
|
|
41528
|
+
if (aggr.length > 1) {
|
|
41529
|
+
throw new Error("Linear binning not applicable to multiple aggregates.");
|
|
41530
|
+
}
|
|
41531
|
+
if (!aggrMap.density) {
|
|
41532
|
+
throw new Error("Linear binning not applicable to custom aggregates.");
|
|
41533
|
+
}
|
|
41534
|
+
return binLinear2d2(q, x3, y3, aggrMap.density, nx, groupby);
|
|
41535
|
+
} else {
|
|
41536
|
+
return bin2d2(q, x3, y3, aggrMap, nx, groupby);
|
|
41537
|
+
}
|
|
41189
41538
|
}
|
|
41190
41539
|
async requestTiles() {
|
|
41191
41540
|
const mc = coordinator();
|
|
@@ -41235,22 +41584,20 @@ var RasterTileMark = class extends Grid2DMark {
|
|
|
41235
41584
|
([i, j]) => mc.prefetch(this.tileQuery(tileExtent(i, j)))
|
|
41236
41585
|
);
|
|
41237
41586
|
const tiles = await Promise.all(queries);
|
|
41238
|
-
this.grids = [{
|
|
41587
|
+
this.grids = [{ density: processTiles(m, n, xx, yy, coords, tiles) }];
|
|
41239
41588
|
this.convolve().update();
|
|
41240
41589
|
}
|
|
41241
41590
|
convolve() {
|
|
41242
41591
|
return super.convolve().rasterize();
|
|
41243
41592
|
}
|
|
41244
41593
|
rasterize() {
|
|
41245
|
-
const { bins: bins2, kde
|
|
41594
|
+
const { bins: bins2, kde } = this;
|
|
41246
41595
|
const [w, h] = bins2;
|
|
41247
41596
|
const { canvas, ctx, img } = imageData2(this, w, h);
|
|
41248
|
-
const
|
|
41249
|
-
|
|
41250
|
-
|
|
41251
|
-
|
|
41252
|
-
const palette2 = imagePalette2(this, domain, grid.key?.[idx]);
|
|
41253
|
-
raster2(grid, img.data, w, h, s2, palette2);
|
|
41597
|
+
const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);
|
|
41598
|
+
this.data = kde.map((cell2) => {
|
|
41599
|
+
color3?.(img.data, w, h, cell2[colorProp]);
|
|
41600
|
+
alpha?.(img.data, w, h, cell2[alphaProp]);
|
|
41254
41601
|
ctx.putImageData(img, 0, 0);
|
|
41255
41602
|
return { src: canvas.toDataURL() };
|
|
41256
41603
|
});
|
|
@@ -41284,7 +41631,7 @@ function copy3(m, n, grid, values2, tx, ty) {
|
|
|
41284
41631
|
if (num === 0)
|
|
41285
41632
|
return;
|
|
41286
41633
|
const index2 = values2.getChild("index").toArray();
|
|
41287
|
-
const value = values2.getChild("
|
|
41634
|
+
const value = values2.getChild("density").toArray();
|
|
41288
41635
|
for (let row = 0; row < num; ++row) {
|
|
41289
41636
|
const idx = index2[row];
|
|
41290
41637
|
const i = tx + idx % m;
|
|
@@ -41303,60 +41650,10 @@ function imageData2(mark, w, h) {
|
|
|
41303
41650
|
}
|
|
41304
41651
|
return mark.image;
|
|
41305
41652
|
}
|
|
41306
|
-
function
|
|
41307
|
-
const { densityMap, kde, plot: plot2 } = mark;
|
|
41308
|
-
let domain = densityMap.fill && plot2.getAttribute("colorDomain");
|
|
41309
|
-
if (!domain) {
|
|
41310
|
-
let lo = 0, hi = 0;
|
|
41311
|
-
kde.forEach((grid) => {
|
|
41312
|
-
for (const v2 of grid) {
|
|
41313
|
-
if (v2 < lo)
|
|
41314
|
-
lo = v2;
|
|
41315
|
-
if (v2 > hi)
|
|
41316
|
-
hi = v2;
|
|
41317
|
-
}
|
|
41318
|
-
});
|
|
41319
|
-
domain = lo === 0 && hi === 0 ? [0, 1] : [lo, hi];
|
|
41320
|
-
}
|
|
41321
|
-
const type2 = plot2.getAttribute("colorScale");
|
|
41322
|
-
return scale2({ x: { type: type2, domain, range: [0, 1] } }).apply;
|
|
41323
|
-
}
|
|
41324
|
-
function imagePalette2(mark, domain, value, steps = 1024) {
|
|
41325
|
-
const { densityMap, plot: plot2 } = mark;
|
|
41326
|
-
const scheme28 = plot2.getAttribute("colorScheme");
|
|
41327
|
-
const fill = mark.channel("fill");
|
|
41328
|
-
let color3 = isColor2(fill?.value) ? fill.value : void 0;
|
|
41329
|
-
if (densityMap.fill || scheme28 && !color3) {
|
|
41330
|
-
if (scheme28) {
|
|
41331
|
-
try {
|
|
41332
|
-
return palette(
|
|
41333
|
-
steps,
|
|
41334
|
-
scale2({ color: { scheme: scheme28, domain: [0, 1] } }).interpolate
|
|
41335
|
-
);
|
|
41336
|
-
} catch (err) {
|
|
41337
|
-
console.warn(err);
|
|
41338
|
-
}
|
|
41339
|
-
}
|
|
41340
|
-
} else if (domain.length) {
|
|
41341
|
-
const range3 = plot2.getAttribute("colorRange");
|
|
41342
|
-
const spec = {
|
|
41343
|
-
domain,
|
|
41344
|
-
range: range3,
|
|
41345
|
-
scheme: scheme28 || (range3 ? void 0 : "tableau10")
|
|
41346
|
-
};
|
|
41347
|
-
color3 = scale2({ color: spec }).apply(value);
|
|
41348
|
-
}
|
|
41349
|
-
return palette(steps, opacityMap(color3));
|
|
41350
|
-
}
|
|
41351
|
-
function bin1d3(x3, x06, x12, n, reverse3, pad3) {
|
|
41352
|
-
const d = (n - pad3) / (x12 - x06);
|
|
41353
|
-
const f = d !== 1 ? ` * ${d}::DOUBLE` : "";
|
|
41354
|
-
return reverse3 ? sql`(${x12} - ${x3}::DOUBLE)${f}` : sql`(${x3}::DOUBLE - ${x06})${f}`;
|
|
41355
|
-
}
|
|
41356
|
-
function bin2d2(q, xp, yp, value, xn, groupby) {
|
|
41653
|
+
function bin2d2(q, xp, yp, aggs, xn, groupby) {
|
|
41357
41654
|
return q.select({
|
|
41358
41655
|
index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,
|
|
41359
|
-
|
|
41656
|
+
...aggs
|
|
41360
41657
|
}).groupby("index", groupby);
|
|
41361
41658
|
}
|
|
41362
41659
|
function binLinear2d2(q, xp, yp, value, xn, groupby) {
|
|
@@ -41378,7 +41675,7 @@ function binLinear2d2(q, xp, yp, value, xn, groupby) {
|
|
|
41378
41675
|
sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,
|
|
41379
41676
|
sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`
|
|
41380
41677
|
);
|
|
41381
|
-
return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i",
|
|
41678
|
+
return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i", density: sum2("w") }, groupby).groupby("index", groupby).having(neq("density", 0));
|
|
41382
41679
|
}
|
|
41383
41680
|
function tileFloor(value) {
|
|
41384
41681
|
const floored = Math.floor(value);
|
|
@@ -42209,28 +42506,24 @@ function findMark({ marks: marks2 }, channel) {
|
|
|
42209
42506
|
}
|
|
42210
42507
|
|
|
42211
42508
|
// src/transforms/bin.js
|
|
42212
|
-
var EXTENT = [
|
|
42213
|
-
"rectY-x",
|
|
42214
|
-
"rectX-y",
|
|
42215
|
-
"rect-x",
|
|
42216
|
-
"rect-y"
|
|
42217
|
-
];
|
|
42218
|
-
function hasExtent(channel, type2) {
|
|
42219
|
-
return EXTENT.includes(`${type2}-${channel}`);
|
|
42220
|
-
}
|
|
42509
|
+
var EXTENT = /* @__PURE__ */ new Set(["rectY-x", "rectX-y", "rect-x", "rect-y"]);
|
|
42221
42510
|
function bin2(field2, options = { steps: 25 }) {
|
|
42222
42511
|
const fn = (mark, channel) => {
|
|
42223
|
-
|
|
42224
|
-
|
|
42225
|
-
|
|
42226
|
-
|
|
42227
|
-
|
|
42228
|
-
}
|
|
42512
|
+
if (EXTENT.has(`${mark.type}-${channel}`)) {
|
|
42513
|
+
return {
|
|
42514
|
+
[`${channel}1`]: binField(mark, channel, field2, options),
|
|
42515
|
+
[`${channel}2`]: binField(mark, channel, field2, { ...options, offset: 1 })
|
|
42516
|
+
};
|
|
42517
|
+
} else {
|
|
42518
|
+
return {
|
|
42519
|
+
[channel]: binField(mark, channel, field2, options)
|
|
42520
|
+
};
|
|
42521
|
+
}
|
|
42229
42522
|
};
|
|
42230
42523
|
fn[Transform] = true;
|
|
42231
42524
|
return fn;
|
|
42232
42525
|
}
|
|
42233
|
-
function
|
|
42526
|
+
function binField(mark, channel, column3, options) {
|
|
42234
42527
|
return {
|
|
42235
42528
|
column: column3,
|
|
42236
42529
|
label: column3,
|
|
@@ -42244,13 +42537,15 @@ function binField2(mark, column3, options) {
|
|
|
42244
42537
|
return column3;
|
|
42245
42538
|
},
|
|
42246
42539
|
toString() {
|
|
42540
|
+
const { apply: apply2, sqlApply, sqlInvert } = channelScale(mark, channel);
|
|
42247
42541
|
const { min: min5, max: max4 } = mark.stats[column3];
|
|
42248
|
-
const b = bins(min5, max4, options);
|
|
42249
|
-
const col =
|
|
42542
|
+
const b = bins(apply2(min5), apply2(max4), options);
|
|
42543
|
+
const col = sqlApply(column3);
|
|
42250
42544
|
const base = b.min === 0 ? col : `(${col} - ${b.min})`;
|
|
42251
42545
|
const alpha = `${(b.max - b.min) / b.steps}::DOUBLE`;
|
|
42252
42546
|
const off = options.offset ? `${options.offset} + ` : "";
|
|
42253
|
-
|
|
42547
|
+
const expr = `${b.min} + ${alpha} * (${off}FLOOR(${base} / ${alpha}))`;
|
|
42548
|
+
return `${sqlInvert(expr)}`;
|
|
42254
42549
|
}
|
|
42255
42550
|
};
|
|
42256
42551
|
}
|
|
@@ -42294,6 +42589,7 @@ export {
|
|
|
42294
42589
|
Fixed,
|
|
42295
42590
|
GeoMark,
|
|
42296
42591
|
Grid2DMark,
|
|
42592
|
+
HeatmapMark,
|
|
42297
42593
|
HexbinMark,
|
|
42298
42594
|
Highlight,
|
|
42299
42595
|
Interval1D,
|