@hema-to/regl-scatterplot 1.14.1 → 1.16.0-hemato.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.
@@ -172,306 +172,113 @@
172
172
  }
173
173
  return e;
174
174
  }
175
- function _regeneratorRuntime() {
176
- _regeneratorRuntime = function () {
177
- return e;
178
- };
179
- var t,
180
- e = {},
181
- r = Object.prototype,
182
- n = r.hasOwnProperty,
183
- o = Object.defineProperty || function (t, e, r) {
184
- t[e] = r.value;
185
- },
186
- i = "function" == typeof Symbol ? Symbol : {},
187
- a = i.iterator || "@@iterator",
188
- c = i.asyncIterator || "@@asyncIterator",
189
- u = i.toStringTag || "@@toStringTag";
190
- function define(t, e, r) {
191
- return Object.defineProperty(t, e, {
192
- value: r,
193
- enumerable: true,
194
- configurable: true,
195
- writable: true
196
- }), t[e];
197
- }
198
- try {
199
- define({}, "");
200
- } catch (t) {
201
- define = function (t, e, r) {
202
- return t[e] = r;
203
- };
204
- }
205
- function wrap(t, e, r, n) {
206
- var i = e && e.prototype instanceof Generator ? e : Generator,
207
- a = Object.create(i.prototype),
208
- c = new Context(n || []);
209
- return o(a, "_invoke", {
210
- value: makeInvokeMethod(t, r, c)
211
- }), a;
212
- }
213
- function tryCatch(t, e, r) {
214
- try {
215
- return {
216
- type: "normal",
217
- arg: t.call(e, r)
218
- };
219
- } catch (t) {
220
- return {
221
- type: "throw",
222
- arg: t
223
- };
224
- }
225
- }
226
- e.wrap = wrap;
227
- var h = "suspendedStart",
228
- l = "suspendedYield",
229
- f = "executing",
230
- s = "completed",
231
- y = {};
232
- function Generator() {}
233
- function GeneratorFunction() {}
234
- function GeneratorFunctionPrototype() {}
235
- var p = {};
236
- define(p, a, function () {
237
- return this;
238
- });
239
- var d = Object.getPrototypeOf,
240
- v = d && d(d(values([])));
241
- v && v !== r && n.call(v, a) && (p = v);
242
- var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);
243
- function defineIteratorMethods(t) {
244
- ["next", "throw", "return"].forEach(function (e) {
245
- define(t, e, function (t) {
246
- return this._invoke(e, t);
247
- });
248
- });
249
- }
250
- function AsyncIterator(t, e) {
251
- function invoke(r, o, i, a) {
252
- var c = tryCatch(t[r], t, o);
253
- if ("throw" !== c.type) {
254
- var u = c.arg,
255
- h = u.value;
256
- return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) {
257
- invoke("next", t, i, a);
258
- }, function (t) {
259
- invoke("throw", t, i, a);
260
- }) : e.resolve(h).then(function (t) {
261
- u.value = t, i(u);
262
- }, function (t) {
263
- return invoke("throw", t, i, a);
264
- });
265
- }
266
- a(c.arg);
267
- }
268
- var r;
269
- o(this, "_invoke", {
270
- value: function (t, n) {
271
- function callInvokeWithMethodAndArg() {
272
- return new e(function (e, r) {
273
- invoke(t, n, e, r);
274
- });
175
+ function _regenerator() {
176
+ /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
177
+ var e,
178
+ t,
179
+ r = "function" == typeof Symbol ? Symbol : {},
180
+ n = r.iterator || "@@iterator",
181
+ o = r.toStringTag || "@@toStringTag";
182
+ function i(r, n, o, i) {
183
+ var c = n && n.prototype instanceof Generator ? n : Generator,
184
+ u = Object.create(c.prototype);
185
+ return _regeneratorDefine(u, "_invoke", function (r, n, o) {
186
+ var i,
187
+ c,
188
+ u,
189
+ f = 0,
190
+ p = o || [],
191
+ y = false,
192
+ G = {
193
+ p: 0,
194
+ n: 0,
195
+ v: e,
196
+ a: d,
197
+ f: d.bind(e, 4),
198
+ d: function (t, r) {
199
+ return i = t, c = 0, u = e, G.n = r, a;
200
+ }
201
+ };
202
+ function d(r, n) {
203
+ for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) {
204
+ var o,
205
+ i = p[t],
206
+ d = G.p,
207
+ l = i[2];
208
+ r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0));
275
209
  }
276
- return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
210
+ if (o || r > 1) return a;
211
+ throw y = true, n;
277
212
  }
278
- });
279
- }
280
- function makeInvokeMethod(e, r, n) {
281
- var o = h;
282
- return function (i, a) {
283
- if (o === f) throw Error("Generator is already running");
284
- if (o === s) {
285
- if ("throw" === i) throw a;
213
+ return function (o, p, l) {
214
+ if (f > 1) throw TypeError("Generator is already running");
215
+ for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) {
216
+ i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u);
217
+ try {
218
+ if (f = 2, i) {
219
+ if (c || (o = "next"), t = i[o]) {
220
+ if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object");
221
+ if (!t.done) return t;
222
+ u = t.value, c < 2 && (c = 0);
223
+ } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1);
224
+ i = e;
225
+ } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break;
226
+ } catch (t) {
227
+ i = e, c = 1, u = t;
228
+ } finally {
229
+ f = 1;
230
+ }
231
+ }
286
232
  return {
287
233
  value: t,
288
- done: true
234
+ done: y
289
235
  };
290
- }
291
- for (n.method = i, n.arg = a;;) {
292
- var c = n.delegate;
293
- if (c) {
294
- var u = maybeInvokeDelegate(c, n);
295
- if (u) {
296
- if (u === y) continue;
297
- return u;
298
- }
299
- }
300
- if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
301
- if (o === h) throw o = s, n.arg;
302
- n.dispatchException(n.arg);
303
- } else "return" === n.method && n.abrupt("return", n.arg);
304
- o = f;
305
- var p = tryCatch(e, r, n);
306
- if ("normal" === p.type) {
307
- if (o = n.done ? s : l, p.arg === y) continue;
308
- return {
309
- value: p.arg,
310
- done: n.done
311
- };
312
- }
313
- "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg);
314
- }
315
- };
316
- }
317
- function maybeInvokeDelegate(e, r) {
318
- var n = r.method,
319
- o = e.iterator[n];
320
- if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y;
321
- var i = tryCatch(o, e.iterator, r.arg);
322
- if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y;
323
- var a = i.arg;
324
- return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y);
325
- }
326
- function pushTryEntry(t) {
327
- var e = {
328
- tryLoc: t[0]
329
- };
330
- 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);
331
- }
332
- function resetTryEntry(t) {
333
- var e = t.completion || {};
334
- e.type = "normal", delete e.arg, t.completion = e;
335
- }
336
- function Context(t) {
337
- this.tryEntries = [{
338
- tryLoc: "root"
339
- }], t.forEach(pushTryEntry, this), this.reset(true);
236
+ };
237
+ }(r, o, i), true), u;
340
238
  }
341
- function values(e) {
342
- if (e || "" === e) {
343
- var r = e[a];
344
- if (r) return r.call(e);
345
- if ("function" == typeof e.next) return e;
346
- if (!isNaN(e.length)) {
347
- var o = -1,
348
- i = function next() {
349
- for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = false, next;
350
- return next.value = t, next.done = true, next;
351
- };
352
- return i.next = i;
353
- }
354
- }
355
- throw new TypeError(typeof e + " is not iterable");
239
+ var a = {};
240
+ function Generator() {}
241
+ function GeneratorFunction() {}
242
+ function GeneratorFunctionPrototype() {}
243
+ t = Object.getPrototypeOf;
244
+ var c = [][n] ? t(t([][n]())) : (_regeneratorDefine(t = {}, n, function () {
245
+ return this;
246
+ }), t),
247
+ u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c);
248
+ function f(e) {
249
+ return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e;
356
250
  }
357
- return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", {
358
- value: GeneratorFunctionPrototype,
359
- configurable: true
360
- }), o(GeneratorFunctionPrototype, "constructor", {
361
- value: GeneratorFunction,
362
- configurable: true
363
- }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) {
364
- var e = "function" == typeof t && t.constructor;
365
- return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name));
366
- }, e.mark = function (t) {
367
- return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t;
368
- }, e.awrap = function (t) {
369
- return {
370
- __await: t
371
- };
372
- }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {
373
- return this;
374
- }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {
375
- void 0 === i && (i = Promise);
376
- var a = new AsyncIterator(wrap(t, r, n, o), i);
377
- return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {
378
- return t.done ? t.value : a.next();
379
- });
380
- }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () {
251
+ return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine(u), _regeneratorDefine(u, o, "Generator"), _regeneratorDefine(u, n, function () {
381
252
  return this;
382
- }), define(g, "toString", function () {
253
+ }), _regeneratorDefine(u, "toString", function () {
383
254
  return "[object Generator]";
384
- }), e.keys = function (t) {
385
- var e = Object(t),
386
- r = [];
387
- for (var n in e) r.push(n);
388
- return r.reverse(), function next() {
389
- for (; r.length;) {
390
- var t = r.pop();
391
- if (t in e) return next.value = t, next.done = false, next;
392
- }
393
- return next.done = true, next;
255
+ }), (_regenerator = function () {
256
+ return {
257
+ w: i,
258
+ m: f
394
259
  };
395
- }, e.values = values, Context.prototype = {
396
- constructor: Context,
397
- reset: function (e) {
398
- if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = false, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);
399
- },
400
- stop: function () {
401
- this.done = true;
402
- var t = this.tryEntries[0].completion;
403
- if ("throw" === t.type) throw t.arg;
404
- return this.rval;
405
- },
406
- dispatchException: function (e) {
407
- if (this.done) throw e;
408
- var r = this;
409
- function handle(n, o) {
410
- return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o;
411
- }
412
- for (var o = this.tryEntries.length - 1; o >= 0; --o) {
413
- var i = this.tryEntries[o],
414
- a = i.completion;
415
- if ("root" === i.tryLoc) return handle("end");
416
- if (i.tryLoc <= this.prev) {
417
- var c = n.call(i, "catchLoc"),
418
- u = n.call(i, "finallyLoc");
419
- if (c && u) {
420
- if (this.prev < i.catchLoc) return handle(i.catchLoc, true);
421
- if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
422
- } else if (c) {
423
- if (this.prev < i.catchLoc) return handle(i.catchLoc, true);
424
- } else {
425
- if (!u) throw Error("try statement without catch or finally");
426
- if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
427
- }
428
- }
429
- }
430
- },
431
- abrupt: function (t, e) {
432
- for (var r = this.tryEntries.length - 1; r >= 0; --r) {
433
- var o = this.tryEntries[r];
434
- if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) {
435
- var i = o;
436
- break;
437
- }
438
- }
439
- i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);
440
- var a = i ? i.completion : {};
441
- return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a);
442
- },
443
- complete: function (t, e) {
444
- if ("throw" === t.type) throw t.arg;
445
- return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y;
446
- },
447
- finish: function (t) {
448
- for (var e = this.tryEntries.length - 1; e >= 0; --e) {
449
- var r = this.tryEntries[e];
450
- if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;
451
- }
452
- },
453
- catch: function (t) {
454
- for (var e = this.tryEntries.length - 1; e >= 0; --e) {
455
- var r = this.tryEntries[e];
456
- if (r.tryLoc === t) {
457
- var n = r.completion;
458
- if ("throw" === n.type) {
459
- var o = n.arg;
460
- resetTryEntry(r);
461
- }
462
- return o;
463
- }
464
- }
465
- throw Error("illegal catch attempt");
466
- },
467
- delegateYield: function (e, r, n) {
468
- return this.delegate = {
469
- iterator: values(e),
470
- resultName: r,
471
- nextLoc: n
472
- }, "next" === this.method && (this.arg = t), y;
473
- }
474
- }, e;
260
+ })();
261
+ }
262
+ function _regeneratorDefine(e, r, n, t) {
263
+ var i = Object.defineProperty;
264
+ try {
265
+ i({}, "", {});
266
+ } catch (e) {
267
+ i = 0;
268
+ }
269
+ _regeneratorDefine = function (e, r, n, t) {
270
+ function o(r, n) {
271
+ _regeneratorDefine(e, r, function (e) {
272
+ return this._invoke(r, n, e);
273
+ });
274
+ }
275
+ r ? i ? i(e, r, {
276
+ value: n,
277
+ enumerable: !t,
278
+ configurable: !t,
279
+ writable: !t
280
+ }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2));
281
+ }, _regeneratorDefine(e, r, n, t);
475
282
  }
476
283
  function _slicedToArray(r, e) {
477
284
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
@@ -501,88 +308,92 @@
501
308
  }
502
309
  }
503
310
 
504
- // @flekschas/utils v0.32.2 Copyright 2023 Fritz Lekschas
505
311
  /* eslint no-param-reassign:0 */
506
-
507
312
  /**
508
313
  * Cubic in easing function
509
- * @param {number} t - The input time to be eased. Must be in [0, 1] where `0`
314
+ * @param t - The input time to be eased. Must be in [0, 1] where `0`
510
315
  * refers to the start and `1` to the end
511
- * @return {number} The eased time
316
+ * @return The eased time
512
317
  */
513
318
  const cubicIn = t => t * t * t;
514
-
515
319
  /**
516
320
  * Cubic in and out easing function
517
- * @param {number} t - The input time to be eased. Must be in [0, 1] where `0`
321
+ * @param t - The input time to be eased. Must be in [0, 1] where `0`
518
322
  * refers to the start and `1` to the end
519
- * @return {number} The eased time
323
+ * @return The eased time
520
324
  */
521
325
  const cubicInOut = t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
522
-
523
326
  /**
524
327
  * Cubic out easing function
525
- * @param {number} t - The input time to be eased. Must be in [0, 1] where `0`
328
+ * @param t - The input time to be eased. Must be in [0, 1] where `0`
526
329
  * refers to the start and `1` to the end
527
- * @return {number} The eased time
330
+ * @return The eased time
528
331
  */
529
332
  const cubicOut = t => --t * t * t + 1;
530
-
531
333
  /**
532
334
  * Linear easing function
533
- * @param {number} t - The input time to be eased. Must be in [0, 1] where `0`
335
+ * @param t - The input time to be eased. Must be in [0, 1] where `0`
534
336
  * refers to the start and `1` to the end
535
- * @return {number} Same as the input
337
+ * @return Same as the input
536
338
  */
537
339
  const linear = t => t;
538
-
539
340
  /**
540
341
  * Quadratic in easing function
541
- * @param {number} t - The input time to be eased. Must be in [0, 1] where `0`
342
+ * @param t - The input time to be eased. Must be in [0, 1] where `0`
542
343
  * refers to the start and `1` to the end
543
- * @return {number} The eased time
344
+ * @return The eased time
544
345
  */
545
346
  const quadIn = t => t * t;
546
-
547
347
  /**
548
348
  * Quadratic in and out easing function
549
- * @param {number} t - The input time to be eased. Must be in [0, 1] where `0`
349
+ * @param t - The input time to be eased. Must be in [0, 1] where `0`
550
350
  * refers to the start and `1` to the end
551
- * @return {number} The eased time
351
+ * @return The eased time
552
352
  */
553
353
  const quadInOut = t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
554
-
555
354
  /**
556
355
  * Quadratic out easing function
557
- * @param {number} t - The input time to be eased. Must be in [0, 1] where `0`
356
+ * @param t - The input time to be eased. Must be in [0, 1] where `0`
558
357
  * refers to the start and `1` to the end
559
- * @return {number} The eased time
358
+ * @return The eased time
560
359
  */
561
360
  const quadOut = t => t * (2 - t);
562
361
 
362
+ /**
363
+ * Restrict value to be within [min, max]
364
+ * @description About 18% faster than `Math.max(min, Math.min(max, value))`
365
+ * @param value - Value to be clamped
366
+ * @param min - Min value
367
+ * @param max - Max value
368
+ * @return Clamped value
369
+ */
563
370
  /**
564
371
  * Identity function
565
- * @type {<T>(x: T) => T}
566
- * @param {*} x - Any kind of value
567
- * @return {*} `x`
372
+ * @param x - Any kind of value
373
+ * @return `x`
568
374
  */
569
375
  const identity = x => x;
570
376
 
571
377
  /**
572
378
  * Check if two arrays contain the same elements
573
- * @type {<T>(a: T[], b: T[]) => Boolean}
574
- * @param {array} a - First array
575
- * @param {array} b - Second array
576
- * @return {boolean} If `true` the two arrays contain the same elements
379
+ * @param a - First array
380
+ * @param b - Second array
381
+ * @return If `true` the two arrays contain the same elements
577
382
  */
578
383
  const hasSameElements = (a, b) => {
579
- if (a === b) return true;
580
- if (a.length !== b.length) return false;
384
+ if (a === b) {
385
+ return true;
386
+ }
387
+ if (a.length !== b.length) {
388
+ return false;
389
+ }
581
390
  const aSet = new Set(a);
582
391
  const bSet = new Set(b);
583
392
  // Since the arrays could contain duplicates, we have to check the set length
584
393
  // as well
585
- if (aSet.size !== bSet.size) return false;
394
+ if (aSet.size !== bSet.size) {
395
+ return false;
396
+ }
586
397
  return b.every(element => aSet.has(element));
587
398
  };
588
399
 
@@ -592,11 +403,10 @@
592
403
  * @description
593
404
  * This is identical but much faster than `Math.hypot(...v)`
594
405
  *
595
- * @param {number[]} v - Numerical vector
596
- * @return {number} L2 norm
406
+ * @param v - Numerical vector
407
+ * @return L2 norm
597
408
  */
598
409
  const l2Norm = v => Math.sqrt(v.reduce((sum, x) => sum + x ** 2, 0));
599
-
600
410
  /**
601
411
  * Get the maximum number of a vector while ignoring NaNs
602
412
  *
@@ -604,35 +414,32 @@
604
414
  * This version is muuuch faster than `Math.max(...v)` and supports vectors
605
415
  * longer than 256^2, which is a limitation of `Math.max.apply(null, v)`.
606
416
  *
607
- * @param {number[]} v - Numerical vector
608
- * @return {number} The largest number
417
+ * @param v - Numerical vector
418
+ * @return The largest number
609
419
  */
610
- const max$1 = v => v.reduce((_max, a) => a > _max ? a : _max, -Infinity);
611
-
420
+ const max$1 = v => v.reduce((_max, a) => a > _max ? a : _max, Number.NEGATIVE_INFINITY);
612
421
  /**
613
422
  * Initialize an array of a certain length using a mapping function
614
423
  *
615
424
  * @description
616
425
  * This is equivalent to `Array.from({ length }, mapFn)` but about 60% faster
617
426
  *
618
- * @param {number} length - Size of the array
619
- * @param {function} mapFn - Mapping function
620
- * @return {array} Initialized array
621
- * @type {<T = number>(length: number, mapFn: (i: number, length: number) => T) => T[]}
427
+ * @param length - Size of the array
428
+ * @param mapFn - Mapping function
429
+ * @return Initialized array
622
430
  */
623
- const rangeMap = (length, mapFn = x => x) => {
431
+ const rangeMap = (length, mapFn = identity) => {
624
432
  const out = [];
625
433
  for (let i = 0; i < length; i++) {
626
434
  out.push(mapFn(i, length));
627
435
  }
628
436
  return out;
629
437
  };
630
-
631
438
  /**
632
439
  * Get the unique union of two vectors of integers
633
- * @param {number[]} v - First vector of integers
634
- * @param {number[]} w - Second vector of integers
635
- * @return {number[]} Unique union of `v` and `w`
440
+ * @param v - First vector of integers
441
+ * @param w - Second vector of integers
442
+ * @return Unique union of `v` and `w`
636
443
  */
637
444
  const unionIntegers = (v, w) => {
638
445
  const a = [];
@@ -651,9 +458,9 @@
651
458
  /**
652
459
  * Assign properties, constructors, etc. to an object
653
460
  *
654
- * @param {object} target - The target object that gets `sources` assigned to it
655
- * @param {}
656
- * @return {object}
461
+ * @param target - The target object that gets `sources` assigned to it
462
+ * @param sources - The sources to be assigned to the target object
463
+ * @return An object representing the union of the target and sources objects
657
464
  */
658
465
  const assign = (target, ...sources) => {
659
466
  sources.forEach(source => {
@@ -662,11 +469,10 @@
662
469
  descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
663
470
  return descriptors;
664
471
  }, {});
665
-
666
472
  // By default, Object.assign copies enumerable Symbols, too
667
473
  Object.getOwnPropertySymbols(source).forEach(symbol => {
668
474
  const descriptor = Object.getOwnPropertyDescriptor(source, symbol);
669
- if (descriptor.enumerable) {
475
+ if (descriptor?.enumerable) {
670
476
  descriptors[symbol] = descriptor;
671
477
  }
672
478
  });
@@ -677,30 +483,25 @@
677
483
 
678
484
  /**
679
485
  * Convenience function to compose functions
680
- * @param {...function} fns - Array of functions
681
- * @return {function} The composed function
682
- */
683
- const pipe = (...fns) =>
684
- /**
685
- * @param {*} x - Some value
686
- * @return {*} Output of the composed function
486
+ * @param fns - Array of functions
487
+ * @return The composed function
687
488
  */
688
- x => fns.reduce((y, f) => f(y), x);
689
-
489
+ function pipe(...fns) {
490
+ return x => fns.reduce((y, f) => f(y), x);
491
+ }
690
492
  /**
691
493
  * Assign a constructor to the object
692
- * @param {function} constructor - Constructor functions
494
+ * @param constructorFn - Constructor functions
693
495
  */
694
- const withConstructor = constructor => self => assign({
496
+ const withConstructor = constructorFn => self => assign({
695
497
  __proto__: {
696
- constructor
498
+ constructor: constructorFn
697
499
  }
698
500
  }, self);
699
-
700
501
  /**
701
502
  * Assign a static property to an object
702
- * @param {string} name - Name of the property
703
- * @param {*} value - Static value
503
+ * @param name - Name of the property
504
+ * @param value - Static value
704
505
  */
705
506
  const withStaticProperty = (name, value) => self => assign(self, {
706
507
  get [name]() {
@@ -708,43 +509,61 @@
708
509
  }
709
510
  });
710
511
 
512
+ /**
513
+ * L distance between a pair of vectors
514
+ *
515
+ * @description
516
+ * Identical but much faster than `lDist(l)([fromX, fromY], [toX, toY])`
517
+ *
518
+ * @param l - Defines the Lp space
519
+ */
711
520
  /**
712
521
  * L2 distance between a pair of points
713
522
  *
714
523
  * @description
715
524
  * Identical but much faster than `l2Dist([fromX, fromY], [toX, toY])`
716
525
  *
717
- * @param {number} fromX - X coordinate of the first point
718
- * @param {number} fromY - Y coordinate of the first point
719
- * @param {number} toX - X coordinate of the second point
720
- * @param {number} toY - Y coordinate of the first point
721
- * @return {number} L2 distance
526
+ * @paramfromX - X coordinate of the first point
527
+ * @paramfromY - Y coordinate of the first point
528
+ * @paramtoX - X coordinate of the second point
529
+ * @paramtoY - Y coordinate of the first point
530
+ * @returnL2 distance
722
531
  */
723
532
  const l2PointDist = (fromX, fromY, toX, toY) => Math.sqrt((fromX - toX) ** 2 + (fromY - toY) ** 2);
724
533
 
725
534
  /**
726
535
  * Create a worker from a function
727
- * @param {function} fn - Function to be turned into a worker
728
- * @return {Worker} Worker function
536
+ * @param fn - Function to be turned into a worker
537
+ * @return Worker function
729
538
  */
730
539
  const createWorker$1 = fn => new Worker(window.URL.createObjectURL(new Blob([`(${fn.toString()})()`], {
731
- type: 'text/javascript'
540
+ type: "text/javascript"
732
541
  })));
733
542
 
543
+ /**
544
+ * Debounce a function call.
545
+ *
546
+ * @description
547
+ * Function calls are delayed by `wait` milliseconds and only one out of
548
+ * multiple function calls is executed.
549
+ *
550
+ * @param fn - Function to be debounced
551
+ * @param wait - Number of milliseconds to debounce the function call.
552
+ * @return Debounced function
553
+ */
734
554
  /**
735
555
  * Get a promise that resolves after the next `n` animation frames
736
- * @param {number} n - Number of animation frames to wait
737
- * @return {Promise} A promise that resolves after the next `n` animation frames
556
+ * @param n - Number of animation frames to wait
557
+ * @return A promise that resolves after the next `n` animation frames
738
558
  */
739
559
  const nextAnimationFrame = (n = 1) => new Promise(resolve => {
740
560
  let i = 0;
741
561
  const raf = () => requestAnimationFrame(() => {
742
562
  i++;
743
- if (i < n) raf();else resolve();
563
+ if (i < n) raf();else resolve(undefined);
744
564
  });
745
565
  raf();
746
566
  });
747
-
748
567
  /**
749
568
  * Throttle and debounce a function call
750
569
  *
@@ -767,17 +586,15 @@
767
586
  * 6. No call => nothing
768
587
  * 7. No call => f(args5) called due to debouncing
769
588
  *
770
- * @param {functon} fn - Function to be throttled and debounced
771
- * @param {number} throttleTime - Throttle intevals in milliseconds
772
- * @param {number} debounceTime - Debounce wait time in milliseconds. By default
773
- * this is the same as `throttleTime`.
774
- * @return {function} - Throttled and debounced function
589
+ * @param fn - Function to be throttled and debounced
590
+ * @param throttleTime - Throttle intevals in milliseconds
591
+ * @param debounceTime - Debounce wait time in milliseconds. By default this is
592
+ * the same as `throttleTime`.
593
+ * @return Throttled and debounced function
775
594
  */
776
- const throttleAndDebounce = (fn, throttleTime, debounceTime = null) => {
595
+ const throttleAndDebounce = (fn, throttleTime, debounceTime) => {
777
596
  let timeout;
778
597
  let blockedCalls = 0;
779
-
780
- // eslint-disable-next-line no-param-reassign
781
598
  debounceTime = debounceTime === null ? throttleTime : debounceTime;
782
599
  const debounced = (...args) => {
783
600
  const later = () => {
@@ -795,7 +612,10 @@
795
612
  };
796
613
  let isWaiting = false;
797
614
  const throttledAndDebounced = (...args) => {
798
- if (!isWaiting) {
615
+ if (isWaiting) {
616
+ blockedCalls++;
617
+ debounced(...args);
618
+ } else {
799
619
  fn(...args);
800
620
  debounced(...args);
801
621
  isWaiting = true;
@@ -803,9 +623,6 @@
803
623
  setTimeout(() => {
804
624
  isWaiting = false;
805
625
  }, throttleTime);
806
- } else {
807
- blockedCalls++;
808
- debounced(...args);
809
626
  }
810
627
  };
811
628
  throttledAndDebounced.reset = () => {
@@ -822,17 +639,10 @@
822
639
  * Common utilities
823
640
  * @module glMatrix
824
641
  */
642
+
825
643
  // Configuration Constants
826
644
  var EPSILON = 0.000001;
827
- var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
828
- if (!Math.hypot) Math.hypot = function () {
829
- var y = 0,
830
- i = arguments.length;
831
- while (i--) {
832
- y += arguments[i] * arguments[i];
833
- }
834
- return Math.sqrt(y);
835
- };
645
+ var ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array;
836
646
 
837
647
  /**
838
648
  * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.
@@ -844,7 +654,6 @@
844
654
  *
845
655
  * @returns {mat4} a new 4x4 matrix
846
656
  */
847
-
848
657
  function create$2() {
849
658
  var out = new ARRAY_TYPE(16);
850
659
  if (ARRAY_TYPE != Float32Array) {
@@ -867,13 +676,13 @@
867
676
  out[15] = 1;
868
677
  return out;
869
678
  }
679
+
870
680
  /**
871
681
  * Creates a new mat4 initialized with values from an existing matrix
872
682
  *
873
683
  * @param {ReadonlyMat4} a matrix to clone
874
684
  * @returns {mat4} a new 4x4 matrix
875
685
  */
876
-
877
686
  function clone(a) {
878
687
  var out = new ARRAY_TYPE(16);
879
688
  out[0] = a[0];
@@ -894,14 +703,14 @@
894
703
  out[15] = a[15];
895
704
  return out;
896
705
  }
706
+
897
707
  /**
898
708
  * Inverts a mat4
899
709
  *
900
710
  * @param {mat4} out the receiving matrix
901
711
  * @param {ReadonlyMat4} a the source matrix
902
- * @returns {mat4} out
712
+ * @returns {mat4 | null} out, or null if source matrix is not invertible
903
713
  */
904
-
905
714
  function invert(out, a) {
906
715
  var a00 = a[0],
907
716
  a01 = a[1],
@@ -930,8 +739,9 @@
930
739
  var b08 = a20 * a33 - a23 * a30;
931
740
  var b09 = a21 * a32 - a22 * a31;
932
741
  var b10 = a21 * a33 - a23 * a31;
933
- var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
742
+ var b11 = a22 * a33 - a23 * a32;
934
743
 
744
+ // Calculate the determinant
935
745
  var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
936
746
  if (!det) {
937
747
  return null;
@@ -955,6 +765,7 @@
955
765
  out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
956
766
  return out;
957
767
  }
768
+
958
769
  /**
959
770
  * Multiplies two mat4s
960
771
  *
@@ -963,7 +774,6 @@
963
774
  * @param {ReadonlyMat4} b the second operand
964
775
  * @returns {mat4} out
965
776
  */
966
-
967
777
  function multiply(out, a, b) {
968
778
  var a00 = a[0],
969
779
  a01 = a[1],
@@ -980,8 +790,9 @@
980
790
  var a30 = a[12],
981
791
  a31 = a[13],
982
792
  a32 = a[14],
983
- a33 = a[15]; // Cache only the current line of the second matrix
793
+ a33 = a[15];
984
794
 
795
+ // Cache only the current line of the second matrix
985
796
  var b0 = b[0],
986
797
  b1 = b[1],
987
798
  b2 = b[2],
@@ -1016,6 +827,7 @@
1016
827
  out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
1017
828
  return out;
1018
829
  }
830
+
1019
831
  /**
1020
832
  * Creates a matrix from a vector translation
1021
833
  * This is equivalent to (but much faster than):
@@ -1027,7 +839,6 @@
1027
839
  * @param {ReadonlyVec3} v Translation vector
1028
840
  * @returns {mat4} out
1029
841
  */
1030
-
1031
842
  function fromTranslation(out, v) {
1032
843
  out[0] = 1;
1033
844
  out[1] = 0;
@@ -1047,6 +858,7 @@
1047
858
  out[15] = 1;
1048
859
  return out;
1049
860
  }
861
+
1050
862
  /**
1051
863
  * Creates a matrix from a vector scaling
1052
864
  * This is equivalent to (but much faster than):
@@ -1058,7 +870,6 @@
1058
870
  * @param {ReadonlyVec3} v Scaling vector
1059
871
  * @returns {mat4} out
1060
872
  */
1061
-
1062
873
  function fromScaling(out, v) {
1063
874
  out[0] = v[0];
1064
875
  out[1] = 0;
@@ -1078,6 +889,7 @@
1078
889
  out[15] = 1;
1079
890
  return out;
1080
891
  }
892
+
1081
893
  /**
1082
894
  * Creates a matrix from a given angle around a given axis
1083
895
  * This is equivalent to (but much faster than):
@@ -1090,12 +902,11 @@
1090
902
  * @param {ReadonlyVec3} axis the axis to rotate around
1091
903
  * @returns {mat4} out
1092
904
  */
1093
-
1094
905
  function fromRotation(out, rad, axis) {
1095
906
  var x = axis[0],
1096
907
  y = axis[1],
1097
908
  z = axis[2];
1098
- var len = Math.hypot(x, y, z);
909
+ var len = Math.sqrt(x * x + y * y + z * z);
1099
910
  var s, c, t;
1100
911
  if (len < EPSILON) {
1101
912
  return null;
@@ -1106,8 +917,9 @@
1106
917
  z *= len;
1107
918
  s = Math.sin(rad);
1108
919
  c = Math.cos(rad);
1109
- t = 1 - c; // Perform rotation-specific matrix multiplication
920
+ t = 1 - c;
1110
921
 
922
+ // Perform rotation-specific matrix multiplication
1111
923
  out[0] = x * x * t + c;
1112
924
  out[1] = y * x * t + z * s;
1113
925
  out[2] = z * x * t - y * s;
@@ -1126,6 +938,7 @@
1126
938
  out[15] = 1;
1127
939
  return out;
1128
940
  }
941
+
1129
942
  /**
1130
943
  * Returns the translation vector component of a transformation
1131
944
  * matrix. If a matrix is built with fromRotationTranslation,
@@ -1135,24 +948,23 @@
1135
948
  * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
1136
949
  * @return {vec3} out
1137
950
  */
1138
-
1139
951
  function getTranslation(out, mat) {
1140
952
  out[0] = mat[12];
1141
953
  out[1] = mat[13];
1142
954
  out[2] = mat[14];
1143
955
  return out;
1144
956
  }
957
+
1145
958
  /**
1146
959
  * Returns the scaling factor component of a transformation
1147
960
  * matrix. If a matrix is built with fromRotationTranslationScale
1148
- * with a normalized Quaternion paramter, the returned vector will be
961
+ * with a normalized Quaternion parameter, the returned vector will be
1149
962
  * the same as the scaling vector
1150
963
  * originally supplied.
1151
964
  * @param {vec3} out Vector to receive scaling factor component
1152
965
  * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
1153
966
  * @return {vec3} out
1154
967
  */
1155
-
1156
968
  function getScaling(out, mat) {
1157
969
  var m11 = mat[0];
1158
970
  var m12 = mat[1];
@@ -1163,9 +975,9 @@
1163
975
  var m31 = mat[8];
1164
976
  var m32 = mat[9];
1165
977
  var m33 = mat[10];
1166
- out[0] = Math.hypot(m11, m12, m13);
1167
- out[1] = Math.hypot(m21, m22, m23);
1168
- out[2] = Math.hypot(m31, m32, m33);
978
+ out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);
979
+ out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);
980
+ out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);
1169
981
  return out;
1170
982
  }
1171
983
 
@@ -1179,7 +991,6 @@
1179
991
  *
1180
992
  * @returns {vec4} a new 4D vector
1181
993
  */
1182
-
1183
994
  function create$1() {
1184
995
  var out = new ARRAY_TYPE(4);
1185
996
  if (ARRAY_TYPE != Float32Array) {
@@ -1190,6 +1001,7 @@
1190
1001
  }
1191
1002
  return out;
1192
1003
  }
1004
+
1193
1005
  /**
1194
1006
  * Transforms the vec4 with a mat4.
1195
1007
  *
@@ -1198,7 +1010,6 @@
1198
1010
  * @param {ReadonlyMat4} m matrix to transform with
1199
1011
  * @returns {vec4} out
1200
1012
  */
1201
-
1202
1013
  function transformMat4(out, a, m) {
1203
1014
  var x = a[0],
1204
1015
  y = a[1],
@@ -1210,6 +1021,7 @@
1210
1021
  out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
1211
1022
  return out;
1212
1023
  }
1024
+
1213
1025
  /**
1214
1026
  * Perform some operation over an array of vec4s.
1215
1027
  *
@@ -1222,7 +1034,6 @@
1222
1034
  * @returns {Array} a
1223
1035
  * @function
1224
1036
  */
1225
-
1226
1037
  (function () {
1227
1038
  var vec = create$1();
1228
1039
  return function (a, stride, offset, count, fn, arg) {
@@ -1263,7 +1074,6 @@
1263
1074
  *
1264
1075
  * @returns {vec2} a new 2D vector
1265
1076
  */
1266
-
1267
1077
  function create() {
1268
1078
  var out = new ARRAY_TYPE(2);
1269
1079
  if (ARRAY_TYPE != Float32Array) {
@@ -1272,25 +1082,21 @@
1272
1082
  }
1273
1083
  return out;
1274
1084
  }
1085
+
1275
1086
  /**
1276
- * Get the angle between two 2D vectors
1087
+ * Get the smallest angle between two 2D vectors
1277
1088
  * @param {ReadonlyVec2} a The first operand
1278
1089
  * @param {ReadonlyVec2} b The second operand
1279
1090
  * @returns {Number} The angle in radians
1280
1091
  */
1281
-
1282
1092
  function angle(a, b) {
1283
- var x1 = a[0],
1284
- y1 = a[1],
1285
- x2 = b[0],
1286
- y2 = b[1],
1287
- // mag is the product of the magnitudes of a and b
1288
- mag = Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2),
1289
- // mag &&.. short circuits if mag == 0
1290
- cosine = mag && (x1 * x2 + y1 * y2) / mag; // Math.min(Math.max(cosine, -1), 1) clamps the cosine between -1 and 1
1291
-
1292
- return Math.acos(Math.min(Math.max(cosine, -1), 1));
1093
+ var ax = a[0],
1094
+ ay = a[1],
1095
+ bx = b[0],
1096
+ by = b[1];
1097
+ return Math.abs(Math.atan2(ay * bx - ax * by, ax * bx + ay * by));
1293
1098
  }
1099
+
1294
1100
  /**
1295
1101
  * Perform some operation over an array of vec2s.
1296
1102
  *
@@ -1303,7 +1109,6 @@
1303
1109
  * @returns {Array} a
1304
1110
  * @function
1305
1111
  */
1306
-
1307
1112
  (function () {
1308
1113
  var vec = create();
1309
1114
  return function (a, stride, offset, count, fn, arg) {
@@ -1751,10 +1556,10 @@
1751
1556
 
1752
1557
  // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
1753
1558
  if (data.length > 80 * dim) {
1754
- minX = Infinity;
1755
- minY = Infinity;
1756
- let maxX = -Infinity;
1757
- let maxY = -Infinity;
1559
+ minX = data[0];
1560
+ minY = data[1];
1561
+ let maxX = minX;
1562
+ let maxY = minY;
1758
1563
  for (let i = dim; i < outerLen; i += dim) {
1759
1564
  const x = data[i];
1760
1565
  const y = data[i + 1];
@@ -2056,7 +1861,7 @@
2056
1861
  // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
2057
1862
  function isValidDiagonal(a, b) {
2058
1863
  return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && (
2059
- // dones't intersect other edges
1864
+ // doesn't intersect other edges
2060
1865
  locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && (
2061
1866
  // locally visible
2062
1867
  area(a.prev, a, b.prev) || area(a, b.prev, b)) ||
@@ -2700,105 +2505,281 @@ void main() {
2700
2505
  };
2701
2506
  };
2702
2507
 
2703
- /**
2704
- * KDBush - A fast static index for 2D points
2705
- * @license ISC License
2706
- * @copyright Vladimir Agafonkin 2018
2707
- * @version 4.0.2
2708
- * @see https://github.com/mourner/kdbush/
2709
- */
2710
- var createKDBushClass = (function () {
2711
- var ARRAY_TYPES = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
2508
+ var version = "1.16.0-hemato.0";
2712
2509
 
2713
- /** @typedef {Int8ArrayConstructor | Uint8ArrayConstructor | Uint8ClampedArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor} TypedArrayConstructor */
2510
+ const FRAGMENT_SHADER$2 = `
2511
+ precision mediump float;
2714
2512
 
2715
- var VERSION = 1; // serialized format version
2716
- var HEADER_SIZE = 8;
2717
- var KDBush = /*#__PURE__*/function () {
2718
- /**
2719
- * Creates an index that will hold a given number of items.
2720
- * @param {number} numItems
2721
- * @param {number} [nodeSize=64] Size of the KD-tree node (64 by default).
2722
- * @param {TypedArrayConstructor} [ArrayType=Float64Array] The array type used for coordinates storage (`Float64Array` by default).
2723
- * @param {ArrayBuffer} [data] (For internal use only)
2724
- */
2725
- function KDBush(numItems) {
2726
- var nodeSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 64;
2727
- var ArrayType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Float64Array;
2728
- var data = arguments.length > 3 ? arguments[3] : undefined;
2729
- _classCallCheck(this, KDBush);
2730
- if (isNaN(numItems) || numItems < 0) throw new Error("Unexpected numItems value: ".concat(numItems, "."));
2731
- this.numItems = +numItems;
2732
- this.nodeSize = Math.min(Math.max(+nodeSize, 2), 65535);
2733
- this.ArrayType = ArrayType;
2734
- this.IndexArrayType = numItems < 65536 ? Uint16Array : Uint32Array;
2735
- var arrayTypeIndex = ARRAY_TYPES.indexOf(this.ArrayType);
2736
- var coordsByteSize = numItems * 2 * this.ArrayType.BYTES_PER_ELEMENT;
2737
- var idsByteSize = numItems * this.IndexArrayType.BYTES_PER_ELEMENT;
2738
- var padCoords = (8 - idsByteSize % 8) % 8;
2739
- if (arrayTypeIndex < 0) {
2740
- throw new Error("Unexpected typed array class: ".concat(ArrayType, "."));
2741
- }
2742
- if (data && data instanceof ArrayBuffer) {
2743
- // reconstruct an index from a buffer
2744
- this.data = data;
2745
- this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
2746
- this.coords = new this.ArrayType(this.data, HEADER_SIZE + idsByteSize + padCoords, numItems * 2);
2747
- this._pos = numItems * 2;
2748
- this._finished = true;
2749
- } else {
2750
- // initialize a new index
2751
- this.data = new ArrayBuffer(HEADER_SIZE + coordsByteSize + idsByteSize + padCoords);
2752
- this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
2753
- this.coords = new this.ArrayType(this.data, HEADER_SIZE + idsByteSize + padCoords, numItems * 2);
2754
- this._pos = 0;
2755
- this._finished = false;
2513
+ uniform sampler2D texture;
2756
2514
 
2757
- // set header
2758
- new Uint8Array(this.data, 0, 2).set([0xdb, (VERSION << 4) + arrayTypeIndex]);
2759
- new Uint16Array(this.data, 2, 1)[0] = nodeSize;
2760
- new Uint32Array(this.data, 4, 1)[0] = numItems;
2761
- }
2762
- }
2515
+ varying vec2 uv;
2763
2516
 
2764
- /**
2765
- * Add a point to the index.
2766
- * @param {number} x
2767
- * @param {number} y
2768
- * @returns {number} An incremental index associated with the added item (starting from `0`).
2769
- */
2770
- return _createClass(KDBush, [{
2771
- key: "add",
2772
- value: function add(x, y) {
2773
- var index = this._pos >> 1;
2774
- this.ids[index] = index;
2775
- this.coords[this._pos++] = x;
2776
- this.coords[this._pos++] = y;
2777
- return index;
2778
- }
2517
+ void main () {
2518
+ gl_FragColor = texture2D(texture, uv);
2519
+ }
2520
+ `;
2779
2521
 
2780
- /**
2781
- * Perform indexing of the added points.
2782
- */
2783
- }, {
2784
- key: "finish",
2785
- value: function finish() {
2786
- var numAdded = this._pos >> 1;
2787
- if (numAdded !== this.numItems) {
2788
- throw new Error("Added ".concat(numAdded, " items when expected ").concat(this.numItems, "."));
2789
- }
2790
- // kd-sort both arrays for efficient search
2791
- sort(this.ids, this.coords, this.nodeSize, 0, this.numItems - 1, 0);
2792
- this._finished = true;
2793
- return this;
2794
- }
2522
+ const VERTEX_SHADER = `
2523
+ precision mediump float;
2795
2524
 
2796
- /**
2797
- * Search the index for items within a given bounding box.
2798
- * @param {number} minX
2799
- * @param {number} minY
2800
- * @param {number} maxX
2801
- * @param {number} maxY
2525
+ uniform mat4 modelViewProjection;
2526
+
2527
+ attribute vec2 position;
2528
+
2529
+ varying vec2 uv;
2530
+
2531
+ void main () {
2532
+ uv = position;
2533
+ gl_Position = modelViewProjection * vec4(-1.0 + 2.0 * uv.x, 1.0 - 2.0 * uv.y, 0, 1);
2534
+ }
2535
+ `;
2536
+
2537
+ var AUTO = 'auto';
2538
+ var COLOR_NORMAL_IDX = 0;
2539
+ var COLOR_ACTIVE_IDX = 1;
2540
+ var COLOR_HOVER_IDX = 2;
2541
+ var COLOR_BG_IDX = 3;
2542
+ var COLOR_NUM_STATES = 4;
2543
+ var FLOAT_BYTES = Float32Array.BYTES_PER_ELEMENT;
2544
+ var GL_EXTENSIONS = ['OES_texture_float', 'OES_element_index_uint', 'WEBGL_color_buffer_float', 'EXT_float_blend'];
2545
+ var CLEAR_OPTIONS = {
2546
+ color: [0, 0, 0, 0],
2547
+ // Transparent background color
2548
+ depth: 1
2549
+ };
2550
+ var MOUSE_MODE_PANZOOM = 'panZoom';
2551
+ var MOUSE_MODE_LASSO = 'lasso';
2552
+ var MOUSE_MODE_ROTATE = 'rotate';
2553
+ var MOUSE_MODES = [MOUSE_MODE_PANZOOM, MOUSE_MODE_LASSO, MOUSE_MODE_ROTATE];
2554
+ var DEFAULT_MOUSE_MODE = MOUSE_MODE_PANZOOM;
2555
+
2556
+ // Easing
2557
+ var EASING_FNS = {
2558
+ cubicIn: cubicIn,
2559
+ cubicInOut: cubicInOut,
2560
+ cubicOut: cubicOut,
2561
+ linear: linear,
2562
+ quadIn: quadIn,
2563
+ quadInOut: quadInOut,
2564
+ quadOut: quadOut
2565
+ };
2566
+ var DEFAULT_EASING = cubicInOut;
2567
+ var CONTINUOUS = 'continuous';
2568
+ var CATEGORICAL = 'categorical';
2569
+ var VALUE_ZW_DATA_TYPES = [CONTINUOUS, CATEGORICAL];
2570
+
2571
+ // Default lasso
2572
+ var LASSO_CLEAR_ON_DESELECT = 'deselect';
2573
+ var LASSO_CLEAR_ON_END = 'lassoEnd';
2574
+ var LASSO_CLEAR_EVENTS = [LASSO_CLEAR_ON_DESELECT, LASSO_CLEAR_ON_END];
2575
+ var LASSO_BRUSH_MIN_MIN_DIST = 3;
2576
+ var DEFAULT_LASSO_COLOR = [0, 0.666666667, 1, 1];
2577
+ var DEFAULT_LASSO_LINE_WIDTH = 2;
2578
+ var DEFAULT_LASSO_INITIATOR = false;
2579
+ var DEFAULT_LASSO_MIN_DELAY$1 = 10;
2580
+ var DEFAULT_LASSO_MIN_DIST$1 = 3;
2581
+ var DEFAULT_LASSO_CLEAR_EVENT = LASSO_CLEAR_ON_END;
2582
+ var DEFAULT_LASSO_ON_LONG_PRESS = false;
2583
+ var DEFAULT_LASSO_LONG_PRESS_TIME = 750;
2584
+ var DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME = 500;
2585
+ var DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY = 100;
2586
+ var DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME = 250;
2587
+ var DEFAULT_LASSO_BRUSH_SIZE = 24;
2588
+ var DEFAULT_LASSO_MODE = null;
2589
+
2590
+ // Key mapping
2591
+ var KEY_ACTION_INTERSECT = 'intersect';
2592
+ var KEY_ACTION_LASSO = 'lasso';
2593
+ var KEY_ACTION_ROTATE = 'rotate';
2594
+ var KEY_ACTION_MERGE = 'merge';
2595
+ var KEY_ACTION_REMOVE = 'remove';
2596
+ var KEY_ACTIONS = [KEY_ACTION_LASSO, KEY_ACTION_ROTATE, KEY_ACTION_INTERSECT, KEY_ACTION_MERGE, KEY_ACTION_REMOVE];
2597
+ var KEY_ALT = 'alt';
2598
+ var KEY_CMD = 'cmd';
2599
+ var KEY_CTRL = 'ctrl';
2600
+ var KEY_META = 'meta';
2601
+ var KEY_SHIFT = 'shift';
2602
+ var KEYS = [KEY_ALT, KEY_CMD, KEY_CTRL, KEY_META, KEY_SHIFT];
2603
+ var DEFAULT_ACTION_KEY_MAP = _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, KEY_ACTION_REMOVE, KEY_ALT), KEY_ACTION_ROTATE, KEY_ALT), KEY_ACTION_LASSO, KEY_SHIFT), KEY_ACTION_MERGE, KEY_CMD);
2604
+
2605
+ // Default attribute
2606
+ var DEFAULT_DATA_ASPECT_RATIO = 1;
2607
+ var DEFAULT_WIDTH = AUTO;
2608
+ var DEFAULT_HEIGHT = AUTO;
2609
+ var DEFAULT_GAMMA = 1;
2610
+
2611
+ // Default styles
2612
+ var MIN_POINT_SIZE = 1;
2613
+ var DEFAULT_POINT_SCALE_MODE = 'asinh';
2614
+ var DEFAULT_POINT_SIZE = 6;
2615
+ var DEFAULT_POINT_SIZE_SELECTED = 2;
2616
+ var DEFAULT_POINT_OUTLINE_WIDTH = 2;
2617
+ var DEFAULT_SIZE_BY = null;
2618
+ var DEFAULT_POINT_ORDER = null;
2619
+ var DEFAULT_POINT_CONNECTION_SIZE = 2;
2620
+ var DEFAULT_POINT_CONNECTION_SIZE_ACTIVE = 2;
2621
+ var DEFAULT_POINT_CONNECTION_SIZE_BY = null;
2622
+ var DEFAULT_POINT_CONNECTION_OPACITY = null;
2623
+ var DEFAULT_POINT_CONNECTION_OPACITY_BY = null;
2624
+ var DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE = 0.66;
2625
+ var DEFAULT_OPACITY = 1;
2626
+ var DEFAULT_OPACITY_BY = null;
2627
+ var DEFAULT_OPACITY_BY_DENSITY_FILL = 0.15;
2628
+ var DEFAULT_OPACITY_BY_DENSITY_DEBOUNCE_TIME = 25;
2629
+ var DEFAULT_OPACITY_INACTIVE_MAX = 1;
2630
+ var DEFAULT_OPACITY_INACTIVE_SCALE = 1;
2631
+ var DEFAULT_COLOR_BY = null;
2632
+ var DEFAULT_COLOR_NORMAL = [0.66, 0.66, 0.66, DEFAULT_OPACITY];
2633
+ var DEFAULT_COLOR_ACTIVE = [0, 0.55, 1, 1];
2634
+ var DEFAULT_COLOR_HOVER = [1, 1, 1, 1];
2635
+ var DEFAULT_COLOR_BG = [0, 0, 0, 1];
2636
+ var DEFAULT_POINT_CONNECTION_COLOR_BY = null;
2637
+ var DEFAULT_POINT_CONNECTION_COLOR_NORMAL = [0.66, 0.66, 0.66, 0.2];
2638
+ var DEFAULT_POINT_CONNECTION_COLOR_ACTIVE = [0, 0.55, 1, 1];
2639
+ var DEFAULT_POINT_CONNECTION_COLOR_HOVER = [1, 1, 1, 1];
2640
+
2641
+ // Annotations
2642
+ var DEFAULT_ANNOTATION_LINE_COLOR = [1, 1, 1, 0.5];
2643
+ var DEFAULT_ANNOTATION_LINE_WIDTH = 1;
2644
+ var DEFAULT_ANNOTATION_HVLINE_LIMIT = 1000;
2645
+
2646
+ // Default view
2647
+ var DEFAULT_TARGET = [0, 0];
2648
+ var DEFAULT_DISTANCE = 1;
2649
+ var DEFAULT_ROTATION = 0;
2650
+ // biome-ignore format: the array should not be formatted
2651
+ var DEFAULT_VIEW = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
2652
+
2653
+ // Error codes
2654
+ var IMAGE_LOAD_ERROR = 'IMAGE_LOAD_ERROR';
2655
+
2656
+ // Default misc
2657
+ var DEFAULT_BACKGROUND_IMAGE = null;
2658
+ var DEFAULT_SHOW_RETICLE = false;
2659
+ var DEFAULT_RETICLE_COLOR = [1, 1, 1, 0.5];
2660
+ var DEFAULT_DESELECT_ON_DBL_CLICK = true;
2661
+ var DEFAULT_DESELECT_ON_ESCAPE = true;
2662
+ var DEFAULT_SHOW_POINT_CONNECTIONS = false;
2663
+ var DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT = 100;
2664
+ var DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE = 1 / 500;
2665
+ var DEFAULT_POINT_SIZE_MOUSE_DETECTION = 'auto';
2666
+ var DEFAULT_PERFORMANCE_MODE = false;
2667
+ var SINGLE_CLICK_DELAY = 200;
2668
+ var LONG_CLICK_TIME = 500;
2669
+ var Z_NAMES = new Set(['z', 'valueZ', 'valueA', 'value1', 'category']);
2670
+ var W_NAMES = new Set(['w', 'valueW', 'valueB', 'value2', 'value']);
2671
+ var DEFAULT_IMAGE_LOAD_TIMEOUT = 15000;
2672
+ var DEFAULT_SPATIAL_INDEX_USE_WORKER = undefined;
2673
+ var DEFAULT_CAMERA_IS_FIXED = false;
2674
+ var DEFAULT_ANTI_ALIASING = 0.5;
2675
+ var DEFAULT_PIXEL_ALIGNED = false;
2676
+ var DEFAULT_LASSO_TYPE$1 = 'lasso';
2677
+ var SKIP_DEPRECATION_VALUE_TRANSLATION = Symbol('SKIP_DEPRECATION_VALUE_TRANSLATION');
2678
+
2679
+ // Error messages
2680
+ var ERROR_POINTS_NOT_DRAWN = 'Points have not been drawn';
2681
+ var ERROR_INSTANCE_IS_DESTROYED = 'The instance was already destroyed';
2682
+ var ERROR_IS_DRAWING = 'Ignoring draw call as the previous draw call has not yet finished. To avoid this warning `await` the draw call.';
2683
+
2684
+ /**
2685
+ * KDBush - A fast static index for 2D points
2686
+ * @license ISC License
2687
+ * @copyright Vladimir Agafonkin 2018
2688
+ * @version 4.0.2
2689
+ * @see https://github.com/mourner/kdbush/
2690
+ */
2691
+ var createKDBushClass = (function () {
2692
+ var ARRAY_TYPES = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
2693
+
2694
+ /** @typedef {Int8ArrayConstructor | Uint8ArrayConstructor | Uint8ClampedArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor} TypedArrayConstructor */
2695
+
2696
+ var VERSION = 1; // serialized format version
2697
+ var HEADER_SIZE = 8;
2698
+ var KDBush = /*#__PURE__*/function () {
2699
+ /**
2700
+ * Creates an index that will hold a given number of items.
2701
+ * @param {number} numItems
2702
+ * @param {number} [nodeSize=64] Size of the KD-tree node (64 by default).
2703
+ * @param {TypedArrayConstructor} [ArrayType=Float64Array] The array type used for coordinates storage (`Float64Array` by default).
2704
+ * @param {ArrayBuffer} [data] (For internal use only)
2705
+ */
2706
+ function KDBush(numItems) {
2707
+ var nodeSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 64;
2708
+ var ArrayType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Float64Array;
2709
+ var data = arguments.length > 3 ? arguments[3] : undefined;
2710
+ _classCallCheck(this, KDBush);
2711
+ if (isNaN(numItems) || numItems < 0) throw new Error("Unexpected numItems value: ".concat(numItems, "."));
2712
+ this.numItems = +numItems;
2713
+ this.nodeSize = Math.min(Math.max(+nodeSize, 2), 65535);
2714
+ this.ArrayType = ArrayType;
2715
+ this.IndexArrayType = numItems < 65536 ? Uint16Array : Uint32Array;
2716
+ var arrayTypeIndex = ARRAY_TYPES.indexOf(this.ArrayType);
2717
+ var coordsByteSize = numItems * 2 * this.ArrayType.BYTES_PER_ELEMENT;
2718
+ var idsByteSize = numItems * this.IndexArrayType.BYTES_PER_ELEMENT;
2719
+ var padCoords = (8 - idsByteSize % 8) % 8;
2720
+ if (arrayTypeIndex < 0) {
2721
+ throw new Error("Unexpected typed array class: ".concat(ArrayType, "."));
2722
+ }
2723
+ if (data && data instanceof ArrayBuffer) {
2724
+ // reconstruct an index from a buffer
2725
+ this.data = data;
2726
+ this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
2727
+ this.coords = new this.ArrayType(this.data, HEADER_SIZE + idsByteSize + padCoords, numItems * 2);
2728
+ this._pos = numItems * 2;
2729
+ this._finished = true;
2730
+ } else {
2731
+ // initialize a new index
2732
+ this.data = new ArrayBuffer(HEADER_SIZE + coordsByteSize + idsByteSize + padCoords);
2733
+ this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
2734
+ this.coords = new this.ArrayType(this.data, HEADER_SIZE + idsByteSize + padCoords, numItems * 2);
2735
+ this._pos = 0;
2736
+ this._finished = false;
2737
+
2738
+ // set header
2739
+ new Uint8Array(this.data, 0, 2).set([0xdb, (VERSION << 4) + arrayTypeIndex]);
2740
+ new Uint16Array(this.data, 2, 1)[0] = nodeSize;
2741
+ new Uint32Array(this.data, 4, 1)[0] = numItems;
2742
+ }
2743
+ }
2744
+
2745
+ /**
2746
+ * Add a point to the index.
2747
+ * @param {number} x
2748
+ * @param {number} y
2749
+ * @returns {number} An incremental index associated with the added item (starting from `0`).
2750
+ */
2751
+ return _createClass(KDBush, [{
2752
+ key: "add",
2753
+ value: function add(x, y) {
2754
+ var index = this._pos >> 1;
2755
+ this.ids[index] = index;
2756
+ this.coords[this._pos++] = x;
2757
+ this.coords[this._pos++] = y;
2758
+ return index;
2759
+ }
2760
+
2761
+ /**
2762
+ * Perform indexing of the added points.
2763
+ */
2764
+ }, {
2765
+ key: "finish",
2766
+ value: function finish() {
2767
+ var numAdded = this._pos >> 1;
2768
+ if (numAdded !== this.numItems) {
2769
+ throw new Error("Added ".concat(numAdded, " items when expected ").concat(this.numItems, "."));
2770
+ }
2771
+ // kd-sort both arrays for efficient search
2772
+ sort(this.ids, this.coords, this.nodeSize, 0, this.numItems - 1, 0);
2773
+ this._finished = true;
2774
+ return this;
2775
+ }
2776
+
2777
+ /**
2778
+ * Search the index for items within a given bounding box.
2779
+ * @param {number} minX
2780
+ * @param {number} minY
2781
+ * @param {number} maxX
2782
+ * @param {number} maxY
2802
2783
  * @returns {number[]} An array of indices correponding to the found items.
2803
2784
  */
2804
2785
  }, {
@@ -3049,8 +3030,6 @@ void main() {
3049
3030
  error: new Error('Invalid point data')
3050
3031
  });
3051
3032
  }
3052
-
3053
- // biome-ignore lint/correctness/noUndeclaredVariables: KDBush is made available during compilation
3054
3033
  var index = new KDBush(points.length, event.data.nodeSize);
3055
3034
  var _iterator = _createForOfIteratorHelper(points),
3056
3035
  _step;
@@ -3071,15 +3050,12 @@ void main() {
3071
3050
  });
3072
3051
  });
3073
3052
 
3074
- // biome-ignore lint/style/useNamingConvention: KDBush is a library name
3075
3053
  var KDBush$1 = createKDBushClass();
3076
3054
  var WORKER_THRESHOLD = 1000000;
3077
3055
  var createWorker = function createWorker(fn) {
3078
3056
  var kdbushStr = createKDBushClass.toString();
3079
3057
  var fnStr = fn.toString();
3080
- var workerStr =
3081
- // biome-ignore lint/style/useTemplate: Prefer one assignment per line
3082
- "const createKDBushClass = ".concat(kdbushStr, ";") + 'KDBush = createKDBushClass();' + "const createWorker = ".concat(fnStr, ";") + 'createWorker();';
3058
+ var workerStr = "const createKDBushClass = ".concat(kdbushStr, ";") + 'KDBush = createKDBushClass();' + "const createWorker = ".concat(fnStr, ";") + 'createWorker();';
3083
3059
  var blob = new Blob([workerStr], {
3084
3060
  type: 'text/javascript'
3085
3061
  });
@@ -3140,161 +3116,18 @@ void main() {
3140
3116
  }
3141
3117
  });
3142
3118
  };
3119
+ var kdbushFrom = function kdbushFrom(buffer) {
3120
+ return KDBush$1.from(buffer);
3121
+ };
3143
3122
 
3144
3123
  var DEFAULT_LASSO_START_INITIATOR_SHOW = true;
3145
- var DEFAULT_LASSO_MIN_DELAY$1 = 8;
3146
- var DEFAULT_LASSO_MIN_DIST$1 = 2;
3147
- var DEFAULT_LASSO_TYPE$1 = 'freeform';
3124
+ var DEFAULT_LASSO_MIN_DELAY = 8;
3125
+ var DEFAULT_LASSO_MIN_DIST = 2;
3126
+ var DEFAULT_LASSO_TYPE = 'freeform';
3148
3127
  var DEFAULT_BRUSH_SIZE = 24;
3149
3128
  var LASSO_SHOW_START_INITIATOR_TIME = 2500;
3150
3129
  var LASSO_HIDE_START_INITIATOR_TIME = 250;
3151
3130
 
3152
- var AUTO = 'auto';
3153
- var COLOR_NORMAL_IDX = 0;
3154
- var COLOR_ACTIVE_IDX = 1;
3155
- var COLOR_HOVER_IDX = 2;
3156
- var COLOR_BG_IDX = 3;
3157
- var COLOR_NUM_STATES = 4;
3158
- var FLOAT_BYTES = Float32Array.BYTES_PER_ELEMENT;
3159
- var GL_EXTENSIONS = ['OES_texture_float', 'OES_element_index_uint', 'WEBGL_color_buffer_float', 'EXT_float_blend'];
3160
- var CLEAR_OPTIONS = {
3161
- color: [0, 0, 0, 0],
3162
- // Transparent background color
3163
- depth: 1
3164
- };
3165
- var MOUSE_MODE_PANZOOM = 'panZoom';
3166
- var MOUSE_MODE_LASSO = 'lasso';
3167
- var MOUSE_MODE_ROTATE = 'rotate';
3168
- var MOUSE_MODES = [MOUSE_MODE_PANZOOM, MOUSE_MODE_LASSO, MOUSE_MODE_ROTATE];
3169
- var DEFAULT_MOUSE_MODE = MOUSE_MODE_PANZOOM;
3170
-
3171
- // Easing
3172
- var EASING_FNS = {
3173
- cubicIn: cubicIn,
3174
- cubicInOut: cubicInOut,
3175
- cubicOut: cubicOut,
3176
- linear: linear,
3177
- quadIn: quadIn,
3178
- quadInOut: quadInOut,
3179
- quadOut: quadOut
3180
- };
3181
- var DEFAULT_EASING = cubicInOut;
3182
- var CONTINUOUS = 'continuous';
3183
- var CATEGORICAL = 'categorical';
3184
- var VALUE_ZW_DATA_TYPES = [CONTINUOUS, CATEGORICAL];
3185
-
3186
- // Default lasso
3187
- var LASSO_CLEAR_ON_DESELECT = 'deselect';
3188
- var LASSO_CLEAR_ON_END = 'lassoEnd';
3189
- var LASSO_CLEAR_EVENTS = [LASSO_CLEAR_ON_DESELECT, LASSO_CLEAR_ON_END];
3190
- var LASSO_BRUSH_MIN_MIN_DIST = 3;
3191
- var DEFAULT_LASSO_COLOR = [0, 0.666666667, 1, 1];
3192
- var DEFAULT_LASSO_LINE_WIDTH = 2;
3193
- var DEFAULT_LASSO_INITIATOR = false;
3194
- var DEFAULT_LASSO_MIN_DELAY = 10;
3195
- var DEFAULT_LASSO_MIN_DIST = 3;
3196
- var DEFAULT_LASSO_CLEAR_EVENT = LASSO_CLEAR_ON_END;
3197
- var DEFAULT_LASSO_ON_LONG_PRESS = false;
3198
- var DEFAULT_LASSO_LONG_PRESS_TIME = 750;
3199
- var DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME = 500;
3200
- var DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY = 100;
3201
- var DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME = 250;
3202
- var DEFAULT_LASSO_BRUSH_SIZE = 24;
3203
- var DEFAULT_LASSO_MODE = null;
3204
-
3205
- // Key mapping
3206
- var KEY_ACTION_INTERSECT = 'intersect';
3207
- var KEY_ACTION_LASSO = 'lasso';
3208
- var KEY_ACTION_ROTATE = 'rotate';
3209
- var KEY_ACTION_MERGE = 'merge';
3210
- var KEY_ACTION_REMOVE = 'remove';
3211
- var KEY_ACTIONS = [KEY_ACTION_LASSO, KEY_ACTION_ROTATE, KEY_ACTION_INTERSECT, KEY_ACTION_MERGE, KEY_ACTION_REMOVE];
3212
- var KEY_ALT = 'alt';
3213
- var KEY_CMD = 'cmd';
3214
- var KEY_CTRL = 'ctrl';
3215
- var KEY_META = 'meta';
3216
- var KEY_SHIFT = 'shift';
3217
- var KEYS = [KEY_ALT, KEY_CMD, KEY_CTRL, KEY_META, KEY_SHIFT];
3218
- var DEFAULT_ACTION_KEY_MAP = _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, KEY_ACTION_REMOVE, KEY_ALT), KEY_ACTION_ROTATE, KEY_ALT), KEY_ACTION_LASSO, KEY_SHIFT), KEY_ACTION_MERGE, KEY_CMD);
3219
-
3220
- // Default attribute
3221
- var DEFAULT_DATA_ASPECT_RATIO = 1;
3222
- var DEFAULT_WIDTH = AUTO;
3223
- var DEFAULT_HEIGHT = AUTO;
3224
- var DEFAULT_GAMMA = 1;
3225
-
3226
- // Default styles
3227
- var MIN_POINT_SIZE = 1;
3228
- var DEFAULT_POINT_SCALE_MODE = 'asinh';
3229
- var DEFAULT_POINT_SIZE = 6;
3230
- var DEFAULT_POINT_SIZE_SELECTED = 2;
3231
- var DEFAULT_POINT_OUTLINE_WIDTH = 2;
3232
- var DEFAULT_SIZE_BY = null;
3233
- var DEFAULT_POINT_CONNECTION_SIZE = 2;
3234
- var DEFAULT_POINT_CONNECTION_SIZE_ACTIVE = 2;
3235
- var DEFAULT_POINT_CONNECTION_SIZE_BY = null;
3236
- var DEFAULT_POINT_CONNECTION_OPACITY = null;
3237
- var DEFAULT_POINT_CONNECTION_OPACITY_BY = null;
3238
- var DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE = 0.66;
3239
- var DEFAULT_OPACITY = 1;
3240
- var DEFAULT_OPACITY_BY = null;
3241
- var DEFAULT_OPACITY_BY_DENSITY_FILL = 0.15;
3242
- var DEFAULT_OPACITY_BY_DENSITY_DEBOUNCE_TIME = 25;
3243
- var DEFAULT_OPACITY_INACTIVE_MAX = 1;
3244
- var DEFAULT_OPACITY_INACTIVE_SCALE = 1;
3245
- var DEFAULT_COLOR_BY = null;
3246
- var DEFAULT_COLOR_NORMAL = [0.66, 0.66, 0.66, DEFAULT_OPACITY];
3247
- var DEFAULT_COLOR_ACTIVE = [0, 0.55, 1, 1];
3248
- var DEFAULT_COLOR_HOVER = [1, 1, 1, 1];
3249
- var DEFAULT_COLOR_BG = [0, 0, 0, 1];
3250
- var DEFAULT_POINT_CONNECTION_COLOR_BY = null;
3251
- var DEFAULT_POINT_CONNECTION_COLOR_NORMAL = [0.66, 0.66, 0.66, 0.2];
3252
- var DEFAULT_POINT_CONNECTION_COLOR_ACTIVE = [0, 0.55, 1, 1];
3253
- var DEFAULT_POINT_CONNECTION_COLOR_HOVER = [1, 1, 1, 1];
3254
-
3255
- // Annotations
3256
- var DEFAULT_ANNOTATION_LINE_COLOR = [1, 1, 1, 0.5];
3257
- var DEFAULT_ANNOTATION_LINE_WIDTH = 1;
3258
- var DEFAULT_ANNOTATION_HVLINE_LIMIT = 1000;
3259
-
3260
- // Default view
3261
- var DEFAULT_TARGET = [0, 0];
3262
- var DEFAULT_DISTANCE = 1;
3263
- var DEFAULT_ROTATION = 0;
3264
- // biome-ignore format: the array should not be formatted
3265
- var DEFAULT_VIEW = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
3266
-
3267
- // Error codes
3268
- var IMAGE_LOAD_ERROR = 'IMAGE_LOAD_ERROR';
3269
-
3270
- // Default misc
3271
- var DEFAULT_BACKGROUND_IMAGE = null;
3272
- var DEFAULT_SHOW_RETICLE = false;
3273
- var DEFAULT_RETICLE_COLOR = [1, 1, 1, 0.5];
3274
- var DEFAULT_DESELECT_ON_DBL_CLICK = true;
3275
- var DEFAULT_DESELECT_ON_ESCAPE = true;
3276
- var DEFAULT_SHOW_POINT_CONNECTIONS = false;
3277
- var DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT = 100;
3278
- var DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE = 1 / 500;
3279
- var DEFAULT_POINT_SIZE_MOUSE_DETECTION = 'auto';
3280
- var DEFAULT_PERFORMANCE_MODE = false;
3281
- var SINGLE_CLICK_DELAY = 200;
3282
- var LONG_CLICK_TIME = 500;
3283
- var Z_NAMES = new Set(['z', 'valueZ', 'valueA', 'value1', 'category']);
3284
- var W_NAMES = new Set(['w', 'valueW', 'valueB', 'value2', 'value']);
3285
- var DEFAULT_IMAGE_LOAD_TIMEOUT = 15000;
3286
- var DEFAULT_SPATIAL_INDEX_USE_WORKER = undefined;
3287
- var DEFAULT_CAMERA_IS_FIXED = false;
3288
- var DEFAULT_ANTI_ALIASING = 0.5;
3289
- var DEFAULT_PIXEL_ALIGNED = false;
3290
- var DEFAULT_LASSO_TYPE = 'lasso';
3291
- var SKIP_DEPRECATION_VALUE_TRANSLATION = Symbol('SKIP_DEPRECATION_VALUE_TRANSLATION');
3292
-
3293
- // Error messages
3294
- var ERROR_POINTS_NOT_DRAWN = 'Points have not been drawn';
3295
- var ERROR_INSTANCE_IS_DESTROYED = 'The instance was already destroyed';
3296
- var ERROR_IS_DRAWING = 'Ignoring draw call as the previous draw call has not yet finished. To avoid this warning `await` the draw call.';
3297
-
3298
3131
  var getInTime = function getInTime(p, time, extraTime) {
3299
3132
  return (1 - p) * time + extraTime;
3300
3133
  };
@@ -3572,13 +3405,13 @@ void main() {
3572
3405
  _ref$longPressIndicat = _ref.longPressIndicatorParentElement,
3573
3406
  initialLongPressIndicatorParentElement = _ref$longPressIndicat === void 0 ? document.body : _ref$longPressIndicat,
3574
3407
  _ref$minDelay = _ref.minDelay,
3575
- initialMinDelay = _ref$minDelay === void 0 ? DEFAULT_LASSO_MIN_DELAY$1 : _ref$minDelay,
3408
+ initialMinDelay = _ref$minDelay === void 0 ? DEFAULT_LASSO_MIN_DELAY : _ref$minDelay,
3576
3409
  _ref$minDist = _ref.minDist,
3577
- initialMinDist = _ref$minDist === void 0 ? DEFAULT_LASSO_MIN_DIST$1 : _ref$minDist,
3410
+ initialMinDist = _ref$minDist === void 0 ? DEFAULT_LASSO_MIN_DIST : _ref$minDist,
3578
3411
  _ref$pointNorm = _ref.pointNorm,
3579
3412
  initialPointNorm = _ref$pointNorm === void 0 ? identity : _ref$pointNorm,
3580
3413
  _ref$type = _ref.type,
3581
- initialType = _ref$type === void 0 ? DEFAULT_LASSO_TYPE$1 : _ref$type,
3414
+ initialType = _ref$type === void 0 ? DEFAULT_LASSO_TYPE : _ref$type,
3582
3415
  _ref$brushSize = _ref.brushSize,
3583
3416
  initialBrushSize = _ref$brushSize === void 0 ? DEFAULT_BRUSH_SIZE : _ref$brushSize;
3584
3417
  var enableInitiator = initialenableInitiator;
@@ -4177,1002 +4010,998 @@ void main() {
4177
4010
  return pipe(withStaticProperty('initiator', initiator), withStaticProperty('longPressIndicator', longPress), withPublicMethods(), withConstructor(_createLasso))({});
4178
4011
  };
4179
4012
 
4180
- /**
4181
- * Check if all GL extensions are supported and enabled and warn otherwise
4182
- * @param {import('regl').Regl} regl Regl instance to be tested
4183
- * @param {boolean} silent If `true` the function will not print `console.warn` statements
4184
- * @return {boolean} If `true` all required GL extensions are supported
4185
- */
4186
- var checkReglExtensions = function checkReglExtensions(regl, silent) {
4187
- if (!regl) {
4188
- return false;
4189
- }
4190
- return GL_EXTENSIONS.reduce(function (every, extension) {
4191
- if (!regl.hasExtension(extension)) {
4192
- if (!silent) {
4193
- // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning
4194
- console.warn("WebGL: ".concat(extension, " extension not supported. Scatterplot might not render properly"));
4195
- }
4196
- return false;
4197
- }
4198
- return every;
4199
- }, true);
4200
- };
4201
-
4202
- /**
4203
- * Create a new Regl instance with `GL_EXTENSIONS` enables
4204
- * @param {HTMLCanvasElement} canvas Canvas element to be rendered on
4205
- * @return {import('regl').Regl} New Regl instance
4206
- */
4207
- var createRegl = function createRegl(canvas) {
4208
- var gl = canvas.getContext('webgl', {
4209
- antialias: true,
4210
- preserveDrawingBuffer: true
4211
- });
4212
- var extensions = [];
4013
+ const FRAGMENT_SHADER$1 = `
4014
+ precision highp float;
4213
4015
 
4214
- // Needed to run the tests properly as the headless-gl doesn't support all
4215
- // extensions, which is fine for the functional tests.
4216
- var _iterator = _createForOfIteratorHelper(GL_EXTENSIONS),
4217
- _step;
4218
- try {
4219
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
4220
- var extension = _step.value;
4221
- if (gl.getExtension(extension)) {
4222
- extensions.push(extension);
4223
- } else {
4224
- // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning
4225
- console.warn("WebGL: ".concat(extension, " extension not supported. Scatterplot might not render properly"));
4226
- }
4227
- }
4228
- } catch (err) {
4229
- _iterator.e(err);
4230
- } finally {
4231
- _iterator.f();
4232
- }
4233
- return createOriginalRegl__default.default({
4234
- gl: gl,
4235
- extensions: extensions
4236
- });
4237
- };
4016
+ uniform float antiAliasing;
4238
4017
 
4239
- /**
4240
- * L2 distance between a pair of 2D points
4241
- * @param {number} x1 X coordinate of the first point
4242
- * @param {number} y1 Y coordinate of the first point
4243
- * @param {number} x2 X coordinate of the second point
4244
- * @param {number} y2 Y coordinate of the first point
4245
- * @return {number} L2 distance
4246
- */
4247
- var dist = function dist(x1, y1, x2, y2) {
4248
- return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
4249
- };
4018
+ varying vec4 color;
4019
+ varying float finalPointSize;
4250
4020
 
4251
- /**
4252
- * Get the bounding box of a set of 2D positions
4253
- * @param {array} positions2d 2D positions to be checked
4254
- * @return {array} Quadruple of form `[xMin, yMin, xMax, yMax]` defining the
4255
- * bounding box
4256
- */
4257
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
4258
- var getBBox = function getBBox(positions2d) {
4259
- var xMin = Number.POSITIVE_INFINITY;
4260
- var xMax = Number.NEGATIVE_INFINITY;
4261
- var yMin = Number.POSITIVE_INFINITY;
4262
- var yMax = Number.NEGATIVE_INFINITY;
4263
- for (var i = 0; i < positions2d.length; i += 2) {
4264
- xMin = positions2d[i] < xMin ? positions2d[i] : xMin;
4265
- xMax = positions2d[i] > xMax ? positions2d[i] : xMax;
4266
- yMin = positions2d[i + 1] < yMin ? positions2d[i + 1] : yMin;
4267
- yMax = positions2d[i + 1] > yMax ? positions2d[i + 1] : yMax;
4268
- }
4269
- return [xMin, yMin, xMax, yMax];
4270
- };
4021
+ float linearstep(float edge0, float edge1, float x) {
4022
+ return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
4023
+ }
4271
4024
 
4272
- /**
4273
- * Test whether a bounding box is actually specifying an area
4274
- * @param {array} bBox The bounding box to be checked
4275
- * @return {array} `true` if the bounding box is valid
4276
- */
4277
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
4278
- var isValidBBox = function isValidBBox(_ref) {
4279
- var _ref2 = _slicedToArray(_ref, 4),
4280
- xMin = _ref2[0],
4281
- yMin = _ref2[1],
4282
- xMax = _ref2[2],
4283
- yMax = _ref2[3];
4284
- return Number.isFinite(xMin) && Number.isFinite(yMin) && Number.isFinite(xMax) && Number.isFinite(yMax) && xMax - xMin > 0 && yMax - yMin > 0;
4285
- };
4286
- var REGEX_HEX_TO_RGB = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
4025
+ void main() {
4026
+ vec2 c = gl_PointCoord * 2.0 - 1.0;
4027
+ float sdf = length(c) * finalPointSize;
4028
+ float alpha = linearstep(finalPointSize + antiAliasing, finalPointSize - antiAliasing, sdf);
4287
4029
 
4288
- /**
4289
- * Convert a HEX-encoded color to an RGB-encoded color
4290
- * @param {string} hex HEX-encoded color string.
4291
- * @param {boolean} isNormalize If `true` the returned RGB values will be
4292
- * normalized to `[0,1]`.
4293
- * @return {array} Triple holding the RGB values.
4294
- */
4295
- var hexToRgb = function hexToRgb(hex) {
4296
- var isNormalize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4297
- return hex.replace(REGEX_HEX_TO_RGB, function (_m, r, g, b) {
4298
- return "#".concat(r).concat(r).concat(g).concat(g).concat(b).concat(b);
4299
- }).substring(1).match(/.{2}/g).map(function (x) {
4300
- return Number.parseInt(x, 16) / Math.pow(255, isNormalize);
4301
- });
4302
- };
4303
- var isConditionalArray = function isConditionalArray(a, condition) {
4304
- var _ref3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
4305
- _ref3$minLength = _ref3.minLength,
4306
- minLength = _ref3$minLength === void 0 ? 0 : _ref3$minLength;
4307
- return Array.isArray(a) && a.length >= minLength && a.every(condition);
4308
- };
4309
- var isPositiveNumber = function isPositiveNumber(x) {
4310
- return !Number.isNaN(+x) && +x >= 0;
4311
- };
4312
- var isStrictlyPositiveNumber = function isStrictlyPositiveNumber(x) {
4313
- return !Number.isNaN(+x) && +x > 0;
4314
- };
4030
+ gl_FragColor = vec4(color.rgb, alpha * color.a);
4031
+ }
4032
+ `;
4315
4033
 
4316
- /**
4317
- * Create a function to limit choices to a predefined list
4318
- * @param {array} choices Array of acceptable choices
4319
- * @param {*} defaultOption Default choice
4320
- * @return {function} Function limiting the choices
4321
- */
4322
- var limit = function limit(choices, defaultChoice) {
4323
- return function (choice) {
4324
- return choices.indexOf(choice) >= 0 ? choice : defaultChoice;
4325
- };
4326
- };
4034
+ const createVertexShader = (globalState) => `
4035
+ precision highp float;
4327
4036
 
4328
- /**
4329
- * Promised-based image loading
4330
- * @param {string} src Remote image source, i.e., a URL
4331
- * @param {boolean} isCrossOrigin If `true` allow loading image from a source of another origin.
4332
- * @return {Promise<HTMLImageElement>} Promise resolving to the image once its loaded
4333
- */
4334
- var loadImage = function loadImage(src) {
4335
- var isCrossOrigin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4336
- var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_IMAGE_LOAD_TIMEOUT;
4337
- return new Promise(function (resolve, reject) {
4338
- var image = new Image();
4339
- if (isCrossOrigin) {
4340
- image.crossOrigin = 'anonymous';
4341
- }
4342
- image.src = src;
4343
- image.onload = function () {
4344
- resolve(image);
4345
- };
4346
- var rejectPromise = function rejectPromise() {
4347
- reject(new Error(IMAGE_LOAD_ERROR));
4348
- };
4349
- image.onerror = rejectPromise;
4350
- setTimeout(rejectPromise, timeout);
4351
- });
4352
- };
4037
+ uniform sampler2D colorTex;
4038
+ uniform float colorTexRes;
4039
+ uniform float colorTexEps;
4040
+ uniform sampler2D stateTex;
4041
+ uniform float stateTexRes;
4042
+ uniform float stateTexEps;
4043
+ uniform float devicePixelRatio;
4044
+ uniform sampler2D encodingTex;
4045
+ uniform float encodingTexRes;
4046
+ uniform float encodingTexEps;
4047
+ uniform float pointSizeExtra;
4048
+ uniform float pointOpacityMax;
4049
+ uniform float pointOpacityScale;
4050
+ uniform float numPoints;
4051
+ uniform float globalState;
4052
+ uniform float isColoredByZ;
4053
+ uniform float isColoredByW;
4054
+ uniform float isOpacityByZ;
4055
+ uniform float isOpacityByW;
4056
+ uniform float isOpacityByDensity;
4057
+ uniform float isSizedByZ;
4058
+ uniform float isSizedByW;
4059
+ uniform float isPixelAligned;
4060
+ uniform float colorMultiplicator;
4061
+ uniform float opacityMultiplicator;
4062
+ uniform float opacityDensity;
4063
+ uniform float sizeMultiplicator;
4064
+ uniform float numColorStates;
4065
+ uniform float pointScale;
4066
+ uniform float drawingBufferWidth;
4067
+ uniform float drawingBufferHeight;
4068
+ uniform mat4 modelViewProjection;
4353
4069
 
4354
- /**
4355
- * @deprecated Please use `scatterplot.createTextureFromUrl(url)`
4356
- *
4357
- * Create a Regl texture from an URL.
4358
- * @param {import('regl').Regl} regl Regl instance used for creating the texture.
4359
- * @param {string} url Source URL of the image.
4360
- * @return {Promise<import('regl').Texture2D>} Promise resolving to the texture object.
4361
- */
4362
- var createTextureFromUrl = function createTextureFromUrl(regl, url) {
4363
- var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_IMAGE_LOAD_TIMEOUT;
4364
- return new Promise(function (resolve, reject) {
4365
- loadImage(url, url.indexOf(window.location.origin) !== 0 && url.indexOf('base64') === -1, timeout).then(function (image) {
4366
- resolve(regl.texture(image));
4367
- })["catch"](function (error) {
4368
- reject(error);
4369
- });
4370
- });
4371
- };
4070
+ attribute vec2 stateIndex;
4372
4071
 
4373
- /**
4374
- * Convert a HEX-encoded color to an RGBA-encoded color
4375
- * @param {string} hex HEX-encoded color string.
4376
- * @param {boolean} isNormalize If `true` the returned RGBA values will be
4377
- * normalized to `[0,1]`.
4378
- * @return {array} Triple holding the RGBA values.
4379
- */
4380
- var hexToRgba = function hexToRgba(hex) {
4381
- var isNormalize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4382
- return [].concat(_toConsumableArray(hexToRgb(hex, isNormalize)), [Math.pow(255, !isNormalize)]);
4383
- };
4384
- var REGEX_IS_HEX = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i;
4072
+ varying vec4 color;
4073
+ varying float finalPointSize;
4385
4074
 
4386
- /**
4387
- * Tests if a string is a valid HEX color encoding
4388
- * @param {string} hex HEX-encoded color string.
4389
- * @return {boolean} If `true` the string is a valid HEX color encoding.
4390
- */
4391
- var isHex = function isHex(hex) {
4392
- return REGEX_IS_HEX.test(hex);
4393
- };
4075
+ void main() {
4076
+ vec4 state = texture2D(stateTex, stateIndex);
4394
4077
 
4395
- /**
4396
- * Tests if a number is in `[0,1]`.
4397
- * @param {number} x Number to be tested.
4398
- * @return {boolean} If `true` the number is in `[0,1]`.
4399
- */
4400
- var isNormFloat = function isNormFloat(x) {
4401
- return x >= 0 && x <= 1;
4402
- };
4078
+ if (isPixelAligned < 0.5) {
4079
+ gl_Position = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
4080
+ } else {
4081
+ vec4 clipSpacePosition = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
4082
+ vec2 ndcPosition = clipSpacePosition.xy / clipSpacePosition.w;
4083
+ vec2 pixelPos = 0.5 * (ndcPosition + 1.0) * vec2(drawingBufferWidth, drawingBufferHeight);
4084
+ pixelPos = floor(pixelPos + 0.5); // Snap to nearest pixel
4085
+ vec2 snappedPosition = (pixelPos / vec2(drawingBufferWidth, drawingBufferHeight)) * 2.0 - 1.0;
4086
+ gl_Position = vec4(snappedPosition, 0.0, 1.0);
4087
+ }
4403
4088
 
4404
- /**
4405
- * Tests if an array consist of normalized numbers that are in `[0,1]` only.
4406
- * @param {array} a Array to be tested
4407
- * @return {boolean} If `true` the array contains only numbers in `[0,1]`.
4408
- */
4409
- var isNormFloatArray = function isNormFloatArray(a) {
4410
- return Array.isArray(a) && a.every(isNormFloat);
4411
- };
4412
4089
 
4413
- /**
4414
- * Computes the cross product to determine the orientation of three points
4415
- * @param {number} x1 X-coordinate of first point
4416
- * @param {number} y1 Y-coordinate of first point
4417
- * @param {number} x2 X-coordinate of second point
4418
- * @param {number} y2 Y-coordinate of second point
4419
- * @param {number} px X-coordinate of test point
4420
- * @param {number} py Y-coordinate of test point
4421
- * @return {number} Positive if counterclockwise, negative if clockwise
4422
- */
4423
- function crossProduct(x1, y1, x2, y2, px, py) {
4424
- return (x2 - x1) * (py - y1) - (px - x1) * (y2 - y1);
4425
- }
4090
+ // Determine color index
4091
+ float colorIndexZ = isColoredByZ * floor(state.z * colorMultiplicator);
4092
+ float colorIndexW = isColoredByW * floor(state.w * colorMultiplicator);
4426
4093
 
4427
- /**
4428
- * Determines if a point lies within a polygon using the non-zero winding rule.
4429
- * This handles self-intersecting polygons and overlapping areas correctly.
4430
- * @param {Array} polygon 1D list of vertices defining the polygon [x1,y1,x2,y2,...]
4431
- * @param {Array} point Tuple of the form [x,y] to be tested
4432
- * @return {boolean} True if point lies within the polygon
4433
- */
4434
- var isPointInPolygon = function isPointInPolygon(polygon) {
4435
- var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [],
4436
- _ref5 = _slicedToArray(_ref4, 2),
4437
- px = _ref5[0],
4438
- py = _ref5[1];
4439
- var winding = 0;
4440
- for (var i = 0, j = polygon.length - 2; i < polygon.length; i += 2) {
4441
- var x1 = polygon[i];
4442
- var y1 = polygon[i + 1];
4443
- var x2 = polygon[j];
4444
- var y2 = polygon[j + 1];
4445
- if (y1 <= py) {
4446
- if (y2 > py) {
4447
- var orientation = crossProduct(x1, y1, x2, y2, px, py);
4448
- if (orientation > 0) {
4449
- winding++;
4450
- }
4451
- }
4452
- } else if (y2 <= py) {
4453
- var _orientation = crossProduct(x1, y1, x2, y2, px, py);
4454
- if (_orientation < 0) {
4455
- winding--;
4456
- }
4457
- }
4458
- j = i;
4459
- }
4460
- return winding !== 0;
4461
- };
4094
+ // Multiply by the number of color states per color
4095
+ // I.e., normal, active, hover, background, etc.
4096
+ float colorIndex = (colorIndexZ + colorIndexW) * numColorStates;
4462
4097
 
4463
- /**
4464
- * Tests if a variable is a string
4465
- * @param {*} s Variable to be tested
4466
- * @return {boolean} If `true` variable is a string
4467
- */
4468
- var isString = function isString(s) {
4469
- return typeof s === 'string' || s instanceof String;
4470
- };
4098
+ // Half a "pixel" or "texel" in texture coordinates
4099
+ float colorLinearIndex = colorIndex + globalState;
4471
4100
 
4472
- /**
4473
- * Tests if a number is an interger and in `[0,255]`.
4474
- * @param {number} x Number to be tested.
4475
- * @return {boolean} If `true` the number is an interger and in `[0,255]`.
4476
- */
4477
- var isUint8 = function isUint8(x) {
4478
- return Number.isInteger(x) && x >= 0 && x <= 255;
4479
- };
4101
+ // Need to add cEps here to avoid floating point issue that can lead to
4102
+ // dramatic changes in which color is loaded as floor(3/2.9999) = 1 but
4103
+ // floor(3/3.0001) = 0!
4104
+ float colorRowIndex = floor((colorLinearIndex + colorTexEps) / colorTexRes);
4480
4105
 
4481
- /**
4482
- * Tests if an array consist of Uint8 numbers only.
4483
- * @param {array} a Array to be tested.
4484
- * @return {boolean} If `true` the array contains only Uint8 numbers.
4485
- */
4486
- var isUint8Array = function isUint8Array(a) {
4487
- return Array.isArray(a) && a.every(isUint8);
4488
- };
4106
+ vec2 colorTexIndex = vec2(
4107
+ (colorLinearIndex / colorTexRes) - colorRowIndex + colorTexEps,
4108
+ colorRowIndex / colorTexRes + colorTexEps
4109
+ );
4110
+
4111
+ color = texture2D(colorTex, colorTexIndex);
4112
+
4113
+ // Retrieve point size
4114
+ float pointSizeIndexZ = isSizedByZ * floor(state.z * sizeMultiplicator);
4115
+ float pointSizeIndexW = isSizedByW * floor(state.w * sizeMultiplicator);
4116
+ float pointSizeIndex = pointSizeIndexZ + pointSizeIndexW;
4117
+
4118
+ float pointSizeRowIndex = floor((pointSizeIndex + encodingTexEps) / encodingTexRes);
4119
+ vec2 pointSizeTexIndex = vec2(
4120
+ (pointSizeIndex / encodingTexRes) - pointSizeRowIndex + encodingTexEps,
4121
+ pointSizeRowIndex / encodingTexRes + encodingTexEps
4122
+ );
4123
+ float pointSize = texture2D(encodingTex, pointSizeTexIndex).x;
4124
+
4125
+ // Retrieve opacity
4126
+ ${
4127
+ (() => {
4128
+ // Drawing the inner border of selected points
4129
+ if (globalState === 3) return '';
4130
+
4131
+ // Draw points with opacity encoding or dynamic opacity
4132
+ return `
4133
+ if (isOpacityByDensity < 0.5) {
4134
+ float opacityIndexZ = isOpacityByZ * floor(state.z * opacityMultiplicator);
4135
+ float opacityIndexW = isOpacityByW * floor(state.w * opacityMultiplicator);
4136
+ float opacityIndex = opacityIndexZ + opacityIndexW;
4137
+
4138
+ float opacityRowIndex = floor((opacityIndex + encodingTexEps) / encodingTexRes);
4139
+ vec2 opacityTexIndex = vec2(
4140
+ (opacityIndex / encodingTexRes) - opacityRowIndex + encodingTexEps,
4141
+ opacityRowIndex / encodingTexRes + encodingTexEps
4142
+ );
4143
+ color.a = texture2D(encodingTex, opacityTexIndex)[${1 + globalState}];
4144
+ } else {
4145
+ color.a = min(1.0, opacityDensity + globalState);
4146
+ }
4147
+ `;
4148
+ })()
4149
+ }
4150
+
4151
+ color.a = min(pointOpacityMax, color.a) * pointOpacityScale;
4152
+ finalPointSize = (pointSize * pointScale) + pointSizeExtra;
4153
+ gl_PointSize = finalPointSize;
4154
+ }
4155
+ `;
4156
+
4157
+ const FRAGMENT_SHADER = `precision highp float;
4158
+
4159
+ varying vec4 color;
4160
+
4161
+ void main() {
4162
+ gl_FragColor = color;
4163
+ }
4164
+ `;
4165
+
4166
+ const SHADER$1 = `precision highp float;
4167
+
4168
+ uniform sampler2D startStateTex;
4169
+ uniform sampler2D endStateTex;
4170
+ uniform float t;
4171
+
4172
+ varying vec2 particleTextureIndex;
4173
+
4174
+ void main() {
4175
+ // Interpolate x, y, and value
4176
+ vec3 start = texture2D(startStateTex, particleTextureIndex).xyw;
4177
+ vec3 end = texture2D(endStateTex, particleTextureIndex).xyw;
4178
+ vec3 curr = start * (1.0 - t) + end * t;
4179
+
4180
+ // The category cannot be interpolated
4181
+ float endCategory = texture2D(endStateTex, particleTextureIndex).z;
4182
+
4183
+ gl_FragColor = vec4(curr.xy, endCategory, curr.z);
4184
+ }`;
4185
+
4186
+ const SHADER = `precision highp float;
4187
+
4188
+ attribute vec2 position;
4189
+ varying vec2 particleTextureIndex;
4190
+
4191
+ void main() {
4192
+ // map normalized device coords to texture coords
4193
+ particleTextureIndex = 0.5 * (1.0 + position);
4194
+
4195
+ gl_Position = vec4(position, 0, 1);
4196
+ }`;
4489
4197
 
4490
4198
  /**
4491
- * Tests if an array is encoding an RGB color.
4492
- * @param {array} rgb Array to be tested
4493
- * @return {boolean} If `true` the array hold a triple of Uint8 numbers or
4494
- * a triple of normalized floats.
4199
+ * Check if all GL extensions are supported and enabled and warn otherwise
4200
+ * @param {import('regl').Regl} regl Regl instance to be tested
4201
+ * @param {boolean} silent If `true` the function will not print `console.warn` statements
4202
+ * @return {boolean} If `true` all required GL extensions are supported
4495
4203
  */
4496
- var isRgb = function isRgb(rgb) {
4497
- return rgb.length === 3 && (isNormFloatArray(rgb) || isUint8Array(rgb));
4204
+ var checkReglExtensions = function checkReglExtensions(regl, silent) {
4205
+ if (!regl) {
4206
+ return false;
4207
+ }
4208
+ return GL_EXTENSIONS.reduce(function (every, extension) {
4209
+ if (!regl.hasExtension(extension)) {
4210
+ if (!silent) {
4211
+ // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning
4212
+ console.warn("WebGL: ".concat(extension, " extension not supported. Scatterplot might not render properly"));
4213
+ }
4214
+ return false;
4215
+ }
4216
+ return every;
4217
+ }, true);
4498
4218
  };
4499
4219
 
4500
4220
  /**
4501
- * Tests if an array is encoding an RGBA color.
4502
- * @param {array} rgb Array to be tested
4503
- * @return {boolean} If `true` the array hold a quadruple of Uint8 numbers or
4504
- * a quadruple of normalized floats.
4221
+ * Create a new Regl instance with `GL_EXTENSIONS` enables
4222
+ * @param {HTMLCanvasElement} canvas Canvas element to be rendered on
4223
+ * @return {import('regl').Regl} New Regl instance
4505
4224
  */
4506
- var isRgba = function isRgba(rgba) {
4507
- return rgba.length === 4 && (isNormFloatArray(rgba) || isUint8Array(rgba));
4225
+ var createRegl = function createRegl(canvas) {
4226
+ var gl = canvas.getContext('webgl', {
4227
+ antialias: true,
4228
+ preserveDrawingBuffer: true
4229
+ });
4230
+ var extensions = [];
4231
+
4232
+ // Needed to run the tests properly as the headless-gl doesn't support all
4233
+ // extensions, which is fine for the functional tests.
4234
+ var _iterator = _createForOfIteratorHelper(GL_EXTENSIONS),
4235
+ _step;
4236
+ try {
4237
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
4238
+ var extension = _step.value;
4239
+ if (gl.getExtension(extension)) {
4240
+ extensions.push(extension);
4241
+ } else {
4242
+ // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning
4243
+ console.warn("WebGL: ".concat(extension, " extension not supported. Scatterplot might not render properly"));
4244
+ }
4245
+ }
4246
+ } catch (err) {
4247
+ _iterator.e(err);
4248
+ } finally {
4249
+ _iterator.f();
4250
+ }
4251
+ return createOriginalRegl__default.default({
4252
+ gl: gl,
4253
+ extensions: extensions
4254
+ });
4508
4255
  };
4509
4256
 
4510
4257
  /**
4511
- * Test if a color is multiple colors
4512
- * @param {*} color To be tested
4513
- * @return {boolean} If `true`, `color` is an array of colors.
4258
+ * L2 distance between a pair of 2D points
4259
+ * @param {number} x1 X coordinate of the first point
4260
+ * @param {number} y1 Y coordinate of the first point
4261
+ * @param {number} x2 X coordinate of the second point
4262
+ * @param {number} y2 Y coordinate of the first point
4263
+ * @return {number} L2 distance
4514
4264
  */
4515
- var isMultipleColors = function isMultipleColors(color) {
4516
- return Array.isArray(color) && color.length > 0 && (Array.isArray(color[0]) || isString(color[0]));
4265
+ var dist = function dist(x1, y1, x2, y2) {
4266
+ return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
4517
4267
  };
4518
4268
 
4519
4269
  /**
4520
- * Test if two arrays contain the same RGBA quadruples
4270
+ * Get the bounding box of a set of 2D positions
4271
+ * @param {array} positions2d 2D positions to be checked
4272
+ * @return {array} Quadruple of form `[xMin, yMin, xMax, yMax]` defining the
4273
+ * bounding box
4521
4274
  */
4522
- var isSameRgbas = function isSameRgbas(a, b) {
4523
- if (!(Array.isArray(a) && Array.isArray(b)) || a.length !== b.length) {
4524
- return false;
4525
- }
4526
- if (a.length === 0) {
4527
- return true;
4528
- }
4529
-
4530
- // We need to test whether a and b are arrays of RGBA quadruples
4531
- if (!(Array.isArray(a[0]) && Array.isArray(b[0]))) {
4532
- return false;
4275
+ var getBBox = function getBBox(positions2d) {
4276
+ var xMin = Number.POSITIVE_INFINITY;
4277
+ var xMax = Number.NEGATIVE_INFINITY;
4278
+ var yMin = Number.POSITIVE_INFINITY;
4279
+ var yMax = Number.NEGATIVE_INFINITY;
4280
+ for (var i = 0; i < positions2d.length; i += 2) {
4281
+ xMin = positions2d[i] < xMin ? positions2d[i] : xMin;
4282
+ xMax = positions2d[i] > xMax ? positions2d[i] : xMax;
4283
+ yMin = positions2d[i + 1] < yMin ? positions2d[i + 1] : yMin;
4284
+ yMax = positions2d[i + 1] > yMax ? positions2d[i + 1] : yMax;
4533
4285
  }
4534
- return a.every(function (_ref6, i) {
4535
- var _ref7 = _slicedToArray(_ref6, 4),
4536
- r1 = _ref7[0],
4537
- g1 = _ref7[1],
4538
- b1 = _ref7[2],
4539
- a1 = _ref7[3];
4540
- var _b$i = _slicedToArray(b[i], 4),
4541
- r2 = _b$i[0],
4542
- g2 = _b$i[1],
4543
- b2 = _b$i[2],
4544
- a2 = _b$i[3];
4545
- return r1 === r2 && g1 === g2 && b1 === b2 && a1 === a2;
4546
- });
4286
+ return [xMin, yMin, xMax, yMax];
4547
4287
  };
4548
4288
 
4549
4289
  /**
4550
- * Fast version of `Math.max`. Based on
4551
- * https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not
4552
- * very fast
4553
- * @param {number} a Value A
4554
- * @param {number} b Value B
4555
- * @return {boolean} If `true` A is greater than B.
4290
+ * Test whether a bounding box is actually specifying an area
4291
+ * @param {array} bBox The bounding box to be checked
4292
+ * @return {array} `true` if the bounding box is valid
4556
4293
  */
4557
- var max = function max(a, b) {
4558
- return a > b ? a : b;
4294
+ var isValidBBox = function isValidBBox(_ref) {
4295
+ var _ref2 = _slicedToArray(_ref, 4),
4296
+ xMin = _ref2[0],
4297
+ yMin = _ref2[1],
4298
+ xMax = _ref2[2],
4299
+ yMax = _ref2[3];
4300
+ return Number.isFinite(xMin) && Number.isFinite(yMin) && Number.isFinite(xMax) && Number.isFinite(yMax) && xMax - xMin > 0 && yMax - yMin > 0;
4559
4301
  };
4302
+ var REGEX_HEX_TO_RGB = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
4560
4303
 
4561
4304
  /**
4562
- * Fast version of `Math.min`. Based on
4563
- * https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not
4564
- * very fast
4565
- * @param {number} a Value A
4566
- * @param {number} b Value B
4567
- * @return {boolean} If `true` A is smaller than B.
4305
+ * Convert a HEX-encoded color to an RGB-encoded color
4306
+ * @param {string} hex HEX-encoded color string.
4307
+ * @param {boolean} isNormalize If `true` the returned RGB values will be
4308
+ * normalized to `[0,1]`.
4309
+ * @return {array} Triple holding the RGB values.
4568
4310
  */
4569
- var min = function min(a, b) {
4570
- return a < b ? a : b;
4311
+ var hexToRgb = function hexToRgb(hex) {
4312
+ var isNormalize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4313
+ return hex.replace(REGEX_HEX_TO_RGB, function (_m, r, g, b) {
4314
+ return "#".concat(r).concat(r).concat(g).concat(g).concat(b).concat(b);
4315
+ }).substring(1).match(/.{2}/g).map(function (x) {
4316
+ return Number.parseInt(x, 16) / Math.pow(255, isNormalize);
4317
+ });
4318
+ };
4319
+ var isConditionalArray = function isConditionalArray(a, condition) {
4320
+ var _ref3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
4321
+ _ref3$minLength = _ref3.minLength,
4322
+ minLength = _ref3$minLength === void 0 ? 0 : _ref3$minLength;
4323
+ return Array.isArray(a) && a.length >= minLength && a.every(condition);
4324
+ };
4325
+ var isPositiveNumber = function isPositiveNumber(x) {
4326
+ return !Number.isNaN(+x) && +x >= 0;
4327
+ };
4328
+ var isStrictlyPositiveNumber = function isStrictlyPositiveNumber(x) {
4329
+ return !Number.isNaN(+x) && +x > 0;
4571
4330
  };
4572
4331
 
4573
4332
  /**
4574
- * Convert a color to an RGBA color
4575
- * @param {*} color Color to be converted. Currently supports:
4576
- * HEX, RGB, or RGBA.
4577
- * @param {boolean} isNormalize If `true` the returned RGBA values will be
4578
- * normalized to `[0,1]`.
4579
- * @return {array} Quadruple defining an RGBA color.
4333
+ * Create a function to limit choices to a predefined list
4334
+ * @param {array} choices Array of acceptable choices
4335
+ * @param {*} defaultOption Default choice
4336
+ * @return {function} Function limiting the choices
4580
4337
  */
4581
- var toRgba = function toRgba(color, shouldNormalize) {
4582
- if (isRgba(color)) {
4583
- var isNormalized = isNormFloatArray(color);
4584
- if (shouldNormalize && isNormalized || !(shouldNormalize || isNormalized)) {
4585
- return color;
4586
- }
4587
- if (shouldNormalize && !isNormalized) {
4588
- return color.map(function (x) {
4589
- return x / 255;
4590
- });
4338
+ var limit = function limit(choices, defaultChoice) {
4339
+ return function (choice) {
4340
+ return choices.indexOf(choice) >= 0 ? choice : defaultChoice;
4341
+ };
4342
+ };
4343
+
4344
+ /**
4345
+ * Promised-based image loading
4346
+ * @param {string} src Remote image source, i.e., a URL
4347
+ * @param {boolean} isCrossOrigin If `true` allow loading image from a source of another origin.
4348
+ * @return {Promise<HTMLImageElement>} Promise resolving to the image once its loaded
4349
+ */
4350
+ var loadImage = function loadImage(src) {
4351
+ var isCrossOrigin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4352
+ var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_IMAGE_LOAD_TIMEOUT;
4353
+ return new Promise(function (resolve, reject) {
4354
+ var image = new Image();
4355
+ if (isCrossOrigin) {
4356
+ image.crossOrigin = 'anonymous';
4591
4357
  }
4592
- return color.map(function (x) {
4593
- return x * 255;
4358
+ image.src = src;
4359
+ image.onload = function () {
4360
+ resolve(image);
4361
+ };
4362
+ var rejectPromise = function rejectPromise() {
4363
+ reject(new Error(IMAGE_LOAD_ERROR));
4364
+ };
4365
+ image.onerror = rejectPromise;
4366
+ setTimeout(rejectPromise, timeout);
4367
+ });
4368
+ };
4369
+
4370
+ /**
4371
+ * @deprecated Please use `scatterplot.createTextureFromUrl(url)`
4372
+ *
4373
+ * Create a Regl texture from an URL.
4374
+ * @param {import('regl').Regl} regl Regl instance used for creating the texture.
4375
+ * @param {string} url Source URL of the image.
4376
+ * @return {Promise<import('regl').Texture2D>} Promise resolving to the texture object.
4377
+ */
4378
+ var createTextureFromUrl = function createTextureFromUrl(regl, url) {
4379
+ var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_IMAGE_LOAD_TIMEOUT;
4380
+ return new Promise(function (resolve, reject) {
4381
+ loadImage(url, url.indexOf(window.location.origin) !== 0 && url.indexOf('base64') === -1, timeout).then(function (image) {
4382
+ resolve(regl.texture(image));
4383
+ })["catch"](function (error) {
4384
+ reject(error);
4594
4385
  });
4595
- }
4596
- if (isRgb(color)) {
4597
- var base = Math.pow(255, !shouldNormalize);
4598
- var _isNormalized = isNormFloatArray(color);
4599
- if (shouldNormalize && _isNormalized || !(shouldNormalize || _isNormalized)) {
4600
- return [].concat(_toConsumableArray(color), [base]);
4601
- }
4602
- if (shouldNormalize && !_isNormalized) {
4603
- return [].concat(_toConsumableArray(color.map(function (x) {
4604
- return x / 255;
4605
- })), [base]);
4606
- }
4607
- return [].concat(_toConsumableArray(color.map(function (x) {
4608
- return x * 255;
4609
- })), [base]);
4610
- }
4611
- if (isHex(color)) {
4612
- return hexToRgba(color, shouldNormalize);
4613
- }
4386
+ });
4387
+ };
4614
4388
 
4615
- // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning
4616
- console.warn('Only HEX, RGB, and RGBA are handled by this function. Returning white instead.');
4617
- return shouldNormalize ? [1, 1, 1, 1] : [255, 255, 255, 255];
4389
+ /**
4390
+ * Convert a HEX-encoded color to an RGBA-encoded color
4391
+ * @param {string} hex HEX-encoded color string.
4392
+ * @param {boolean} isNormalize If `true` the returned RGBA values will be
4393
+ * normalized to `[0,1]`.
4394
+ * @return {array} Triple holding the RGBA values.
4395
+ */
4396
+ var hexToRgba = function hexToRgba(hex) {
4397
+ var isNormalize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4398
+ return [].concat(_toConsumableArray(hexToRgb(hex, isNormalize)), [Math.pow(255, !isNormalize)]);
4618
4399
  };
4400
+ var REGEX_IS_HEX = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i;
4619
4401
 
4620
4402
  /**
4621
- * Flip the key-value pairs of an object
4622
- * @param {object} obj - Object to be flipped
4623
- * @return {object} Flipped object
4403
+ * Tests if a string is a valid HEX color encoding
4404
+ * @param {string} hex HEX-encoded color string.
4405
+ * @return {boolean} If `true` the string is a valid HEX color encoding.
4624
4406
  */
4625
- var flipObj = function flipObj(obj) {
4626
- return Object.entries(obj).reduce(function (out, _ref8) {
4627
- var _ref9 = _slicedToArray(_ref8, 2),
4628
- key = _ref9[0],
4629
- value = _ref9[1];
4630
- if (out[value]) {
4631
- out[value] = [].concat(_toConsumableArray(out[value]), [key]);
4632
- } else {
4633
- out[value] = key;
4634
- }
4635
- return out;
4636
- }, {});
4407
+ var isHex = function isHex(hex) {
4408
+ return REGEX_IS_HEX.test(hex);
4637
4409
  };
4638
- var rgbBrightness = function rgbBrightness(rgb) {
4639
- return 0.21 * rgb[0] + 0.72 * rgb[1] + 0.07 * rgb[2];
4410
+
4411
+ /**
4412
+ * Tests if a number is in `[0,1]`.
4413
+ * @param {number} x Number to be tested.
4414
+ * @return {boolean} If `true` the number is in `[0,1]`.
4415
+ */
4416
+ var isNormFloat = function isNormFloat(x) {
4417
+ return x >= 0 && x <= 1;
4640
4418
  };
4641
4419
 
4642
4420
  /**
4643
- * Clip a number between min and max
4644
- * @param {number} value - The value to be clipped
4645
- * @param {number} minValue - The minimum value
4646
- * @param {number} maxValue - The maximum value
4647
- * @return {number} The clipped value
4421
+ * Tests if an array consist of normalized numbers that are in `[0,1]` only.
4422
+ * @param {array} a Array to be tested
4423
+ * @return {boolean} If `true` the array contains only numbers in `[0,1]`.
4648
4424
  */
4649
- var clip = function clip(value, minValue, maxValue) {
4650
- return Math.min(maxValue, Math.max(minValue, value));
4425
+ var isNormFloatArray = function isNormFloatArray(a) {
4426
+ return Array.isArray(a) && a.every(isNormFloat);
4651
4427
  };
4652
4428
 
4653
4429
  /**
4654
- * Convert object- or array-oriented points to array-oriented points
4655
- * @param {import('./types').Points} points - The point data
4656
- * @return {number[][]} Array-oriented points
4430
+ * Computes the cross product to determine the orientation of three points
4431
+ * @param {number} x1 X-coordinate of first point
4432
+ * @param {number} y1 Y-coordinate of first point
4433
+ * @param {number} x2 X-coordinate of second point
4434
+ * @param {number} y2 Y-coordinate of second point
4435
+ * @param {number} px X-coordinate of test point
4436
+ * @param {number} py Y-coordinate of test point
4437
+ * @return {number} Positive if counterclockwise, negative if clockwise
4657
4438
  */
4658
- var toArrayOrientedPoints = function toArrayOrientedPoints(points) {
4659
- return new Promise(function (resolve, reject) {
4660
- if (!points || Array.isArray(points)) {
4661
- resolve(points);
4662
- } else {
4663
- var length = Array.isArray(points.x) || ArrayBuffer.isView(points.x) ? points.x.length : 0;
4664
- var getX = (Array.isArray(points.x) || ArrayBuffer.isView(points.x)) && function (i) {
4665
- return points.x[i];
4666
- };
4667
- var getY = (Array.isArray(points.y) || ArrayBuffer.isView(points.y)) && function (i) {
4668
- return points.y[i];
4669
- };
4670
- var getL = (Array.isArray(points.line) || ArrayBuffer.isView(points.line)) && function (i) {
4671
- return points.line[i];
4672
- };
4439
+ function crossProduct(x1, y1, x2, y2, px, py) {
4440
+ return (x2 - x1) * (py - y1) - (px - x1) * (y2 - y1);
4441
+ }
4673
4442
 
4674
- // biome-ignore lint/style/useNamingConvention: LO stands for line and order
4675
- var getLO = (Array.isArray(points.lineOrder) || ArrayBuffer.isView(points.lineOrder)) && function (i) {
4676
- return points.lineOrder[i];
4677
- };
4678
- var components = Object.keys(points);
4679
- var getZ = function () {
4680
- var z = components.find(function (c) {
4681
- return Z_NAMES.has(c);
4682
- });
4683
- return z && (Array.isArray(points[z]) || ArrayBuffer.isView(points[z])) && function (i) {
4684
- return points[z][i];
4685
- };
4686
- }();
4687
- var getW = function () {
4688
- var w = components.find(function (c) {
4689
- return W_NAMES.has(c);
4690
- });
4691
- return w && (Array.isArray(points[w]) || ArrayBuffer.isView(points[w])) && function (i) {
4692
- return points[w][i];
4693
- };
4694
- }();
4695
- if (getX && getY && getZ && getW && getL && getLO) {
4696
- resolve(points.x.map(function (x, i) {
4697
- return [x, getY(i), getZ(i), getW(i), getL(i), getLO(i)];
4698
- }));
4699
- } else if (getX && getY && getZ && getW && getL) {
4700
- resolve(Array.from({
4701
- length: length
4702
- }, function (_, i) {
4703
- return [getX(i), getY(i), getZ(i), getW(i), getL(i)];
4704
- }));
4705
- } else if (getX && getY && getZ && getW) {
4706
- resolve(Array.from({
4707
- length: length
4708
- }, function (_, i) {
4709
- return [getX(i), getY(i), getZ(i), getW(i)];
4710
- }));
4711
- } else if (getX && getY && getZ) {
4712
- resolve(Array.from({
4713
- length: length
4714
- }, function (_, i) {
4715
- return [getX(i), getY(i), getZ(i)];
4716
- }));
4717
- } else if (getX && getY) {
4718
- resolve(Array.from({
4719
- length: length
4720
- }, function (_, i) {
4721
- return [getX(i), getY(i)];
4722
- }));
4723
- } else {
4724
- reject(new Error('You need to specify at least x and y'));
4443
+ /**
4444
+ * Determines if a point lies within a polygon using the non-zero winding rule.
4445
+ * This handles self-intersecting polygons and overlapping areas correctly.
4446
+ * @param {Array} polygon 1D list of vertices defining the polygon [x1,y1,x2,y2,...]
4447
+ * @param {Array} point Tuple of the form [x,y] to be tested
4448
+ * @return {boolean} True if point lies within the polygon
4449
+ */
4450
+ var isPointInPolygon = function isPointInPolygon(polygon) {
4451
+ var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [],
4452
+ _ref5 = _slicedToArray(_ref4, 2),
4453
+ px = _ref5[0],
4454
+ py = _ref5[1];
4455
+ var winding = 0;
4456
+ for (var i = 0, j = polygon.length - 2; i < polygon.length; i += 2) {
4457
+ var x1 = polygon[i];
4458
+ var y1 = polygon[i + 1];
4459
+ var x2 = polygon[j];
4460
+ var y2 = polygon[j + 1];
4461
+ if (y1 <= py) {
4462
+ if (y2 > py) {
4463
+ var orientation = crossProduct(x1, y1, x2, y2, px, py);
4464
+ if (orientation > 0) {
4465
+ winding++;
4466
+ }
4467
+ }
4468
+ } else if (y2 <= py) {
4469
+ var _orientation = crossProduct(x1, y1, x2, y2, px, py);
4470
+ if (_orientation < 0) {
4471
+ winding--;
4725
4472
  }
4726
4473
  }
4727
- });
4474
+ j = i;
4475
+ }
4476
+ return winding !== 0;
4728
4477
  };
4729
- var isHorizontalLine = function isHorizontalLine(annotation) {
4730
- return Number.isFinite(annotation.y) && !('x' in annotation);
4478
+
4479
+ /**
4480
+ * Tests if a variable is a string
4481
+ * @param {*} s Variable to be tested
4482
+ * @return {boolean} If `true` variable is a string
4483
+ */
4484
+ var isString = function isString(s) {
4485
+ return typeof s === 'string' || s instanceof String;
4731
4486
  };
4732
- var isVerticalLine = function isVerticalLine(annotation) {
4733
- return Number.isFinite(annotation.x) && !('y' in annotation);
4487
+
4488
+ /**
4489
+ * Tests if a number is an interger and in `[0,255]`.
4490
+ * @param {number} x Number to be tested.
4491
+ * @return {boolean} If `true` the number is an interger and in `[0,255]`.
4492
+ */
4493
+ var isUint8 = function isUint8(x) {
4494
+ return Number.isInteger(x) && x >= 0 && x <= 255;
4734
4495
  };
4735
- var isDomRect = function isDomRect(annotation) {
4736
- return Number.isFinite(annotation.x) && Number.isFinite(annotation.y) && Number.isFinite(annotation.width) && Number.isFinite(annotation.height);
4496
+
4497
+ /**
4498
+ * Tests if an array consist of Uint8 numbers only.
4499
+ * @param {array} a Array to be tested.
4500
+ * @return {boolean} If `true` the array contains only Uint8 numbers.
4501
+ */
4502
+ var isUint8Array = function isUint8Array(a) {
4503
+ return Array.isArray(a) && a.every(isUint8);
4737
4504
  };
4738
- var isRect = function isRect(annotation) {
4739
- return Number.isFinite(annotation.x1) && Number.isFinite(annotation.y1) && Number.isFinite(annotation.x2) && Number.isFinite(annotation.x2);
4505
+
4506
+ /**
4507
+ * Tests if an array is encoding an RGB color.
4508
+ * @param {array} rgb Array to be tested
4509
+ * @return {boolean} If `true` the array hold a triple of Uint8 numbers or
4510
+ * a triple of normalized floats.
4511
+ */
4512
+ var isRgb = function isRgb(rgb) {
4513
+ return rgb.length === 3 && (isNormFloatArray(rgb) || isUint8Array(rgb));
4740
4514
  };
4741
- var isPolygon = function isPolygon(annotation) {
4742
- return 'vertices' in annotation && annotation.vertices.length > 1;
4515
+
4516
+ /**
4517
+ * Tests if an array is encoding an RGBA color.
4518
+ * @param {array} rgb Array to be tested
4519
+ * @return {boolean} If `true` the array hold a quadruple of Uint8 numbers or
4520
+ * a quadruple of normalized floats.
4521
+ */
4522
+ var isRgba = function isRgba(rgba) {
4523
+ return rgba.length === 4 && (isNormFloatArray(rgba) || isUint8Array(rgba));
4743
4524
  };
4744
- var insertionSort = function insertionSort(array) {
4745
- var end = array.length;
4746
- for (var i = 1; i < end; i++) {
4747
- // Choosing the first element in our unsorted subarray
4748
- var current = array[i];
4749
- // The last element of our sorted subarray
4750
- var j = i - 1;
4751
- while (j > -1 && current < array[j]) {
4752
- array[j + 1] = array[j];
4753
- j--;
4754
- }
4755
- array[j + 1] = current;
4756
- }
4757
- return array;
4525
+
4526
+ /**
4527
+ * Test if a color is multiple colors
4528
+ * @param {*} color To be tested
4529
+ * @return {boolean} If `true`, `color` is an array of colors.
4530
+ */
4531
+ var isMultipleColors = function isMultipleColors(color) {
4532
+ return Array.isArray(color) && color.length > 0 && (Array.isArray(color[0]) || isString(color[0]));
4758
4533
  };
4759
4534
 
4760
- var createRenderer = function createRenderer() {
4761
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4762
- var regl = options.regl,
4763
- _options$canvas = options.canvas,
4764
- canvas = _options$canvas === void 0 ? document.createElement('canvas') : _options$canvas,
4765
- _options$gamma = options.gamma,
4766
- _gamma = _options$gamma === void 0 ? DEFAULT_GAMMA : _options$gamma;
4767
- var isDestroyed = false;
4768
- if (!regl) {
4769
- regl = createRegl(canvas);
4535
+ /**
4536
+ * Test if two arrays contain the same RGBA quadruples
4537
+ */
4538
+ var isSameRgbas = function isSameRgbas(a, b) {
4539
+ if (!(Array.isArray(a) && Array.isArray(b)) || a.length !== b.length) {
4540
+ return false;
4541
+ }
4542
+ if (a.length === 0) {
4543
+ return true;
4770
4544
  }
4771
- var isSupportingAllGlExtensions = checkReglExtensions(regl);
4772
- var fboRes = [canvas.width, canvas.height];
4773
- var fbo = regl.framebuffer({
4774
- width: fboRes[0],
4775
- height: fboRes[1],
4776
- colorFormat: 'rgba',
4777
- colorType: 'float'
4778
- });
4779
4545
 
4780
- /**
4781
- * Render the float32 framebuffer to the internal canvas
4782
- *
4783
- * From https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds
4784
- */
4785
- var renderToCanvas = regl({
4786
- vert: "\n precision highp float;\n attribute vec2 xy;\n void main () {\n gl_Position = vec4(xy, 0, 1);\n }",
4787
- frag: "\n precision highp float;\n uniform vec2 srcRes;\n uniform sampler2D src;\n uniform float gamma;\n\n vec3 approxLinearToSRGB (vec3 rgb, float gamma) {\n return pow(clamp(rgb, vec3(0), vec3(1)), vec3(1.0 / gamma));\n }\n\n void main () {\n vec4 color = texture2D(src, gl_FragCoord.xy / srcRes);\n gl_FragColor = vec4(approxLinearToSRGB(color.rgb, gamma), color.a);\n }",
4788
- attributes: {
4789
- xy: [-4, -4, 4, -4, 0, 4]
4790
- },
4791
- uniforms: {
4792
- src: function src() {
4793
- return fbo;
4794
- },
4795
- srcRes: function srcRes() {
4796
- return fboRes;
4797
- },
4798
- gamma: function gamma() {
4799
- return _gamma;
4800
- }
4801
- },
4802
- count: 3,
4803
- depth: {
4804
- enable: false
4805
- },
4806
- blend: {
4807
- enable: true,
4808
- func: {
4809
- // biome-ignore lint/style/useNamingConvention: Regl internal
4810
- srcRGB: 'one',
4811
- srcAlpha: 'one',
4812
- // biome-ignore lint/style/useNamingConvention: Regl internal
4813
- dstRGB: 'one minus src alpha',
4814
- dstAlpha: 'one minus src alpha'
4815
- }
4816
- }
4546
+ // We need to test whether a and b are arrays of RGBA quadruples
4547
+ if (!(Array.isArray(a[0]) && Array.isArray(b[0]))) {
4548
+ return false;
4549
+ }
4550
+ return a.every(function (_ref6, i) {
4551
+ var _ref7 = _slicedToArray(_ref6, 4),
4552
+ r1 = _ref7[0],
4553
+ g1 = _ref7[1],
4554
+ b1 = _ref7[2],
4555
+ a1 = _ref7[3];
4556
+ var _b$i = _slicedToArray(b[i], 4),
4557
+ r2 = _b$i[0],
4558
+ g2 = _b$i[1],
4559
+ b2 = _b$i[2],
4560
+ a2 = _b$i[3];
4561
+ return r1 === r2 && g1 === g2 && b1 === b2 && a1 === a2;
4817
4562
  });
4563
+ };
4818
4564
 
4819
- /**
4820
- * Copy the pixels from the internal canvas onto the target canvas
4821
- */
4822
- var copyTo = function copyTo(targetCanvas) {
4823
- var ctx = targetCanvas.getContext('2d');
4824
- ctx.clearRect(0, 0, targetCanvas.width, targetCanvas.height);
4825
- ctx.drawImage(canvas, (canvas.width - targetCanvas.width) / 2, (canvas.height - targetCanvas.height) / 2, targetCanvas.width, targetCanvas.height, 0, 0, targetCanvas.width, targetCanvas.height);
4826
- };
4565
+ /**
4566
+ * Fast version of `Math.max`. Based on
4567
+ * https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not
4568
+ * very fast
4569
+ * @param {number} a Value A
4570
+ * @param {number} b Value B
4571
+ * @return {boolean} If `true` A is greater than B.
4572
+ */
4573
+ var max = function max(a, b) {
4574
+ return a > b ? a : b;
4575
+ };
4827
4576
 
4828
- /**
4829
- * The render function
4830
- */
4831
- var render = function render(/** @type {(): void} */draw, /** @type {HTMLCanvasElement} */targetCanvas) {
4832
- // Clear internal canvas
4833
- regl.clear(CLEAR_OPTIONS);
4834
- fbo.use(function () {
4835
- // Clear framebuffer
4836
- regl.clear(CLEAR_OPTIONS);
4837
- draw();
4577
+ /**
4578
+ * Fast version of `Math.min`. Based on
4579
+ * https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not
4580
+ * very fast
4581
+ * @param {number} a Value A
4582
+ * @param {number} b Value B
4583
+ * @return {boolean} If `true` A is smaller than B.
4584
+ */
4585
+ var min = function min(a, b) {
4586
+ return a < b ? a : b;
4587
+ };
4588
+
4589
+ /**
4590
+ * Convert a color to an RGBA color
4591
+ * @param {*} color Color to be converted. Currently supports:
4592
+ * HEX, RGB, or RGBA.
4593
+ * @param {boolean} isNormalize If `true` the returned RGBA values will be
4594
+ * normalized to `[0,1]`.
4595
+ * @return {array} Quadruple defining an RGBA color.
4596
+ */
4597
+ var toRgba = function toRgba(color, shouldNormalize) {
4598
+ if (isRgba(color)) {
4599
+ var isNormalized = isNormFloatArray(color);
4600
+ if (shouldNormalize && isNormalized || !(shouldNormalize || isNormalized)) {
4601
+ return color;
4602
+ }
4603
+ if (shouldNormalize && !isNormalized) {
4604
+ return color.map(function (x) {
4605
+ return x / 255;
4606
+ });
4607
+ }
4608
+ return color.map(function (x) {
4609
+ return x * 255;
4838
4610
  });
4839
- renderToCanvas();
4840
- copyTo(targetCanvas);
4841
- };
4611
+ }
4612
+ if (isRgb(color)) {
4613
+ var base = Math.pow(255, !shouldNormalize);
4614
+ var _isNormalized = isNormFloatArray(color);
4615
+ if (shouldNormalize && _isNormalized || !(shouldNormalize || _isNormalized)) {
4616
+ return [].concat(_toConsumableArray(color), [base]);
4617
+ }
4618
+ if (shouldNormalize && !_isNormalized) {
4619
+ return [].concat(_toConsumableArray(color.map(function (x) {
4620
+ return x / 255;
4621
+ })), [base]);
4622
+ }
4623
+ return [].concat(_toConsumableArray(color.map(function (x) {
4624
+ return x * 255;
4625
+ })), [base]);
4626
+ }
4627
+ if (isHex(color)) {
4628
+ return hexToRgba(color, shouldNormalize);
4629
+ }
4842
4630
 
4843
- /**
4844
- * Update Regl's viewport, drawingBufferWidth, and drawingBufferHeight
4845
- *
4846
- * @description Call this method after the viewport has changed, e.g., width
4847
- * or height have been altered
4848
- */
4849
- var refresh = function refresh() {
4850
- regl.poll();
4851
- };
4852
- var drawFns = new Set();
4631
+ // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning
4632
+ console.warn('Only HEX, RGB, and RGBA are handled by this function. Returning white instead.');
4633
+ return shouldNormalize ? [1, 1, 1, 1] : [255, 255, 255, 255];
4634
+ };
4853
4635
 
4854
- /**
4855
- * Register an draw function that is going to be invoked on every animation
4856
- * frame.
4857
- */
4858
- var onFrame = function onFrame(/** @type {(): void} */draw) {
4859
- drawFns.add(draw);
4860
- return function () {
4861
- drawFns["delete"](draw);
4862
- };
4863
- };
4864
- var frame = regl.frame(function () {
4865
- var iterator = drawFns.values();
4866
- var result = iterator.next();
4867
- while (!result.done) {
4868
- result.value(); // The draw function
4869
- result = iterator.next();
4636
+ /**
4637
+ * Flip the key-value pairs of an object
4638
+ * @param {object} obj - Object to be flipped
4639
+ * @return {object} Flipped object
4640
+ */
4641
+ var flipObj = function flipObj(obj) {
4642
+ return Object.entries(obj).reduce(function (out, _ref8) {
4643
+ var _ref9 = _slicedToArray(_ref8, 2),
4644
+ key = _ref9[0],
4645
+ value = _ref9[1];
4646
+ if (out[value]) {
4647
+ out[value] = [].concat(_toConsumableArray(out[value]), [key]);
4648
+ } else {
4649
+ out[value] = key;
4650
+ }
4651
+ return out;
4652
+ }, {});
4653
+ };
4654
+ var rgbBrightness = function rgbBrightness(rgb) {
4655
+ return 0.21 * rgb[0] + 0.72 * rgb[1] + 0.07 * rgb[2];
4656
+ };
4657
+
4658
+ /**
4659
+ * Clip a number between min and max
4660
+ * @param {number} value - The value to be clipped
4661
+ * @param {number} minValue - The minimum value
4662
+ * @param {number} maxValue - The maximum value
4663
+ * @return {number} The clipped value
4664
+ */
4665
+ var clip = function clip(value, minValue, maxValue) {
4666
+ return Math.min(maxValue, Math.max(minValue, value));
4667
+ };
4668
+
4669
+ /**
4670
+ * Convert object- or array-oriented points to array-oriented points
4671
+ * @param {import('./types').Points} points - The point data
4672
+ * @return {number[][]} Array-oriented points
4673
+ */
4674
+ var toArrayOrientedPoints = function toArrayOrientedPoints(points) {
4675
+ return new Promise(function (resolve, reject) {
4676
+ if (!points || Array.isArray(points)) {
4677
+ resolve(points);
4678
+ } else {
4679
+ var length = Array.isArray(points.x) || ArrayBuffer.isView(points.x) ? points.x.length : 0;
4680
+ var getX = (Array.isArray(points.x) || ArrayBuffer.isView(points.x)) && function (i) {
4681
+ return points.x[i];
4682
+ };
4683
+ var getY = (Array.isArray(points.y) || ArrayBuffer.isView(points.y)) && function (i) {
4684
+ return points.y[i];
4685
+ };
4686
+ var getL = (Array.isArray(points.line) || ArrayBuffer.isView(points.line)) && function (i) {
4687
+ return points.line[i];
4688
+ };
4689
+ var getLO = (Array.isArray(points.lineOrder) || ArrayBuffer.isView(points.lineOrder)) && function (i) {
4690
+ return points.lineOrder[i];
4691
+ };
4692
+ var components = Object.keys(points);
4693
+ var getZ = function () {
4694
+ var z = components.find(function (c) {
4695
+ return Z_NAMES.has(c);
4696
+ });
4697
+ return z && (Array.isArray(points[z]) || ArrayBuffer.isView(points[z])) && function (i) {
4698
+ return points[z][i];
4699
+ };
4700
+ }();
4701
+ var getW = function () {
4702
+ var w = components.find(function (c) {
4703
+ return W_NAMES.has(c);
4704
+ });
4705
+ return w && (Array.isArray(points[w]) || ArrayBuffer.isView(points[w])) && function (i) {
4706
+ return points[w][i];
4707
+ };
4708
+ }();
4709
+ if (getX && getY && getZ && getW && getL && getLO) {
4710
+ resolve(points.x.map(function (x, i) {
4711
+ return [x, getY(i), getZ(i), getW(i), getL(i), getLO(i)];
4712
+ }));
4713
+ } else if (getX && getY && getZ && getW && getL) {
4714
+ resolve(Array.from({
4715
+ length: length
4716
+ }, function (_, i) {
4717
+ return [getX(i), getY(i), getZ(i), getW(i), getL(i)];
4718
+ }));
4719
+ } else if (getX && getY && getZ && getW) {
4720
+ resolve(Array.from({
4721
+ length: length
4722
+ }, function (_, i) {
4723
+ return [getX(i), getY(i), getZ(i), getW(i)];
4724
+ }));
4725
+ } else if (getX && getY && getZ) {
4726
+ resolve(Array.from({
4727
+ length: length
4728
+ }, function (_, i) {
4729
+ return [getX(i), getY(i), getZ(i)];
4730
+ }));
4731
+ } else if (getX && getY) {
4732
+ resolve(Array.from({
4733
+ length: length
4734
+ }, function (_, i) {
4735
+ return [getX(i), getY(i)];
4736
+ }));
4737
+ } else {
4738
+ reject(new Error('You need to specify at least x and y'));
4739
+ }
4870
4740
  }
4871
4741
  });
4872
- var resize = function resize(/** @type {number} */customWidth, /** @type {number} */customHeight) {
4873
- // We need to limit the width and height by the screen size to prevent
4874
- // a bug in VSCode where the window height is said to be taller than the
4875
- // screen height. The problem with too large dimensions is that at some
4876
- // point WebGL will break down because there's an upper limit on how large
4877
- // any buffer and texture can be. It also harms the performance quite a bit.
4878
- //
4879
- // By restricting the widht/height to the screen size we should have a safe
4880
- // upper limit for the canvas size.
4881
- //
4882
- // @see
4883
- // https://github.com/microsoft/vscode/issues/225808
4884
- // https://github.com/flekschas/jupyter-scatter/issues/37
4885
- var width = customWidth === undefined ? Math.min(window.innerWidth, window.screen.availWidth) : customWidth;
4886
- var height = customHeight === undefined ? Math.min(window.innerHeight, window.screen.availHeight) : customHeight;
4887
- canvas.width = width * window.devicePixelRatio;
4888
- canvas.height = height * window.devicePixelRatio;
4889
- fboRes[0] = canvas.width;
4890
- fboRes[1] = canvas.height;
4891
- fbo.resize.apply(fbo, fboRes);
4892
- };
4893
- var resizeHandler = function resizeHandler() {
4894
- resize();
4895
- };
4896
- if (!options.canvas) {
4897
- window.addEventListener('resize', resizeHandler);
4898
- window.addEventListener('orientationchange', resizeHandler);
4899
- resize();
4742
+ };
4743
+ var isHorizontalLine = function isHorizontalLine(annotation) {
4744
+ return Number.isFinite(annotation.y) && !('x' in annotation);
4745
+ };
4746
+ var isVerticalLine = function isVerticalLine(annotation) {
4747
+ return Number.isFinite(annotation.x) && !('y' in annotation);
4748
+ };
4749
+ var isDomRect = function isDomRect(annotation) {
4750
+ return Number.isFinite(annotation.x) && Number.isFinite(annotation.y) && Number.isFinite(annotation.width) && Number.isFinite(annotation.height);
4751
+ };
4752
+ var isRect = function isRect(annotation) {
4753
+ return Number.isFinite(annotation.x1) && Number.isFinite(annotation.y1) && Number.isFinite(annotation.x2) && Number.isFinite(annotation.x2);
4754
+ };
4755
+ var isPolygonAnnotation = function isPolygonAnnotation(annotation) {
4756
+ return 'vertices' in annotation && annotation.vertices.length > 1;
4757
+ };
4758
+
4759
+ /**
4760
+ * Check if an array is a valid list of 2D vertices
4761
+ * @param {any} arg - The argument to check
4762
+ * @returns {boolean} True if argument is an array of [x, y] coordinate pairs
4763
+ */
4764
+ var isVertices = function isVertices(arg) {
4765
+ if (!Array.isArray(arg) || arg.length < 3) {
4766
+ return false;
4767
+ }
4768
+ var _iterator2 = _createForOfIteratorHelper(arg),
4769
+ _step2;
4770
+ try {
4771
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
4772
+ var vertex = _step2.value;
4773
+ if (!Array.isArray(vertex) || vertex.length !== 2 || typeof vertex[0] !== 'number' || typeof vertex[1] !== 'number') {
4774
+ return false;
4775
+ }
4776
+ }
4777
+ } catch (err) {
4778
+ _iterator2.e(err);
4779
+ } finally {
4780
+ _iterator2.f();
4781
+ }
4782
+ return true;
4783
+ };
4784
+
4785
+ /**
4786
+ * Ensure a list of vertices forms a closed polygon
4787
+ * @param {Array<[number, number]>} vertices - Array of [x, y] coordinates
4788
+ * @returns {Array<[number, number]>} Closed polygon (first vertex repeated at end if needed)
4789
+ */
4790
+ var verticesToPolygon = function verticesToPolygon(vertices) {
4791
+ var polygon = _toConsumableArray(vertices);
4792
+ var firstVertex = vertices.at(0);
4793
+ var lastVertex = vertices.at(-1);
4794
+ if (firstVertex[0] !== lastVertex[0] || firstVertex[1] !== lastVertex[1]) {
4795
+ polygon.push(firstVertex);
4796
+ }
4797
+ return polygon;
4798
+ };
4799
+ var insertionSort = function insertionSort(array) {
4800
+ var end = array.length;
4801
+ for (var i = 1; i < end; i++) {
4802
+ // Choosing the first element in our unsorted subarray
4803
+ var current = array[i];
4804
+ // The last element of our sorted subarray
4805
+ var j = i - 1;
4806
+ while (j > -1 && current < array[j]) {
4807
+ array[j + 1] = array[j];
4808
+ j--;
4809
+ }
4810
+ array[j + 1] = current;
4811
+ }
4812
+ return array;
4813
+ };
4814
+
4815
+ var createRenderer = function createRenderer() {
4816
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4817
+ var regl = options.regl,
4818
+ _options$canvas = options.canvas,
4819
+ canvas = _options$canvas === void 0 ? document.createElement('canvas') : _options$canvas,
4820
+ _options$gamma = options.gamma,
4821
+ _gamma = _options$gamma === void 0 ? DEFAULT_GAMMA : _options$gamma;
4822
+ var isDestroyed = false;
4823
+ if (!regl) {
4824
+ regl = createRegl(canvas);
4900
4825
  }
4826
+ var isSupportingAllGlExtensions = checkReglExtensions(regl);
4827
+ var fboRes = [canvas.width, canvas.height];
4828
+ var fbo = regl.framebuffer({
4829
+ width: fboRes[0],
4830
+ height: fboRes[1],
4831
+ colorFormat: 'rgba',
4832
+ colorType: 'float'
4833
+ });
4901
4834
 
4902
4835
  /**
4903
- * Destroy the renderer to free resources and cancel animation frames
4836
+ * Render the float32 framebuffer to the internal canvas
4837
+ *
4838
+ * From https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds
4904
4839
  */
4905
- var destroy = function destroy() {
4906
- isDestroyed = true;
4907
- window.removeEventListener('resize', resizeHandler);
4908
- window.removeEventListener('orientationchange', resizeHandler);
4909
- frame.cancel();
4910
- canvas = undefined;
4911
- regl.destroy();
4912
- regl = undefined;
4913
- };
4914
- return {
4915
- /**
4916
- * Get the associated canvas element
4917
- * @return {HTMLCanvasElement} The associated canvas element
4918
- */
4919
- get canvas() {
4920
- return canvas;
4921
- },
4922
- /**
4923
- * Get the associated Regl instance
4924
- * @return {import('regl').Regl} The associated Regl instance
4925
- */
4926
- get regl() {
4927
- return regl;
4928
- },
4929
- /**
4930
- * Get the gamma value
4931
- * @return {number} The gamma value
4932
- */
4933
- get gamma() {
4934
- return _gamma;
4935
- },
4936
- /**
4937
- * Set gamma to a new value
4938
- * @param {number} newGamma - The new gamma value
4939
- */
4940
- set gamma(newGamma) {
4941
- _gamma = +newGamma;
4840
+ var renderToCanvas = regl({
4841
+ vert: "\n precision highp float;\n attribute vec2 xy;\n void main () {\n gl_Position = vec4(xy, 0, 1);\n }",
4842
+ frag: "\n precision highp float;\n uniform vec2 srcRes;\n uniform sampler2D src;\n uniform float gamma;\n\n vec3 approxLinearToSRGB (vec3 rgb, float gamma) {\n return pow(clamp(rgb, vec3(0), vec3(1)), vec3(1.0 / gamma));\n }\n\n void main () {\n vec4 color = texture2D(src, gl_FragCoord.xy / srcRes);\n gl_FragColor = vec4(approxLinearToSRGB(color.rgb, gamma), color.a);\n }",
4843
+ attributes: {
4844
+ xy: [-4, -4, 4, -4, 0, 4]
4942
4845
  },
4943
- /**
4944
- * Get whether the browser supports all necessary WebGL features
4945
- * @return {boolean} If `true` the browser supports all necessary WebGL features
4946
- */
4947
- get isSupported() {
4948
- return isSupportingAllGlExtensions;
4846
+ uniforms: {
4847
+ src: function src() {
4848
+ return fbo;
4849
+ },
4850
+ srcRes: function srcRes() {
4851
+ return fboRes;
4852
+ },
4853
+ gamma: function gamma() {
4854
+ return _gamma;
4855
+ }
4949
4856
  },
4950
- /**
4951
- * Get whether the renderer (and its Regl instance) is destroyed
4952
- * @return {boolean} If `true` the renderer is destroyed
4953
- */
4954
- get isDestroyed() {
4955
- return isDestroyed;
4857
+ count: 3,
4858
+ depth: {
4859
+ enable: false
4956
4860
  },
4957
- render: render,
4958
- resize: resize,
4959
- onFrame: onFrame,
4960
- refresh: refresh,
4961
- destroy: destroy
4962
- };
4963
- };
4964
-
4965
- const FRAGMENT_SHADER$2 = `
4966
- precision mediump float;
4967
-
4968
- uniform sampler2D texture;
4969
-
4970
- varying vec2 uv;
4971
-
4972
- void main () {
4973
- gl_FragColor = texture2D(texture, uv);
4974
- }
4975
- `;
4976
-
4977
- const VERTEX_SHADER = `
4978
- precision mediump float;
4979
-
4980
- uniform mat4 modelViewProjection;
4981
-
4982
- attribute vec2 position;
4983
-
4984
- varying vec2 uv;
4985
-
4986
- void main () {
4987
- uv = position;
4988
- gl_Position = modelViewProjection * vec4(-1.0 + 2.0 * uv.x, 1.0 - 2.0 * uv.y, 0, 1);
4989
- }
4990
- `;
4991
-
4992
- const FRAGMENT_SHADER$1 = `precision highp float;
4993
-
4994
- varying vec4 color;
4995
-
4996
- void main() {
4997
- gl_FragColor = color;
4998
- }
4999
- `;
5000
-
5001
- const SHADER$1 = `precision highp float;
5002
-
5003
- uniform sampler2D startStateTex;
5004
- uniform sampler2D endStateTex;
5005
- uniform float t;
5006
-
5007
- varying vec2 particleTextureIndex;
5008
-
5009
- void main() {
5010
- // Interpolate x, y, and value
5011
- vec3 start = texture2D(startStateTex, particleTextureIndex).xyw;
5012
- vec3 end = texture2D(endStateTex, particleTextureIndex).xyw;
5013
- vec3 curr = start * (1.0 - t) + end * t;
5014
-
5015
- // The category cannot be interpolated
5016
- float endCategory = texture2D(endStateTex, particleTextureIndex).z;
5017
-
5018
- gl_FragColor = vec4(curr.xy, endCategory, curr.z);
5019
- }`;
5020
-
5021
- const SHADER = `precision highp float;
5022
-
5023
- attribute vec2 position;
5024
- varying vec2 particleTextureIndex;
5025
-
5026
- void main() {
5027
- // map normalized device coords to texture coords
5028
- particleTextureIndex = 0.5 * (1.0 + position);
5029
-
5030
- gl_Position = vec4(position, 0, 1);
5031
- }`;
5032
-
5033
- const FRAGMENT_SHADER = `
5034
- precision highp float;
5035
-
5036
- uniform float antiAliasing;
5037
-
5038
- varying vec4 color;
5039
- varying float finalPointSize;
5040
-
5041
- float linearstep(float edge0, float edge1, float x) {
5042
- return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
5043
- }
5044
-
5045
- void main() {
5046
- vec2 c = gl_PointCoord * 2.0 - 1.0;
5047
- float sdf = length(c) * finalPointSize;
5048
- float alpha = linearstep(finalPointSize + antiAliasing, finalPointSize - antiAliasing, sdf);
5049
-
5050
- gl_FragColor = vec4(color.rgb, alpha * color.a);
5051
- }
5052
- `;
5053
-
5054
- const createVertexShader = (globalState) => `
5055
- precision highp float;
5056
-
5057
- uniform sampler2D colorTex;
5058
- uniform float colorTexRes;
5059
- uniform float colorTexEps;
5060
- uniform sampler2D stateTex;
5061
- uniform float stateTexRes;
5062
- uniform float stateTexEps;
5063
- uniform float devicePixelRatio;
5064
- uniform sampler2D encodingTex;
5065
- uniform float encodingTexRes;
5066
- uniform float encodingTexEps;
5067
- uniform float pointSizeExtra;
5068
- uniform float pointOpacityMax;
5069
- uniform float pointOpacityScale;
5070
- uniform float numPoints;
5071
- uniform float globalState;
5072
- uniform float isColoredByZ;
5073
- uniform float isColoredByW;
5074
- uniform float isOpacityByZ;
5075
- uniform float isOpacityByW;
5076
- uniform float isOpacityByDensity;
5077
- uniform float isSizedByZ;
5078
- uniform float isSizedByW;
5079
- uniform float isPixelAligned;
5080
- uniform float colorMultiplicator;
5081
- uniform float opacityMultiplicator;
5082
- uniform float opacityDensity;
5083
- uniform float sizeMultiplicator;
5084
- uniform float numColorStates;
5085
- uniform float pointScale;
5086
- uniform float drawingBufferWidth;
5087
- uniform float drawingBufferHeight;
5088
- uniform mat4 modelViewProjection;
5089
-
5090
- attribute vec2 stateIndex;
5091
-
5092
- varying vec4 color;
5093
- varying float finalPointSize;
5094
-
5095
- void main() {
5096
- vec4 state = texture2D(stateTex, stateIndex);
5097
-
5098
- if (isPixelAligned < 0.5) {
5099
- gl_Position = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
5100
- } else {
5101
- vec4 clipSpacePosition = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
5102
- vec2 ndcPosition = clipSpacePosition.xy / clipSpacePosition.w;
5103
- vec2 pixelPos = 0.5 * (ndcPosition + 1.0) * vec2(drawingBufferWidth, drawingBufferHeight);
5104
- pixelPos = floor(pixelPos + 0.5); // Snap to nearest pixel
5105
- vec2 snappedPosition = (pixelPos / vec2(drawingBufferWidth, drawingBufferHeight)) * 2.0 - 1.0;
5106
- gl_Position = vec4(snappedPosition, 0.0, 1.0);
5107
- }
5108
-
5109
-
5110
- // Determine color index
5111
- float colorIndexZ = isColoredByZ * floor(state.z * colorMultiplicator);
5112
- float colorIndexW = isColoredByW * floor(state.w * colorMultiplicator);
5113
-
5114
- // Multiply by the number of color states per color
5115
- // I.e., normal, active, hover, background, etc.
5116
- float colorIndex = (colorIndexZ + colorIndexW) * numColorStates;
5117
-
5118
- // Half a "pixel" or "texel" in texture coordinates
5119
- float colorLinearIndex = colorIndex + globalState;
5120
-
5121
- // Need to add cEps here to avoid floating point issue that can lead to
5122
- // dramatic changes in which color is loaded as floor(3/2.9999) = 1 but
5123
- // floor(3/3.0001) = 0!
5124
- float colorRowIndex = floor((colorLinearIndex + colorTexEps) / colorTexRes);
5125
-
5126
- vec2 colorTexIndex = vec2(
5127
- (colorLinearIndex / colorTexRes) - colorRowIndex + colorTexEps,
5128
- colorRowIndex / colorTexRes + colorTexEps
5129
- );
5130
-
5131
- color = texture2D(colorTex, colorTexIndex);
5132
-
5133
- // Retrieve point size
5134
- float pointSizeIndexZ = isSizedByZ * floor(state.z * sizeMultiplicator);
5135
- float pointSizeIndexW = isSizedByW * floor(state.w * sizeMultiplicator);
5136
- float pointSizeIndex = pointSizeIndexZ + pointSizeIndexW;
4861
+ blend: {
4862
+ enable: true,
4863
+ func: {
4864
+ srcRGB: 'one',
4865
+ srcAlpha: 'one',
4866
+ dstRGB: 'one minus src alpha',
4867
+ dstAlpha: 'one minus src alpha'
4868
+ }
4869
+ }
4870
+ });
5137
4871
 
5138
- float pointSizeRowIndex = floor((pointSizeIndex + encodingTexEps) / encodingTexRes);
5139
- vec2 pointSizeTexIndex = vec2(
5140
- (pointSizeIndex / encodingTexRes) - pointSizeRowIndex + encodingTexEps,
5141
- pointSizeRowIndex / encodingTexRes + encodingTexEps
5142
- );
5143
- float pointSize = texture2D(encodingTex, pointSizeTexIndex).x;
4872
+ /**
4873
+ * Copy the pixels from the internal canvas onto the target canvas
4874
+ */
4875
+ var copyTo = function copyTo(targetCanvas) {
4876
+ var ctx = targetCanvas.getContext('2d');
4877
+ ctx.clearRect(0, 0, targetCanvas.width, targetCanvas.height);
4878
+ ctx.drawImage(canvas, (canvas.width - targetCanvas.width) / 2, (canvas.height - targetCanvas.height) / 2, targetCanvas.width, targetCanvas.height, 0, 0, targetCanvas.width, targetCanvas.height);
4879
+ };
5144
4880
 
5145
- // Retrieve opacity
5146
- ${
5147
- (() => {
5148
- // Drawing the inner border of selected points
5149
- if (globalState === 3) return '';
4881
+ /**
4882
+ * The render function
4883
+ */
4884
+ var render = function render(/** @type {(): void} */draw, /** @type {HTMLCanvasElement} */targetCanvas) {
4885
+ // Clear internal canvas
4886
+ regl.clear(CLEAR_OPTIONS);
4887
+ fbo.use(function () {
4888
+ // Clear framebuffer
4889
+ regl.clear(CLEAR_OPTIONS);
4890
+ draw();
4891
+ });
4892
+ renderToCanvas();
4893
+ copyTo(targetCanvas);
4894
+ };
5150
4895
 
5151
- // Draw points with opacity encoding or dynamic opacity
5152
- return `
5153
- if (isOpacityByDensity < 0.5) {
5154
- float opacityIndexZ = isOpacityByZ * floor(state.z * opacityMultiplicator);
5155
- float opacityIndexW = isOpacityByW * floor(state.w * opacityMultiplicator);
5156
- float opacityIndex = opacityIndexZ + opacityIndexW;
4896
+ /**
4897
+ * Update Regl's viewport, drawingBufferWidth, and drawingBufferHeight
4898
+ *
4899
+ * @description Call this method after the viewport has changed, e.g., width
4900
+ * or height have been altered
4901
+ */
4902
+ var refresh = function refresh() {
4903
+ regl.poll();
4904
+ };
4905
+ var drawFns = new Set();
5157
4906
 
5158
- float opacityRowIndex = floor((opacityIndex + encodingTexEps) / encodingTexRes);
5159
- vec2 opacityTexIndex = vec2(
5160
- (opacityIndex / encodingTexRes) - opacityRowIndex + encodingTexEps,
5161
- opacityRowIndex / encodingTexRes + encodingTexEps
5162
- );
5163
- color.a = texture2D(encodingTex, opacityTexIndex)[${1 + globalState}];
5164
- } else {
5165
- color.a = min(1.0, opacityDensity + globalState);
5166
- }
5167
- `;
5168
- })()
5169
- }
4907
+ /**
4908
+ * Register an draw function that is going to be invoked on every animation
4909
+ * frame.
4910
+ */
4911
+ var onFrame = function onFrame(/** @type {(): void} */draw) {
4912
+ drawFns.add(draw);
4913
+ return function () {
4914
+ drawFns["delete"](draw);
4915
+ };
4916
+ };
4917
+ var frame = regl.frame(function () {
4918
+ var iterator = drawFns.values();
4919
+ var result = iterator.next();
4920
+ while (!result.done) {
4921
+ result.value(); // The draw function
4922
+ result = iterator.next();
4923
+ }
4924
+ });
4925
+ var resize = function resize(/** @type {number} */customWidth, /** @type {number} */customHeight) {
4926
+ var width = customWidth == null ? window.innerWidth : customWidth;
4927
+ var height = customHeight == null ? window.innerHeight : customHeight;
4928
+ canvas.width = width * window.devicePixelRatio;
4929
+ canvas.height = height * window.devicePixelRatio;
4930
+ fboRes[0] = canvas.width;
4931
+ fboRes[1] = canvas.height;
4932
+ fbo.resize.apply(fbo, fboRes);
4933
+ };
4934
+ var resizeHandler = function resizeHandler() {
4935
+ resize();
4936
+ };
4937
+ if (!options.canvas) {
4938
+ window.addEventListener('resize', resizeHandler);
4939
+ window.addEventListener('orientationchange', resizeHandler);
4940
+ resize();
4941
+ }
5170
4942
 
5171
- color.a = min(pointOpacityMax, color.a) * pointOpacityScale;
5172
- finalPointSize = (pointSize * pointScale) + pointSizeExtra;
5173
- gl_PointSize = finalPointSize;
5174
- }
5175
- `;
4943
+ /**
4944
+ * Destroy the renderer to free resources and cancel animation frames
4945
+ */
4946
+ var destroy = function destroy() {
4947
+ isDestroyed = true;
4948
+ window.removeEventListener('resize', resizeHandler);
4949
+ window.removeEventListener('orientationchange', resizeHandler);
4950
+ frame.cancel();
4951
+ canvas = undefined;
4952
+ regl.destroy();
4953
+ regl = undefined;
4954
+ };
4955
+ return {
4956
+ /**
4957
+ * Get the associated canvas element
4958
+ * @return {HTMLCanvasElement} The associated canvas element
4959
+ */
4960
+ get canvas() {
4961
+ return canvas;
4962
+ },
4963
+ /**
4964
+ * Get the associated Regl instance
4965
+ * @return {import('regl').Regl} The associated Regl instance
4966
+ */
4967
+ get regl() {
4968
+ return regl;
4969
+ },
4970
+ /**
4971
+ * Get the gamma value
4972
+ * @return {number} The gamma value
4973
+ */
4974
+ get gamma() {
4975
+ return _gamma;
4976
+ },
4977
+ /**
4978
+ * Set gamma to a new value
4979
+ * @param {number} newGamma - The new gamma value
4980
+ */
4981
+ set gamma(newGamma) {
4982
+ _gamma = +newGamma;
4983
+ },
4984
+ /**
4985
+ * Get whether the browser supports all necessary WebGL features
4986
+ * @return {boolean} If `true` the browser supports all necessary WebGL features
4987
+ */
4988
+ get isSupported() {
4989
+ return isSupportingAllGlExtensions;
4990
+ },
4991
+ /**
4992
+ * Get whether the renderer (and its Regl instance) is destroyed
4993
+ * @return {boolean} If `true` the renderer is destroyed
4994
+ */
4995
+ get isDestroyed() {
4996
+ return isDestroyed;
4997
+ },
4998
+ render: render,
4999
+ resize: resize,
5000
+ onFrame: onFrame,
5001
+ refresh: refresh,
5002
+ destroy: destroy
5003
+ };
5004
+ };
5176
5005
 
5177
5006
  /* eslint-env worker */
5178
5007
  /* eslint no-restricted-globals: 1 */
@@ -5268,7 +5097,6 @@ void main() {
5268
5097
  * @param {[type]} simplified [description]
5269
5098
  * @return {[type]} [description]
5270
5099
  */
5271
- // biome-ignore lint/style/useNamingConvention: DP stands for Douglas Peucker
5272
5100
  var _simplifyDPStep = function simplifyDPStep(points, first, last, tolerance, simplified) {
5273
5101
  var maxDist = tolerance;
5274
5102
  var index;
@@ -5363,7 +5191,6 @@ void main() {
5363
5191
  var groupPoints = function groupPoints(points) {
5364
5192
  var groupedPoints = {};
5365
5193
  var isOrdered = !Number.isNaN(+points[0][5]);
5366
- // biome-ignore lint/complexity/noForEach: somehow for .. of does not work in a worker
5367
5194
  points.forEach(function (point) {
5368
5195
  var segId = point[4];
5369
5196
  if (!groupedPoints[segId]) {
@@ -5377,7 +5204,6 @@ void main() {
5377
5204
  });
5378
5205
 
5379
5206
  // The filtering ensures that non-existing array entries are removed
5380
- // biome-ignore lint/complexity/noForEach: somehow for .. of does not work in a worker
5381
5207
  Object.entries(groupedPoints).forEach(function (idPoints) {
5382
5208
  groupedPoints[idPoints[0]] = idPoints[1].filter(function (v) {
5383
5209
  return v;
@@ -5429,8 +5255,6 @@ void main() {
5429
5255
  });
5430
5256
  };
5431
5257
 
5432
- var version = "1.14.1+1.0.1";
5433
-
5434
5258
  var deprecations = {
5435
5259
  showRecticle: {
5436
5260
  replacement: 'showReticle',
@@ -5544,9 +5368,9 @@ void main() {
5544
5368
  _initialProperties$la2 = initialProperties.lassoLineWidth,
5545
5369
  lassoLineWidth = _initialProperties$la2 === void 0 ? DEFAULT_LASSO_LINE_WIDTH : _initialProperties$la2,
5546
5370
  _initialProperties$la3 = initialProperties.lassoMinDelay,
5547
- lassoMinDelay = _initialProperties$la3 === void 0 ? DEFAULT_LASSO_MIN_DELAY : _initialProperties$la3,
5371
+ lassoMinDelay = _initialProperties$la3 === void 0 ? DEFAULT_LASSO_MIN_DELAY$1 : _initialProperties$la3,
5548
5372
  _initialProperties$la4 = initialProperties.lassoMinDist,
5549
- lassoMinDist = _initialProperties$la4 === void 0 ? DEFAULT_LASSO_MIN_DIST : _initialProperties$la4,
5373
+ lassoMinDist = _initialProperties$la4 === void 0 ? DEFAULT_LASSO_MIN_DIST$1 : _initialProperties$la4,
5550
5374
  _initialProperties$la5 = initialProperties.lassoMode,
5551
5375
  lassoMode = _initialProperties$la5 === void 0 ? DEFAULT_LASSO_MODE : _initialProperties$la5,
5552
5376
  _initialProperties$la6 = initialProperties.lassoClearEvent,
@@ -5557,20 +5381,20 @@ void main() {
5557
5381
  lassoInitiatorParentElement = _initialProperties$la8 === void 0 ? document.body : _initialProperties$la8,
5558
5382
  _initialProperties$la9 = initialProperties.lassoLongPressIndicatorParentElement,
5559
5383
  lassoLongPressIndicatorParentElement = _initialProperties$la9 === void 0 ? document.body : _initialProperties$la9,
5560
- _initialProperties$la10 = initialProperties.lassoOnLongPress,
5561
- lassoOnLongPress = _initialProperties$la10 === void 0 ? DEFAULT_LASSO_ON_LONG_PRESS : _initialProperties$la10,
5562
- _initialProperties$la11 = initialProperties.lassoLongPressTime,
5563
- lassoLongPressTime = _initialProperties$la11 === void 0 ? DEFAULT_LASSO_LONG_PRESS_TIME : _initialProperties$la11,
5564
- _initialProperties$la12 = initialProperties.lassoLongPressAfterEffectTime,
5565
- lassoLongPressAfterEffectTime = _initialProperties$la12 === void 0 ? DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME : _initialProperties$la12,
5566
- _initialProperties$la13 = initialProperties.lassoLongPressEffectDelay,
5567
- lassoLongPressEffectDelay = _initialProperties$la13 === void 0 ? DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY : _initialProperties$la13,
5568
- _initialProperties$la14 = initialProperties.lassoLongPressRevertEffectTime,
5569
- lassoLongPressRevertEffectTime = _initialProperties$la14 === void 0 ? DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME : _initialProperties$la14,
5570
- _initialProperties$la15 = initialProperties.lassoType,
5571
- lassoType = _initialProperties$la15 === void 0 ? DEFAULT_LASSO_TYPE : _initialProperties$la15,
5572
- _initialProperties$la16 = initialProperties.lassoBrushSize,
5573
- lassoBrushSize = _initialProperties$la16 === void 0 ? DEFAULT_LASSO_BRUSH_SIZE : _initialProperties$la16,
5384
+ _initialProperties$la0 = initialProperties.lassoOnLongPress,
5385
+ lassoOnLongPress = _initialProperties$la0 === void 0 ? DEFAULT_LASSO_ON_LONG_PRESS : _initialProperties$la0,
5386
+ _initialProperties$la1 = initialProperties.lassoLongPressTime,
5387
+ lassoLongPressTime = _initialProperties$la1 === void 0 ? DEFAULT_LASSO_LONG_PRESS_TIME : _initialProperties$la1,
5388
+ _initialProperties$la10 = initialProperties.lassoLongPressAfterEffectTime,
5389
+ lassoLongPressAfterEffectTime = _initialProperties$la10 === void 0 ? DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME : _initialProperties$la10,
5390
+ _initialProperties$la11 = initialProperties.lassoLongPressEffectDelay,
5391
+ lassoLongPressEffectDelay = _initialProperties$la11 === void 0 ? DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY : _initialProperties$la11,
5392
+ _initialProperties$la12 = initialProperties.lassoLongPressRevertEffectTime,
5393
+ lassoLongPressRevertEffectTime = _initialProperties$la12 === void 0 ? DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME : _initialProperties$la12,
5394
+ _initialProperties$la13 = initialProperties.lassoType,
5395
+ lassoType = _initialProperties$la13 === void 0 ? DEFAULT_LASSO_TYPE$1 : _initialProperties$la13,
5396
+ _initialProperties$la14 = initialProperties.lassoBrushSize,
5397
+ lassoBrushSize = _initialProperties$la14 === void 0 ? DEFAULT_LASSO_BRUSH_SIZE : _initialProperties$la14,
5574
5398
  _initialProperties$ac = initialProperties.actionKeyMap,
5575
5399
  actionKeyMap = _initialProperties$ac === void 0 ? DEFAULT_ACTION_KEY_MAP : _initialProperties$ac,
5576
5400
  _initialProperties$mo = initialProperties.mouseMode,
@@ -5599,26 +5423,26 @@ void main() {
5599
5423
  pointConnectionOpacity = _initialProperties$po8 === void 0 ? DEFAULT_POINT_CONNECTION_OPACITY : _initialProperties$po8,
5600
5424
  _initialProperties$po9 = initialProperties.pointConnectionOpacityBy,
5601
5425
  pointConnectionOpacityBy = _initialProperties$po9 === void 0 ? DEFAULT_POINT_CONNECTION_OPACITY_BY : _initialProperties$po9,
5602
- _initialProperties$po10 = initialProperties.pointConnectionOpacityActive,
5603
- pointConnectionOpacityActive = _initialProperties$po10 === void 0 ? DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE : _initialProperties$po10,
5604
- _initialProperties$po11 = initialProperties.pointConnectionSize,
5605
- pointConnectionSize = _initialProperties$po11 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE : _initialProperties$po11,
5606
- _initialProperties$po12 = initialProperties.pointConnectionSizeActive,
5607
- pointConnectionSizeActive = _initialProperties$po12 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE_ACTIVE : _initialProperties$po12,
5608
- _initialProperties$po13 = initialProperties.pointConnectionSizeBy,
5609
- pointConnectionSizeBy = _initialProperties$po13 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE_BY : _initialProperties$po13,
5610
- _initialProperties$po14 = initialProperties.pointConnectionMaxIntPointsPerSegment,
5611
- pointConnectionMaxIntPointsPerSegment = _initialProperties$po14 === void 0 ? DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT : _initialProperties$po14,
5612
- _initialProperties$po15 = initialProperties.pointConnectionTolerance,
5613
- pointConnectionTolerance = _initialProperties$po15 === void 0 ? DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE : _initialProperties$po15,
5614
- _initialProperties$po16 = initialProperties.pointSize,
5615
- pointSize = _initialProperties$po16 === void 0 ? DEFAULT_POINT_SIZE : _initialProperties$po16,
5616
- _initialProperties$po17 = initialProperties.pointSizeSelected,
5617
- pointSizeSelected = _initialProperties$po17 === void 0 ? DEFAULT_POINT_SIZE_SELECTED : _initialProperties$po17,
5618
- _initialProperties$po18 = initialProperties.pointSizeMouseDetection,
5619
- pointSizeMouseDetection = _initialProperties$po18 === void 0 ? DEFAULT_POINT_SIZE_MOUSE_DETECTION : _initialProperties$po18,
5620
- _initialProperties$po19 = initialProperties.pointOutlineWidth,
5621
- pointOutlineWidth = _initialProperties$po19 === void 0 ? DEFAULT_POINT_OUTLINE_WIDTH : _initialProperties$po19,
5426
+ _initialProperties$po0 = initialProperties.pointConnectionOpacityActive,
5427
+ pointConnectionOpacityActive = _initialProperties$po0 === void 0 ? DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE : _initialProperties$po0,
5428
+ _initialProperties$po1 = initialProperties.pointConnectionSize,
5429
+ pointConnectionSize = _initialProperties$po1 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE : _initialProperties$po1,
5430
+ _initialProperties$po10 = initialProperties.pointConnectionSizeActive,
5431
+ pointConnectionSizeActive = _initialProperties$po10 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE_ACTIVE : _initialProperties$po10,
5432
+ _initialProperties$po11 = initialProperties.pointConnectionSizeBy,
5433
+ pointConnectionSizeBy = _initialProperties$po11 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE_BY : _initialProperties$po11,
5434
+ _initialProperties$po12 = initialProperties.pointConnectionMaxIntPointsPerSegment,
5435
+ pointConnectionMaxIntPointsPerSegment = _initialProperties$po12 === void 0 ? DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT : _initialProperties$po12,
5436
+ _initialProperties$po13 = initialProperties.pointConnectionTolerance,
5437
+ pointConnectionTolerance = _initialProperties$po13 === void 0 ? DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE : _initialProperties$po13,
5438
+ _initialProperties$po14 = initialProperties.pointSize,
5439
+ pointSize = _initialProperties$po14 === void 0 ? DEFAULT_POINT_SIZE : _initialProperties$po14,
5440
+ _initialProperties$po15 = initialProperties.pointSizeSelected,
5441
+ pointSizeSelected = _initialProperties$po15 === void 0 ? DEFAULT_POINT_SIZE_SELECTED : _initialProperties$po15,
5442
+ _initialProperties$po16 = initialProperties.pointSizeMouseDetection,
5443
+ pointSizeMouseDetection = _initialProperties$po16 === void 0 ? DEFAULT_POINT_SIZE_MOUSE_DETECTION : _initialProperties$po16,
5444
+ _initialProperties$po17 = initialProperties.pointOutlineWidth,
5445
+ pointOutlineWidth = _initialProperties$po17 === void 0 ? DEFAULT_POINT_OUTLINE_WIDTH : _initialProperties$po17,
5622
5446
  _initialProperties$op = initialProperties.opacity,
5623
5447
  opacity = _initialProperties$op === void 0 ? AUTO : _initialProperties$op,
5624
5448
  _initialProperties$op2 = initialProperties.opacityBy,
@@ -5631,8 +5455,10 @@ void main() {
5631
5455
  opacityInactiveScale = _initialProperties$op5 === void 0 ? DEFAULT_OPACITY_INACTIVE_SCALE : _initialProperties$op5,
5632
5456
  _initialProperties$si = initialProperties.sizeBy,
5633
5457
  sizeBy = _initialProperties$si === void 0 ? DEFAULT_SIZE_BY : _initialProperties$si,
5634
- _initialProperties$po20 = initialProperties.pointScaleMode,
5635
- pointScaleMode = _initialProperties$po20 === void 0 ? DEFAULT_POINT_SCALE_MODE : _initialProperties$po20,
5458
+ _initialProperties$po18 = initialProperties.pointOrder,
5459
+ pointOrder = _initialProperties$po18 === void 0 ? DEFAULT_POINT_ORDER : _initialProperties$po18,
5460
+ _initialProperties$po19 = initialProperties.pointScaleMode,
5461
+ pointScaleMode = _initialProperties$po19 === void 0 ? DEFAULT_POINT_SCALE_MODE : _initialProperties$po19,
5636
5462
  _initialProperties$he = initialProperties.height,
5637
5463
  height = _initialProperties$he === void 0 ? DEFAULT_HEIGHT : _initialProperties$he,
5638
5464
  _initialProperties$wi = initialProperties.width,
@@ -5702,9 +5528,7 @@ void main() {
5702
5528
  var pointConnections;
5703
5529
  var pointConnectionMap;
5704
5530
  var computingPointConnectionCurves;
5705
- // biome-ignore lint/style/useNamingConvention: HLine stands for HorizontalLine
5706
5531
  var reticleHLine;
5707
- // biome-ignore lint/style/useNamingConvention: VLine stands for VerticalLine
5708
5532
  var reticleVLine;
5709
5533
  var computedPointSizeMouseDetection;
5710
5534
  var lassoInitiatorTimeout;
@@ -5796,6 +5620,8 @@ void main() {
5796
5620
  var normalPointsIndexBuffer; // Buffer holding the indices pointing to the correct texel
5797
5621
  var selectedPointsIndexBuffer; // Used for pointing to the selected texels
5798
5622
  var hoveredPointIndexBuffer; // Used for pointing to the hovered texels
5623
+ var pointOrderIndices = null; // Validated ordered point indices (Int32Array or null)
5624
+ var pointOrderIndex = null; // Float32Array of tex coords in pointOrder sequence
5799
5625
 
5800
5626
  var cameraZoomTargetStart; // Stores the start (i.e., current) camera target for zooming
5801
5627
  var cameraZoomTargetEnd; // Stores the end camera target for zooming
@@ -5816,10 +5642,7 @@ void main() {
5816
5642
  var isPointsDrawn = false;
5817
5643
  var isAnnotationsDrawn = false;
5818
5644
  var isMouseOverCanvasChecked = false;
5819
-
5820
- // biome-ignore lint/style/useNamingConvention: ZDate is not one word
5821
5645
  var valueZDataType = CATEGORICAL;
5822
- // biome-ignore lint/style/useNamingConvention: WDate is not one word
5823
5646
  var valueWDataType = CATEGORICAL;
5824
5647
 
5825
5648
  /** @type{number|undefined} */
@@ -5883,10 +5706,7 @@ void main() {
5883
5706
  }
5884
5707
  return points;
5885
5708
  };
5886
-
5887
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5888
5709
  var getPointsInBBox = function getPointsInBBox(x0, y0, x1, y1) {
5889
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5890
5710
  var pointsInBBox = spatialIndex.range(x0, y0, x1, y1);
5891
5711
  if (isPointsFiltered) {
5892
5712
  return pointsInBBox.filter(function (i) {
@@ -5907,7 +5727,6 @@ void main() {
5907
5727
  var pointSizeNdc = getPointSizeNdc(4);
5908
5728
 
5909
5729
  // Get all points within a close range
5910
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5911
5730
  var pointsInBBox = getPointsInBBox(xNdc - pointSizeNdc, yNdc - pointSizeNdc, xNdc + pointSizeNdc, yNdc + pointSizeNdc);
5912
5731
 
5913
5732
  // Find the closest point
@@ -5949,7 +5768,6 @@ void main() {
5949
5768
  }
5950
5769
 
5951
5770
  // ...to efficiently preselect potentially selected points
5952
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5953
5771
  var pointsInBBox = getPointsInBBox.apply(void 0, _toConsumableArray(bBox));
5954
5772
  // next we test each point in the bounding box if it is in the polygon too
5955
5773
  var pointsInPolygon = [];
@@ -6050,6 +5868,49 @@ void main() {
6050
5868
  }
6051
5869
  };
6052
5870
 
5871
+ /**
5872
+ * Convert vertices from data space to GL space
5873
+ * @param {Array<[number, number]>} vertices - Vertices in data space
5874
+ * @returns {number[] | null} Flat array of GL coordinates or null if scales not defined
5875
+ */
5876
+ var verticesFromDataToGl = function verticesFromDataToGl(vertices) {
5877
+ // Check if xScale/yScale are defined
5878
+ if (!(xScale && yScale)) {
5879
+ // biome-ignore lint/suspicious/noConsole: User warning for missing configuration
5880
+ console.warn('xScale and yScale must be defined for programmatic lasso selection');
5881
+ return null;
5882
+ }
5883
+ var verticesGl = [];
5884
+ var _iterator5 = _createForOfIteratorHelper(vertices),
5885
+ _step5;
5886
+ try {
5887
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
5888
+ var _step5$value = _slicedToArray(_step5.value, 2),
5889
+ x = _step5$value[0],
5890
+ y = _step5$value[1];
5891
+ // Step 1: Data space → normalized [0, 1]
5892
+ var xNorm = (x - xDomainStart) / xDomainSize;
5893
+ var yNorm = (y - yDomainStart) / yDomainSize;
5894
+
5895
+ // Step 2: Normalized [0, 1] → NDC [-1, 1]
5896
+ var xNdc = xNorm * 2 - 1;
5897
+ var yNdc = yNorm * 2 - 1;
5898
+
5899
+ // Step 3: NDC → GL space (camera transform)
5900
+ var _getScatterGlPos3 = getScatterGlPos(xNdc, yNdc),
5901
+ _getScatterGlPos4 = _slicedToArray(_getScatterGlPos3, 2),
5902
+ xGl = _getScatterGlPos4[0],
5903
+ yGl = _getScatterGlPos4[1];
5904
+ verticesGl.push(xGl, yGl);
5905
+ }
5906
+ } catch (err) {
5907
+ _iterator5.e(err);
5908
+ } finally {
5909
+ _iterator5.f();
5910
+ }
5911
+ return verticesGl;
5912
+ };
5913
+
6053
5914
  /**
6054
5915
  * Select and highlight a set of points
6055
5916
  * @param {number | number[]} pointIdxs
@@ -6130,22 +5991,61 @@ void main() {
6130
5991
  setPointConnectionColorState(selectedPoints, 1);
6131
5992
  if (!preventEvent) {
6132
5993
  pubSub.publish('select', {
6133
- points: selectedPoints
5994
+ points: selectedPoints,
5995
+ lassoMode: lassoMode
6134
5996
  });
6135
5997
  }
6136
5998
  draw = true;
6137
5999
  };
6138
6000
 
6001
+ /**
6002
+ * Lasso a certain area and select contained points
6003
+ * @param {[number, number][]} vertices - Lasso vertices in either data space (default) or GL space
6004
+ * @param {import('./types').ScatterplotMethodOptions['lasso']}
6005
+ */
6006
+ var lassoSelect = function lassoSelect(vertices) {
6007
+ var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
6008
+ _ref4$merge = _ref4.merge,
6009
+ merge = _ref4$merge === void 0 ? false : _ref4$merge,
6010
+ _ref4$remove = _ref4.remove,
6011
+ remove = _ref4$remove === void 0 ? false : _ref4$remove,
6012
+ _ref4$isGl = _ref4.isGl,
6013
+ isGl = _ref4$isGl === void 0 ? false : _ref4$isGl;
6014
+ if (!isVertices(vertices)) {
6015
+ throw new Error('Lasso selection requires at least 3 vertices as [x, y] coordinate pairs');
6016
+ }
6017
+ var closedPolygon = verticesToPolygon(vertices);
6018
+ var polygonGl;
6019
+ var polygonGlFlat;
6020
+ if (isGl) {
6021
+ polygonGl = closedPolygon;
6022
+ polygonGlFlat = closedPolygon.flat();
6023
+ } else {
6024
+ polygonGlFlat = verticesFromDataToGl(closedPolygon);
6025
+ if (!polygonGlFlat) {
6026
+ throw new Error('xScale and yScale must be defined to convert lasso vertices from data space to GL space');
6027
+ }
6028
+ polygonGl = [];
6029
+ for (var i = 0; i < polygonGlFlat.length; i += 2) {
6030
+ polygonGl.push([polygonGlFlat[i], polygonGlFlat[i + 1]]);
6031
+ }
6032
+ }
6033
+ lassoEnd(polygonGl, polygonGlFlat, {
6034
+ merge: merge,
6035
+ remove: remove
6036
+ });
6037
+ };
6038
+
6139
6039
  /**
6140
6040
  * @param {number} point
6141
6041
  * @param {import('./types').ScatterplotMethodOptions['hover']} options
6142
6042
  */
6143
6043
  var hover = function hover(point) {
6144
- var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
6145
- _ref4$showReticleOnce = _ref4.showReticleOnce,
6146
- showReticleOnce = _ref4$showReticleOnce === void 0 ? false : _ref4$showReticleOnce,
6147
- _ref4$preventEvent = _ref4.preventEvent,
6148
- preventEvent = _ref4$preventEvent === void 0 ? false : _ref4$preventEvent;
6044
+ var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
6045
+ _ref5$showReticleOnce = _ref5.showReticleOnce,
6046
+ showReticleOnce = _ref5$showReticleOnce === void 0 ? false : _ref5$showReticleOnce,
6047
+ _ref5$preventEvent = _ref5.preventEvent,
6048
+ preventEvent = _ref5$preventEvent === void 0 ? false : _ref5$preventEvent;
6149
6049
  var needsRedraw = false;
6150
6050
  var isFilteredOut = isPointsFiltered && !filteredPointsSet.has(point);
6151
6051
  if (!isFilteredOut && point >= 0 && point < numPoints) {
@@ -6201,13 +6101,13 @@ void main() {
6201
6101
  pubSub.publish('lassoStart');
6202
6102
  };
6203
6103
  var lassoEnd = function lassoEnd(lassoPoints, lassoPointsFlat) {
6204
- var _ref5 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
6205
- _ref5$intersect = _ref5.intersect,
6206
- intersect = _ref5$intersect === void 0 ? false : _ref5$intersect,
6207
- _ref5$merge = _ref5.merge,
6208
- merge = _ref5$merge === void 0 ? false : _ref5$merge,
6209
- _ref5$remove = _ref5.remove,
6210
- remove = _ref5$remove === void 0 ? false : _ref5$remove;
6104
+ var _ref6 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
6105
+ _ref6$intersect = _ref6.intersect,
6106
+ intersect = _ref6$intersect === void 0 ? false : _ref6$intersect,
6107
+ _ref6$merge = _ref6.merge,
6108
+ merge = _ref6$merge === void 0 ? false : _ref6$merge,
6109
+ _ref6$remove = _ref6.remove,
6110
+ remove = _ref6$remove === void 0 ? false : _ref6$remove;
6211
6111
  camera.config({
6212
6112
  isFixed: cameraIsFixed
6213
6113
  });
@@ -6232,10 +6132,10 @@ void main() {
6232
6132
  enableInitiator: lassoInitiator,
6233
6133
  initiatorParentElement: lassoInitiatorParentElement,
6234
6134
  longPressIndicatorParentElement: lassoLongPressIndicatorParentElement,
6235
- pointNorm: function pointNorm(_ref6) {
6236
- var _ref7 = _slicedToArray(_ref6, 2),
6237
- x = _ref7[0],
6238
- y = _ref7[1];
6135
+ pointNorm: function pointNorm(_ref7) {
6136
+ var _ref8 = _slicedToArray(_ref7, 2),
6137
+ x = _ref8[0],
6138
+ y = _ref8[1];
6239
6139
  return getScatterGlPos(getNdcX(x), getNdcY(y));
6240
6140
  },
6241
6141
  minDelay: lassoMinDelay,
@@ -6697,6 +6597,46 @@ void main() {
6697
6597
  var setSizeBy = function setSizeBy(type) {
6698
6598
  sizeBy = getEncodingType(type, DEFAULT_SIZE_BY);
6699
6599
  };
6600
+ var setPointOrder = function setPointOrder(newPointOrder) {
6601
+ if (newPointOrder === null || newPointOrder === undefined) {
6602
+ pointOrder = null;
6603
+ } else if (Array.isArray(newPointOrder) || ArrayBuffer.isView(newPointOrder)) {
6604
+ pointOrder = newPointOrder;
6605
+ } else {
6606
+ return;
6607
+ }
6608
+ if (isPointsDrawn) {
6609
+ computePointOrderIndex();
6610
+ if (isPointsFiltered) {
6611
+ // Re-apply filter respecting the new point order
6612
+ var filteredPointsBuffer = [];
6613
+ if (pointOrderIndices !== null) {
6614
+ for (var i = 0; i < pointOrderIndices.length; i++) {
6615
+ if (filteredPointsSet.has(pointOrderIndices[i])) {
6616
+ filteredPointsBuffer.push.apply(filteredPointsBuffer, indexToStateTexCoord(pointOrderIndices[i]));
6617
+ }
6618
+ }
6619
+ } else {
6620
+ var sortedFiltered = insertionSort(_toConsumableArray(filteredPointsSet));
6621
+ var _iterator6 = _createForOfIteratorHelper(sortedFiltered),
6622
+ _step6;
6623
+ try {
6624
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
6625
+ var idx = _step6.value;
6626
+ filteredPointsBuffer.push.apply(filteredPointsBuffer, indexToStateTexCoord(idx));
6627
+ }
6628
+ } catch (err) {
6629
+ _iterator6.e(err);
6630
+ } finally {
6631
+ _iterator6.f();
6632
+ }
6633
+ }
6634
+ normalPointsIndexBuffer.subdata(filteredPointsBuffer);
6635
+ } else {
6636
+ normalPointsIndexBuffer.subdata(getEffectivePointIndex(numPoints));
6637
+ }
6638
+ }
6639
+ };
6700
6640
  var setPointConnectionColorBy = function setPointConnectionColorBy(type) {
6701
6641
  pointConnectionColorBy = getEncodingType(type, DEFAULT_POINT_CONNECTION_COLOR_BY, {
6702
6642
  allowSegment: true,
@@ -6912,15 +6852,13 @@ void main() {
6912
6852
  var getPointOpacityMax = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : getPointOpacityMaxBase;
6913
6853
  var getPointOpacityScale = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : getPointOpacityScaleBase;
6914
6854
  return renderer.regl({
6915
- frag: renderPointsAsSquares ? FRAGMENT_SHADER$1 : FRAGMENT_SHADER,
6855
+ frag: renderPointsAsSquares ? FRAGMENT_SHADER : FRAGMENT_SHADER$1,
6916
6856
  vert: createVertexShader(globalState),
6917
6857
  blend: {
6918
6858
  enable: !disableAlphaBlending,
6919
6859
  func: {
6920
- // biome-ignore lint/style/useNamingConvention: Regl specific
6921
6860
  srcRGB: 'src alpha',
6922
6861
  srcAlpha: 'one',
6923
- // biome-ignore lint/style/useNamingConvention: Regl specific
6924
6862
  dstRGB: 'one minus src alpha',
6925
6863
  dstAlpha: 'one minus src alpha'
6926
6864
  }
@@ -7036,10 +6974,8 @@ void main() {
7036
6974
  blend: {
7037
6975
  enable: true,
7038
6976
  func: {
7039
- // biome-ignore lint/style/useNamingConvention: Regl specific
7040
6977
  srcRGB: 'src alpha',
7041
6978
  srcAlpha: 'one',
7042
- // biome-ignore lint/style/useNamingConvention: Regl specific
7043
6979
  dstRGB: 'one minus src alpha',
7044
6980
  dstAlpha: 'one minus src alpha'
7045
6981
  }
@@ -7107,6 +7043,41 @@ void main() {
7107
7043
  }
7108
7044
  return index;
7109
7045
  };
7046
+ var computePointOrderIndex = function computePointOrderIndex() {
7047
+ if (pointOrder === null) {
7048
+ pointOrderIndices = null;
7049
+ pointOrderIndex = null;
7050
+ return;
7051
+ }
7052
+ var includedSet = new Set();
7053
+ var orderedIndices = [];
7054
+ for (var i = 0; i < pointOrder.length; i++) {
7055
+ var idx = pointOrder[i];
7056
+ if (Number.isFinite(idx) && idx >= 0 && idx < numPoints && !includedSet.has(idx)) {
7057
+ orderedIndices.push(idx);
7058
+ includedSet.add(idx);
7059
+ }
7060
+ }
7061
+
7062
+ // Append any missing indices in sequential order
7063
+ for (var _i2 = 0; _i2 < numPoints; _i2++) {
7064
+ if (!includedSet.has(_i2)) {
7065
+ orderedIndices.push(_i2);
7066
+ }
7067
+ }
7068
+ pointOrderIndices = orderedIndices;
7069
+ pointOrderIndex = new Float32Array(orderedIndices.length * 2);
7070
+ var j = 0;
7071
+ for (var _i3 = 0; _i3 < orderedIndices.length; _i3++) {
7072
+ var texCoord = indexToStateTexCoord(orderedIndices[_i3]);
7073
+ pointOrderIndex[j] = texCoord[0];
7074
+ pointOrderIndex[j + 1] = texCoord[1];
7075
+ j += 2;
7076
+ }
7077
+ };
7078
+ var getEffectivePointIndex = function getEffectivePointIndex(count) {
7079
+ return pointOrderIndex !== null ? pointOrderIndex : createPointIndex(count);
7080
+ };
7110
7081
  var createStateTexture = function createStateTexture(newPoints) {
7111
7082
  var dataTypes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7112
7083
  var numNewPoints = newPoints.length;
@@ -7185,8 +7156,17 @@ void main() {
7185
7156
  return new Promise(function (resolve) {
7186
7157
  isPointsDrawn = false;
7187
7158
  var preventFilterReset = (options === null || options === void 0 ? void 0 : options.preventFilterReset) && newPoints.length === numPoints;
7159
+ var prevNumPoints = numPoints;
7188
7160
  numPoints = newPoints.length;
7189
7161
  numPointsInView = numPoints;
7162
+
7163
+ // Reset pointOrder when re-drawing with different-length data
7164
+ // (ordering becomes meaningless). Skip on first draw (prevNumPoints === 0).
7165
+ if (prevNumPoints > 0 && numPoints !== prevNumPoints) {
7166
+ pointOrder = null;
7167
+ pointOrderIndices = null;
7168
+ pointOrderIndex = null;
7169
+ }
7190
7170
  if (stateTex) {
7191
7171
  stateTex.destroy();
7192
7172
  }
@@ -7195,10 +7175,11 @@ void main() {
7195
7175
  w: options.wDataType
7196
7176
  });
7197
7177
  if (!preventFilterReset) {
7178
+ computePointOrderIndex();
7198
7179
  normalPointsIndexBuffer({
7199
7180
  usage: 'static',
7200
7181
  type: 'float',
7201
- data: createPointIndex(numPoints)
7182
+ data: getEffectivePointIndex(numPoints)
7202
7183
  });
7203
7184
  }
7204
7185
  createKdbush(options.spatialIndex || newPoints, {
@@ -7244,8 +7225,8 @@ void main() {
7244
7225
  colorIndices[index] = [0];
7245
7226
  var cumLength = 0;
7246
7227
  // Assign the color index based on the cumulative length
7247
- for (var _i2 = 0; _i2 < curve.length / 2 - 1; _i2++) {
7248
- cumLength += segLengths[_i2];
7228
+ for (var _i4 = 0; _i4 < curve.length / 2 - 1; _i4++) {
7229
+ cumLength += segLengths[_i4];
7249
7230
  // The `4` comes from the fact that we have 4 color states:
7250
7231
  // normal, active, hover, and background
7251
7232
  colorIndices[index].push(Math.floor(cumLength / totalLength * maxColorIdx) * 4);
@@ -7262,10 +7243,10 @@ void main() {
7262
7243
  if (colorEncoding) {
7263
7244
  var encodingIdx = getEncodingIdx(colorEncoding);
7264
7245
  var encodingValueToIdx = getEncodingValueToIdx(getEncodingDataType(colorEncoding), pointConnectionColorBy === 'inherit' ? pointColor : pointConnectionColor);
7265
- return pointConnectionMap.reduce(function (colorIndices, _ref8) {
7266
- var _ref9 = _slicedToArray(_ref8, 2),
7267
- index = _ref9[0],
7268
- referencePoint = _ref9[1];
7246
+ return pointConnectionMap.reduce(function (colorIndices, _ref9) {
7247
+ var _ref0 = _slicedToArray(_ref9, 2),
7248
+ index = _ref0[0],
7249
+ referencePoint = _ref0[1];
7269
7250
  // The `4` comes from the fact that we have 4 color states:
7270
7251
  // normal, active, hover, and background
7271
7252
  colorIndices[index] = encodingValueToIdx(referencePoint[encodingIdx]) * 4;
@@ -7281,11 +7262,11 @@ void main() {
7281
7262
  if (maxOpacityIdx < 1) {
7282
7263
  return [];
7283
7264
  }
7284
- return pointConnectionMap.reduce(function (opacities, _ref10) {
7285
- var _ref11 = _slicedToArray(_ref10, 3),
7286
- index = _ref11[0];
7287
- _ref11[1];
7288
- var length = _ref11[2];
7265
+ return pointConnectionMap.reduce(function (opacities, _ref1) {
7266
+ var _ref10 = _slicedToArray(_ref1, 3),
7267
+ index = _ref10[0];
7268
+ _ref10[1];
7269
+ var length = _ref10[2];
7289
7270
  opacities[index] = rangeMap(length, function (i) {
7290
7271
  return pointConnectionOpacity[Math.floor(i / (length - 1) * maxOpacityIdx)];
7291
7272
  });
@@ -7296,10 +7277,10 @@ void main() {
7296
7277
  var encodingIdx = getEncodingIdx(opacityEncoding);
7297
7278
  var encodingRangeMap = pointConnectionOpacityBy === 'inherit' ? opacity : pointConnectionOpacity;
7298
7279
  var encodingValueToIdx = getEncodingValueToIdx(getEncodingDataType(opacityEncoding), encodingRangeMap);
7299
- return pointConnectionMap.reduce(function (opacities, _ref12) {
7300
- var _ref13 = _slicedToArray(_ref12, 2),
7301
- index = _ref13[0],
7302
- referencePoint = _ref13[1];
7280
+ return pointConnectionMap.reduce(function (opacities, _ref11) {
7281
+ var _ref12 = _slicedToArray(_ref11, 2),
7282
+ index = _ref12[0],
7283
+ referencePoint = _ref12[1];
7303
7284
  opacities[index] = encodingRangeMap[encodingValueToIdx(referencePoint[encodingIdx])];
7304
7285
  return opacities;
7305
7286
  }, []);
@@ -7313,11 +7294,11 @@ void main() {
7313
7294
  if (maxSizeIdx < 1) {
7314
7295
  return [];
7315
7296
  }
7316
- return pointConnectionMap.reduce(function (widths, _ref14) {
7317
- var _ref15 = _slicedToArray(_ref14, 3),
7318
- index = _ref15[0];
7319
- _ref15[1];
7320
- var length = _ref15[2];
7297
+ return pointConnectionMap.reduce(function (widths, _ref13) {
7298
+ var _ref14 = _slicedToArray(_ref13, 3),
7299
+ index = _ref14[0];
7300
+ _ref14[1];
7301
+ var length = _ref14[2];
7321
7302
  widths[index] = rangeMap(length, function (i) {
7322
7303
  return pointConnectionSize[Math.floor(i / (length - 1) * maxSizeIdx)];
7323
7304
  });
@@ -7328,10 +7309,10 @@ void main() {
7328
7309
  var encodingIdx = getEncodingIdx(sizeEncoding);
7329
7310
  var encodingRangeMap = pointConnectionSizeBy === 'inherit' ? pointSize : pointConnectionSize;
7330
7311
  var encodingValueToIdx = getEncodingValueToIdx(getEncodingDataType(sizeEncoding), encodingRangeMap);
7331
- return pointConnectionMap.reduce(function (widths, _ref16) {
7332
- var _ref17 = _slicedToArray(_ref16, 2),
7333
- index = _ref17[0],
7334
- referencePoint = _ref17[1];
7312
+ return pointConnectionMap.reduce(function (widths, _ref15) {
7313
+ var _ref16 = _slicedToArray(_ref15, 2),
7314
+ index = _ref16[0],
7315
+ referencePoint = _ref16[1];
7335
7316
  widths[index] = encodingRangeMap[encodingValueToIdx(referencePoint[encodingIdx])];
7336
7317
  return widths;
7337
7318
  }, []);
@@ -7379,12 +7360,12 @@ void main() {
7379
7360
  * @param {import('./types').ScatterplotMethodOptions['filter']}
7380
7361
  */
7381
7362
  var unfilter = function unfilter() {
7382
- var _ref18 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
7383
- _ref18$preventEvent = _ref18.preventEvent,
7384
- preventEvent = _ref18$preventEvent === void 0 ? false : _ref18$preventEvent;
7363
+ var _ref17 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
7364
+ _ref17$preventEvent = _ref17.preventEvent,
7365
+ preventEvent = _ref17$preventEvent === void 0 ? false : _ref17$preventEvent;
7385
7366
  isPointsFiltered = false;
7386
7367
  filteredPointsSet.clear();
7387
- normalPointsIndexBuffer.subdata(createPointIndex(numPoints));
7368
+ normalPointsIndexBuffer.subdata(getEffectivePointIndex(numPoints));
7388
7369
  return new Promise(function (resolve) {
7389
7370
  var finish = function finish() {
7390
7371
  pubSub.subscribe('draw', function () {
@@ -7416,20 +7397,20 @@ void main() {
7416
7397
  * @param {import('./types').ScatterplotMethodOptions['filter']}
7417
7398
  */
7418
7399
  var filter = function filter(pointIdxs) {
7419
- var _ref19 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
7420
- _ref19$preventEvent = _ref19.preventEvent,
7421
- preventEvent = _ref19$preventEvent === void 0 ? false : _ref19$preventEvent;
7400
+ var _ref18 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
7401
+ _ref18$preventEvent = _ref18.preventEvent,
7402
+ preventEvent = _ref18$preventEvent === void 0 ? false : _ref18$preventEvent;
7422
7403
  isPointsFiltered = true;
7423
7404
  filteredPointsSet.clear();
7424
7405
  var pointIdxsArray = Array.isArray(pointIdxs) ? pointIdxs : [pointIdxs];
7425
7406
  var filteredPoints = [];
7426
7407
  var filteredPointsBuffer = [];
7427
7408
  var filteredSelectedPoints = [];
7428
- var _iterator5 = _createForOfIteratorHelper(pointIdxsArray),
7429
- _step5;
7409
+ var _iterator7 = _createForOfIteratorHelper(pointIdxsArray),
7410
+ _step7;
7430
7411
  try {
7431
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
7432
- var pointIdx = _step5.value;
7412
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
7413
+ var pointIdx = _step7.value;
7433
7414
  if (!Number.isFinite(pointIdx) || pointIdx < 0 || pointIdx >= numPoints) {
7434
7415
  // Skip invalid filtered points
7435
7416
  continue;
@@ -7441,24 +7422,35 @@ void main() {
7441
7422
  }
7442
7423
  }
7443
7424
  } catch (err) {
7444
- _iterator5.e(err);
7425
+ _iterator7.e(err);
7445
7426
  } finally {
7446
- _iterator5.f();
7427
+ _iterator7.f();
7428
+ }
7429
+ var orderedFilteredPoints;
7430
+ if (pointOrderIndices !== null) {
7431
+ // Maintain the custom point order within the filtered set
7432
+ orderedFilteredPoints = [];
7433
+ for (var i = 0; i < pointOrderIndices.length; i++) {
7434
+ if (filteredPointsSet.has(pointOrderIndices[i])) {
7435
+ orderedFilteredPoints.push(pointOrderIndices[i]);
7436
+ }
7437
+ }
7438
+ } else {
7439
+ orderedFilteredPoints = insertionSort([].concat(filteredPoints));
7447
7440
  }
7448
- var sortedFilteredPoints = insertionSort([].concat(filteredPoints));
7449
- var _iterator6 = _createForOfIteratorHelper(sortedFilteredPoints),
7450
- _step6;
7441
+ var _iterator8 = _createForOfIteratorHelper(orderedFilteredPoints),
7442
+ _step8;
7451
7443
  try {
7452
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
7453
- var _pointIdx = _step6.value;
7444
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
7445
+ var _pointIdx = _step8.value;
7454
7446
  filteredPointsBuffer.push.apply(filteredPointsBuffer, indexToStateTexCoord(_pointIdx));
7455
7447
  }
7456
7448
 
7457
7449
  // Update the normal points index buffers
7458
7450
  } catch (err) {
7459
- _iterator6.e(err);
7451
+ _iterator8.e(err);
7460
7452
  } finally {
7461
- _iterator6.f();
7453
+ _iterator8.f();
7462
7454
  }
7463
7455
  normalPointsIndexBuffer.subdata(filteredPointsBuffer);
7464
7456
 
@@ -7558,11 +7550,11 @@ void main() {
7558
7550
  clearCachedCamera();
7559
7551
  pubSub.publish('transitionEnd');
7560
7552
  };
7561
- var startTransition = function startTransition(_ref20) {
7562
- var _ref20$duration = _ref20.duration,
7563
- duration = _ref20$duration === void 0 ? 500 : _ref20$duration,
7564
- _ref20$easing = _ref20.easing,
7565
- easing = _ref20$easing === void 0 ? DEFAULT_EASING : _ref20$easing;
7553
+ var startTransition = function startTransition(_ref19) {
7554
+ var _ref19$duration = _ref19.duration,
7555
+ duration = _ref19$duration === void 0 ? 500 : _ref19$duration,
7556
+ _ref19$easing = _ref19.easing,
7557
+ easing = _ref19$easing === void 0 ? DEFAULT_EASING : _ref19$easing;
7566
7558
  if (isTransitioning) {
7567
7559
  pubSub.publish('transitionEnd');
7568
7560
  }
@@ -7752,11 +7744,11 @@ void main() {
7752
7744
  newColorIndices.push(_idx);
7753
7745
  }
7754
7746
  };
7755
- var _iterator7 = _createForOfIteratorHelper(newAnnotations),
7756
- _step7;
7747
+ var _iterator9 = _createForOfIteratorHelper(newAnnotations),
7748
+ _step9;
7757
7749
  try {
7758
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
7759
- var annotation = _step7.value;
7750
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
7751
+ var annotation = _step9.value;
7760
7752
  if (isHorizontalLine(annotation)) {
7761
7753
  var _annotation$x, _annotation$x2;
7762
7754
  newPoints.push([(_annotation$x = annotation.x1) !== null && _annotation$x !== void 0 ? _annotation$x : -annotationHVLineLimit, annotation.y, (_annotation$x2 = annotation.x2) !== null && _annotation$x2 !== void 0 ? _annotation$x2 : annotationHVLineLimit, annotation.y]);
@@ -7779,21 +7771,21 @@ void main() {
7779
7771
  addColorAndWidth(annotation);
7780
7772
  continue;
7781
7773
  }
7782
- if (isPolygon(annotation)) {
7774
+ if (isPolygonAnnotation(annotation)) {
7783
7775
  newPoints.push(annotation.vertices.flatMap(identity));
7784
7776
  addColorAndWidth(annotation);
7785
7777
  }
7786
7778
  }
7787
7779
  } catch (err) {
7788
- _iterator7.e(err);
7780
+ _iterator9.e(err);
7789
7781
  } finally {
7790
- _iterator7.f();
7782
+ _iterator9.f();
7791
7783
  }
7792
7784
  annotations.setStyle({
7793
7785
  color: Array.from(newColors.values()).sort(function (a, b) {
7794
7786
  return a.idx > b.idx ? 1 : -1;
7795
- }).map(function (_ref21) {
7796
- var color = _ref21.color;
7787
+ }).map(function (_ref20) {
7788
+ var color = _ref20.color;
7797
7789
  return color;
7798
7790
  })
7799
7791
  });
@@ -7825,17 +7817,16 @@ void main() {
7825
7817
  * @param {number[]} pointIdxs - A list of point indices
7826
7818
  * @returns {import('./types').Rect} The bounding box
7827
7819
  */
7828
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
7829
7820
  var getBBoxOfPoints = function getBBoxOfPoints(pointIdxs) {
7830
7821
  var xMin = Number.POSITIVE_INFINITY;
7831
7822
  var xMax = Number.NEGATIVE_INFINITY;
7832
7823
  var yMin = Number.POSITIVE_INFINITY;
7833
7824
  var yMax = Number.NEGATIVE_INFINITY;
7834
- var _iterator8 = _createForOfIteratorHelper(pointIdxs),
7835
- _step8;
7825
+ var _iterator0 = _createForOfIteratorHelper(pointIdxs),
7826
+ _step0;
7836
7827
  try {
7837
- for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
7838
- var pointIdx = _step8.value;
7828
+ for (_iterator0.s(); !(_step0 = _iterator0.n()).done;) {
7829
+ var pointIdx = _step0.value;
7839
7830
  var _points$pointIdx2 = _slicedToArray(points[pointIdx], 2),
7840
7831
  x = _points$pointIdx2[0],
7841
7832
  y = _points$pointIdx2[1];
@@ -7845,9 +7836,9 @@ void main() {
7845
7836
  yMax = Math.max(yMax, y);
7846
7837
  }
7847
7838
  } catch (err) {
7848
- _iterator8.e(err);
7839
+ _iterator0.e(err);
7849
7840
  } finally {
7850
- _iterator8.f();
7841
+ _iterator0.f();
7851
7842
  }
7852
7843
  return {
7853
7844
  x: xMin,
@@ -7871,7 +7862,6 @@ void main() {
7871
7862
  // Vertical field of view
7872
7863
  // The Arc Tangent is based on the original camera position. Otherwise
7873
7864
  // we would have to do `Math.atan(1 / camera.view[5])`
7874
- // biome-ignore lint/style/useNamingConvention: FOV stands for field of view
7875
7865
  var vFOV = 2 * Math.atan(1);
7876
7866
  var aspectRatio = viewAspectRatio / dataAspectRatio;
7877
7867
  var distance = rect.height * aspectRatio >= rect.width ?
@@ -8186,10 +8176,10 @@ void main() {
8186
8176
  }
8187
8177
  };
8188
8178
  var setActionKeyMap = function setActionKeyMap(newActionKeyMap) {
8189
- actionKeyMap = Object.entries(newActionKeyMap).reduce(function (map, _ref22) {
8190
- var _ref23 = _slicedToArray(_ref22, 2),
8191
- action = _ref23[0],
8192
- key = _ref23[1];
8179
+ actionKeyMap = Object.entries(newActionKeyMap).reduce(function (map, _ref21) {
8180
+ var _ref22 = _slicedToArray(_ref21, 2),
8181
+ action = _ref22[0],
8182
+ key = _ref22[1];
8193
8183
  if (KEYS.includes(key) && KEY_ACTIONS.includes(action)) {
8194
8184
  map[action] = key;
8195
8185
  }
@@ -8221,8 +8211,6 @@ void main() {
8221
8211
  color: reticleColor
8222
8212
  });
8223
8213
  };
8224
-
8225
- // biome-ignore lint/style/useNamingConvention: XScale are two words
8226
8214
  var setXScale = function setXScale(newXScale) {
8227
8215
  if (!newXScale) {
8228
8216
  return;
@@ -8233,8 +8221,6 @@ void main() {
8233
8221
  xScale.range([0, currentWidth]);
8234
8222
  updateScales();
8235
8223
  };
8236
-
8237
- // biome-ignore lint/style/useNamingConvention: YScale are two words
8238
8224
  var setYScale = function setYScale(newYScale) {
8239
8225
  if (!newYScale) {
8240
8226
  return;
@@ -8375,8 +8361,6 @@ void main() {
8375
8361
  var setAnnotationLineWidth = function setAnnotationLineWidth(newAnnotationLineWidth) {
8376
8362
  annotationLineWidth = +newAnnotationLineWidth;
8377
8363
  };
8378
-
8379
- // biome-ignore lint/style/useNamingConvention: HVLine stands for horizontal vertical line
8380
8364
  var setAnnotationHVLineLimit = function setAnnotationHVLineLimit(newAnnotationHVLineLimit) {
8381
8365
  annotationHVLineLimit = +newAnnotationHVLineLimit;
8382
8366
  };
@@ -8434,6 +8418,9 @@ void main() {
8434
8418
  if (property === 'sizeBy') {
8435
8419
  return sizeBy;
8436
8420
  }
8421
+ if (property === 'pointOrder') {
8422
+ return pointOrder !== null ? _toConsumableArray(pointOrder) : null;
8423
+ }
8437
8424
  if (property === 'deselectOnDblClick') {
8438
8425
  return deselectOnDblClick;
8439
8426
  }
@@ -8716,6 +8703,9 @@ void main() {
8716
8703
  if (properties.sizeBy !== undefined) {
8717
8704
  setSizeBy(properties.sizeBy);
8718
8705
  }
8706
+ if (properties.pointOrder !== undefined) {
8707
+ setPointOrder(properties.pointOrder);
8708
+ }
8719
8709
  if (properties.opacity !== undefined) {
8720
8710
  setOpacity(properties.opacity);
8721
8711
  }
@@ -8899,9 +8889,9 @@ void main() {
8899
8889
  * @param {import('./types').ScatterplotMethodOptions['preventEvent']} options
8900
8890
  */
8901
8891
  var view = function view(cameraView) {
8902
- var _ref24 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
8903
- _ref24$preventEvent = _ref24.preventEvent,
8904
- preventEvent = _ref24$preventEvent === void 0 ? false : _ref24$preventEvent;
8892
+ var _ref23 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
8893
+ _ref23$preventEvent = _ref23.preventEvent,
8894
+ preventEvent = _ref23$preventEvent === void 0 ? false : _ref23$preventEvent;
8905
8895
  setCameraView(cameraView);
8906
8896
  draw = true;
8907
8897
  preventEventView = preventEvent;
@@ -8929,9 +8919,9 @@ void main() {
8929
8919
  * @param {import('./types').ScatterplotMethodOptions['preventEvent']} options
8930
8920
  */
8931
8921
  var reset = function reset() {
8932
- var _ref25 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
8933
- _ref25$preventEvent = _ref25.preventEvent,
8934
- preventEvent = _ref25$preventEvent === void 0 ? false : _ref25$preventEvent;
8922
+ var _ref24 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
8923
+ _ref24$preventEvent = _ref24.preventEvent,
8924
+ preventEvent = _ref24$preventEvent === void 0 ? false : _ref24$preventEvent;
8935
8925
  initCamera();
8936
8926
  updateScales();
8937
8927
  if (preventEvent) {
@@ -8944,8 +8934,8 @@ void main() {
8944
8934
  yScale: yScale
8945
8935
  });
8946
8936
  };
8947
- var keyUpHandler = function keyUpHandler(_ref26) {
8948
- var key = _ref26.key;
8937
+ var keyUpHandler = function keyUpHandler(_ref25) {
8938
+ var key = _ref25.key;
8949
8939
  switch (key) {
8950
8940
  case 'Escape':
8951
8941
  {
@@ -9018,10 +9008,10 @@ void main() {
9018
9008
  * @returns {Promise<ImageData>}
9019
9009
  */
9020
9010
  var exportFnAdvanced = /*#__PURE__*/function () {
9021
- var _ref27 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(options) {
9011
+ var _ref26 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(options) {
9022
9012
  var dpr, currPointSize, currWidth, currHeight, currRendererWidth, currRendererHeight, currPixelAligned, currAntiAliasing, scale, newPointSize, newWidth, newHeight, imageData;
9023
- return _regeneratorRuntime().wrap(function _callee$(_context) {
9024
- while (1) switch (_context.prev = _context.next) {
9013
+ return _regenerator().w(function (_context) {
9014
+ while (1) switch (_context.n) {
9025
9015
  case 0:
9026
9016
  canvas.style.userSelect = 'none';
9027
9017
  dpr = window.devicePixelRatio;
@@ -9045,12 +9035,12 @@ void main() {
9045
9035
  setAntiAliasing((options === null || options === void 0 ? void 0 : options.antiAliasing) || antiAliasing);
9046
9036
  renderer.resize(width, height);
9047
9037
  renderer.refresh();
9048
- _context.next = 22;
9038
+ _context.n = 1;
9049
9039
  return new Promise(function (resolve) {
9050
9040
  pubSub.subscribe('draw', resolve, 1);
9051
9041
  redraw();
9052
9042
  });
9053
- case 22:
9043
+ case 1:
9054
9044
  imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
9055
9045
  renderer.resize(currRendererWidth, currRendererHeight);
9056
9046
  renderer.refresh();
@@ -9059,22 +9049,19 @@ void main() {
9059
9049
  setHeight(currHeight);
9060
9050
  setPixelAligned(currPixelAligned);
9061
9051
  setAntiAliasing(currAntiAliasing);
9062
- _context.next = 32;
9052
+ _context.n = 2;
9063
9053
  return new Promise(function (resolve) {
9064
9054
  pubSub.subscribe('draw', resolve, 1);
9065
9055
  redraw();
9066
9056
  });
9067
- case 32:
9057
+ case 2:
9068
9058
  canvas.style.userSelect = null;
9069
- return _context.abrupt("return", imageData);
9070
- case 34:
9071
- case "end":
9072
- return _context.stop();
9059
+ return _context.a(2, imageData);
9073
9060
  }
9074
9061
  }, _callee);
9075
9062
  }));
9076
9063
  return function exportFnAdvanced(_x) {
9077
- return _ref27.apply(this, arguments);
9064
+ return _ref26.apply(this, arguments);
9078
9065
  };
9079
9066
  }();
9080
9067
 
@@ -9312,6 +9299,9 @@ void main() {
9312
9299
  };
9313
9300
  init();
9314
9301
  return {
9302
+ attachSpatialIndex: function attachSpatialIndex(buffer) {
9303
+ spatialIndex = kdbushFrom(buffer);
9304
+ },
9315
9305
  /**
9316
9306
  * Get whether the browser supports all necessary WebGL features
9317
9307
  * @return {boolean} If `true` the browser supports all necessary WebGL features
@@ -9335,6 +9325,7 @@ void main() {
9335
9325
  get: get,
9336
9326
  getScreenPosition: getScreenPosition,
9337
9327
  hover: hover,
9328
+ lassoSelect: lassoSelect,
9338
9329
  redraw: redraw,
9339
9330
  refresh: renderer.refresh,
9340
9331
  reset: withDraw(reset),