vega-functions 5.11.0 → 5.13.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.

Potentially problematic release.


This version of vega-functions might be problematic. Click here for more details.

@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vega-util'), require('vega-expression'), require('d3-geo'), require('d3-color'), require('vega-dataflow'), require('vega-scale'), require('vega-scenegraph'), require('vega-selections'), require('vega-statistics'), require('vega-time'), require('d3-array')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'vega-util', 'vega-expression', 'd3-geo', 'd3-color', 'vega-dataflow', 'vega-scale', 'vega-scenegraph', 'vega-selections', 'vega-statistics', 'vega-time', 'd3-array'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.vega = {}, global.vega, global.vega, global.d3, global.d3, global.vega, global.vega, global.vega, global.vega, global.vega, global.vega, global.d3));
5
- }(this, (function (exports, vegaUtil, vegaExpression, d3Geo, d3Color, vegaDataflow, vegaScale, vegaScenegraph, vegaSelections, vegaStatistics, vegaTime, d3Array) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vega-util'), require('vega-expression'), require('vega-dataflow'), require('vega-scale'), require('vega-scenegraph'), require('vega-selections'), require('vega-statistics'), require('vega-time')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'vega-util', 'vega-expression', 'vega-dataflow', 'vega-scale', 'vega-scenegraph', 'vega-selections', 'vega-statistics', 'vega-time'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.vega = {}, global.vega, global.vega, global.vega, global.vega, global.vega, global.vega, global.vega, global.vega));
5
+ })(this, (function (exports, vegaUtil, vegaExpression, vegaDataflow, vegaScale, vegaScenegraph, vegaSelections, vegaStatistics, vegaTime) { 'use strict';
6
6
 
7
7
  function data(name) {
8
8
  const data = this.context.data[name];
@@ -142,6 +142,572 @@
142
142
  };
143
143
  }
144
144
 
145
+ // https://github.com/python/cpython/blob/a74eea238f5baba15797e2e8b570d153bc8690a7/Modules/mathmodule.c#L1423
146
+ class Adder {
147
+ constructor() {
148
+ this._partials = new Float64Array(32);
149
+ this._n = 0;
150
+ }
151
+
152
+ add(x) {
153
+ const p = this._partials;
154
+ let i = 0;
155
+
156
+ for (let j = 0; j < this._n && j < 32; j++) {
157
+ const y = p[j],
158
+ hi = x + y,
159
+ lo = Math.abs(x) < Math.abs(y) ? x - (hi - y) : y - (hi - x);
160
+ if (lo) p[i++] = lo;
161
+ x = hi;
162
+ }
163
+
164
+ p[i] = x;
165
+ this._n = i + 1;
166
+ return this;
167
+ }
168
+
169
+ valueOf() {
170
+ const p = this._partials;
171
+ let n = this._n,
172
+ x,
173
+ y,
174
+ lo,
175
+ hi = 0;
176
+
177
+ if (n > 0) {
178
+ hi = p[--n];
179
+
180
+ while (n > 0) {
181
+ x = hi;
182
+ y = p[--n];
183
+ hi = x + y;
184
+ lo = y - (hi - x);
185
+ if (lo) break;
186
+ }
187
+
188
+ if (n > 0 && (lo < 0 && p[n - 1] < 0 || lo > 0 && p[n - 1] > 0)) {
189
+ y = lo * 2;
190
+ x = hi + y;
191
+ if (y == x - hi) hi = x;
192
+ }
193
+ }
194
+
195
+ return hi;
196
+ }
197
+
198
+ }
199
+
200
+ function range$2(start, stop, step) {
201
+ start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
202
+ var i = -1,
203
+ n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
204
+ range = new Array(n);
205
+
206
+ while (++i < n) {
207
+ range[i] = start + i * step;
208
+ }
209
+
210
+ return range;
211
+ }
212
+
213
+ var epsilon = 1e-6;
214
+ var epsilon2 = 1e-12;
215
+ var pi = Math.PI;
216
+ var halfPi = pi / 2;
217
+ var quarterPi = pi / 4;
218
+ var tau = pi * 2;
219
+ var degrees$1 = 180 / pi;
220
+ var radians$1 = pi / 180;
221
+ var abs = Math.abs;
222
+ var atan2 = Math.atan2;
223
+ var cos = Math.cos;
224
+ var hypot = Math.hypot;
225
+ var sin = Math.sin;
226
+ var sqrt = Math.sqrt;
227
+ function asin(x) {
228
+ return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x);
229
+ }
230
+
231
+ function noop() {}
232
+
233
+ function streamGeometry(geometry, stream) {
234
+ if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
235
+ streamGeometryType[geometry.type](geometry, stream);
236
+ }
237
+ }
238
+
239
+ var streamObjectType = {
240
+ Feature: function (object, stream) {
241
+ streamGeometry(object.geometry, stream);
242
+ },
243
+ FeatureCollection: function (object, stream) {
244
+ var features = object.features,
245
+ i = -1,
246
+ n = features.length;
247
+
248
+ while (++i < n) streamGeometry(features[i].geometry, stream);
249
+ }
250
+ };
251
+ var streamGeometryType = {
252
+ Sphere: function (object, stream) {
253
+ stream.sphere();
254
+ },
255
+ Point: function (object, stream) {
256
+ object = object.coordinates;
257
+ stream.point(object[0], object[1], object[2]);
258
+ },
259
+ MultiPoint: function (object, stream) {
260
+ var coordinates = object.coordinates,
261
+ i = -1,
262
+ n = coordinates.length;
263
+
264
+ while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
265
+ },
266
+ LineString: function (object, stream) {
267
+ streamLine(object.coordinates, stream, 0);
268
+ },
269
+ MultiLineString: function (object, stream) {
270
+ var coordinates = object.coordinates,
271
+ i = -1,
272
+ n = coordinates.length;
273
+
274
+ while (++i < n) streamLine(coordinates[i], stream, 0);
275
+ },
276
+ Polygon: function (object, stream) {
277
+ streamPolygon(object.coordinates, stream);
278
+ },
279
+ MultiPolygon: function (object, stream) {
280
+ var coordinates = object.coordinates,
281
+ i = -1,
282
+ n = coordinates.length;
283
+
284
+ while (++i < n) streamPolygon(coordinates[i], stream);
285
+ },
286
+ GeometryCollection: function (object, stream) {
287
+ var geometries = object.geometries,
288
+ i = -1,
289
+ n = geometries.length;
290
+
291
+ while (++i < n) streamGeometry(geometries[i], stream);
292
+ }
293
+ };
294
+
295
+ function streamLine(coordinates, stream, closed) {
296
+ var i = -1,
297
+ n = coordinates.length - closed,
298
+ coordinate;
299
+ stream.lineStart();
300
+
301
+ while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
302
+
303
+ stream.lineEnd();
304
+ }
305
+
306
+ function streamPolygon(coordinates, stream) {
307
+ var i = -1,
308
+ n = coordinates.length;
309
+ stream.polygonStart();
310
+
311
+ while (++i < n) streamLine(coordinates[i], stream, 1);
312
+
313
+ stream.polygonEnd();
314
+ }
315
+
316
+ function geoStream (object, stream) {
317
+ if (object && streamObjectType.hasOwnProperty(object.type)) {
318
+ streamObjectType[object.type](object, stream);
319
+ } else {
320
+ streamGeometry(object, stream);
321
+ }
322
+ }
323
+
324
+ var areaRingSum = new Adder(); // hello?
325
+
326
+ var areaSum = new Adder(),
327
+ lambda00$2,
328
+ phi00$2,
329
+ lambda0$1,
330
+ cosPhi0,
331
+ sinPhi0;
332
+ var areaStream = {
333
+ point: noop,
334
+ lineStart: noop,
335
+ lineEnd: noop,
336
+ polygonStart: function () {
337
+ areaRingSum = new Adder();
338
+ areaStream.lineStart = areaRingStart;
339
+ areaStream.lineEnd = areaRingEnd;
340
+ },
341
+ polygonEnd: function () {
342
+ var areaRing = +areaRingSum;
343
+ areaSum.add(areaRing < 0 ? tau + areaRing : areaRing);
344
+ this.lineStart = this.lineEnd = this.point = noop;
345
+ },
346
+ sphere: function () {
347
+ areaSum.add(tau);
348
+ }
349
+ };
350
+
351
+ function areaRingStart() {
352
+ areaStream.point = areaPointFirst;
353
+ }
354
+
355
+ function areaRingEnd() {
356
+ areaPoint(lambda00$2, phi00$2);
357
+ }
358
+
359
+ function areaPointFirst(lambda, phi) {
360
+ areaStream.point = areaPoint;
361
+ lambda00$2 = lambda, phi00$2 = phi;
362
+ lambda *= radians$1, phi *= radians$1;
363
+ lambda0$1 = lambda, cosPhi0 = cos(phi = phi / 2 + quarterPi), sinPhi0 = sin(phi);
364
+ }
365
+
366
+ function areaPoint(lambda, phi) {
367
+ lambda *= radians$1, phi *= radians$1;
368
+ phi = phi / 2 + quarterPi; // half the angular distance from south pole
369
+ // Spherical excess E for a spherical triangle with vertices: south pole,
370
+ // previous point, current point. Uses a formula derived from Cagnoli’s
371
+ // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
372
+
373
+ var dLambda = lambda - lambda0$1,
374
+ sdLambda = dLambda >= 0 ? 1 : -1,
375
+ adLambda = sdLambda * dLambda,
376
+ cosPhi = cos(phi),
377
+ sinPhi = sin(phi),
378
+ k = sinPhi0 * sinPhi,
379
+ u = cosPhi0 * cosPhi + k * cos(adLambda),
380
+ v = k * sdLambda * sin(adLambda);
381
+ areaRingSum.add(atan2(v, u)); // Advance the previous points.
382
+
383
+ lambda0$1 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
384
+ }
385
+
386
+ function area (object) {
387
+ areaSum = new Adder();
388
+ geoStream(object, areaStream);
389
+ return areaSum * 2;
390
+ }
391
+
392
+ function spherical(cartesian) {
393
+ return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
394
+ }
395
+ function cartesian(spherical) {
396
+ var lambda = spherical[0],
397
+ phi = spherical[1],
398
+ cosPhi = cos(phi);
399
+ return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];
400
+ }
401
+ function cartesianCross(a, b) {
402
+ return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
403
+ } // TODO return a
404
+
405
+ function cartesianNormalizeInPlace(d) {
406
+ var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
407
+ d[0] /= l, d[1] /= l, d[2] /= l;
408
+ }
409
+
410
+ var lambda0, phi0, lambda1, phi1, // bounds
411
+ lambda2, // previous lambda-coordinate
412
+ lambda00$1, phi00$1, // first point
413
+ p0, // previous 3D point
414
+ deltaSum, ranges, range$1;
415
+ var boundsStream = {
416
+ point: boundsPoint,
417
+ lineStart: boundsLineStart,
418
+ lineEnd: boundsLineEnd,
419
+ polygonStart: function () {
420
+ boundsStream.point = boundsRingPoint;
421
+ boundsStream.lineStart = boundsRingStart;
422
+ boundsStream.lineEnd = boundsRingEnd;
423
+ deltaSum = new Adder();
424
+ areaStream.polygonStart();
425
+ },
426
+ polygonEnd: function () {
427
+ areaStream.polygonEnd();
428
+ boundsStream.point = boundsPoint;
429
+ boundsStream.lineStart = boundsLineStart;
430
+ boundsStream.lineEnd = boundsLineEnd;
431
+ if (areaRingSum < 0) lambda0 = -(lambda1 = 180), phi0 = -(phi1 = 90);else if (deltaSum > epsilon) phi1 = 90;else if (deltaSum < -epsilon) phi0 = -90;
432
+ range$1[0] = lambda0, range$1[1] = lambda1;
433
+ },
434
+ sphere: function () {
435
+ lambda0 = -(lambda1 = 180), phi0 = -(phi1 = 90);
436
+ }
437
+ };
438
+
439
+ function boundsPoint(lambda, phi) {
440
+ ranges.push(range$1 = [lambda0 = lambda, lambda1 = lambda]);
441
+ if (phi < phi0) phi0 = phi;
442
+ if (phi > phi1) phi1 = phi;
443
+ }
444
+
445
+ function linePoint(lambda, phi) {
446
+ var p = cartesian([lambda * radians$1, phi * radians$1]);
447
+
448
+ if (p0) {
449
+ var normal = cartesianCross(p0, p),
450
+ equatorial = [normal[1], -normal[0], 0],
451
+ inflection = cartesianCross(equatorial, normal);
452
+ cartesianNormalizeInPlace(inflection);
453
+ inflection = spherical(inflection);
454
+ var delta = lambda - lambda2,
455
+ sign = delta > 0 ? 1 : -1,
456
+ lambdai = inflection[0] * degrees$1 * sign,
457
+ phii,
458
+ antimeridian = abs(delta) > 180;
459
+
460
+ if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
461
+ phii = inflection[1] * degrees$1;
462
+ if (phii > phi1) phi1 = phii;
463
+ } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
464
+ phii = -inflection[1] * degrees$1;
465
+ if (phii < phi0) phi0 = phii;
466
+ } else {
467
+ if (phi < phi0) phi0 = phi;
468
+ if (phi > phi1) phi1 = phi;
469
+ }
470
+
471
+ if (antimeridian) {
472
+ if (lambda < lambda2) {
473
+ if (angle(lambda0, lambda) > angle(lambda0, lambda1)) lambda1 = lambda;
474
+ } else {
475
+ if (angle(lambda, lambda1) > angle(lambda0, lambda1)) lambda0 = lambda;
476
+ }
477
+ } else {
478
+ if (lambda1 >= lambda0) {
479
+ if (lambda < lambda0) lambda0 = lambda;
480
+ if (lambda > lambda1) lambda1 = lambda;
481
+ } else {
482
+ if (lambda > lambda2) {
483
+ if (angle(lambda0, lambda) > angle(lambda0, lambda1)) lambda1 = lambda;
484
+ } else {
485
+ if (angle(lambda, lambda1) > angle(lambda0, lambda1)) lambda0 = lambda;
486
+ }
487
+ }
488
+ }
489
+ } else {
490
+ ranges.push(range$1 = [lambda0 = lambda, lambda1 = lambda]);
491
+ }
492
+
493
+ if (phi < phi0) phi0 = phi;
494
+ if (phi > phi1) phi1 = phi;
495
+ p0 = p, lambda2 = lambda;
496
+ }
497
+
498
+ function boundsLineStart() {
499
+ boundsStream.point = linePoint;
500
+ }
501
+
502
+ function boundsLineEnd() {
503
+ range$1[0] = lambda0, range$1[1] = lambda1;
504
+ boundsStream.point = boundsPoint;
505
+ p0 = null;
506
+ }
507
+
508
+ function boundsRingPoint(lambda, phi) {
509
+ if (p0) {
510
+ var delta = lambda - lambda2;
511
+ deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
512
+ } else {
513
+ lambda00$1 = lambda, phi00$1 = phi;
514
+ }
515
+
516
+ areaStream.point(lambda, phi);
517
+ linePoint(lambda, phi);
518
+ }
519
+
520
+ function boundsRingStart() {
521
+ areaStream.lineStart();
522
+ }
523
+
524
+ function boundsRingEnd() {
525
+ boundsRingPoint(lambda00$1, phi00$1);
526
+ areaStream.lineEnd();
527
+ if (abs(deltaSum) > epsilon) lambda0 = -(lambda1 = 180);
528
+ range$1[0] = lambda0, range$1[1] = lambda1;
529
+ p0 = null;
530
+ } // Finds the left-right distance between two longitudes.
531
+ // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
532
+ // the distance between ±180° to be 360°.
533
+
534
+
535
+ function angle(lambda0, lambda1) {
536
+ return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
537
+ }
538
+
539
+ function rangeCompare(a, b) {
540
+ return a[0] - b[0];
541
+ }
542
+
543
+ function rangeContains(range, x) {
544
+ return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
545
+ }
546
+
547
+ function bounds (feature) {
548
+ var i, n, a, b, merged, deltaMax, delta;
549
+ phi1 = lambda1 = -(lambda0 = phi0 = Infinity);
550
+ ranges = [];
551
+ geoStream(feature, boundsStream); // First, sort ranges by their minimum longitudes.
552
+
553
+ if (n = ranges.length) {
554
+ ranges.sort(rangeCompare); // Then, merge any ranges that overlap.
555
+
556
+ for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
557
+ b = ranges[i];
558
+
559
+ if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
560
+ if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
561
+ if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
562
+ } else {
563
+ merged.push(a = b);
564
+ }
565
+ } // Finally, find the largest gap between the merged ranges.
566
+ // The final bounding box will be the inverse of this gap.
567
+
568
+
569
+ for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
570
+ b = merged[i];
571
+ if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0 = b[0], lambda1 = a[1];
572
+ }
573
+ }
574
+
575
+ ranges = range$1 = null;
576
+ return lambda0 === Infinity || phi0 === Infinity ? [[NaN, NaN], [NaN, NaN]] : [[lambda0, phi0], [lambda1, phi1]];
577
+ }
578
+
579
+ var W0, W1, X0, Y0, Z0, X1, Y1, Z1, X2, Y2, Z2, lambda00, phi00, // first point
580
+ x0, y0, z0; // previous point
581
+
582
+ var centroidStream = {
583
+ sphere: noop,
584
+ point: centroidPoint,
585
+ lineStart: centroidLineStart,
586
+ lineEnd: centroidLineEnd,
587
+ polygonStart: function () {
588
+ centroidStream.lineStart = centroidRingStart;
589
+ centroidStream.lineEnd = centroidRingEnd;
590
+ },
591
+ polygonEnd: function () {
592
+ centroidStream.lineStart = centroidLineStart;
593
+ centroidStream.lineEnd = centroidLineEnd;
594
+ }
595
+ }; // Arithmetic mean of Cartesian vectors.
596
+
597
+ function centroidPoint(lambda, phi) {
598
+ lambda *= radians$1, phi *= radians$1;
599
+ var cosPhi = cos(phi);
600
+ centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi));
601
+ }
602
+
603
+ function centroidPointCartesian(x, y, z) {
604
+ ++W0;
605
+ X0 += (x - X0) / W0;
606
+ Y0 += (y - Y0) / W0;
607
+ Z0 += (z - Z0) / W0;
608
+ }
609
+
610
+ function centroidLineStart() {
611
+ centroidStream.point = centroidLinePointFirst;
612
+ }
613
+
614
+ function centroidLinePointFirst(lambda, phi) {
615
+ lambda *= radians$1, phi *= radians$1;
616
+ var cosPhi = cos(phi);
617
+ x0 = cosPhi * cos(lambda);
618
+ y0 = cosPhi * sin(lambda);
619
+ z0 = sin(phi);
620
+ centroidStream.point = centroidLinePoint;
621
+ centroidPointCartesian(x0, y0, z0);
622
+ }
623
+
624
+ function centroidLinePoint(lambda, phi) {
625
+ lambda *= radians$1, phi *= radians$1;
626
+ var cosPhi = cos(phi),
627
+ x = cosPhi * cos(lambda),
628
+ y = cosPhi * sin(lambda),
629
+ z = sin(phi),
630
+ w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
631
+ W1 += w;
632
+ X1 += w * (x0 + (x0 = x));
633
+ Y1 += w * (y0 + (y0 = y));
634
+ Z1 += w * (z0 + (z0 = z));
635
+ centroidPointCartesian(x0, y0, z0);
636
+ }
637
+
638
+ function centroidLineEnd() {
639
+ centroidStream.point = centroidPoint;
640
+ } // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
641
+ // J. Applied Mechanics 42, 239 (1975).
642
+
643
+
644
+ function centroidRingStart() {
645
+ centroidStream.point = centroidRingPointFirst;
646
+ }
647
+
648
+ function centroidRingEnd() {
649
+ centroidRingPoint(lambda00, phi00);
650
+ centroidStream.point = centroidPoint;
651
+ }
652
+
653
+ function centroidRingPointFirst(lambda, phi) {
654
+ lambda00 = lambda, phi00 = phi;
655
+ lambda *= radians$1, phi *= radians$1;
656
+ centroidStream.point = centroidRingPoint;
657
+ var cosPhi = cos(phi);
658
+ x0 = cosPhi * cos(lambda);
659
+ y0 = cosPhi * sin(lambda);
660
+ z0 = sin(phi);
661
+ centroidPointCartesian(x0, y0, z0);
662
+ }
663
+
664
+ function centroidRingPoint(lambda, phi) {
665
+ lambda *= radians$1, phi *= radians$1;
666
+ var cosPhi = cos(phi),
667
+ x = cosPhi * cos(lambda),
668
+ y = cosPhi * sin(lambda),
669
+ z = sin(phi),
670
+ cx = y0 * z - z0 * y,
671
+ cy = z0 * x - x0 * z,
672
+ cz = x0 * y - y0 * x,
673
+ m = hypot(cx, cy, cz),
674
+ w = asin(m),
675
+ // line weight = angle
676
+ v = m && -w / m; // area weight multiplier
677
+
678
+ X2.add(v * cx);
679
+ Y2.add(v * cy);
680
+ Z2.add(v * cz);
681
+ W1 += w;
682
+ X1 += w * (x0 + (x0 = x));
683
+ Y1 += w * (y0 + (y0 = y));
684
+ Z1 += w * (z0 + (z0 = z));
685
+ centroidPointCartesian(x0, y0, z0);
686
+ }
687
+
688
+ function centroid (object) {
689
+ W0 = W1 = X0 = Y0 = Z0 = X1 = Y1 = Z1 = 0;
690
+ X2 = new Adder();
691
+ Y2 = new Adder();
692
+ Z2 = new Adder();
693
+ geoStream(object, centroidStream);
694
+ var x = +X2,
695
+ y = +Y2,
696
+ z = +Z2,
697
+ m = hypot(x, y, z); // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
698
+
699
+ if (m < epsilon2) {
700
+ x = X1, y = Y1, z = Z1; // If the feature has zero length, fall back to arithmetic mean of point vectors.
701
+
702
+ if (W1 < epsilon) x = X0, y = Y0, z = Z0;
703
+ m = hypot(x, y, z); // If the feature still has an undefined ccentroid, then return.
704
+
705
+ if (m < epsilon2) return [NaN, NaN];
706
+ }
707
+
708
+ return [atan2(y, x) * degrees$1, asin(z / m) * degrees$1];
709
+ }
710
+
145
711
  function geoMethod(methodName, globalMethod) {
146
712
  return function (projection, geojson, group) {
147
713
  if (projection) {
@@ -155,9 +721,9 @@
155
721
  };
156
722
  }
157
723
 
158
- const geoArea = geoMethod('area', d3Geo.geoArea);
159
- const geoBounds = geoMethod('bounds', d3Geo.geoBounds);
160
- const geoCentroid = geoMethod('centroid', d3Geo.geoCentroid);
724
+ const geoArea = geoMethod('area', area);
725
+ const geoBounds = geoMethod('bounds', bounds);
726
+ const geoCentroid = geoMethod('centroid', centroid);
161
727
 
162
728
  function inScope (item) {
163
729
  const group = this.context.group;
@@ -193,6 +759,466 @@
193
759
  return log(this.context.dataflow, 'debug', arguments);
194
760
  }
195
761
 
762
+ function define (constructor, factory, prototype) {
763
+ constructor.prototype = factory.prototype = prototype;
764
+ prototype.constructor = constructor;
765
+ }
766
+ function extend(parent, definition) {
767
+ var prototype = Object.create(parent.prototype);
768
+
769
+ for (var key in definition) prototype[key] = definition[key];
770
+
771
+ return prototype;
772
+ }
773
+
774
+ function Color() {}
775
+ var darker = 0.7;
776
+ var brighter = 1 / darker;
777
+ var reI = "\\s*([+-]?\\d+)\\s*",
778
+ reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
779
+ reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
780
+ reHex = /^#([0-9a-f]{3,8})$/,
781
+ reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
782
+ reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
783
+ reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
784
+ reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
785
+ reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
786
+ reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
787
+ var named = {
788
+ aliceblue: 0xf0f8ff,
789
+ antiquewhite: 0xfaebd7,
790
+ aqua: 0x00ffff,
791
+ aquamarine: 0x7fffd4,
792
+ azure: 0xf0ffff,
793
+ beige: 0xf5f5dc,
794
+ bisque: 0xffe4c4,
795
+ black: 0x000000,
796
+ blanchedalmond: 0xffebcd,
797
+ blue: 0x0000ff,
798
+ blueviolet: 0x8a2be2,
799
+ brown: 0xa52a2a,
800
+ burlywood: 0xdeb887,
801
+ cadetblue: 0x5f9ea0,
802
+ chartreuse: 0x7fff00,
803
+ chocolate: 0xd2691e,
804
+ coral: 0xff7f50,
805
+ cornflowerblue: 0x6495ed,
806
+ cornsilk: 0xfff8dc,
807
+ crimson: 0xdc143c,
808
+ cyan: 0x00ffff,
809
+ darkblue: 0x00008b,
810
+ darkcyan: 0x008b8b,
811
+ darkgoldenrod: 0xb8860b,
812
+ darkgray: 0xa9a9a9,
813
+ darkgreen: 0x006400,
814
+ darkgrey: 0xa9a9a9,
815
+ darkkhaki: 0xbdb76b,
816
+ darkmagenta: 0x8b008b,
817
+ darkolivegreen: 0x556b2f,
818
+ darkorange: 0xff8c00,
819
+ darkorchid: 0x9932cc,
820
+ darkred: 0x8b0000,
821
+ darksalmon: 0xe9967a,
822
+ darkseagreen: 0x8fbc8f,
823
+ darkslateblue: 0x483d8b,
824
+ darkslategray: 0x2f4f4f,
825
+ darkslategrey: 0x2f4f4f,
826
+ darkturquoise: 0x00ced1,
827
+ darkviolet: 0x9400d3,
828
+ deeppink: 0xff1493,
829
+ deepskyblue: 0x00bfff,
830
+ dimgray: 0x696969,
831
+ dimgrey: 0x696969,
832
+ dodgerblue: 0x1e90ff,
833
+ firebrick: 0xb22222,
834
+ floralwhite: 0xfffaf0,
835
+ forestgreen: 0x228b22,
836
+ fuchsia: 0xff00ff,
837
+ gainsboro: 0xdcdcdc,
838
+ ghostwhite: 0xf8f8ff,
839
+ gold: 0xffd700,
840
+ goldenrod: 0xdaa520,
841
+ gray: 0x808080,
842
+ green: 0x008000,
843
+ greenyellow: 0xadff2f,
844
+ grey: 0x808080,
845
+ honeydew: 0xf0fff0,
846
+ hotpink: 0xff69b4,
847
+ indianred: 0xcd5c5c,
848
+ indigo: 0x4b0082,
849
+ ivory: 0xfffff0,
850
+ khaki: 0xf0e68c,
851
+ lavender: 0xe6e6fa,
852
+ lavenderblush: 0xfff0f5,
853
+ lawngreen: 0x7cfc00,
854
+ lemonchiffon: 0xfffacd,
855
+ lightblue: 0xadd8e6,
856
+ lightcoral: 0xf08080,
857
+ lightcyan: 0xe0ffff,
858
+ lightgoldenrodyellow: 0xfafad2,
859
+ lightgray: 0xd3d3d3,
860
+ lightgreen: 0x90ee90,
861
+ lightgrey: 0xd3d3d3,
862
+ lightpink: 0xffb6c1,
863
+ lightsalmon: 0xffa07a,
864
+ lightseagreen: 0x20b2aa,
865
+ lightskyblue: 0x87cefa,
866
+ lightslategray: 0x778899,
867
+ lightslategrey: 0x778899,
868
+ lightsteelblue: 0xb0c4de,
869
+ lightyellow: 0xffffe0,
870
+ lime: 0x00ff00,
871
+ limegreen: 0x32cd32,
872
+ linen: 0xfaf0e6,
873
+ magenta: 0xff00ff,
874
+ maroon: 0x800000,
875
+ mediumaquamarine: 0x66cdaa,
876
+ mediumblue: 0x0000cd,
877
+ mediumorchid: 0xba55d3,
878
+ mediumpurple: 0x9370db,
879
+ mediumseagreen: 0x3cb371,
880
+ mediumslateblue: 0x7b68ee,
881
+ mediumspringgreen: 0x00fa9a,
882
+ mediumturquoise: 0x48d1cc,
883
+ mediumvioletred: 0xc71585,
884
+ midnightblue: 0x191970,
885
+ mintcream: 0xf5fffa,
886
+ mistyrose: 0xffe4e1,
887
+ moccasin: 0xffe4b5,
888
+ navajowhite: 0xffdead,
889
+ navy: 0x000080,
890
+ oldlace: 0xfdf5e6,
891
+ olive: 0x808000,
892
+ olivedrab: 0x6b8e23,
893
+ orange: 0xffa500,
894
+ orangered: 0xff4500,
895
+ orchid: 0xda70d6,
896
+ palegoldenrod: 0xeee8aa,
897
+ palegreen: 0x98fb98,
898
+ paleturquoise: 0xafeeee,
899
+ palevioletred: 0xdb7093,
900
+ papayawhip: 0xffefd5,
901
+ peachpuff: 0xffdab9,
902
+ peru: 0xcd853f,
903
+ pink: 0xffc0cb,
904
+ plum: 0xdda0dd,
905
+ powderblue: 0xb0e0e6,
906
+ purple: 0x800080,
907
+ rebeccapurple: 0x663399,
908
+ red: 0xff0000,
909
+ rosybrown: 0xbc8f8f,
910
+ royalblue: 0x4169e1,
911
+ saddlebrown: 0x8b4513,
912
+ salmon: 0xfa8072,
913
+ sandybrown: 0xf4a460,
914
+ seagreen: 0x2e8b57,
915
+ seashell: 0xfff5ee,
916
+ sienna: 0xa0522d,
917
+ silver: 0xc0c0c0,
918
+ skyblue: 0x87ceeb,
919
+ slateblue: 0x6a5acd,
920
+ slategray: 0x708090,
921
+ slategrey: 0x708090,
922
+ snow: 0xfffafa,
923
+ springgreen: 0x00ff7f,
924
+ steelblue: 0x4682b4,
925
+ tan: 0xd2b48c,
926
+ teal: 0x008080,
927
+ thistle: 0xd8bfd8,
928
+ tomato: 0xff6347,
929
+ turquoise: 0x40e0d0,
930
+ violet: 0xee82ee,
931
+ wheat: 0xf5deb3,
932
+ white: 0xffffff,
933
+ whitesmoke: 0xf5f5f5,
934
+ yellow: 0xffff00,
935
+ yellowgreen: 0x9acd32
936
+ };
937
+ define(Color, color, {
938
+ copy: function (channels) {
939
+ return Object.assign(new this.constructor(), this, channels);
940
+ },
941
+ displayable: function () {
942
+ return this.rgb().displayable();
943
+ },
944
+ hex: color_formatHex,
945
+ // Deprecated! Use color.formatHex.
946
+ formatHex: color_formatHex,
947
+ formatHsl: color_formatHsl,
948
+ formatRgb: color_formatRgb,
949
+ toString: color_formatRgb
950
+ });
951
+
952
+ function color_formatHex() {
953
+ return this.rgb().formatHex();
954
+ }
955
+
956
+ function color_formatHsl() {
957
+ return hslConvert(this).formatHsl();
958
+ }
959
+
960
+ function color_formatRgb() {
961
+ return this.rgb().formatRgb();
962
+ }
963
+
964
+ function color(format) {
965
+ var m, l;
966
+ format = (format + "").trim().toLowerCase();
967
+ return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
968
+ : l === 3 ? new Rgb(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
969
+ : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
970
+ : l === 4 ? rgba(m >> 12 & 0xf | m >> 8 & 0xf0, m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, ((m & 0xf) << 4 | m & 0xf) / 0xff) // #f000
971
+ : null // invalid hex
972
+ ) : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
973
+ : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
974
+ : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
975
+ : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
976
+ : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
977
+ : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
978
+ : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
979
+ : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null;
980
+ }
981
+
982
+ function rgbn(n) {
983
+ return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
984
+ }
985
+
986
+ function rgba(r, g, b, a) {
987
+ if (a <= 0) r = g = b = NaN;
988
+ return new Rgb(r, g, b, a);
989
+ }
990
+
991
+ function rgbConvert(o) {
992
+ if (!(o instanceof Color)) o = color(o);
993
+ if (!o) return new Rgb();
994
+ o = o.rgb();
995
+ return new Rgb(o.r, o.g, o.b, o.opacity);
996
+ }
997
+ function rgb(r, g, b, opacity) {
998
+ return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
999
+ }
1000
+ function Rgb(r, g, b, opacity) {
1001
+ this.r = +r;
1002
+ this.g = +g;
1003
+ this.b = +b;
1004
+ this.opacity = +opacity;
1005
+ }
1006
+ define(Rgb, rgb, extend(Color, {
1007
+ brighter: function (k) {
1008
+ k = k == null ? brighter : Math.pow(brighter, k);
1009
+ return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
1010
+ },
1011
+ darker: function (k) {
1012
+ k = k == null ? darker : Math.pow(darker, k);
1013
+ return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
1014
+ },
1015
+ rgb: function () {
1016
+ return this;
1017
+ },
1018
+ displayable: function () {
1019
+ return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
1020
+ },
1021
+ hex: rgb_formatHex,
1022
+ // Deprecated! Use color.formatHex.
1023
+ formatHex: rgb_formatHex,
1024
+ formatRgb: rgb_formatRgb,
1025
+ toString: rgb_formatRgb
1026
+ }));
1027
+
1028
+ function rgb_formatHex() {
1029
+ return "#" + hex(this.r) + hex(this.g) + hex(this.b);
1030
+ }
1031
+
1032
+ function rgb_formatRgb() {
1033
+ var a = this.opacity;
1034
+ a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
1035
+ return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
1036
+ }
1037
+
1038
+ function hex(value) {
1039
+ value = Math.max(0, Math.min(255, Math.round(value) || 0));
1040
+ return (value < 16 ? "0" : "") + value.toString(16);
1041
+ }
1042
+
1043
+ function hsla(h, s, l, a) {
1044
+ if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
1045
+ return new Hsl(h, s, l, a);
1046
+ }
1047
+
1048
+ function hslConvert(o) {
1049
+ if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
1050
+ if (!(o instanceof Color)) o = color(o);
1051
+ if (!o) return new Hsl();
1052
+ if (o instanceof Hsl) return o;
1053
+ o = o.rgb();
1054
+ var r = o.r / 255,
1055
+ g = o.g / 255,
1056
+ b = o.b / 255,
1057
+ min = Math.min(r, g, b),
1058
+ max = Math.max(r, g, b),
1059
+ h = NaN,
1060
+ s = max - min,
1061
+ l = (max + min) / 2;
1062
+
1063
+ if (s) {
1064
+ if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
1065
+ s /= l < 0.5 ? max + min : 2 - max - min;
1066
+ h *= 60;
1067
+ } else {
1068
+ s = l > 0 && l < 1 ? 0 : h;
1069
+ }
1070
+
1071
+ return new Hsl(h, s, l, o.opacity);
1072
+ }
1073
+ function hsl(h, s, l, opacity) {
1074
+ return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
1075
+ }
1076
+
1077
+ function Hsl(h, s, l, opacity) {
1078
+ this.h = +h;
1079
+ this.s = +s;
1080
+ this.l = +l;
1081
+ this.opacity = +opacity;
1082
+ }
1083
+
1084
+ define(Hsl, hsl, extend(Color, {
1085
+ brighter: function (k) {
1086
+ k = k == null ? brighter : Math.pow(brighter, k);
1087
+ return new Hsl(this.h, this.s, this.l * k, this.opacity);
1088
+ },
1089
+ darker: function (k) {
1090
+ k = k == null ? darker : Math.pow(darker, k);
1091
+ return new Hsl(this.h, this.s, this.l * k, this.opacity);
1092
+ },
1093
+ rgb: function () {
1094
+ var h = this.h % 360 + (this.h < 0) * 360,
1095
+ s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
1096
+ l = this.l,
1097
+ m2 = l + (l < 0.5 ? l : 1 - l) * s,
1098
+ m1 = 2 * l - m2;
1099
+ return new Rgb(hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
1100
+ },
1101
+ displayable: function () {
1102
+ return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
1103
+ },
1104
+ formatHsl: function () {
1105
+ var a = this.opacity;
1106
+ a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
1107
+ return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
1108
+ }
1109
+ }));
1110
+ /* From FvD 13.37, CSS Color Module Level 3 */
1111
+
1112
+ function hsl2rgb(h, m1, m2) {
1113
+ return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
1114
+ }
1115
+
1116
+ const radians = Math.PI / 180;
1117
+ const degrees = 180 / Math.PI;
1118
+
1119
+ const K = 18,
1120
+ Xn = 0.96422,
1121
+ Yn = 1,
1122
+ Zn = 0.82521,
1123
+ t0 = 4 / 29,
1124
+ t1 = 6 / 29,
1125
+ t2 = 3 * t1 * t1,
1126
+ t3 = t1 * t1 * t1;
1127
+
1128
+ function labConvert(o) {
1129
+ if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
1130
+ if (o instanceof Hcl) return hcl2lab(o);
1131
+ if (!(o instanceof Rgb)) o = rgbConvert(o);
1132
+ var r = rgb2lrgb(o.r),
1133
+ g = rgb2lrgb(o.g),
1134
+ b = rgb2lrgb(o.b),
1135
+ y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn),
1136
+ x,
1137
+ z;
1138
+ if (r === g && g === b) x = z = y;else {
1139
+ x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn);
1140
+ z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn);
1141
+ }
1142
+ return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
1143
+ }
1144
+ function lab(l, a, b, opacity) {
1145
+ return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
1146
+ }
1147
+ function Lab(l, a, b, opacity) {
1148
+ this.l = +l;
1149
+ this.a = +a;
1150
+ this.b = +b;
1151
+ this.opacity = +opacity;
1152
+ }
1153
+ define(Lab, lab, extend(Color, {
1154
+ brighter: function (k) {
1155
+ return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity);
1156
+ },
1157
+ darker: function (k) {
1158
+ return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity);
1159
+ },
1160
+ rgb: function () {
1161
+ var y = (this.l + 16) / 116,
1162
+ x = isNaN(this.a) ? y : y + this.a / 500,
1163
+ z = isNaN(this.b) ? y : y - this.b / 200;
1164
+ x = Xn * lab2xyz(x);
1165
+ y = Yn * lab2xyz(y);
1166
+ z = Zn * lab2xyz(z);
1167
+ return new Rgb(lrgb2rgb(3.1338561 * x - 1.6168667 * y - 0.4906146 * z), lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z), lrgb2rgb(0.0719453 * x - 0.2289914 * y + 1.4052427 * z), this.opacity);
1168
+ }
1169
+ }));
1170
+
1171
+ function xyz2lab(t) {
1172
+ return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
1173
+ }
1174
+
1175
+ function lab2xyz(t) {
1176
+ return t > t1 ? t * t * t : t2 * (t - t0);
1177
+ }
1178
+
1179
+ function lrgb2rgb(x) {
1180
+ return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
1181
+ }
1182
+
1183
+ function rgb2lrgb(x) {
1184
+ return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
1185
+ }
1186
+
1187
+ function hclConvert(o) {
1188
+ if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
1189
+ if (!(o instanceof Lab)) o = labConvert(o);
1190
+ if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0 < o.l && o.l < 100 ? 0 : NaN, o.l, o.opacity);
1191
+ var h = Math.atan2(o.b, o.a) * degrees;
1192
+ return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
1193
+ }
1194
+ function hcl(h, c, l, opacity) {
1195
+ return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
1196
+ }
1197
+ function Hcl(h, c, l, opacity) {
1198
+ this.h = +h;
1199
+ this.c = +c;
1200
+ this.l = +l;
1201
+ this.opacity = +opacity;
1202
+ }
1203
+
1204
+ function hcl2lab(o) {
1205
+ if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity);
1206
+ var h = o.h * radians;
1207
+ return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
1208
+ }
1209
+
1210
+ define(Hcl, hcl, extend(Color, {
1211
+ brighter: function (k) {
1212
+ return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity);
1213
+ },
1214
+ darker: function (k) {
1215
+ return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity);
1216
+ },
1217
+ rgb: function () {
1218
+ return hcl2lab(this).rgb();
1219
+ }
1220
+ }));
1221
+
196
1222
  function channel_luminance_value(channelValue) {
197
1223
  const val = channelValue / 255;
198
1224
 
@@ -204,7 +1230,7 @@
204
1230
  }
205
1231
 
206
1232
  function luminance(color) {
207
- const c = d3Color.rgb(color),
1233
+ const c = rgb(color),
208
1234
  r = channel_luminance_value(c.r),
209
1235
  g = channel_luminance_value(c.g),
210
1236
  b = channel_luminance_value(c.b);
@@ -311,6 +1337,12 @@
311
1337
  return Math.atan2(t[0].clientY - t[1].clientY, t[0].clientX - t[1].clientX);
312
1338
  }
313
1339
 
1340
+ const accessors = {};
1341
+ function pluck (data, name) {
1342
+ const accessor = accessors[name] || (accessors[name] = vegaUtil.field(name));
1343
+ return vegaUtil.isArray(data) ? data.map(accessor) : accessor(data);
1344
+ }
1345
+
314
1346
  function array(seq) {
315
1347
  return vegaUtil.isArray(seq) || ArrayBuffer.isView(seq) ? seq : null;
316
1348
  }
@@ -462,6 +1494,96 @@
462
1494
  return p;
463
1495
  }
464
1496
 
1497
+ /**
1498
+ * Appends a new point to the lasso
1499
+ *
1500
+ * @param {*} lasso the lasso in pixel space
1501
+ * @param {*} x the x coordinate in pixel space
1502
+ * @param {*} y the y coordinate in pixel space
1503
+ * @param {*} minDist the minimum distance, in pixels, that thenew point needs to be apart from the last point
1504
+ * @returns a new array containing the lasso with the new point
1505
+ */
1506
+
1507
+ function lassoAppend(lasso, x, y, minDist = 5) {
1508
+ const last = lasso[lasso.length - 1]; // Add point to lasso if distance to last point exceed minDist or its the first point
1509
+
1510
+ if (last === undefined || Math.sqrt((last[0] - x) ** 2 + (last[1] - y) ** 2) > minDist) {
1511
+ lasso.push([x, y]);
1512
+ return [...lasso];
1513
+ }
1514
+
1515
+ return lasso;
1516
+ }
1517
+ /**
1518
+ * Generates a svg path command which draws a lasso
1519
+ *
1520
+ * @param {*} lasso the lasso in pixel space in the form [[x,y], [x,y], ...]
1521
+ * @returns the svg path command that draws the lasso
1522
+ */
1523
+
1524
+ function lassoPath(lasso) {
1525
+ return (lasso ?? []).reduce((svg, [x, y], i) => {
1526
+ return svg += i == 0 ? `M ${x},${y} ` : i === lasso.length - 1 ? ' Z' : `L ${x},${y} `;
1527
+ }, '');
1528
+ }
1529
+ /**
1530
+ * Inverts the lasso from pixel space to an array of vega scenegraph tuples
1531
+ *
1532
+ * @param {*} data the dataset
1533
+ * @param {*} pixelLasso the lasso in pixel space, [[x,y], [x,y], ...]
1534
+ * @param {*} unit the unit where the lasso is defined
1535
+ *
1536
+ * @returns an array of vega scenegraph tuples
1537
+ */
1538
+
1539
+ function intersectLasso(markname, pixelLasso, unit) {
1540
+ const {
1541
+ x,
1542
+ y,
1543
+ mark
1544
+ } = unit;
1545
+ const bb = new vegaScenegraph.Bounds().set(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER); // Get bounding box around lasso
1546
+
1547
+ for (const [px, py] of pixelLasso) {
1548
+ if (px < bb.x1) bb.x1 = px;
1549
+ if (px > bb.x2) bb.x2 = px;
1550
+ if (py < bb.y1) bb.y1 = py;
1551
+ if (py > bb.y2) bb.y2 = py;
1552
+ } // Translate bb against unit coordinates
1553
+
1554
+
1555
+ bb.translate(x, y);
1556
+ const intersection = intersect([[bb.x1, bb.y1], [bb.x2, bb.y2]], markname, mark); // Check every point against the lasso
1557
+
1558
+ return intersection.filter(tuple => pointInPolygon(tuple.x, tuple.y, pixelLasso));
1559
+ }
1560
+ /**
1561
+ * Performs a test if a point is inside a polygon based on the idea from
1562
+ * https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
1563
+ *
1564
+ * This method will not need the same start/end point since it wraps around the edges of the array
1565
+ *
1566
+ * @param {*} test a point to test against
1567
+ * @param {*} polygon a polygon in the form [[x,y], [x,y], ...]
1568
+ * @returns true if the point lies inside the polygon, false otherwise
1569
+ */
1570
+
1571
+ function pointInPolygon(testx, testy, polygon) {
1572
+ let intersections = 0;
1573
+
1574
+ for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
1575
+ const [prevX, prevY] = polygon[j];
1576
+ const [x, y] = polygon[i]; // count intersections
1577
+
1578
+ if (y > testy != prevY > testy && testx < (prevX - x) * (testy - y) / (prevY - y) + x) {
1579
+ intersections++;
1580
+ }
1581
+ } // point is in polygon if intersection count is odd
1582
+
1583
+
1584
+ return intersections & 1;
1585
+ }
1586
+
465
1587
  const functionContext = {
466
1588
  random() {
467
1589
  return vegaStatistics.random();
@@ -499,7 +1621,12 @@
499
1621
  },
500
1622
 
501
1623
  toBoolean: vegaUtil.toBoolean,
502
- toDate: vegaUtil.toDate,
1624
+
1625
+ toDate(_) {
1626
+ return vegaUtil.toDate(_);
1627
+ },
1628
+
1629
+ // suppress extra arguments
503
1630
  toNumber: vegaUtil.toNumber,
504
1631
  toString: vegaUtil.toString,
505
1632
  indexof,
@@ -513,16 +1640,17 @@
513
1640
  merge,
514
1641
  pad: vegaUtil.pad,
515
1642
  peek: vegaUtil.peek,
1643
+ pluck,
516
1644
  span: vegaUtil.span,
517
1645
  inrange: vegaUtil.inrange,
518
1646
  truncate: vegaUtil.truncate,
519
- rgb: d3Color.rgb,
520
- lab: d3Color.lab,
521
- hcl: d3Color.hcl,
522
- hsl: d3Color.hsl,
1647
+ rgb,
1648
+ lab,
1649
+ hcl,
1650
+ hsl,
523
1651
  luminance,
524
1652
  contrast,
525
- sequence: d3Array.range,
1653
+ sequence: range$2,
526
1654
  format,
527
1655
  utcFormat,
528
1656
  utcParse,
@@ -546,7 +1674,12 @@
546
1674
  warn,
547
1675
  info,
548
1676
  debug,
549
- extent: vegaUtil.extent,
1677
+
1678
+ extent(_) {
1679
+ return vegaUtil.extent(_);
1680
+ },
1681
+
1682
+ // suppress extra arguments
550
1683
  inScope,
551
1684
  intersect,
552
1685
  clampRange: vegaUtil.clampRange,
@@ -567,7 +1700,10 @@
567
1700
  zoomPow: vegaUtil.zoomPow,
568
1701
  zoomSymlog: vegaUtil.zoomSymlog,
569
1702
  encode,
570
- modify
1703
+ modify,
1704
+ lassoAppend,
1705
+ lassoPath,
1706
+ intersectLasso
571
1707
  };
572
1708
  const eventFunctions = ['view', 'item', 'group', 'xy', 'x', 'y'],
573
1709
  // event functions
@@ -588,7 +1724,7 @@
588
1724
  visitors: astVisitors
589
1725
  }; // export code generator
590
1726
 
591
- const codeGenerator = vegaExpression.codegen(codegenParams); // Build expression function registry
1727
+ const codeGenerator = vegaExpression.codegenExpression(codegenParams); // Build expression function registry
592
1728
 
593
1729
  function buildFunctions(codegen) {
594
1730
  const fn = vegaExpression.functions(codegen);
@@ -635,7 +1771,9 @@
635
1771
  expressionFunction('treeAncestors', treeAncestors, dataVisitor); // register Vega-Lite selection functions
636
1772
 
637
1773
  expressionFunction('vlSelectionTest', vegaSelections.selectionTest, vegaSelections.selectionVisitor);
1774
+ expressionFunction('vlSelectionIdTest', vegaSelections.selectionIdTest, vegaSelections.selectionVisitor);
638
1775
  expressionFunction('vlSelectionResolve', vegaSelections.selectionResolve, vegaSelections.selectionVisitor);
1776
+ expressionFunction('vlSelectionTuples', vegaSelections.selectionTuples);
639
1777
 
640
1778
  function parser (expr, scope) {
641
1779
  const params = {}; // parse the expression to an abstract syntax tree (ast)
@@ -644,7 +1782,7 @@
644
1782
 
645
1783
  try {
646
1784
  expr = vegaUtil.isString(expr) ? expr : vegaUtil.stringValue(expr) + '';
647
- ast = vegaExpression.parse(expr);
1785
+ ast = vegaExpression.parseExpression(expr);
648
1786
  } catch (err) {
649
1787
  vegaUtil.error('Expression parse error: ' + expr);
650
1788
  } // analyze ast function calls for dependencies
@@ -720,6 +1858,7 @@
720
1858
  exports.pathShape = pathShape;
721
1859
  exports.pinchAngle = pinchAngle;
722
1860
  exports.pinchDistance = pinchDistance;
1861
+ exports.pluck = pluck;
723
1862
  exports.range = range;
724
1863
  exports.replace = replace;
725
1864
  exports.reverse = reverse;
@@ -740,4 +1879,4 @@
740
1879
 
741
1880
  Object.defineProperty(exports, '__esModule', { value: true });
742
1881
 
743
- })));
1882
+ }));