@hema-to/regl-scatterplot 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1110 -0
- package/dist/regl-scatterplot.esm.d.ts +126 -0
- package/dist/regl-scatterplot.esm.js +9962 -0
- package/dist/regl-scatterplot.js +9385 -0
- package/dist/regl-scatterplot.min.js +8 -0
- package/dist/types.d.ts +306 -0
- package/package.json +100 -0
- package/src/bg.fs +13 -0
- package/src/bg.vs +16 -0
- package/src/constants.js +189 -0
- package/src/index.js +4654 -0
- package/src/kdbush-class.js +369 -0
- package/src/kdbush-worker.js +20 -0
- package/src/kdbush.js +69 -0
- package/src/lasso-manager/constants.js +7 -0
- package/src/lasso-manager/create-long-press-animations.js +257 -0
- package/src/lasso-manager/create-long-press-elements.js +68 -0
- package/src/lasso-manager/index.js +781 -0
- package/src/lasso-manager/utils.js +40 -0
- package/src/point-simple.fs +10 -0
- package/src/point-update.fs +21 -0
- package/src/point-update.vs +13 -0
- package/src/point.fs +22 -0
- package/src/point.vs +124 -0
- package/src/renderer.js +252 -0
- package/src/spline-curve-worker.js +271 -0
- package/src/spline-curve.js +23 -0
- package/src/types.d.ts +306 -0
- package/src/utils.js +598 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KDBush - A fast static index for 2D points
|
|
3
|
+
* @license ISC License
|
|
4
|
+
* @copyright Vladimir Agafonkin 2018
|
|
5
|
+
* @version 4.0.2
|
|
6
|
+
* @see https://github.com/mourner/kdbush/
|
|
7
|
+
*/
|
|
8
|
+
export default () => {
|
|
9
|
+
const ARRAY_TYPES = [
|
|
10
|
+
Int8Array,
|
|
11
|
+
Uint8Array,
|
|
12
|
+
Uint8ClampedArray,
|
|
13
|
+
Int16Array,
|
|
14
|
+
Uint16Array,
|
|
15
|
+
Int32Array,
|
|
16
|
+
Uint32Array,
|
|
17
|
+
Float32Array,
|
|
18
|
+
Float64Array,
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
/** @typedef {Int8ArrayConstructor | Uint8ArrayConstructor | Uint8ClampedArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor} TypedArrayConstructor */
|
|
22
|
+
|
|
23
|
+
const VERSION = 1; // serialized format version
|
|
24
|
+
const HEADER_SIZE = 8;
|
|
25
|
+
|
|
26
|
+
class KDBush {
|
|
27
|
+
/**
|
|
28
|
+
* Creates an index from raw `ArrayBuffer` data.
|
|
29
|
+
* @param {ArrayBuffer} data
|
|
30
|
+
*/
|
|
31
|
+
static from(data) {
|
|
32
|
+
if (!(data instanceof ArrayBuffer)) {
|
|
33
|
+
throw new Error('Data must be an instance of ArrayBuffer.');
|
|
34
|
+
}
|
|
35
|
+
const [magic, versionAndType] = new Uint8Array(data, 0, 2);
|
|
36
|
+
if (magic !== 0xdb) {
|
|
37
|
+
throw new Error('Data does not appear to be in a KDBush format.');
|
|
38
|
+
}
|
|
39
|
+
const version = versionAndType >> 4;
|
|
40
|
+
if (version !== VERSION) {
|
|
41
|
+
throw new Error(`Got v${version} data when expected v${VERSION}.`);
|
|
42
|
+
}
|
|
43
|
+
const ArrayType = ARRAY_TYPES[versionAndType & 0x0f];
|
|
44
|
+
if (!ArrayType) {
|
|
45
|
+
throw new Error('Unrecognized array type.');
|
|
46
|
+
}
|
|
47
|
+
const [nodeSize] = new Uint16Array(data, 2, 1);
|
|
48
|
+
const [numItems] = new Uint32Array(data, 4, 1);
|
|
49
|
+
|
|
50
|
+
return new KDBush(numItems, nodeSize, ArrayType, data);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates an index that will hold a given number of items.
|
|
55
|
+
* @param {number} numItems
|
|
56
|
+
* @param {number} [nodeSize=64] Size of the KD-tree node (64 by default).
|
|
57
|
+
* @param {TypedArrayConstructor} [ArrayType=Float64Array] The array type used for coordinates storage (`Float64Array` by default).
|
|
58
|
+
* @param {ArrayBuffer} [data] (For internal use only)
|
|
59
|
+
*/
|
|
60
|
+
constructor(numItems, nodeSize = 64, ArrayType = Float64Array, data) {
|
|
61
|
+
if (isNaN(numItems) || numItems < 0)
|
|
62
|
+
throw new Error(`Unexpected numItems value: ${numItems}.`);
|
|
63
|
+
|
|
64
|
+
this.numItems = +numItems;
|
|
65
|
+
this.nodeSize = Math.min(Math.max(+nodeSize, 2), 65535);
|
|
66
|
+
this.ArrayType = ArrayType;
|
|
67
|
+
this.IndexArrayType = numItems < 65536 ? Uint16Array : Uint32Array;
|
|
68
|
+
|
|
69
|
+
const arrayTypeIndex = ARRAY_TYPES.indexOf(this.ArrayType);
|
|
70
|
+
const coordsByteSize = numItems * 2 * this.ArrayType.BYTES_PER_ELEMENT;
|
|
71
|
+
const idsByteSize = numItems * this.IndexArrayType.BYTES_PER_ELEMENT;
|
|
72
|
+
const padCoords = (8 - (idsByteSize % 8)) % 8;
|
|
73
|
+
|
|
74
|
+
if (arrayTypeIndex < 0) {
|
|
75
|
+
throw new Error(`Unexpected typed array class: ${ArrayType}.`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (data && data instanceof ArrayBuffer) {
|
|
79
|
+
// reconstruct an index from a buffer
|
|
80
|
+
this.data = data;
|
|
81
|
+
this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
|
|
82
|
+
this.coords = new this.ArrayType(
|
|
83
|
+
this.data,
|
|
84
|
+
HEADER_SIZE + idsByteSize + padCoords,
|
|
85
|
+
numItems * 2
|
|
86
|
+
);
|
|
87
|
+
this._pos = numItems * 2;
|
|
88
|
+
this._finished = true;
|
|
89
|
+
} else {
|
|
90
|
+
// initialize a new index
|
|
91
|
+
this.data = new ArrayBuffer(
|
|
92
|
+
HEADER_SIZE + coordsByteSize + idsByteSize + padCoords
|
|
93
|
+
);
|
|
94
|
+
this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
|
|
95
|
+
this.coords = new this.ArrayType(
|
|
96
|
+
this.data,
|
|
97
|
+
HEADER_SIZE + idsByteSize + padCoords,
|
|
98
|
+
numItems * 2
|
|
99
|
+
);
|
|
100
|
+
this._pos = 0;
|
|
101
|
+
this._finished = false;
|
|
102
|
+
|
|
103
|
+
// set header
|
|
104
|
+
new Uint8Array(this.data, 0, 2).set([
|
|
105
|
+
0xdb,
|
|
106
|
+
(VERSION << 4) + arrayTypeIndex,
|
|
107
|
+
]);
|
|
108
|
+
new Uint16Array(this.data, 2, 1)[0] = nodeSize;
|
|
109
|
+
new Uint32Array(this.data, 4, 1)[0] = numItems;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Add a point to the index.
|
|
115
|
+
* @param {number} x
|
|
116
|
+
* @param {number} y
|
|
117
|
+
* @returns {number} An incremental index associated with the added item (starting from `0`).
|
|
118
|
+
*/
|
|
119
|
+
add(x, y) {
|
|
120
|
+
const index = this._pos >> 1;
|
|
121
|
+
this.ids[index] = index;
|
|
122
|
+
this.coords[this._pos++] = x;
|
|
123
|
+
this.coords[this._pos++] = y;
|
|
124
|
+
return index;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Perform indexing of the added points.
|
|
129
|
+
*/
|
|
130
|
+
finish() {
|
|
131
|
+
const numAdded = this._pos >> 1;
|
|
132
|
+
if (numAdded !== this.numItems) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
`Added ${numAdded} items when expected ${this.numItems}.`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
// kd-sort both arrays for efficient search
|
|
138
|
+
sort(this.ids, this.coords, this.nodeSize, 0, this.numItems - 1, 0);
|
|
139
|
+
|
|
140
|
+
this._finished = true;
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Search the index for items within a given bounding box.
|
|
146
|
+
* @param {number} minX
|
|
147
|
+
* @param {number} minY
|
|
148
|
+
* @param {number} maxX
|
|
149
|
+
* @param {number} maxY
|
|
150
|
+
* @returns {number[]} An array of indices correponding to the found items.
|
|
151
|
+
*/
|
|
152
|
+
range(minX, minY, maxX, maxY) {
|
|
153
|
+
if (!this._finished)
|
|
154
|
+
throw new Error('Data not yet indexed - call index.finish().');
|
|
155
|
+
|
|
156
|
+
const { ids, coords, nodeSize } = this;
|
|
157
|
+
const stack = [0, ids.length - 1, 0];
|
|
158
|
+
const result = [];
|
|
159
|
+
|
|
160
|
+
// recursively search for items in range in the kd-sorted arrays
|
|
161
|
+
while (stack.length) {
|
|
162
|
+
const axis = stack.pop() || 0;
|
|
163
|
+
const right = stack.pop() || 0;
|
|
164
|
+
const left = stack.pop() || 0;
|
|
165
|
+
|
|
166
|
+
// if we reached "tree node", search linearly
|
|
167
|
+
if (right - left <= nodeSize) {
|
|
168
|
+
for (let i = left; i <= right; i++) {
|
|
169
|
+
const x = coords[2 * i];
|
|
170
|
+
const y = coords[2 * i + 1];
|
|
171
|
+
if (x >= minX && x <= maxX && y >= minY && y <= maxY)
|
|
172
|
+
result.push(ids[i]);
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// otherwise find the middle index
|
|
178
|
+
const m = (left + right) >> 1;
|
|
179
|
+
|
|
180
|
+
// include the middle item if it's in range
|
|
181
|
+
const x = coords[2 * m];
|
|
182
|
+
const y = coords[2 * m + 1];
|
|
183
|
+
if (x >= minX && x <= maxX && y >= minY && y <= maxY)
|
|
184
|
+
result.push(ids[m]);
|
|
185
|
+
|
|
186
|
+
// queue search in halves that intersect the query
|
|
187
|
+
if (axis === 0 ? minX <= x : minY <= y) {
|
|
188
|
+
stack.push(left);
|
|
189
|
+
stack.push(m - 1);
|
|
190
|
+
stack.push(1 - axis);
|
|
191
|
+
}
|
|
192
|
+
if (axis === 0 ? maxX >= x : maxY >= y) {
|
|
193
|
+
stack.push(m + 1);
|
|
194
|
+
stack.push(right);
|
|
195
|
+
stack.push(1 - axis);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return result;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Search the index for items within a given radius.
|
|
204
|
+
* @param {number} qx
|
|
205
|
+
* @param {number} qy
|
|
206
|
+
* @param {number} r Query radius.
|
|
207
|
+
* @returns {number[]} An array of indices correponding to the found items.
|
|
208
|
+
*/
|
|
209
|
+
within(qx, qy, r) {
|
|
210
|
+
if (!this._finished)
|
|
211
|
+
throw new Error('Data not yet indexed - call index.finish().');
|
|
212
|
+
|
|
213
|
+
const { ids, coords, nodeSize } = this;
|
|
214
|
+
const stack = [0, ids.length - 1, 0];
|
|
215
|
+
const result = [];
|
|
216
|
+
const r2 = r * r;
|
|
217
|
+
|
|
218
|
+
// recursively search for items within radius in the kd-sorted arrays
|
|
219
|
+
while (stack.length) {
|
|
220
|
+
const axis = stack.pop() || 0;
|
|
221
|
+
const right = stack.pop() || 0;
|
|
222
|
+
const left = stack.pop() || 0;
|
|
223
|
+
|
|
224
|
+
// if we reached "tree node", search linearly
|
|
225
|
+
if (right - left <= nodeSize) {
|
|
226
|
+
for (let i = left; i <= right; i++) {
|
|
227
|
+
if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2)
|
|
228
|
+
result.push(ids[i]);
|
|
229
|
+
}
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// otherwise find the middle index
|
|
234
|
+
const m = (left + right) >> 1;
|
|
235
|
+
|
|
236
|
+
// include the middle item if it's in range
|
|
237
|
+
const x = coords[2 * m];
|
|
238
|
+
const y = coords[2 * m + 1];
|
|
239
|
+
if (sqDist(x, y, qx, qy) <= r2) result.push(ids[m]);
|
|
240
|
+
|
|
241
|
+
// queue search in halves that intersect the query
|
|
242
|
+
if (axis === 0 ? qx - r <= x : qy - r <= y) {
|
|
243
|
+
stack.push(left);
|
|
244
|
+
stack.push(m - 1);
|
|
245
|
+
stack.push(1 - axis);
|
|
246
|
+
}
|
|
247
|
+
if (axis === 0 ? qx + r >= x : qy + r >= y) {
|
|
248
|
+
stack.push(m + 1);
|
|
249
|
+
stack.push(right);
|
|
250
|
+
stack.push(1 - axis);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {Uint16Array | Uint32Array} ids
|
|
260
|
+
* @param {InstanceType<TypedArrayConstructor>} coords
|
|
261
|
+
* @param {number} nodeSize
|
|
262
|
+
* @param {number} left
|
|
263
|
+
* @param {number} right
|
|
264
|
+
* @param {number} axis
|
|
265
|
+
*/
|
|
266
|
+
function sort(ids, coords, nodeSize, left, right, axis) {
|
|
267
|
+
if (right - left <= nodeSize) return;
|
|
268
|
+
|
|
269
|
+
const m = (left + right) >> 1; // middle index
|
|
270
|
+
|
|
271
|
+
// sort ids and coords around the middle index so that the halves lie
|
|
272
|
+
// either left/right or top/bottom correspondingly (taking turns)
|
|
273
|
+
select(ids, coords, m, left, right, axis);
|
|
274
|
+
|
|
275
|
+
// recursively kd-sort first half and second half on the opposite axis
|
|
276
|
+
sort(ids, coords, nodeSize, left, m - 1, 1 - axis);
|
|
277
|
+
sort(ids, coords, nodeSize, m + 1, right, 1 - axis);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Custom Floyd-Rivest selection algorithm: sort ids and coords so that
|
|
282
|
+
* [left..k-1] items are smaller than k-th item (on either x or y axis)
|
|
283
|
+
* @param {Uint16Array | Uint32Array} ids
|
|
284
|
+
* @param {InstanceType<TypedArrayConstructor>} coords
|
|
285
|
+
* @param {number} k
|
|
286
|
+
* @param {number} left
|
|
287
|
+
* @param {number} right
|
|
288
|
+
* @param {number} axis
|
|
289
|
+
*/
|
|
290
|
+
function select(ids, coords, k, left, right, axis) {
|
|
291
|
+
while (right > left) {
|
|
292
|
+
if (right - left > 600) {
|
|
293
|
+
const n = right - left + 1;
|
|
294
|
+
const m = k - left + 1;
|
|
295
|
+
const z = Math.log(n);
|
|
296
|
+
const s = 0.5 * Math.exp((2 * z) / 3);
|
|
297
|
+
const sd =
|
|
298
|
+
0.5 * Math.sqrt((z * s * (n - s)) / n) * (m - n / 2 < 0 ? -1 : 1);
|
|
299
|
+
const newLeft = Math.max(left, Math.floor(k - (m * s) / n + sd));
|
|
300
|
+
const newRight = Math.min(
|
|
301
|
+
right,
|
|
302
|
+
Math.floor(k + ((n - m) * s) / n + sd)
|
|
303
|
+
);
|
|
304
|
+
select(ids, coords, k, newLeft, newRight, axis);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const t = coords[2 * k + axis];
|
|
308
|
+
let i = left;
|
|
309
|
+
let j = right;
|
|
310
|
+
|
|
311
|
+
swapItem(ids, coords, left, k);
|
|
312
|
+
if (coords[2 * right + axis] > t) swapItem(ids, coords, left, right);
|
|
313
|
+
|
|
314
|
+
while (i < j) {
|
|
315
|
+
swapItem(ids, coords, i, j);
|
|
316
|
+
i++;
|
|
317
|
+
j--;
|
|
318
|
+
while (coords[2 * i + axis] < t) i++;
|
|
319
|
+
while (coords[2 * j + axis] > t) j--;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (coords[2 * left + axis] === t) swapItem(ids, coords, left, j);
|
|
323
|
+
else {
|
|
324
|
+
j++;
|
|
325
|
+
swapItem(ids, coords, j, right);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (j <= k) left = j + 1;
|
|
329
|
+
if (k <= j) right = j - 1;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* @param {Uint16Array | Uint32Array} ids
|
|
335
|
+
* @param {InstanceType<TypedArrayConstructor>} coords
|
|
336
|
+
* @param {number} i
|
|
337
|
+
* @param {number} j
|
|
338
|
+
*/
|
|
339
|
+
function swapItem(ids, coords, i, j) {
|
|
340
|
+
swap(ids, i, j);
|
|
341
|
+
swap(coords, 2 * i, 2 * j);
|
|
342
|
+
swap(coords, 2 * i + 1, 2 * j + 1);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @param {InstanceType<TypedArrayConstructor>} arr
|
|
347
|
+
* @param {number} i
|
|
348
|
+
* @param {number} j
|
|
349
|
+
*/
|
|
350
|
+
function swap(arr, i, j) {
|
|
351
|
+
const tmp = arr[i];
|
|
352
|
+
arr[i] = arr[j];
|
|
353
|
+
arr[j] = tmp;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* @param {number} ax
|
|
358
|
+
* @param {number} ay
|
|
359
|
+
* @param {number} bx
|
|
360
|
+
* @param {number} by
|
|
361
|
+
*/
|
|
362
|
+
function sqDist(ax, ay, bx, by) {
|
|
363
|
+
const dx = ax - bx;
|
|
364
|
+
const dy = ay - by;
|
|
365
|
+
return dx * dx + dy * dy;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return KDBush;
|
|
369
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default () => {
|
|
2
|
+
addEventListener('message', (event) => {
|
|
3
|
+
const points = event.data.points;
|
|
4
|
+
|
|
5
|
+
if (points.length === 0) {
|
|
6
|
+
self.postMessage({ error: new Error('Invalid point data') });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// biome-ignore lint/correctness/noUndeclaredVariables: KDBush is made available during compilation
|
|
10
|
+
const index = new KDBush(points.length, event.data.nodeSize);
|
|
11
|
+
|
|
12
|
+
for (const [x, y] of points) {
|
|
13
|
+
index.add(x, y);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
index.finish();
|
|
17
|
+
|
|
18
|
+
postMessage(index.data, [index.data]);
|
|
19
|
+
});
|
|
20
|
+
};
|
package/src/kdbush.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// biome-ignore lint/style/useNamingConvention: KDBush is a library name
|
|
2
|
+
import createKDBushClass from './kdbush-class.js';
|
|
3
|
+
import workerFn from './kdbush-worker.js';
|
|
4
|
+
|
|
5
|
+
// biome-ignore lint/style/useNamingConvention: KDBush is a library name
|
|
6
|
+
const KDBush = createKDBushClass();
|
|
7
|
+
const WORKER_THRESHOLD = 1000000;
|
|
8
|
+
|
|
9
|
+
const createWorker = (fn) => {
|
|
10
|
+
const kdbushStr = createKDBushClass.toString();
|
|
11
|
+
const fnStr = fn.toString();
|
|
12
|
+
const workerStr =
|
|
13
|
+
// biome-ignore lint/style/useTemplate: Prefer one assignment per line
|
|
14
|
+
`const createKDBushClass = ${kdbushStr};` +
|
|
15
|
+
'KDBush = createKDBushClass();' +
|
|
16
|
+
`const createWorker = ${fnStr};` +
|
|
17
|
+
'createWorker();';
|
|
18
|
+
|
|
19
|
+
const blob = new Blob([workerStr], { type: 'text/javascript' });
|
|
20
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
21
|
+
const worker = new Worker(workerUrl, { name: 'KDBush' });
|
|
22
|
+
|
|
23
|
+
// Clean up URL
|
|
24
|
+
URL.revokeObjectURL(workerUrl);
|
|
25
|
+
|
|
26
|
+
return worker;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create KDBush from an either point data or an existing spatial index
|
|
31
|
+
* @param {import('./types').Points | ArrayBuffer} pointsOrIndex - Points or KDBush index
|
|
32
|
+
* @param {Partial<import('./types').CreateKDBushOptions>} options - Options for configuring the index and its creation
|
|
33
|
+
* @return {Promise<KDBush>} KDBush instance
|
|
34
|
+
*/
|
|
35
|
+
const createKdbush = (
|
|
36
|
+
pointsOrIndex,
|
|
37
|
+
options = { nodeSize: 16, useWorker: undefined },
|
|
38
|
+
) =>
|
|
39
|
+
new Promise((resolve, reject) => {
|
|
40
|
+
if (pointsOrIndex instanceof ArrayBuffer) {
|
|
41
|
+
resolve(KDBush.from(pointsOrIndex));
|
|
42
|
+
} else if (
|
|
43
|
+
(pointsOrIndex.length < WORKER_THRESHOLD ||
|
|
44
|
+
options.useWorker === false) &&
|
|
45
|
+
options.useWorker !== true
|
|
46
|
+
) {
|
|
47
|
+
const index = new KDBush(pointsOrIndex.length, options.nodeSize);
|
|
48
|
+
for (const pointOrIndex of pointsOrIndex) {
|
|
49
|
+
index.add(pointOrIndex[0], pointOrIndex[1]);
|
|
50
|
+
}
|
|
51
|
+
index.finish();
|
|
52
|
+
resolve(index);
|
|
53
|
+
} else {
|
|
54
|
+
const worker = createWorker(workerFn);
|
|
55
|
+
|
|
56
|
+
worker.onmessage = (e) => {
|
|
57
|
+
if (e.data.error) {
|
|
58
|
+
reject(e.data.error);
|
|
59
|
+
} else {
|
|
60
|
+
resolve(KDBush.from(e.data));
|
|
61
|
+
}
|
|
62
|
+
worker.terminate();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
worker.postMessage({ points: pointsOrIndex, nodeSize: options.nodeSize });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export default createKdbush;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const DEFAULT_LASSO_START_INITIATOR_SHOW = true;
|
|
2
|
+
export const DEFAULT_LASSO_MIN_DELAY = 8;
|
|
3
|
+
export const DEFAULT_LASSO_MIN_DIST = 2;
|
|
4
|
+
export const DEFAULT_LASSO_TYPE = 'freeform';
|
|
5
|
+
export const DEFAULT_BRUSH_SIZE = 24;
|
|
6
|
+
export const LASSO_SHOW_START_INITIATOR_TIME = 2500;
|
|
7
|
+
export const LASSO_HIDE_START_INITIATOR_TIME = 250;
|