@hema-to/regl-scatterplot 1.14.1-hemato.3 → 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,990 +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
- var width = customWidth == null ? window.innerWidth : customWidth;
4874
- var height = customHeight == null ? window.innerHeight : customHeight;
4875
- canvas.width = width * window.devicePixelRatio;
4876
- canvas.height = height * window.devicePixelRatio;
4877
- fboRes[0] = canvas.width;
4878
- fboRes[1] = canvas.height;
4879
- fbo.resize.apply(fbo, fboRes);
4880
- };
4881
- var resizeHandler = function resizeHandler() {
4882
- resize();
4883
- };
4884
- if (!options.canvas) {
4885
- window.addEventListener('resize', resizeHandler);
4886
- window.addEventListener('orientationchange', resizeHandler);
4887
- 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();
4888
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);
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
+ });
4889
4834
 
4890
4835
  /**
4891
- * 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
4892
4839
  */
4893
- var destroy = function destroy() {
4894
- isDestroyed = true;
4895
- window.removeEventListener('resize', resizeHandler);
4896
- window.removeEventListener('orientationchange', resizeHandler);
4897
- frame.cancel();
4898
- canvas = undefined;
4899
- regl.destroy();
4900
- regl = undefined;
4901
- };
4902
- return {
4903
- /**
4904
- * Get the associated canvas element
4905
- * @return {HTMLCanvasElement} The associated canvas element
4906
- */
4907
- get canvas() {
4908
- return canvas;
4909
- },
4910
- /**
4911
- * Get the associated Regl instance
4912
- * @return {import('regl').Regl} The associated Regl instance
4913
- */
4914
- get regl() {
4915
- return regl;
4916
- },
4917
- /**
4918
- * Get the gamma value
4919
- * @return {number} The gamma value
4920
- */
4921
- get gamma() {
4922
- return _gamma;
4923
- },
4924
- /**
4925
- * Set gamma to a new value
4926
- * @param {number} newGamma - The new gamma value
4927
- */
4928
- set gamma(newGamma) {
4929
- _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]
4930
4845
  },
4931
- /**
4932
- * Get whether the browser supports all necessary WebGL features
4933
- * @return {boolean} If `true` the browser supports all necessary WebGL features
4934
- */
4935
- get isSupported() {
4936
- 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
+ }
4937
4856
  },
4938
- /**
4939
- * Get whether the renderer (and its Regl instance) is destroyed
4940
- * @return {boolean} If `true` the renderer is destroyed
4941
- */
4942
- get isDestroyed() {
4943
- return isDestroyed;
4857
+ count: 3,
4858
+ depth: {
4859
+ enable: false
4944
4860
  },
4945
- render: render,
4946
- resize: resize,
4947
- onFrame: onFrame,
4948
- refresh: refresh,
4949
- destroy: destroy
4950
- };
4951
- };
4952
-
4953
- const FRAGMENT_SHADER$2 = `
4954
- precision mediump float;
4955
-
4956
- uniform sampler2D texture;
4957
-
4958
- varying vec2 uv;
4959
-
4960
- void main () {
4961
- gl_FragColor = texture2D(texture, uv);
4962
- }
4963
- `;
4964
-
4965
- const VERTEX_SHADER = `
4966
- precision mediump float;
4967
-
4968
- uniform mat4 modelViewProjection;
4969
-
4970
- attribute vec2 position;
4971
-
4972
- varying vec2 uv;
4973
-
4974
- void main () {
4975
- uv = position;
4976
- gl_Position = modelViewProjection * vec4(-1.0 + 2.0 * uv.x, 1.0 - 2.0 * uv.y, 0, 1);
4977
- }
4978
- `;
4979
-
4980
- const FRAGMENT_SHADER$1 = `precision highp float;
4981
-
4982
- varying vec4 color;
4983
-
4984
- void main() {
4985
- gl_FragColor = color;
4986
- }
4987
- `;
4988
-
4989
- const SHADER$1 = `precision highp float;
4990
-
4991
- uniform sampler2D startStateTex;
4992
- uniform sampler2D endStateTex;
4993
- uniform float t;
4994
-
4995
- varying vec2 particleTextureIndex;
4996
-
4997
- void main() {
4998
- // Interpolate x, y, and value
4999
- vec3 start = texture2D(startStateTex, particleTextureIndex).xyw;
5000
- vec3 end = texture2D(endStateTex, particleTextureIndex).xyw;
5001
- vec3 curr = start * (1.0 - t) + end * t;
5002
-
5003
- // The category cannot be interpolated
5004
- float endCategory = texture2D(endStateTex, particleTextureIndex).z;
5005
-
5006
- gl_FragColor = vec4(curr.xy, endCategory, curr.z);
5007
- }`;
5008
-
5009
- const SHADER = `precision highp float;
5010
-
5011
- attribute vec2 position;
5012
- varying vec2 particleTextureIndex;
5013
-
5014
- void main() {
5015
- // map normalized device coords to texture coords
5016
- particleTextureIndex = 0.5 * (1.0 + position);
5017
-
5018
- gl_Position = vec4(position, 0, 1);
5019
- }`;
5020
-
5021
- const FRAGMENT_SHADER = `
5022
- precision highp float;
5023
-
5024
- uniform float antiAliasing;
5025
-
5026
- varying vec4 color;
5027
- varying float finalPointSize;
5028
-
5029
- float linearstep(float edge0, float edge1, float x) {
5030
- return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
5031
- }
5032
-
5033
- void main() {
5034
- vec2 c = gl_PointCoord * 2.0 - 1.0;
5035
- float sdf = length(c) * finalPointSize;
5036
- float alpha = linearstep(finalPointSize + antiAliasing, finalPointSize - antiAliasing, sdf);
5037
-
5038
- gl_FragColor = vec4(color.rgb, alpha * color.a);
5039
- }
5040
- `;
5041
-
5042
- const createVertexShader = (globalState) => `
5043
- precision highp float;
5044
-
5045
- uniform sampler2D colorTex;
5046
- uniform float colorTexRes;
5047
- uniform float colorTexEps;
5048
- uniform sampler2D stateTex;
5049
- uniform float stateTexRes;
5050
- uniform float stateTexEps;
5051
- uniform float devicePixelRatio;
5052
- uniform sampler2D encodingTex;
5053
- uniform float encodingTexRes;
5054
- uniform float encodingTexEps;
5055
- uniform float pointSizeExtra;
5056
- uniform float pointOpacityMax;
5057
- uniform float pointOpacityScale;
5058
- uniform float numPoints;
5059
- uniform float globalState;
5060
- uniform float isColoredByZ;
5061
- uniform float isColoredByW;
5062
- uniform float isOpacityByZ;
5063
- uniform float isOpacityByW;
5064
- uniform float isOpacityByDensity;
5065
- uniform float isSizedByZ;
5066
- uniform float isSizedByW;
5067
- uniform float isPixelAligned;
5068
- uniform float colorMultiplicator;
5069
- uniform float opacityMultiplicator;
5070
- uniform float opacityDensity;
5071
- uniform float sizeMultiplicator;
5072
- uniform float numColorStates;
5073
- uniform float pointScale;
5074
- uniform float drawingBufferWidth;
5075
- uniform float drawingBufferHeight;
5076
- uniform mat4 modelViewProjection;
5077
-
5078
- attribute vec2 stateIndex;
5079
-
5080
- varying vec4 color;
5081
- varying float finalPointSize;
5082
-
5083
- void main() {
5084
- vec4 state = texture2D(stateTex, stateIndex);
5085
-
5086
- if (isPixelAligned < 0.5) {
5087
- gl_Position = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
5088
- } else {
5089
- vec4 clipSpacePosition = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
5090
- vec2 ndcPosition = clipSpacePosition.xy / clipSpacePosition.w;
5091
- vec2 pixelPos = 0.5 * (ndcPosition + 1.0) * vec2(drawingBufferWidth, drawingBufferHeight);
5092
- pixelPos = floor(pixelPos + 0.5); // Snap to nearest pixel
5093
- vec2 snappedPosition = (pixelPos / vec2(drawingBufferWidth, drawingBufferHeight)) * 2.0 - 1.0;
5094
- gl_Position = vec4(snappedPosition, 0.0, 1.0);
5095
- }
5096
-
5097
-
5098
- // Determine color index
5099
- float colorIndexZ = isColoredByZ * floor(state.z * colorMultiplicator);
5100
- float colorIndexW = isColoredByW * floor(state.w * colorMultiplicator);
5101
-
5102
- // Multiply by the number of color states per color
5103
- // I.e., normal, active, hover, background, etc.
5104
- float colorIndex = (colorIndexZ + colorIndexW) * numColorStates;
5105
-
5106
- // Half a "pixel" or "texel" in texture coordinates
5107
- float colorLinearIndex = colorIndex + globalState;
5108
-
5109
- // Need to add cEps here to avoid floating point issue that can lead to
5110
- // dramatic changes in which color is loaded as floor(3/2.9999) = 1 but
5111
- // floor(3/3.0001) = 0!
5112
- float colorRowIndex = floor((colorLinearIndex + colorTexEps) / colorTexRes);
5113
-
5114
- vec2 colorTexIndex = vec2(
5115
- (colorLinearIndex / colorTexRes) - colorRowIndex + colorTexEps,
5116
- colorRowIndex / colorTexRes + colorTexEps
5117
- );
5118
-
5119
- color = texture2D(colorTex, colorTexIndex);
5120
-
5121
- // Retrieve point size
5122
- float pointSizeIndexZ = isSizedByZ * floor(state.z * sizeMultiplicator);
5123
- float pointSizeIndexW = isSizedByW * floor(state.w * sizeMultiplicator);
5124
- 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
+ });
5125
4871
 
5126
- float pointSizeRowIndex = floor((pointSizeIndex + encodingTexEps) / encodingTexRes);
5127
- vec2 pointSizeTexIndex = vec2(
5128
- (pointSizeIndex / encodingTexRes) - pointSizeRowIndex + encodingTexEps,
5129
- pointSizeRowIndex / encodingTexRes + encodingTexEps
5130
- );
5131
- 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
+ };
5132
4880
 
5133
- // Retrieve opacity
5134
- ${
5135
- (() => {
5136
- // Drawing the inner border of selected points
5137
- 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
+ };
5138
4895
 
5139
- // Draw points with opacity encoding or dynamic opacity
5140
- return `
5141
- if (isOpacityByDensity < 0.5) {
5142
- float opacityIndexZ = isOpacityByZ * floor(state.z * opacityMultiplicator);
5143
- float opacityIndexW = isOpacityByW * floor(state.w * opacityMultiplicator);
5144
- 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();
5145
4906
 
5146
- float opacityRowIndex = floor((opacityIndex + encodingTexEps) / encodingTexRes);
5147
- vec2 opacityTexIndex = vec2(
5148
- (opacityIndex / encodingTexRes) - opacityRowIndex + encodingTexEps,
5149
- opacityRowIndex / encodingTexRes + encodingTexEps
5150
- );
5151
- color.a = texture2D(encodingTex, opacityTexIndex)[${1 + globalState}];
5152
- } else {
5153
- color.a = min(1.0, opacityDensity + globalState);
5154
- }
5155
- `;
5156
- })()
5157
- }
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
+ }
5158
4942
 
5159
- color.a = min(pointOpacityMax, color.a) * pointOpacityScale;
5160
- finalPointSize = (pointSize * pointScale) + pointSizeExtra;
5161
- gl_PointSize = finalPointSize;
5162
- }
5163
- `;
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
+ };
5164
5005
 
5165
5006
  /* eslint-env worker */
5166
5007
  /* eslint no-restricted-globals: 1 */
@@ -5256,7 +5097,6 @@ void main() {
5256
5097
  * @param {[type]} simplified [description]
5257
5098
  * @return {[type]} [description]
5258
5099
  */
5259
- // biome-ignore lint/style/useNamingConvention: DP stands for Douglas Peucker
5260
5100
  var _simplifyDPStep = function simplifyDPStep(points, first, last, tolerance, simplified) {
5261
5101
  var maxDist = tolerance;
5262
5102
  var index;
@@ -5351,7 +5191,6 @@ void main() {
5351
5191
  var groupPoints = function groupPoints(points) {
5352
5192
  var groupedPoints = {};
5353
5193
  var isOrdered = !Number.isNaN(+points[0][5]);
5354
- // biome-ignore lint/complexity/noForEach: somehow for .. of does not work in a worker
5355
5194
  points.forEach(function (point) {
5356
5195
  var segId = point[4];
5357
5196
  if (!groupedPoints[segId]) {
@@ -5365,7 +5204,6 @@ void main() {
5365
5204
  });
5366
5205
 
5367
5206
  // The filtering ensures that non-existing array entries are removed
5368
- // biome-ignore lint/complexity/noForEach: somehow for .. of does not work in a worker
5369
5207
  Object.entries(groupedPoints).forEach(function (idPoints) {
5370
5208
  groupedPoints[idPoints[0]] = idPoints[1].filter(function (v) {
5371
5209
  return v;
@@ -5417,8 +5255,6 @@ void main() {
5417
5255
  });
5418
5256
  };
5419
5257
 
5420
- var version = "1.14.1-hemato.3";
5421
-
5422
5258
  var deprecations = {
5423
5259
  showRecticle: {
5424
5260
  replacement: 'showReticle',
@@ -5532,9 +5368,9 @@ void main() {
5532
5368
  _initialProperties$la2 = initialProperties.lassoLineWidth,
5533
5369
  lassoLineWidth = _initialProperties$la2 === void 0 ? DEFAULT_LASSO_LINE_WIDTH : _initialProperties$la2,
5534
5370
  _initialProperties$la3 = initialProperties.lassoMinDelay,
5535
- lassoMinDelay = _initialProperties$la3 === void 0 ? DEFAULT_LASSO_MIN_DELAY : _initialProperties$la3,
5371
+ lassoMinDelay = _initialProperties$la3 === void 0 ? DEFAULT_LASSO_MIN_DELAY$1 : _initialProperties$la3,
5536
5372
  _initialProperties$la4 = initialProperties.lassoMinDist,
5537
- lassoMinDist = _initialProperties$la4 === void 0 ? DEFAULT_LASSO_MIN_DIST : _initialProperties$la4,
5373
+ lassoMinDist = _initialProperties$la4 === void 0 ? DEFAULT_LASSO_MIN_DIST$1 : _initialProperties$la4,
5538
5374
  _initialProperties$la5 = initialProperties.lassoMode,
5539
5375
  lassoMode = _initialProperties$la5 === void 0 ? DEFAULT_LASSO_MODE : _initialProperties$la5,
5540
5376
  _initialProperties$la6 = initialProperties.lassoClearEvent,
@@ -5545,20 +5381,20 @@ void main() {
5545
5381
  lassoInitiatorParentElement = _initialProperties$la8 === void 0 ? document.body : _initialProperties$la8,
5546
5382
  _initialProperties$la9 = initialProperties.lassoLongPressIndicatorParentElement,
5547
5383
  lassoLongPressIndicatorParentElement = _initialProperties$la9 === void 0 ? document.body : _initialProperties$la9,
5548
- _initialProperties$la10 = initialProperties.lassoOnLongPress,
5549
- lassoOnLongPress = _initialProperties$la10 === void 0 ? DEFAULT_LASSO_ON_LONG_PRESS : _initialProperties$la10,
5550
- _initialProperties$la11 = initialProperties.lassoLongPressTime,
5551
- lassoLongPressTime = _initialProperties$la11 === void 0 ? DEFAULT_LASSO_LONG_PRESS_TIME : _initialProperties$la11,
5552
- _initialProperties$la12 = initialProperties.lassoLongPressAfterEffectTime,
5553
- lassoLongPressAfterEffectTime = _initialProperties$la12 === void 0 ? DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME : _initialProperties$la12,
5554
- _initialProperties$la13 = initialProperties.lassoLongPressEffectDelay,
5555
- lassoLongPressEffectDelay = _initialProperties$la13 === void 0 ? DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY : _initialProperties$la13,
5556
- _initialProperties$la14 = initialProperties.lassoLongPressRevertEffectTime,
5557
- lassoLongPressRevertEffectTime = _initialProperties$la14 === void 0 ? DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME : _initialProperties$la14,
5558
- _initialProperties$la15 = initialProperties.lassoType,
5559
- lassoType = _initialProperties$la15 === void 0 ? DEFAULT_LASSO_TYPE : _initialProperties$la15,
5560
- _initialProperties$la16 = initialProperties.lassoBrushSize,
5561
- 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,
5562
5398
  _initialProperties$ac = initialProperties.actionKeyMap,
5563
5399
  actionKeyMap = _initialProperties$ac === void 0 ? DEFAULT_ACTION_KEY_MAP : _initialProperties$ac,
5564
5400
  _initialProperties$mo = initialProperties.mouseMode,
@@ -5587,26 +5423,26 @@ void main() {
5587
5423
  pointConnectionOpacity = _initialProperties$po8 === void 0 ? DEFAULT_POINT_CONNECTION_OPACITY : _initialProperties$po8,
5588
5424
  _initialProperties$po9 = initialProperties.pointConnectionOpacityBy,
5589
5425
  pointConnectionOpacityBy = _initialProperties$po9 === void 0 ? DEFAULT_POINT_CONNECTION_OPACITY_BY : _initialProperties$po9,
5590
- _initialProperties$po10 = initialProperties.pointConnectionOpacityActive,
5591
- pointConnectionOpacityActive = _initialProperties$po10 === void 0 ? DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE : _initialProperties$po10,
5592
- _initialProperties$po11 = initialProperties.pointConnectionSize,
5593
- pointConnectionSize = _initialProperties$po11 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE : _initialProperties$po11,
5594
- _initialProperties$po12 = initialProperties.pointConnectionSizeActive,
5595
- pointConnectionSizeActive = _initialProperties$po12 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE_ACTIVE : _initialProperties$po12,
5596
- _initialProperties$po13 = initialProperties.pointConnectionSizeBy,
5597
- pointConnectionSizeBy = _initialProperties$po13 === void 0 ? DEFAULT_POINT_CONNECTION_SIZE_BY : _initialProperties$po13,
5598
- _initialProperties$po14 = initialProperties.pointConnectionMaxIntPointsPerSegment,
5599
- pointConnectionMaxIntPointsPerSegment = _initialProperties$po14 === void 0 ? DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT : _initialProperties$po14,
5600
- _initialProperties$po15 = initialProperties.pointConnectionTolerance,
5601
- pointConnectionTolerance = _initialProperties$po15 === void 0 ? DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE : _initialProperties$po15,
5602
- _initialProperties$po16 = initialProperties.pointSize,
5603
- pointSize = _initialProperties$po16 === void 0 ? DEFAULT_POINT_SIZE : _initialProperties$po16,
5604
- _initialProperties$po17 = initialProperties.pointSizeSelected,
5605
- pointSizeSelected = _initialProperties$po17 === void 0 ? DEFAULT_POINT_SIZE_SELECTED : _initialProperties$po17,
5606
- _initialProperties$po18 = initialProperties.pointSizeMouseDetection,
5607
- pointSizeMouseDetection = _initialProperties$po18 === void 0 ? DEFAULT_POINT_SIZE_MOUSE_DETECTION : _initialProperties$po18,
5608
- _initialProperties$po19 = initialProperties.pointOutlineWidth,
5609
- 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,
5610
5446
  _initialProperties$op = initialProperties.opacity,
5611
5447
  opacity = _initialProperties$op === void 0 ? AUTO : _initialProperties$op,
5612
5448
  _initialProperties$op2 = initialProperties.opacityBy,
@@ -5619,8 +5455,10 @@ void main() {
5619
5455
  opacityInactiveScale = _initialProperties$op5 === void 0 ? DEFAULT_OPACITY_INACTIVE_SCALE : _initialProperties$op5,
5620
5456
  _initialProperties$si = initialProperties.sizeBy,
5621
5457
  sizeBy = _initialProperties$si === void 0 ? DEFAULT_SIZE_BY : _initialProperties$si,
5622
- _initialProperties$po20 = initialProperties.pointScaleMode,
5623
- 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,
5624
5462
  _initialProperties$he = initialProperties.height,
5625
5463
  height = _initialProperties$he === void 0 ? DEFAULT_HEIGHT : _initialProperties$he,
5626
5464
  _initialProperties$wi = initialProperties.width,
@@ -5690,9 +5528,7 @@ void main() {
5690
5528
  var pointConnections;
5691
5529
  var pointConnectionMap;
5692
5530
  var computingPointConnectionCurves;
5693
- // biome-ignore lint/style/useNamingConvention: HLine stands for HorizontalLine
5694
5531
  var reticleHLine;
5695
- // biome-ignore lint/style/useNamingConvention: VLine stands for VerticalLine
5696
5532
  var reticleVLine;
5697
5533
  var computedPointSizeMouseDetection;
5698
5534
  var lassoInitiatorTimeout;
@@ -5784,6 +5620,8 @@ void main() {
5784
5620
  var normalPointsIndexBuffer; // Buffer holding the indices pointing to the correct texel
5785
5621
  var selectedPointsIndexBuffer; // Used for pointing to the selected texels
5786
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
5787
5625
 
5788
5626
  var cameraZoomTargetStart; // Stores the start (i.e., current) camera target for zooming
5789
5627
  var cameraZoomTargetEnd; // Stores the end camera target for zooming
@@ -5804,10 +5642,7 @@ void main() {
5804
5642
  var isPointsDrawn = false;
5805
5643
  var isAnnotationsDrawn = false;
5806
5644
  var isMouseOverCanvasChecked = false;
5807
-
5808
- // biome-ignore lint/style/useNamingConvention: ZDate is not one word
5809
5645
  var valueZDataType = CATEGORICAL;
5810
- // biome-ignore lint/style/useNamingConvention: WDate is not one word
5811
5646
  var valueWDataType = CATEGORICAL;
5812
5647
 
5813
5648
  /** @type{number|undefined} */
@@ -5871,10 +5706,7 @@ void main() {
5871
5706
  }
5872
5707
  return points;
5873
5708
  };
5874
-
5875
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5876
5709
  var getPointsInBBox = function getPointsInBBox(x0, y0, x1, y1) {
5877
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5878
5710
  var pointsInBBox = spatialIndex.range(x0, y0, x1, y1);
5879
5711
  if (isPointsFiltered) {
5880
5712
  return pointsInBBox.filter(function (i) {
@@ -5895,7 +5727,6 @@ void main() {
5895
5727
  var pointSizeNdc = getPointSizeNdc(4);
5896
5728
 
5897
5729
  // Get all points within a close range
5898
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5899
5730
  var pointsInBBox = getPointsInBBox(xNdc - pointSizeNdc, yNdc - pointSizeNdc, xNdc + pointSizeNdc, yNdc + pointSizeNdc);
5900
5731
 
5901
5732
  // Find the closest point
@@ -5937,7 +5768,6 @@ void main() {
5937
5768
  }
5938
5769
 
5939
5770
  // ...to efficiently preselect potentially selected points
5940
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
5941
5771
  var pointsInBBox = getPointsInBBox.apply(void 0, _toConsumableArray(bBox));
5942
5772
  // next we test each point in the bounding box if it is in the polygon too
5943
5773
  var pointsInPolygon = [];
@@ -6038,6 +5868,49 @@ void main() {
6038
5868
  }
6039
5869
  };
6040
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
+
6041
5914
  /**
6042
5915
  * Select and highlight a set of points
6043
5916
  * @param {number | number[]} pointIdxs
@@ -6125,16 +5998,54 @@ void main() {
6125
5998
  draw = true;
6126
5999
  };
6127
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
+
6128
6039
  /**
6129
6040
  * @param {number} point
6130
6041
  * @param {import('./types').ScatterplotMethodOptions['hover']} options
6131
6042
  */
6132
6043
  var hover = function hover(point) {
6133
- var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
6134
- _ref4$showReticleOnce = _ref4.showReticleOnce,
6135
- showReticleOnce = _ref4$showReticleOnce === void 0 ? false : _ref4$showReticleOnce,
6136
- _ref4$preventEvent = _ref4.preventEvent,
6137
- 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;
6138
6049
  var needsRedraw = false;
6139
6050
  var isFilteredOut = isPointsFiltered && !filteredPointsSet.has(point);
6140
6051
  if (!isFilteredOut && point >= 0 && point < numPoints) {
@@ -6190,13 +6101,13 @@ void main() {
6190
6101
  pubSub.publish('lassoStart');
6191
6102
  };
6192
6103
  var lassoEnd = function lassoEnd(lassoPoints, lassoPointsFlat) {
6193
- var _ref5 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
6194
- _ref5$intersect = _ref5.intersect,
6195
- intersect = _ref5$intersect === void 0 ? false : _ref5$intersect,
6196
- _ref5$merge = _ref5.merge,
6197
- merge = _ref5$merge === void 0 ? false : _ref5$merge,
6198
- _ref5$remove = _ref5.remove,
6199
- 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;
6200
6111
  camera.config({
6201
6112
  isFixed: cameraIsFixed
6202
6113
  });
@@ -6221,10 +6132,10 @@ void main() {
6221
6132
  enableInitiator: lassoInitiator,
6222
6133
  initiatorParentElement: lassoInitiatorParentElement,
6223
6134
  longPressIndicatorParentElement: lassoLongPressIndicatorParentElement,
6224
- pointNorm: function pointNorm(_ref6) {
6225
- var _ref7 = _slicedToArray(_ref6, 2),
6226
- x = _ref7[0],
6227
- y = _ref7[1];
6135
+ pointNorm: function pointNorm(_ref7) {
6136
+ var _ref8 = _slicedToArray(_ref7, 2),
6137
+ x = _ref8[0],
6138
+ y = _ref8[1];
6228
6139
  return getScatterGlPos(getNdcX(x), getNdcY(y));
6229
6140
  },
6230
6141
  minDelay: lassoMinDelay,
@@ -6686,6 +6597,46 @@ void main() {
6686
6597
  var setSizeBy = function setSizeBy(type) {
6687
6598
  sizeBy = getEncodingType(type, DEFAULT_SIZE_BY);
6688
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
+ };
6689
6640
  var setPointConnectionColorBy = function setPointConnectionColorBy(type) {
6690
6641
  pointConnectionColorBy = getEncodingType(type, DEFAULT_POINT_CONNECTION_COLOR_BY, {
6691
6642
  allowSegment: true,
@@ -6901,15 +6852,13 @@ void main() {
6901
6852
  var getPointOpacityMax = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : getPointOpacityMaxBase;
6902
6853
  var getPointOpacityScale = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : getPointOpacityScaleBase;
6903
6854
  return renderer.regl({
6904
- frag: renderPointsAsSquares ? FRAGMENT_SHADER$1 : FRAGMENT_SHADER,
6855
+ frag: renderPointsAsSquares ? FRAGMENT_SHADER : FRAGMENT_SHADER$1,
6905
6856
  vert: createVertexShader(globalState),
6906
6857
  blend: {
6907
6858
  enable: !disableAlphaBlending,
6908
6859
  func: {
6909
- // biome-ignore lint/style/useNamingConvention: Regl specific
6910
6860
  srcRGB: 'src alpha',
6911
6861
  srcAlpha: 'one',
6912
- // biome-ignore lint/style/useNamingConvention: Regl specific
6913
6862
  dstRGB: 'one minus src alpha',
6914
6863
  dstAlpha: 'one minus src alpha'
6915
6864
  }
@@ -7025,10 +6974,8 @@ void main() {
7025
6974
  blend: {
7026
6975
  enable: true,
7027
6976
  func: {
7028
- // biome-ignore lint/style/useNamingConvention: Regl specific
7029
6977
  srcRGB: 'src alpha',
7030
6978
  srcAlpha: 'one',
7031
- // biome-ignore lint/style/useNamingConvention: Regl specific
7032
6979
  dstRGB: 'one minus src alpha',
7033
6980
  dstAlpha: 'one minus src alpha'
7034
6981
  }
@@ -7096,6 +7043,41 @@ void main() {
7096
7043
  }
7097
7044
  return index;
7098
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
+ };
7099
7081
  var createStateTexture = function createStateTexture(newPoints) {
7100
7082
  var dataTypes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7101
7083
  var numNewPoints = newPoints.length;
@@ -7174,8 +7156,17 @@ void main() {
7174
7156
  return new Promise(function (resolve) {
7175
7157
  isPointsDrawn = false;
7176
7158
  var preventFilterReset = (options === null || options === void 0 ? void 0 : options.preventFilterReset) && newPoints.length === numPoints;
7159
+ var prevNumPoints = numPoints;
7177
7160
  numPoints = newPoints.length;
7178
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
+ }
7179
7170
  if (stateTex) {
7180
7171
  stateTex.destroy();
7181
7172
  }
@@ -7184,10 +7175,11 @@ void main() {
7184
7175
  w: options.wDataType
7185
7176
  });
7186
7177
  if (!preventFilterReset) {
7178
+ computePointOrderIndex();
7187
7179
  normalPointsIndexBuffer({
7188
7180
  usage: 'static',
7189
7181
  type: 'float',
7190
- data: createPointIndex(numPoints)
7182
+ data: getEffectivePointIndex(numPoints)
7191
7183
  });
7192
7184
  }
7193
7185
  createKdbush(options.spatialIndex || newPoints, {
@@ -7233,8 +7225,8 @@ void main() {
7233
7225
  colorIndices[index] = [0];
7234
7226
  var cumLength = 0;
7235
7227
  // Assign the color index based on the cumulative length
7236
- for (var _i2 = 0; _i2 < curve.length / 2 - 1; _i2++) {
7237
- cumLength += segLengths[_i2];
7228
+ for (var _i4 = 0; _i4 < curve.length / 2 - 1; _i4++) {
7229
+ cumLength += segLengths[_i4];
7238
7230
  // The `4` comes from the fact that we have 4 color states:
7239
7231
  // normal, active, hover, and background
7240
7232
  colorIndices[index].push(Math.floor(cumLength / totalLength * maxColorIdx) * 4);
@@ -7251,10 +7243,10 @@ void main() {
7251
7243
  if (colorEncoding) {
7252
7244
  var encodingIdx = getEncodingIdx(colorEncoding);
7253
7245
  var encodingValueToIdx = getEncodingValueToIdx(getEncodingDataType(colorEncoding), pointConnectionColorBy === 'inherit' ? pointColor : pointConnectionColor);
7254
- return pointConnectionMap.reduce(function (colorIndices, _ref8) {
7255
- var _ref9 = _slicedToArray(_ref8, 2),
7256
- index = _ref9[0],
7257
- referencePoint = _ref9[1];
7246
+ return pointConnectionMap.reduce(function (colorIndices, _ref9) {
7247
+ var _ref0 = _slicedToArray(_ref9, 2),
7248
+ index = _ref0[0],
7249
+ referencePoint = _ref0[1];
7258
7250
  // The `4` comes from the fact that we have 4 color states:
7259
7251
  // normal, active, hover, and background
7260
7252
  colorIndices[index] = encodingValueToIdx(referencePoint[encodingIdx]) * 4;
@@ -7270,11 +7262,11 @@ void main() {
7270
7262
  if (maxOpacityIdx < 1) {
7271
7263
  return [];
7272
7264
  }
7273
- return pointConnectionMap.reduce(function (opacities, _ref10) {
7274
- var _ref11 = _slicedToArray(_ref10, 3),
7275
- index = _ref11[0];
7276
- _ref11[1];
7277
- 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];
7278
7270
  opacities[index] = rangeMap(length, function (i) {
7279
7271
  return pointConnectionOpacity[Math.floor(i / (length - 1) * maxOpacityIdx)];
7280
7272
  });
@@ -7285,10 +7277,10 @@ void main() {
7285
7277
  var encodingIdx = getEncodingIdx(opacityEncoding);
7286
7278
  var encodingRangeMap = pointConnectionOpacityBy === 'inherit' ? opacity : pointConnectionOpacity;
7287
7279
  var encodingValueToIdx = getEncodingValueToIdx(getEncodingDataType(opacityEncoding), encodingRangeMap);
7288
- return pointConnectionMap.reduce(function (opacities, _ref12) {
7289
- var _ref13 = _slicedToArray(_ref12, 2),
7290
- index = _ref13[0],
7291
- referencePoint = _ref13[1];
7280
+ return pointConnectionMap.reduce(function (opacities, _ref11) {
7281
+ var _ref12 = _slicedToArray(_ref11, 2),
7282
+ index = _ref12[0],
7283
+ referencePoint = _ref12[1];
7292
7284
  opacities[index] = encodingRangeMap[encodingValueToIdx(referencePoint[encodingIdx])];
7293
7285
  return opacities;
7294
7286
  }, []);
@@ -7302,11 +7294,11 @@ void main() {
7302
7294
  if (maxSizeIdx < 1) {
7303
7295
  return [];
7304
7296
  }
7305
- return pointConnectionMap.reduce(function (widths, _ref14) {
7306
- var _ref15 = _slicedToArray(_ref14, 3),
7307
- index = _ref15[0];
7308
- _ref15[1];
7309
- 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];
7310
7302
  widths[index] = rangeMap(length, function (i) {
7311
7303
  return pointConnectionSize[Math.floor(i / (length - 1) * maxSizeIdx)];
7312
7304
  });
@@ -7317,10 +7309,10 @@ void main() {
7317
7309
  var encodingIdx = getEncodingIdx(sizeEncoding);
7318
7310
  var encodingRangeMap = pointConnectionSizeBy === 'inherit' ? pointSize : pointConnectionSize;
7319
7311
  var encodingValueToIdx = getEncodingValueToIdx(getEncodingDataType(sizeEncoding), encodingRangeMap);
7320
- return pointConnectionMap.reduce(function (widths, _ref16) {
7321
- var _ref17 = _slicedToArray(_ref16, 2),
7322
- index = _ref17[0],
7323
- referencePoint = _ref17[1];
7312
+ return pointConnectionMap.reduce(function (widths, _ref15) {
7313
+ var _ref16 = _slicedToArray(_ref15, 2),
7314
+ index = _ref16[0],
7315
+ referencePoint = _ref16[1];
7324
7316
  widths[index] = encodingRangeMap[encodingValueToIdx(referencePoint[encodingIdx])];
7325
7317
  return widths;
7326
7318
  }, []);
@@ -7368,12 +7360,12 @@ void main() {
7368
7360
  * @param {import('./types').ScatterplotMethodOptions['filter']}
7369
7361
  */
7370
7362
  var unfilter = function unfilter() {
7371
- var _ref18 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
7372
- _ref18$preventEvent = _ref18.preventEvent,
7373
- 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;
7374
7366
  isPointsFiltered = false;
7375
7367
  filteredPointsSet.clear();
7376
- normalPointsIndexBuffer.subdata(createPointIndex(numPoints));
7368
+ normalPointsIndexBuffer.subdata(getEffectivePointIndex(numPoints));
7377
7369
  return new Promise(function (resolve) {
7378
7370
  var finish = function finish() {
7379
7371
  pubSub.subscribe('draw', function () {
@@ -7405,20 +7397,20 @@ void main() {
7405
7397
  * @param {import('./types').ScatterplotMethodOptions['filter']}
7406
7398
  */
7407
7399
  var filter = function filter(pointIdxs) {
7408
- var _ref19 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
7409
- _ref19$preventEvent = _ref19.preventEvent,
7410
- 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;
7411
7403
  isPointsFiltered = true;
7412
7404
  filteredPointsSet.clear();
7413
7405
  var pointIdxsArray = Array.isArray(pointIdxs) ? pointIdxs : [pointIdxs];
7414
7406
  var filteredPoints = [];
7415
7407
  var filteredPointsBuffer = [];
7416
7408
  var filteredSelectedPoints = [];
7417
- var _iterator5 = _createForOfIteratorHelper(pointIdxsArray),
7418
- _step5;
7409
+ var _iterator7 = _createForOfIteratorHelper(pointIdxsArray),
7410
+ _step7;
7419
7411
  try {
7420
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
7421
- var pointIdx = _step5.value;
7412
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
7413
+ var pointIdx = _step7.value;
7422
7414
  if (!Number.isFinite(pointIdx) || pointIdx < 0 || pointIdx >= numPoints) {
7423
7415
  // Skip invalid filtered points
7424
7416
  continue;
@@ -7430,24 +7422,35 @@ void main() {
7430
7422
  }
7431
7423
  }
7432
7424
  } catch (err) {
7433
- _iterator5.e(err);
7425
+ _iterator7.e(err);
7434
7426
  } finally {
7435
- _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));
7436
7440
  }
7437
- var sortedFilteredPoints = insertionSort([].concat(filteredPoints));
7438
- var _iterator6 = _createForOfIteratorHelper(sortedFilteredPoints),
7439
- _step6;
7441
+ var _iterator8 = _createForOfIteratorHelper(orderedFilteredPoints),
7442
+ _step8;
7440
7443
  try {
7441
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
7442
- var _pointIdx = _step6.value;
7444
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
7445
+ var _pointIdx = _step8.value;
7443
7446
  filteredPointsBuffer.push.apply(filteredPointsBuffer, indexToStateTexCoord(_pointIdx));
7444
7447
  }
7445
7448
 
7446
7449
  // Update the normal points index buffers
7447
7450
  } catch (err) {
7448
- _iterator6.e(err);
7451
+ _iterator8.e(err);
7449
7452
  } finally {
7450
- _iterator6.f();
7453
+ _iterator8.f();
7451
7454
  }
7452
7455
  normalPointsIndexBuffer.subdata(filteredPointsBuffer);
7453
7456
 
@@ -7547,11 +7550,11 @@ void main() {
7547
7550
  clearCachedCamera();
7548
7551
  pubSub.publish('transitionEnd');
7549
7552
  };
7550
- var startTransition = function startTransition(_ref20) {
7551
- var _ref20$duration = _ref20.duration,
7552
- duration = _ref20$duration === void 0 ? 500 : _ref20$duration,
7553
- _ref20$easing = _ref20.easing,
7554
- 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;
7555
7558
  if (isTransitioning) {
7556
7559
  pubSub.publish('transitionEnd');
7557
7560
  }
@@ -7741,11 +7744,11 @@ void main() {
7741
7744
  newColorIndices.push(_idx);
7742
7745
  }
7743
7746
  };
7744
- var _iterator7 = _createForOfIteratorHelper(newAnnotations),
7745
- _step7;
7747
+ var _iterator9 = _createForOfIteratorHelper(newAnnotations),
7748
+ _step9;
7746
7749
  try {
7747
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
7748
- var annotation = _step7.value;
7750
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
7751
+ var annotation = _step9.value;
7749
7752
  if (isHorizontalLine(annotation)) {
7750
7753
  var _annotation$x, _annotation$x2;
7751
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]);
@@ -7768,21 +7771,21 @@ void main() {
7768
7771
  addColorAndWidth(annotation);
7769
7772
  continue;
7770
7773
  }
7771
- if (isPolygon(annotation)) {
7774
+ if (isPolygonAnnotation(annotation)) {
7772
7775
  newPoints.push(annotation.vertices.flatMap(identity));
7773
7776
  addColorAndWidth(annotation);
7774
7777
  }
7775
7778
  }
7776
7779
  } catch (err) {
7777
- _iterator7.e(err);
7780
+ _iterator9.e(err);
7778
7781
  } finally {
7779
- _iterator7.f();
7782
+ _iterator9.f();
7780
7783
  }
7781
7784
  annotations.setStyle({
7782
7785
  color: Array.from(newColors.values()).sort(function (a, b) {
7783
7786
  return a.idx > b.idx ? 1 : -1;
7784
- }).map(function (_ref21) {
7785
- var color = _ref21.color;
7787
+ }).map(function (_ref20) {
7788
+ var color = _ref20.color;
7786
7789
  return color;
7787
7790
  })
7788
7791
  });
@@ -7814,17 +7817,16 @@ void main() {
7814
7817
  * @param {number[]} pointIdxs - A list of point indices
7815
7818
  * @returns {import('./types').Rect} The bounding box
7816
7819
  */
7817
- // biome-ignore lint/style/useNamingConvention: BBox stands for BoundingBox
7818
7820
  var getBBoxOfPoints = function getBBoxOfPoints(pointIdxs) {
7819
7821
  var xMin = Number.POSITIVE_INFINITY;
7820
7822
  var xMax = Number.NEGATIVE_INFINITY;
7821
7823
  var yMin = Number.POSITIVE_INFINITY;
7822
7824
  var yMax = Number.NEGATIVE_INFINITY;
7823
- var _iterator8 = _createForOfIteratorHelper(pointIdxs),
7824
- _step8;
7825
+ var _iterator0 = _createForOfIteratorHelper(pointIdxs),
7826
+ _step0;
7825
7827
  try {
7826
- for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
7827
- var pointIdx = _step8.value;
7828
+ for (_iterator0.s(); !(_step0 = _iterator0.n()).done;) {
7829
+ var pointIdx = _step0.value;
7828
7830
  var _points$pointIdx2 = _slicedToArray(points[pointIdx], 2),
7829
7831
  x = _points$pointIdx2[0],
7830
7832
  y = _points$pointIdx2[1];
@@ -7834,9 +7836,9 @@ void main() {
7834
7836
  yMax = Math.max(yMax, y);
7835
7837
  }
7836
7838
  } catch (err) {
7837
- _iterator8.e(err);
7839
+ _iterator0.e(err);
7838
7840
  } finally {
7839
- _iterator8.f();
7841
+ _iterator0.f();
7840
7842
  }
7841
7843
  return {
7842
7844
  x: xMin,
@@ -7860,7 +7862,6 @@ void main() {
7860
7862
  // Vertical field of view
7861
7863
  // The Arc Tangent is based on the original camera position. Otherwise
7862
7864
  // we would have to do `Math.atan(1 / camera.view[5])`
7863
- // biome-ignore lint/style/useNamingConvention: FOV stands for field of view
7864
7865
  var vFOV = 2 * Math.atan(1);
7865
7866
  var aspectRatio = viewAspectRatio / dataAspectRatio;
7866
7867
  var distance = rect.height * aspectRatio >= rect.width ?
@@ -8175,10 +8176,10 @@ void main() {
8175
8176
  }
8176
8177
  };
8177
8178
  var setActionKeyMap = function setActionKeyMap(newActionKeyMap) {
8178
- actionKeyMap = Object.entries(newActionKeyMap).reduce(function (map, _ref22) {
8179
- var _ref23 = _slicedToArray(_ref22, 2),
8180
- action = _ref23[0],
8181
- 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];
8182
8183
  if (KEYS.includes(key) && KEY_ACTIONS.includes(action)) {
8183
8184
  map[action] = key;
8184
8185
  }
@@ -8210,8 +8211,6 @@ void main() {
8210
8211
  color: reticleColor
8211
8212
  });
8212
8213
  };
8213
-
8214
- // biome-ignore lint/style/useNamingConvention: XScale are two words
8215
8214
  var setXScale = function setXScale(newXScale) {
8216
8215
  if (!newXScale) {
8217
8216
  return;
@@ -8222,8 +8221,6 @@ void main() {
8222
8221
  xScale.range([0, currentWidth]);
8223
8222
  updateScales();
8224
8223
  };
8225
-
8226
- // biome-ignore lint/style/useNamingConvention: YScale are two words
8227
8224
  var setYScale = function setYScale(newYScale) {
8228
8225
  if (!newYScale) {
8229
8226
  return;
@@ -8364,8 +8361,6 @@ void main() {
8364
8361
  var setAnnotationLineWidth = function setAnnotationLineWidth(newAnnotationLineWidth) {
8365
8362
  annotationLineWidth = +newAnnotationLineWidth;
8366
8363
  };
8367
-
8368
- // biome-ignore lint/style/useNamingConvention: HVLine stands for horizontal vertical line
8369
8364
  var setAnnotationHVLineLimit = function setAnnotationHVLineLimit(newAnnotationHVLineLimit) {
8370
8365
  annotationHVLineLimit = +newAnnotationHVLineLimit;
8371
8366
  };
@@ -8423,6 +8418,9 @@ void main() {
8423
8418
  if (property === 'sizeBy') {
8424
8419
  return sizeBy;
8425
8420
  }
8421
+ if (property === 'pointOrder') {
8422
+ return pointOrder !== null ? _toConsumableArray(pointOrder) : null;
8423
+ }
8426
8424
  if (property === 'deselectOnDblClick') {
8427
8425
  return deselectOnDblClick;
8428
8426
  }
@@ -8705,6 +8703,9 @@ void main() {
8705
8703
  if (properties.sizeBy !== undefined) {
8706
8704
  setSizeBy(properties.sizeBy);
8707
8705
  }
8706
+ if (properties.pointOrder !== undefined) {
8707
+ setPointOrder(properties.pointOrder);
8708
+ }
8708
8709
  if (properties.opacity !== undefined) {
8709
8710
  setOpacity(properties.opacity);
8710
8711
  }
@@ -8888,9 +8889,9 @@ void main() {
8888
8889
  * @param {import('./types').ScatterplotMethodOptions['preventEvent']} options
8889
8890
  */
8890
8891
  var view = function view(cameraView) {
8891
- var _ref24 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
8892
- _ref24$preventEvent = _ref24.preventEvent,
8893
- 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;
8894
8895
  setCameraView(cameraView);
8895
8896
  draw = true;
8896
8897
  preventEventView = preventEvent;
@@ -8918,9 +8919,9 @@ void main() {
8918
8919
  * @param {import('./types').ScatterplotMethodOptions['preventEvent']} options
8919
8920
  */
8920
8921
  var reset = function reset() {
8921
- var _ref25 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
8922
- _ref25$preventEvent = _ref25.preventEvent,
8923
- 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;
8924
8925
  initCamera();
8925
8926
  updateScales();
8926
8927
  if (preventEvent) {
@@ -8933,8 +8934,8 @@ void main() {
8933
8934
  yScale: yScale
8934
8935
  });
8935
8936
  };
8936
- var keyUpHandler = function keyUpHandler(_ref26) {
8937
- var key = _ref26.key;
8937
+ var keyUpHandler = function keyUpHandler(_ref25) {
8938
+ var key = _ref25.key;
8938
8939
  switch (key) {
8939
8940
  case 'Escape':
8940
8941
  {
@@ -9007,10 +9008,10 @@ void main() {
9007
9008
  * @returns {Promise<ImageData>}
9008
9009
  */
9009
9010
  var exportFnAdvanced = /*#__PURE__*/function () {
9010
- var _ref27 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(options) {
9011
+ var _ref26 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(options) {
9011
9012
  var dpr, currPointSize, currWidth, currHeight, currRendererWidth, currRendererHeight, currPixelAligned, currAntiAliasing, scale, newPointSize, newWidth, newHeight, imageData;
9012
- return _regeneratorRuntime().wrap(function _callee$(_context) {
9013
- while (1) switch (_context.prev = _context.next) {
9013
+ return _regenerator().w(function (_context) {
9014
+ while (1) switch (_context.n) {
9014
9015
  case 0:
9015
9016
  canvas.style.userSelect = 'none';
9016
9017
  dpr = window.devicePixelRatio;
@@ -9034,12 +9035,12 @@ void main() {
9034
9035
  setAntiAliasing((options === null || options === void 0 ? void 0 : options.antiAliasing) || antiAliasing);
9035
9036
  renderer.resize(width, height);
9036
9037
  renderer.refresh();
9037
- _context.next = 22;
9038
+ _context.n = 1;
9038
9039
  return new Promise(function (resolve) {
9039
9040
  pubSub.subscribe('draw', resolve, 1);
9040
9041
  redraw();
9041
9042
  });
9042
- case 22:
9043
+ case 1:
9043
9044
  imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
9044
9045
  renderer.resize(currRendererWidth, currRendererHeight);
9045
9046
  renderer.refresh();
@@ -9048,22 +9049,19 @@ void main() {
9048
9049
  setHeight(currHeight);
9049
9050
  setPixelAligned(currPixelAligned);
9050
9051
  setAntiAliasing(currAntiAliasing);
9051
- _context.next = 32;
9052
+ _context.n = 2;
9052
9053
  return new Promise(function (resolve) {
9053
9054
  pubSub.subscribe('draw', resolve, 1);
9054
9055
  redraw();
9055
9056
  });
9056
- case 32:
9057
+ case 2:
9057
9058
  canvas.style.userSelect = null;
9058
- return _context.abrupt("return", imageData);
9059
- case 34:
9060
- case "end":
9061
- return _context.stop();
9059
+ return _context.a(2, imageData);
9062
9060
  }
9063
9061
  }, _callee);
9064
9062
  }));
9065
9063
  return function exportFnAdvanced(_x) {
9066
- return _ref27.apply(this, arguments);
9064
+ return _ref26.apply(this, arguments);
9067
9065
  };
9068
9066
  }();
9069
9067
 
@@ -9301,6 +9299,9 @@ void main() {
9301
9299
  };
9302
9300
  init();
9303
9301
  return {
9302
+ attachSpatialIndex: function attachSpatialIndex(buffer) {
9303
+ spatialIndex = kdbushFrom(buffer);
9304
+ },
9304
9305
  /**
9305
9306
  * Get whether the browser supports all necessary WebGL features
9306
9307
  * @return {boolean} If `true` the browser supports all necessary WebGL features
@@ -9324,6 +9325,7 @@ void main() {
9324
9325
  get: get,
9325
9326
  getScreenPosition: getScreenPosition,
9326
9327
  hover: hover,
9328
+ lassoSelect: lassoSelect,
9327
9329
  redraw: redraw,
9328
9330
  refresh: renderer.refresh,
9329
9331
  reset: withDraw(reset),