@loaders.gl/json 4.0.0 → 4.0.2

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.
@@ -36,61 +36,69 @@
36
36
  }
37
37
 
38
38
  // ../worker-utils/src/lib/worker-farm/worker-body.ts
39
- function getParentPort() {
39
+ async function getParentPort() {
40
40
  let parentPort;
41
41
  try {
42
42
  eval("globalThis.parentPort = require('worker_threads').parentPort");
43
43
  parentPort = globalThis.parentPort;
44
44
  } catch {
45
+ try {
46
+ eval("globalThis.workerThreadsPromise = import('worker_threads')");
47
+ const workerThreads = await globalThis.workerThreadsPromise;
48
+ parentPort = workerThreads.parentPort;
49
+ } catch (error) {
50
+ console.error(error.message);
51
+ }
45
52
  }
46
53
  return parentPort;
47
54
  }
48
55
  var onMessageWrapperMap = /* @__PURE__ */ new Map();
49
56
  var WorkerBody = class {
50
57
  /** Check that we are actually in a worker thread */
51
- static inWorkerThread() {
52
- return typeof self !== "undefined" || Boolean(getParentPort());
58
+ static async inWorkerThread() {
59
+ return typeof self !== "undefined" || Boolean(await getParentPort());
53
60
  }
54
61
  /*
55
62
  * (type: WorkerMessageType, payload: WorkerMessagePayload) => any
56
63
  */
57
64
  static set onmessage(onMessage) {
58
- function handleMessage(message) {
59
- const parentPort3 = getParentPort();
60
- const { type, payload } = parentPort3 ? message : message.data;
65
+ async function handleMessage(message) {
66
+ const parentPort2 = await getParentPort();
67
+ const { type, payload } = parentPort2 ? message : message.data;
61
68
  onMessage(type, payload);
62
69
  }
63
- const parentPort2 = getParentPort();
64
- if (parentPort2) {
65
- parentPort2.on("message", handleMessage);
66
- parentPort2.on("exit", () => console.debug("Node worker closing"));
67
- } else {
68
- globalThis.onmessage = handleMessage;
69
- }
70
+ getParentPort().then((parentPort2) => {
71
+ if (parentPort2) {
72
+ parentPort2.on("message", handleMessage);
73
+ parentPort2.on("exit", () => console.debug("Node worker closing"));
74
+ } else {
75
+ globalThis.onmessage = handleMessage;
76
+ }
77
+ });
70
78
  }
71
- static addEventListener(onMessage) {
79
+ static async addEventListener(onMessage) {
72
80
  let onMessageWrapper = onMessageWrapperMap.get(onMessage);
73
81
  if (!onMessageWrapper) {
74
- onMessageWrapper = (message) => {
82
+ onMessageWrapper = async (message) => {
75
83
  if (!isKnownMessage(message)) {
76
84
  return;
77
85
  }
78
- const parentPort3 = getParentPort();
86
+ const parentPort3 = await getParentPort();
79
87
  const { type, payload } = parentPort3 ? message : message.data;
80
88
  onMessage(type, payload);
81
89
  };
82
90
  }
83
- const parentPort2 = getParentPort();
91
+ const parentPort2 = await getParentPort();
84
92
  if (parentPort2) {
85
93
  console.error("not implemented");
86
94
  } else {
87
95
  globalThis.addEventListener("message", onMessageWrapper);
88
96
  }
89
97
  }
90
- static removeEventListener(onMessage) {
98
+ static async removeEventListener(onMessage) {
91
99
  const onMessageWrapper = onMessageWrapperMap.get(onMessage);
92
100
  onMessageWrapperMap.delete(onMessage);
93
- const parentPort2 = getParentPort();
101
+ const parentPort2 = await getParentPort();
94
102
  if (parentPort2) {
95
103
  console.error("not implemented");
96
104
  } else {
@@ -102,10 +110,10 @@
102
110
  * @param type
103
111
  * @param payload
104
112
  */
105
- static postMessage(type, payload) {
113
+ static async postMessage(type, payload) {
106
114
  const data = { source: "loaders.gl", type, payload };
107
115
  const transferList = getTransferList(payload);
108
- const parentPort2 = getParentPort();
116
+ const parentPort2 = await getParentPort();
109
117
  if (parentPort2) {
110
118
  parentPort2.postMessage(data, transferList);
111
119
  } else {
@@ -120,8 +128,8 @@
120
128
 
121
129
  // ../loader-utils/src/lib/worker-loader-utils/create-loader-worker.ts
122
130
  var requestId = 0;
123
- function createLoaderWorker(loader) {
124
- if (!WorkerBody.inWorkerThread()) {
131
+ async function createLoaderWorker(loader) {
132
+ if (!await WorkerBody.inWorkerThread()) {
125
133
  return;
126
134
  }
127
135
  WorkerBody.onmessage = async (type, payload) => {
@@ -253,1356 +261,1356 @@
253
261
  return obj;
254
262
  }
255
263
 
256
- // ../../node_modules/@math.gl/polygon/dist/polygon-utils.js
257
- var DimIndex = {
258
- x: 0,
259
- y: 1,
260
- z: 2
261
- };
262
- function getPolygonSignedArea(points, options = {}) {
263
- const {
264
- start = 0,
265
- end = points.length,
266
- plane = "xy"
267
- } = options;
268
- const dim = options.size || 2;
269
- let area2 = 0;
270
- const i0 = DimIndex[plane[0]];
271
- const i1 = DimIndex[plane[1]];
272
- for (let i = start, j = end - dim; i < end; i += dim) {
273
- area2 += (points[i + i0] - points[j + i0]) * (points[i + i1] + points[j + i1]);
274
- j = i;
264
+ // ../schema/src/lib/table/batches/base-table-batch-aggregator.ts
265
+ var DEFAULT_ROW_COUNT = 100;
266
+ var BaseTableBatchAggregator = class {
267
+ constructor(schema, options) {
268
+ this.length = 0;
269
+ this.rows = null;
270
+ this.cursor = 0;
271
+ this._headers = [];
272
+ this.options = options;
273
+ this.schema = schema;
274
+ if (!Array.isArray(schema)) {
275
+ this._headers = [];
276
+ for (const key in schema) {
277
+ this._headers[schema[key].index] = schema[key].name;
278
+ }
279
+ }
275
280
  }
276
- return area2 / 2;
277
- }
278
-
279
- // ../../node_modules/@math.gl/polygon/dist/earcut.js
280
- function earcut(positions, holeIndices, dim = 2, areas, plane = "xy") {
281
- const hasHoles = holeIndices && holeIndices.length;
282
- const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
283
- let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0], plane);
284
- const triangles = [];
285
- if (!outerNode || outerNode.next === outerNode.prev)
286
- return triangles;
287
- let invSize;
288
- let maxX;
289
- let maxY;
290
- let minX;
291
- let minY;
292
- let x;
293
- let y;
294
- if (hasHoles)
295
- outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas, plane);
296
- if (positions.length > 80 * dim) {
297
- minX = maxX = positions[0];
298
- minY = maxY = positions[1];
299
- for (let i = dim; i < outerLen; i += dim) {
300
- x = positions[i];
301
- y = positions[i + 1];
302
- if (x < minX)
303
- minX = x;
304
- if (y < minY)
305
- minY = y;
306
- if (x > maxX)
307
- maxX = x;
308
- if (y > maxY)
309
- maxY = y;
281
+ rowCount() {
282
+ return this.length;
283
+ }
284
+ addArrayRow(row, cursor) {
285
+ if (Number.isFinite(cursor)) {
286
+ this.cursor = cursor;
310
287
  }
311
- invSize = Math.max(maxX - minX, maxY - minY);
312
- invSize = invSize !== 0 ? 32767 / invSize : 0;
288
+ this.rows = this.rows || new Array(DEFAULT_ROW_COUNT);
289
+ this.rows[this.length] = row;
290
+ this.length++;
313
291
  }
314
- earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
315
- return triangles;
316
- }
317
- function linkedList(data, start, end, dim, clockwise, area2, plane) {
318
- let i;
319
- let last;
320
- if (area2 === void 0) {
321
- area2 = getPolygonSignedArea(data, {
322
- start,
323
- end,
324
- size: dim,
325
- plane
326
- });
292
+ addObjectRow(row, cursor) {
293
+ if (Number.isFinite(cursor)) {
294
+ this.cursor = cursor;
295
+ }
296
+ this.rows = this.rows || new Array(DEFAULT_ROW_COUNT);
297
+ this.rows[this.length] = row;
298
+ this.length++;
327
299
  }
328
- let i0 = DimIndex[plane[0]];
329
- let i1 = DimIndex[plane[1]];
330
- if (clockwise === area2 < 0) {
331
- for (i = start; i < end; i += dim)
332
- last = insertNode(i, data[i + i0], data[i + i1], last);
333
- } else {
334
- for (i = end - dim; i >= start; i -= dim)
335
- last = insertNode(i, data[i + i0], data[i + i1], last);
300
+ getBatch() {
301
+ let rows = this.rows;
302
+ if (!rows) {
303
+ return null;
304
+ }
305
+ rows = rows.slice(0, this.length);
306
+ this.rows = null;
307
+ const batch = {
308
+ shape: this.options.shape,
309
+ batchType: "data",
310
+ data: rows,
311
+ length: this.length,
312
+ schema: this.schema,
313
+ cursor: this.cursor
314
+ };
315
+ return batch;
336
316
  }
337
- if (last && equals(last, last.next)) {
338
- removeNode(last);
339
- last = last.next;
317
+ };
318
+
319
+ // ../schema/src/lib/table/simple-table/row-utils.ts
320
+ function convertToObjectRow(arrayRow, headers) {
321
+ if (!arrayRow) {
322
+ throw new Error("null row");
340
323
  }
341
- return last;
324
+ if (!headers) {
325
+ throw new Error("no headers");
326
+ }
327
+ const objectRow = {};
328
+ for (let i = 0; i < headers.length; i++) {
329
+ objectRow[headers[i]] = arrayRow[i];
330
+ }
331
+ return objectRow;
342
332
  }
343
- function filterPoints(start, end) {
344
- if (!start)
345
- return start;
346
- if (!end)
347
- end = start;
348
- let p = start;
349
- let again;
350
- do {
351
- again = false;
352
- if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
353
- removeNode(p);
354
- p = end = p.prev;
355
- if (p === p.next)
356
- break;
357
- again = true;
358
- } else {
359
- p = p.next;
360
- }
361
- } while (again || p !== end);
362
- return end;
333
+ function convertToArrayRow(objectRow, headers) {
334
+ if (!objectRow) {
335
+ throw new Error("null row");
336
+ }
337
+ if (!headers) {
338
+ throw new Error("no headers");
339
+ }
340
+ const arrayRow = new Array(headers.length);
341
+ for (let i = 0; i < headers.length; i++) {
342
+ arrayRow[i] = objectRow[headers[i]];
343
+ }
344
+ return arrayRow;
363
345
  }
364
- function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
365
- if (!ear)
366
- return;
367
- if (!pass && invSize)
368
- indexCurve(ear, minX, minY, invSize);
369
- let stop = ear;
370
- let prev;
371
- let next;
372
- while (ear.prev !== ear.next) {
373
- prev = ear.prev;
374
- next = ear.next;
375
- if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
376
- triangles.push(prev.i / dim | 0);
377
- triangles.push(ear.i / dim | 0);
378
- triangles.push(next.i / dim | 0);
379
- removeNode(ear);
380
- ear = next.next;
381
- stop = next.next;
382
- continue;
383
- }
384
- ear = next;
385
- if (ear === stop) {
386
- if (!pass) {
387
- earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
388
- } else if (pass === 1) {
389
- ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
390
- earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
391
- } else if (pass === 2) {
392
- splitEarcut(ear, triangles, dim, minX, minY, invSize);
346
+
347
+ // ../schema/src/lib/table/batches/row-table-batch-aggregator.ts
348
+ var DEFAULT_ROW_COUNT2 = 100;
349
+ var RowTableBatchAggregator = class {
350
+ constructor(schema, options) {
351
+ this.length = 0;
352
+ this.objectRows = null;
353
+ this.arrayRows = null;
354
+ this.cursor = 0;
355
+ this._headers = [];
356
+ this.options = options;
357
+ this.schema = schema;
358
+ if (!Array.isArray(schema)) {
359
+ this._headers = [];
360
+ for (const key in schema) {
361
+ this._headers[schema[key].index] = schema[key].name;
393
362
  }
394
- break;
395
363
  }
396
364
  }
397
- }
398
- function isEar(ear) {
399
- const a = ear.prev;
400
- const b = ear;
401
- const c = ear.next;
402
- if (area(a, b, c) >= 0)
403
- return false;
404
- const ax = a.x;
405
- const bx = b.x;
406
- const cx = c.x;
407
- const ay = a.y;
408
- const by = b.y;
409
- const cy = c.y;
410
- const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
411
- const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
412
- const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
413
- const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
414
- let p = c.next;
415
- while (p !== a) {
416
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
417
- return false;
418
- p = p.next;
365
+ rowCount() {
366
+ return this.length;
419
367
  }
420
- return true;
421
- }
422
- function isEarHashed(ear, minX, minY, invSize) {
423
- const a = ear.prev;
424
- const b = ear;
425
- const c = ear.next;
426
- if (area(a, b, c) >= 0)
427
- return false;
428
- const ax = a.x;
429
- const bx = b.x;
430
- const cx = c.x;
431
- const ay = a.y;
432
- const by = b.y;
433
- const cy = c.y;
434
- const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
435
- const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
436
- const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
437
- const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
438
- const minZ = zOrder(x0, y0, minX, minY, invSize);
439
- const maxZ = zOrder(x1, y1, minX, minY, invSize);
440
- let p = ear.prevZ;
441
- let n = ear.nextZ;
442
- while (p && p.z >= minZ && n && n.z <= maxZ) {
443
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
444
- return false;
445
- p = p.prevZ;
446
- if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
447
- return false;
448
- n = n.nextZ;
449
- }
450
- while (p && p.z >= minZ) {
451
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
452
- return false;
453
- p = p.prevZ;
454
- }
455
- while (n && n.z <= maxZ) {
456
- if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
457
- return false;
458
- n = n.nextZ;
368
+ addArrayRow(row, cursor) {
369
+ if (Number.isFinite(cursor)) {
370
+ this.cursor = cursor;
371
+ }
372
+ switch (this.options.shape) {
373
+ case "object-row-table":
374
+ const rowObject = convertToObjectRow(row, this._headers);
375
+ this.addObjectRow(rowObject, cursor);
376
+ break;
377
+ case "array-row-table":
378
+ this.arrayRows = this.arrayRows || new Array(DEFAULT_ROW_COUNT2);
379
+ this.arrayRows[this.length] = row;
380
+ this.length++;
381
+ break;
382
+ }
459
383
  }
460
- return true;
461
- }
462
- function cureLocalIntersections(start, triangles, dim) {
463
- let p = start;
464
- do {
465
- const a = p.prev;
466
- const b = p.next.next;
467
- if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
468
- triangles.push(a.i / dim | 0);
469
- triangles.push(p.i / dim | 0);
470
- triangles.push(b.i / dim | 0);
471
- removeNode(p);
472
- removeNode(p.next);
473
- p = start = b;
384
+ addObjectRow(row, cursor) {
385
+ if (Number.isFinite(cursor)) {
386
+ this.cursor = cursor;
474
387
  }
475
- p = p.next;
476
- } while (p !== start);
477
- return filterPoints(p);
478
- }
479
- function splitEarcut(start, triangles, dim, minX, minY, invSize) {
480
- let a = start;
481
- do {
482
- let b = a.next.next;
483
- while (b !== a.prev) {
484
- if (a.i !== b.i && isValidDiagonal(a, b)) {
485
- let c = splitPolygon(a, b);
486
- a = filterPoints(a, a.next);
487
- c = filterPoints(c, c.next);
488
- earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
489
- earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
490
- return;
491
- }
492
- b = b.next;
388
+ switch (this.options.shape) {
389
+ case "array-row-table":
390
+ const rowArray = convertToArrayRow(row, this._headers);
391
+ this.addArrayRow(rowArray, cursor);
392
+ break;
393
+ case "object-row-table":
394
+ this.objectRows = this.objectRows || new Array(DEFAULT_ROW_COUNT2);
395
+ this.objectRows[this.length] = row;
396
+ this.length++;
397
+ break;
493
398
  }
494
- a = a.next;
495
- } while (a !== start);
496
- }
497
- function eliminateHoles(data, holeIndices, outerNode, dim, areas, plane) {
498
- const queue = [];
499
- let i;
500
- let len;
501
- let start;
502
- let end;
503
- let list;
504
- for (i = 0, len = holeIndices.length; i < len; i++) {
505
- start = holeIndices[i] * dim;
506
- end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
507
- list = linkedList(data, start, end, dim, false, areas && areas[i + 1], plane);
508
- if (list === list.next)
509
- list.steiner = true;
510
- queue.push(getLeftmost(list));
511
399
  }
512
- queue.sort(compareX);
513
- for (i = 0; i < queue.length; i++) {
514
- outerNode = eliminateHole(queue[i], outerNode);
400
+ getBatch() {
401
+ let rows = this.arrayRows || this.objectRows;
402
+ if (!rows) {
403
+ return null;
404
+ }
405
+ rows = rows.slice(0, this.length);
406
+ this.arrayRows = null;
407
+ this.objectRows = null;
408
+ return {
409
+ shape: this.options.shape,
410
+ batchType: "data",
411
+ data: rows,
412
+ length: this.length,
413
+ schema: this.schema,
414
+ cursor: this.cursor
415
+ };
515
416
  }
516
- return outerNode;
517
- }
518
- function compareX(a, b) {
519
- return a.x - b.x;
520
- }
521
- function eliminateHole(hole, outerNode) {
522
- const bridge = findHoleBridge(hole, outerNode);
523
- if (!bridge) {
524
- return outerNode;
417
+ };
418
+
419
+ // ../schema/src/lib/table/batches/columnar-table-batch-aggregator.ts
420
+ var DEFAULT_ROW_COUNT3 = 100;
421
+ var ColumnarTableBatchAggregator = class {
422
+ constructor(schema, options) {
423
+ this.length = 0;
424
+ this.allocated = 0;
425
+ this.columns = {};
426
+ this.schema = schema;
427
+ this._reallocateColumns();
525
428
  }
526
- const bridgeReverse = splitPolygon(bridge, hole);
527
- filterPoints(bridgeReverse, bridgeReverse.next);
528
- return filterPoints(bridge, bridge.next);
529
- }
530
- function findHoleBridge(hole, outerNode) {
531
- let p = outerNode;
532
- const hx = hole.x;
533
- const hy = hole.y;
534
- let qx = -Infinity;
535
- let m;
536
- do {
537
- if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
538
- const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
539
- if (x <= hx && x > qx) {
540
- qx = x;
541
- m = p.x < p.next.x ? p : p.next;
542
- if (x === hx)
543
- return m;
429
+ rowCount() {
430
+ return this.length;
431
+ }
432
+ addArrayRow(row) {
433
+ this._reallocateColumns();
434
+ let i = 0;
435
+ for (const fieldName in this.columns) {
436
+ this.columns[fieldName][this.length] = row[i++];
437
+ }
438
+ this.length++;
439
+ }
440
+ addObjectRow(row) {
441
+ this._reallocateColumns();
442
+ for (const fieldName in row) {
443
+ this.columns[fieldName][this.length] = row[fieldName];
444
+ }
445
+ this.length++;
446
+ }
447
+ getBatch() {
448
+ this._pruneColumns();
449
+ const columns = Array.isArray(this.schema) ? this.columns : {};
450
+ if (!Array.isArray(this.schema)) {
451
+ for (const fieldName in this.schema) {
452
+ const field = this.schema[fieldName];
453
+ columns[field.name] = this.columns[field.index];
544
454
  }
545
455
  }
546
- p = p.next;
547
- } while (p !== outerNode);
548
- if (!m)
549
- return null;
550
- const stop = m;
551
- const mx = m.x;
552
- const my = m.y;
553
- let tanMin = Infinity;
554
- let tan;
555
- p = m;
556
- do {
557
- if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
558
- tan = Math.abs(hy - p.y) / (hx - p.x);
559
- if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
560
- m = p;
561
- tanMin = tan;
456
+ this.columns = {};
457
+ const batch = {
458
+ shape: "columnar-table",
459
+ batchType: "data",
460
+ data: columns,
461
+ schema: this.schema,
462
+ length: this.length
463
+ };
464
+ return batch;
465
+ }
466
+ // HELPERS
467
+ _reallocateColumns() {
468
+ if (this.length < this.allocated) {
469
+ return;
470
+ }
471
+ this.allocated = this.allocated > 0 ? this.allocated *= 2 : DEFAULT_ROW_COUNT3;
472
+ this.columns = {};
473
+ for (const fieldName in this.schema) {
474
+ const field = this.schema[fieldName];
475
+ const ArrayType = field.type || Float32Array;
476
+ const oldColumn = this.columns[field.index];
477
+ if (oldColumn && ArrayBuffer.isView(oldColumn)) {
478
+ const typedArray = new ArrayType(this.allocated);
479
+ typedArray.set(oldColumn);
480
+ this.columns[field.index] = typedArray;
481
+ } else if (oldColumn) {
482
+ oldColumn.length = this.allocated;
483
+ this.columns[field.index] = oldColumn;
484
+ } else {
485
+ this.columns[field.index] = new ArrayType(this.allocated);
562
486
  }
563
487
  }
564
- p = p.next;
565
- } while (p !== stop);
566
- return m;
567
- }
568
- function sectorContainsSector(m, p) {
569
- return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
570
- }
571
- function indexCurve(start, minX, minY, invSize) {
572
- let p = start;
573
- do {
574
- if (p.z === 0)
575
- p.z = zOrder(p.x, p.y, minX, minY, invSize);
576
- p.prevZ = p.prev;
577
- p.nextZ = p.next;
578
- p = p.next;
579
- } while (p !== start);
580
- p.prevZ.nextZ = null;
581
- p.prevZ = null;
582
- sortLinked(p);
583
- }
584
- function sortLinked(list) {
585
- let e;
586
- let i;
587
- let inSize = 1;
588
- let numMerges;
589
- let p;
590
- let pSize;
591
- let q;
592
- let qSize;
593
- let tail;
594
- do {
595
- p = list;
596
- list = null;
597
- tail = null;
598
- numMerges = 0;
599
- while (p) {
600
- numMerges++;
601
- q = p;
602
- pSize = 0;
603
- for (i = 0; i < inSize; i++) {
604
- pSize++;
605
- q = q.nextZ;
606
- if (!q)
607
- break;
608
- }
609
- qSize = inSize;
610
- while (pSize > 0 || qSize > 0 && q) {
611
- if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
612
- e = p;
613
- p = p.nextZ;
614
- pSize--;
615
- } else {
616
- e = q;
617
- q = q.nextZ;
618
- qSize--;
619
- }
620
- if (tail)
621
- tail.nextZ = e;
622
- else
623
- list = e;
624
- e.prevZ = tail;
625
- tail = e;
488
+ }
489
+ _pruneColumns() {
490
+ for (const [columnName, column] of Object.entries(this.columns)) {
491
+ this.columns[columnName] = column.slice(0, this.length);
492
+ }
493
+ }
494
+ };
495
+
496
+ // ../schema/src/lib/table/batches/table-batch-builder.ts
497
+ var DEFAULT_OPTIONS = {
498
+ shape: "array-row-table",
499
+ batchSize: "auto",
500
+ batchDebounceMs: 0,
501
+ limit: 0,
502
+ _limitMB: 0
503
+ };
504
+ var ERR_MESSAGE = "TableBatchBuilder";
505
+ var TableBatchBuilder = class {
506
+ constructor(schema, options) {
507
+ this.aggregator = null;
508
+ this.batchCount = 0;
509
+ this.bytesUsed = 0;
510
+ this.isChunkComplete = false;
511
+ this.lastBatchEmittedMs = Date.now();
512
+ this.totalLength = 0;
513
+ this.totalBytes = 0;
514
+ this.rowBytes = 0;
515
+ this.schema = schema;
516
+ this.options = { ...DEFAULT_OPTIONS, ...options };
517
+ }
518
+ limitReached() {
519
+ if (Boolean(this.options?.limit) && this.totalLength >= this.options.limit) {
520
+ return true;
521
+ }
522
+ if (Boolean(this.options?._limitMB) && this.totalBytes / 1e6 >= this.options._limitMB) {
523
+ return true;
524
+ }
525
+ return false;
526
+ }
527
+ /** @deprecated Use addArrayRow or addObjectRow */
528
+ addRow(row) {
529
+ if (this.limitReached()) {
530
+ return;
531
+ }
532
+ this.totalLength++;
533
+ this.rowBytes = this.rowBytes || this._estimateRowMB(row);
534
+ this.totalBytes += this.rowBytes;
535
+ if (Array.isArray(row)) {
536
+ this.addArrayRow(row);
537
+ } else {
538
+ this.addObjectRow(row);
539
+ }
540
+ }
541
+ /** Add one row to the batch */
542
+ addArrayRow(row) {
543
+ if (!this.aggregator) {
544
+ const TableBatchType = this._getTableBatchType();
545
+ this.aggregator = new TableBatchType(this.schema, this.options);
546
+ }
547
+ this.aggregator.addArrayRow(row);
548
+ }
549
+ /** Add one row to the batch */
550
+ addObjectRow(row) {
551
+ if (!this.aggregator) {
552
+ const TableBatchType = this._getTableBatchType();
553
+ this.aggregator = new TableBatchType(this.schema, this.options);
554
+ }
555
+ this.aggregator.addObjectRow(row);
556
+ }
557
+ /** Mark an incoming raw memory chunk has completed */
558
+ chunkComplete(chunk) {
559
+ if (chunk instanceof ArrayBuffer) {
560
+ this.bytesUsed += chunk.byteLength;
561
+ }
562
+ if (typeof chunk === "string") {
563
+ this.bytesUsed += chunk.length;
564
+ }
565
+ this.isChunkComplete = true;
566
+ }
567
+ getFullBatch(options) {
568
+ return this._isFull() ? this._getBatch(options) : null;
569
+ }
570
+ getFinalBatch(options) {
571
+ return this._getBatch(options);
572
+ }
573
+ // INTERNAL
574
+ _estimateRowMB(row) {
575
+ return Array.isArray(row) ? row.length * 8 : Object.keys(row).length * 8;
576
+ }
577
+ _isFull() {
578
+ if (!this.aggregator || this.aggregator.rowCount() === 0) {
579
+ return false;
580
+ }
581
+ if (this.options.batchSize === "auto") {
582
+ if (!this.isChunkComplete) {
583
+ return false;
626
584
  }
627
- p = q;
585
+ } else if (this.options.batchSize > this.aggregator.rowCount()) {
586
+ return false;
628
587
  }
629
- tail.nextZ = null;
630
- inSize *= 2;
631
- } while (numMerges > 1);
632
- return list;
633
- }
634
- function zOrder(x, y, minX, minY, invSize) {
635
- x = (x - minX) * invSize | 0;
636
- y = (y - minY) * invSize | 0;
637
- x = (x | x << 8) & 16711935;
638
- x = (x | x << 4) & 252645135;
639
- x = (x | x << 2) & 858993459;
640
- x = (x | x << 1) & 1431655765;
641
- y = (y | y << 8) & 16711935;
642
- y = (y | y << 4) & 252645135;
643
- y = (y | y << 2) & 858993459;
644
- y = (y | y << 1) & 1431655765;
645
- return x | y << 1;
646
- }
647
- function getLeftmost(start) {
648
- let p = start;
649
- let leftmost = start;
650
- do {
651
- if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
652
- leftmost = p;
653
- p = p.next;
654
- } while (p !== start);
655
- return leftmost;
656
- }
657
- function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
658
- return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
659
- }
660
- function isValidDiagonal(a, b) {
661
- return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && (area(a.prev, a, b.prev) || area(a, b.prev, b)) || equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
662
- }
663
- function area(p, q, r) {
664
- return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
665
- }
666
- function equals(p1, p2) {
667
- return p1.x === p2.x && p1.y === p2.y;
668
- }
669
- function intersects(p1, q1, p2, q2) {
670
- const o1 = sign(area(p1, q1, p2));
671
- const o2 = sign(area(p1, q1, q2));
672
- const o3 = sign(area(p2, q2, p1));
673
- const o4 = sign(area(p2, q2, q1));
674
- if (o1 !== o2 && o3 !== o4)
675
- return true;
676
- if (o1 === 0 && onSegment(p1, p2, q1))
677
- return true;
678
- if (o2 === 0 && onSegment(p1, q2, q1))
679
- return true;
680
- if (o3 === 0 && onSegment(p2, p1, q2))
681
- return true;
682
- if (o4 === 0 && onSegment(p2, q1, q2))
588
+ if (this.options.batchDebounceMs > Date.now() - this.lastBatchEmittedMs) {
589
+ return false;
590
+ }
591
+ this.isChunkComplete = false;
592
+ this.lastBatchEmittedMs = Date.now();
683
593
  return true;
684
- return false;
685
- }
686
- function onSegment(p, q, r) {
687
- return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
688
- }
689
- function sign(num) {
690
- return num > 0 ? 1 : num < 0 ? -1 : 0;
691
- }
692
- function intersectsPolygon(a, b) {
693
- let p = a;
694
- do {
695
- if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b))
696
- return true;
697
- p = p.next;
698
- } while (p !== a);
699
- return false;
700
- }
701
- function locallyInside(a, b) {
702
- return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
703
- }
704
- function middleInside(a, b) {
705
- let p = a;
706
- let inside = false;
707
- const px = (a.x + b.x) / 2;
708
- const py = (a.y + b.y) / 2;
709
- do {
710
- if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)
711
- inside = !inside;
712
- p = p.next;
713
- } while (p !== a);
714
- return inside;
715
- }
716
- function splitPolygon(a, b) {
717
- const a2 = new Vertex(a.i, a.x, a.y);
718
- const b2 = new Vertex(b.i, b.x, b.y);
719
- const an = a.next;
720
- const bp = b.prev;
721
- a.next = b;
722
- b.prev = a;
723
- a2.next = an;
724
- an.prev = a2;
725
- b2.next = a2;
726
- a2.prev = b2;
727
- bp.next = b2;
728
- b2.prev = bp;
729
- return b2;
730
- }
731
- function insertNode(i, x, y, last) {
732
- const p = new Vertex(i, x, y);
733
- if (!last) {
734
- p.prev = p;
735
- p.next = p;
736
- } else {
737
- p.next = last.next;
738
- p.prev = last;
739
- last.next.prev = p;
740
- last.next = p;
741
594
  }
742
- return p;
743
- }
744
- function removeNode(p) {
745
- p.next.prev = p.prev;
746
- p.prev.next = p.next;
747
- if (p.prevZ)
748
- p.prevZ.nextZ = p.nextZ;
749
- if (p.nextZ)
750
- p.nextZ.prevZ = p.prevZ;
751
- }
752
- var Vertex = class {
753
- constructor(i, x, y) {
754
- _defineProperty(this, "i", void 0);
755
- _defineProperty(this, "x", void 0);
756
- _defineProperty(this, "y", void 0);
757
- _defineProperty(this, "prev", null);
758
- _defineProperty(this, "next", null);
759
- _defineProperty(this, "z", 0);
760
- _defineProperty(this, "prevZ", null);
761
- _defineProperty(this, "nextZ", null);
762
- _defineProperty(this, "steiner", false);
763
- this.i = i;
764
- this.x = x;
765
- this.y = y;
595
+ /**
596
+ * bytesUsed can be set via chunkComplete or via getBatch*
597
+ */
598
+ _getBatch(options) {
599
+ if (!this.aggregator) {
600
+ return null;
601
+ }
602
+ if (options?.bytesUsed) {
603
+ this.bytesUsed = options.bytesUsed;
604
+ }
605
+ const normalizedBatch = this.aggregator.getBatch();
606
+ normalizedBatch.count = this.batchCount;
607
+ normalizedBatch.bytesUsed = this.bytesUsed;
608
+ Object.assign(normalizedBatch, options);
609
+ this.batchCount++;
610
+ this.aggregator = null;
611
+ return normalizedBatch;
612
+ }
613
+ _getTableBatchType() {
614
+ switch (this.options.shape) {
615
+ case "row-table":
616
+ return BaseTableBatchAggregator;
617
+ case "array-row-table":
618
+ case "object-row-table":
619
+ return RowTableBatchAggregator;
620
+ case "columnar-table":
621
+ return ColumnarTableBatchAggregator;
622
+ case "arrow-table":
623
+ if (!TableBatchBuilder.ArrowBatch) {
624
+ throw new Error(ERR_MESSAGE);
625
+ }
626
+ return TableBatchBuilder.ArrowBatch;
627
+ default:
628
+ throw new Error(ERR_MESSAGE);
629
+ }
766
630
  }
767
631
  };
768
632
 
769
- // ../gis/src/lib/flat-geojson-to-binary.ts
770
- function flatGeojsonToBinary(features, geometryInfo, options) {
771
- const propArrayTypes = extractNumericPropTypes(features);
772
- const numericPropKeys = Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array);
773
- return fillArrays(
774
- features,
775
- {
776
- propArrayTypes,
777
- ...geometryInfo
778
- },
779
- {
780
- numericPropKeys: options && options.numericPropKeys || numericPropKeys,
781
- PositionDataType: options ? options.PositionDataType : Float32Array,
782
- triangulate: options ? options.triangulate : true
783
- }
784
- );
633
+ // ../../node_modules/@math.gl/polygon/dist/polygon-utils.js
634
+ var DimIndex = {
635
+ x: 0,
636
+ y: 1,
637
+ z: 2
638
+ };
639
+ function getPolygonSignedArea(points, options = {}) {
640
+ const {
641
+ start = 0,
642
+ end = points.length,
643
+ plane = "xy"
644
+ } = options;
645
+ const dim = options.size || 2;
646
+ let area2 = 0;
647
+ const i0 = DimIndex[plane[0]];
648
+ const i1 = DimIndex[plane[1]];
649
+ for (let i = start, j = end - dim; i < end; i += dim) {
650
+ area2 += (points[i + i0] - points[j + i0]) * (points[i + i1] + points[j + i1]);
651
+ j = i;
652
+ }
653
+ return area2 / 2;
785
654
  }
786
- function extractNumericPropTypes(features) {
787
- const propArrayTypes = {};
788
- for (const feature of features) {
789
- if (feature.properties) {
790
- for (const key in feature.properties) {
791
- const val = feature.properties[key];
792
- propArrayTypes[key] = deduceArrayType(val, propArrayTypes[key]);
793
- }
655
+
656
+ // ../../node_modules/@math.gl/polygon/dist/earcut.js
657
+ function earcut(positions, holeIndices, dim = 2, areas, plane = "xy") {
658
+ const hasHoles = holeIndices && holeIndices.length;
659
+ const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
660
+ let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0], plane);
661
+ const triangles = [];
662
+ if (!outerNode || outerNode.next === outerNode.prev)
663
+ return triangles;
664
+ let invSize;
665
+ let maxX;
666
+ let maxY;
667
+ let minX;
668
+ let minY;
669
+ let x;
670
+ let y;
671
+ if (hasHoles)
672
+ outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas, plane);
673
+ if (positions.length > 80 * dim) {
674
+ minX = maxX = positions[0];
675
+ minY = maxY = positions[1];
676
+ for (let i = dim; i < outerLen; i += dim) {
677
+ x = positions[i];
678
+ y = positions[i + 1];
679
+ if (x < minX)
680
+ minX = x;
681
+ if (y < minY)
682
+ minY = y;
683
+ if (x > maxX)
684
+ maxX = x;
685
+ if (y > maxY)
686
+ maxY = y;
794
687
  }
688
+ invSize = Math.max(maxX - minX, maxY - minY);
689
+ invSize = invSize !== 0 ? 32767 / invSize : 0;
795
690
  }
796
- return propArrayTypes;
691
+ earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
692
+ return triangles;
797
693
  }
798
- function fillArrays(features, geometryInfo, options) {
799
- const {
800
- pointPositionsCount,
801
- pointFeaturesCount,
802
- linePositionsCount,
803
- linePathsCount,
804
- lineFeaturesCount,
805
- polygonPositionsCount,
806
- polygonObjectsCount,
807
- polygonRingsCount,
808
- polygonFeaturesCount,
809
- propArrayTypes,
810
- coordLength
811
- } = geometryInfo;
812
- const { numericPropKeys = [], PositionDataType = Float32Array, triangulate = true } = options;
813
- const hasGlobalId = features[0] && "id" in features[0];
814
- const GlobalFeatureIdsDataType = features.length > 65535 ? Uint32Array : Uint16Array;
815
- const points = {
816
- type: "Point",
817
- positions: new PositionDataType(pointPositionsCount * coordLength),
818
- globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
819
- featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
820
- numericProps: {},
821
- properties: [],
822
- fields: []
823
- };
824
- const lines = {
825
- type: "LineString",
826
- pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
827
- positions: new PositionDataType(linePositionsCount * coordLength),
828
- globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
829
- featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
830
- numericProps: {},
831
- properties: [],
832
- fields: []
833
- };
834
- const polygons = {
835
- type: "Polygon",
836
- polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
837
- primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
838
- positions: new PositionDataType(polygonPositionsCount * coordLength),
839
- globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
840
- featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
841
- numericProps: {},
842
- properties: [],
843
- fields: []
844
- };
845
- if (triangulate) {
846
- polygons.triangles = [];
694
+ function linkedList(data, start, end, dim, clockwise, area2, plane) {
695
+ let i;
696
+ let last;
697
+ if (area2 === void 0) {
698
+ area2 = getPolygonSignedArea(data, {
699
+ start,
700
+ end,
701
+ size: dim,
702
+ plane
703
+ });
704
+ }
705
+ let i0 = DimIndex[plane[0]];
706
+ let i1 = DimIndex[plane[1]];
707
+ if (clockwise === area2 < 0) {
708
+ for (i = start; i < end; i += dim)
709
+ last = insertNode(i, data[i + i0], data[i + i1], last);
710
+ } else {
711
+ for (i = end - dim; i >= start; i -= dim)
712
+ last = insertNode(i, data[i + i0], data[i + i1], last);
847
713
  }
848
- for (const object of [points, lines, polygons]) {
849
- for (const propName of numericPropKeys) {
850
- const T = propArrayTypes[propName];
851
- object.numericProps[propName] = new T(object.positions.length / coordLength);
852
- }
714
+ if (last && equals(last, last.next)) {
715
+ removeNode(last);
716
+ last = last.next;
853
717
  }
854
- lines.pathIndices[linePathsCount] = linePositionsCount;
855
- polygons.polygonIndices[polygonObjectsCount] = polygonPositionsCount;
856
- polygons.primitivePolygonIndices[polygonRingsCount] = polygonPositionsCount;
857
- const indexMap = {
858
- pointPosition: 0,
859
- pointFeature: 0,
860
- linePosition: 0,
861
- linePath: 0,
862
- lineFeature: 0,
863
- polygonPosition: 0,
864
- polygonObject: 0,
865
- polygonRing: 0,
866
- polygonFeature: 0,
867
- feature: 0
868
- };
869
- for (const feature of features) {
870
- const geometry = feature.geometry;
871
- const properties = feature.properties || {};
872
- switch (geometry.type) {
873
- case "Point":
874
- handlePoint(geometry, points, indexMap, coordLength, properties);
875
- points.properties.push(keepStringProperties(properties, numericPropKeys));
876
- if (hasGlobalId) {
877
- points.fields.push({ id: feature.id });
878
- }
879
- indexMap.pointFeature++;
880
- break;
881
- case "LineString":
882
- handleLineString(geometry, lines, indexMap, coordLength, properties);
883
- lines.properties.push(keepStringProperties(properties, numericPropKeys));
884
- if (hasGlobalId) {
885
- lines.fields.push({ id: feature.id });
886
- }
887
- indexMap.lineFeature++;
888
- break;
889
- case "Polygon":
890
- handlePolygon(geometry, polygons, indexMap, coordLength, properties);
891
- polygons.properties.push(keepStringProperties(properties, numericPropKeys));
892
- if (hasGlobalId) {
893
- polygons.fields.push({ id: feature.id });
894
- }
895
- indexMap.polygonFeature++;
718
+ return last;
719
+ }
720
+ function filterPoints(start, end) {
721
+ if (!start)
722
+ return start;
723
+ if (!end)
724
+ end = start;
725
+ let p = start;
726
+ let again;
727
+ do {
728
+ again = false;
729
+ if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
730
+ removeNode(p);
731
+ p = end = p.prev;
732
+ if (p === p.next)
896
733
  break;
897
- default:
898
- throw new Error("Invalid geometry type");
734
+ again = true;
735
+ } else {
736
+ p = p.next;
737
+ }
738
+ } while (again || p !== end);
739
+ return end;
740
+ }
741
+ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
742
+ if (!ear)
743
+ return;
744
+ if (!pass && invSize)
745
+ indexCurve(ear, minX, minY, invSize);
746
+ let stop = ear;
747
+ let prev;
748
+ let next;
749
+ while (ear.prev !== ear.next) {
750
+ prev = ear.prev;
751
+ next = ear.next;
752
+ if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
753
+ triangles.push(prev.i / dim | 0);
754
+ triangles.push(ear.i / dim | 0);
755
+ triangles.push(next.i / dim | 0);
756
+ removeNode(ear);
757
+ ear = next.next;
758
+ stop = next.next;
759
+ continue;
760
+ }
761
+ ear = next;
762
+ if (ear === stop) {
763
+ if (!pass) {
764
+ earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
765
+ } else if (pass === 1) {
766
+ ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
767
+ earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
768
+ } else if (pass === 2) {
769
+ splitEarcut(ear, triangles, dim, minX, minY, invSize);
770
+ }
771
+ break;
899
772
  }
900
- indexMap.feature++;
901
773
  }
902
- return makeAccessorObjects(points, lines, polygons, coordLength);
903
774
  }
904
- function handlePoint(geometry, points, indexMap, coordLength, properties) {
905
- points.positions.set(geometry.data, indexMap.pointPosition * coordLength);
906
- const nPositions = geometry.data.length / coordLength;
907
- fillNumericProperties(points, properties, indexMap.pointPosition, nPositions);
908
- points.globalFeatureIds.fill(
909
- indexMap.feature,
910
- indexMap.pointPosition,
911
- indexMap.pointPosition + nPositions
912
- );
913
- points.featureIds.fill(
914
- indexMap.pointFeature,
915
- indexMap.pointPosition,
916
- indexMap.pointPosition + nPositions
917
- );
918
- indexMap.pointPosition += nPositions;
775
+ function isEar(ear) {
776
+ const a = ear.prev;
777
+ const b = ear;
778
+ const c = ear.next;
779
+ if (area(a, b, c) >= 0)
780
+ return false;
781
+ const ax = a.x;
782
+ const bx = b.x;
783
+ const cx = c.x;
784
+ const ay = a.y;
785
+ const by = b.y;
786
+ const cy = c.y;
787
+ const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
788
+ const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
789
+ const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
790
+ const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
791
+ let p = c.next;
792
+ while (p !== a) {
793
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
794
+ return false;
795
+ p = p.next;
796
+ }
797
+ return true;
919
798
  }
920
- function handleLineString(geometry, lines, indexMap, coordLength, properties) {
921
- lines.positions.set(geometry.data, indexMap.linePosition * coordLength);
922
- const nPositions = geometry.data.length / coordLength;
923
- fillNumericProperties(lines, properties, indexMap.linePosition, nPositions);
924
- lines.globalFeatureIds.fill(
925
- indexMap.feature,
926
- indexMap.linePosition,
927
- indexMap.linePosition + nPositions
928
- );
929
- lines.featureIds.fill(
930
- indexMap.lineFeature,
931
- indexMap.linePosition,
932
- indexMap.linePosition + nPositions
933
- );
934
- for (let i = 0, il = geometry.indices.length; i < il; ++i) {
935
- const start = geometry.indices[i];
936
- const end = i === il - 1 ? geometry.data.length : geometry.indices[i + 1];
937
- lines.pathIndices[indexMap.linePath++] = indexMap.linePosition;
938
- indexMap.linePosition += (end - start) / coordLength;
799
+ function isEarHashed(ear, minX, minY, invSize) {
800
+ const a = ear.prev;
801
+ const b = ear;
802
+ const c = ear.next;
803
+ if (area(a, b, c) >= 0)
804
+ return false;
805
+ const ax = a.x;
806
+ const bx = b.x;
807
+ const cx = c.x;
808
+ const ay = a.y;
809
+ const by = b.y;
810
+ const cy = c.y;
811
+ const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx;
812
+ const y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy;
813
+ const x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx;
814
+ const y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
815
+ const minZ = zOrder(x0, y0, minX, minY, invSize);
816
+ const maxZ = zOrder(x1, y1, minX, minY, invSize);
817
+ let p = ear.prevZ;
818
+ let n = ear.nextZ;
819
+ while (p && p.z >= minZ && n && n.z <= maxZ) {
820
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
821
+ return false;
822
+ p = p.prevZ;
823
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
824
+ return false;
825
+ n = n.nextZ;
826
+ }
827
+ while (p && p.z >= minZ) {
828
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
829
+ return false;
830
+ p = p.prevZ;
831
+ }
832
+ while (n && n.z <= maxZ) {
833
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
834
+ return false;
835
+ n = n.nextZ;
939
836
  }
837
+ return true;
940
838
  }
941
- function handlePolygon(geometry, polygons, indexMap, coordLength, properties) {
942
- polygons.positions.set(geometry.data, indexMap.polygonPosition * coordLength);
943
- const nPositions = geometry.data.length / coordLength;
944
- fillNumericProperties(polygons, properties, indexMap.polygonPosition, nPositions);
945
- polygons.globalFeatureIds.fill(
946
- indexMap.feature,
947
- indexMap.polygonPosition,
948
- indexMap.polygonPosition + nPositions
949
- );
950
- polygons.featureIds.fill(
951
- indexMap.polygonFeature,
952
- indexMap.polygonPosition,
953
- indexMap.polygonPosition + nPositions
954
- );
955
- for (let l = 0, ll = geometry.indices.length; l < ll; ++l) {
956
- const startPosition = indexMap.polygonPosition;
957
- polygons.polygonIndices[indexMap.polygonObject++] = startPosition;
958
- const areas = geometry.areas[l];
959
- const indices = geometry.indices[l];
960
- const nextIndices = geometry.indices[l + 1];
961
- for (let i = 0, il = indices.length; i < il; ++i) {
962
- const start = indices[i];
963
- const end = i === il - 1 ? (
964
- // last line, so either read to:
965
- nextIndices === void 0 ? geometry.data.length : nextIndices[0]
966
- ) : indices[i + 1];
967
- polygons.primitivePolygonIndices[indexMap.polygonRing++] = indexMap.polygonPosition;
968
- indexMap.polygonPosition += (end - start) / coordLength;
839
+ function cureLocalIntersections(start, triangles, dim) {
840
+ let p = start;
841
+ do {
842
+ const a = p.prev;
843
+ const b = p.next.next;
844
+ if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
845
+ triangles.push(a.i / dim | 0);
846
+ triangles.push(p.i / dim | 0);
847
+ triangles.push(b.i / dim | 0);
848
+ removeNode(p);
849
+ removeNode(p.next);
850
+ p = start = b;
851
+ }
852
+ p = p.next;
853
+ } while (p !== start);
854
+ return filterPoints(p);
855
+ }
856
+ function splitEarcut(start, triangles, dim, minX, minY, invSize) {
857
+ let a = start;
858
+ do {
859
+ let b = a.next.next;
860
+ while (b !== a.prev) {
861
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
862
+ let c = splitPolygon(a, b);
863
+ a = filterPoints(a, a.next);
864
+ c = filterPoints(c, c.next);
865
+ earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
866
+ earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
867
+ return;
868
+ }
869
+ b = b.next;
969
870
  }
970
- const endPosition = indexMap.polygonPosition;
971
- triangulatePolygon(polygons, areas, indices, { startPosition, endPosition, coordLength });
972
- }
871
+ a = a.next;
872
+ } while (a !== start);
973
873
  }
974
- function triangulatePolygon(polygons, areas, indices, {
975
- startPosition,
976
- endPosition,
977
- coordLength
978
- }) {
979
- if (!polygons.triangles) {
980
- return;
874
+ function eliminateHoles(data, holeIndices, outerNode, dim, areas, plane) {
875
+ const queue = [];
876
+ let i;
877
+ let len;
878
+ let start;
879
+ let end;
880
+ let list;
881
+ for (i = 0, len = holeIndices.length; i < len; i++) {
882
+ start = holeIndices[i] * dim;
883
+ end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
884
+ list = linkedList(data, start, end, dim, false, areas && areas[i + 1], plane);
885
+ if (list === list.next)
886
+ list.steiner = true;
887
+ queue.push(getLeftmost(list));
981
888
  }
982
- const start = startPosition * coordLength;
983
- const end = endPosition * coordLength;
984
- const polygonPositions = polygons.positions.subarray(start, end);
985
- const offset = indices[0];
986
- const holes = indices.slice(1).map((n) => (n - offset) / coordLength);
987
- const triangles = earcut(polygonPositions, holes, coordLength, areas);
988
- for (let t = 0, tl = triangles.length; t < tl; ++t) {
989
- polygons.triangles.push(startPosition + triangles[t]);
889
+ queue.sort(compareX);
890
+ for (i = 0; i < queue.length; i++) {
891
+ outerNode = eliminateHole(queue[i], outerNode);
990
892
  }
893
+ return outerNode;
991
894
  }
992
- function wrapProps(obj, size) {
993
- const returnObj = {};
994
- for (const key in obj) {
995
- returnObj[key] = { value: obj[key], size };
996
- }
997
- return returnObj;
895
+ function compareX(a, b) {
896
+ return a.x - b.x;
998
897
  }
999
- function makeAccessorObjects(points, lines, polygons, coordLength) {
1000
- const binaryFeatures = {
1001
- shape: "binary-feature-collection",
1002
- points: {
1003
- ...points,
1004
- positions: { value: points.positions, size: coordLength },
1005
- globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
1006
- featureIds: { value: points.featureIds, size: 1 },
1007
- numericProps: wrapProps(points.numericProps, 1)
1008
- },
1009
- lines: {
1010
- ...lines,
1011
- positions: { value: lines.positions, size: coordLength },
1012
- pathIndices: { value: lines.pathIndices, size: 1 },
1013
- globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
1014
- featureIds: { value: lines.featureIds, size: 1 },
1015
- numericProps: wrapProps(lines.numericProps, 1)
1016
- },
1017
- polygons: {
1018
- ...polygons,
1019
- positions: { value: polygons.positions, size: coordLength },
1020
- polygonIndices: { value: polygons.polygonIndices, size: 1 },
1021
- primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
1022
- globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
1023
- featureIds: { value: polygons.featureIds, size: 1 },
1024
- numericProps: wrapProps(polygons.numericProps, 1)
1025
- }
1026
- // triangles not expected
1027
- };
1028
- if (binaryFeatures.polygons && polygons.triangles) {
1029
- binaryFeatures.polygons.triangles = { value: new Uint32Array(polygons.triangles), size: 1 };
898
+ function eliminateHole(hole, outerNode) {
899
+ const bridge = findHoleBridge(hole, outerNode);
900
+ if (!bridge) {
901
+ return outerNode;
1030
902
  }
1031
- return binaryFeatures;
903
+ const bridgeReverse = splitPolygon(bridge, hole);
904
+ filterPoints(bridgeReverse, bridgeReverse.next);
905
+ return filterPoints(bridge, bridge.next);
1032
906
  }
1033
- function fillNumericProperties(object, properties, index, length) {
1034
- for (const numericPropName in object.numericProps) {
1035
- if (numericPropName in properties) {
1036
- const value = properties[numericPropName];
1037
- object.numericProps[numericPropName].fill(value, index, index + length);
907
+ function findHoleBridge(hole, outerNode) {
908
+ let p = outerNode;
909
+ const hx = hole.x;
910
+ const hy = hole.y;
911
+ let qx = -Infinity;
912
+ let m;
913
+ do {
914
+ if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
915
+ const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
916
+ if (x <= hx && x > qx) {
917
+ qx = x;
918
+ m = p.x < p.next.x ? p : p.next;
919
+ if (x === hx)
920
+ return m;
921
+ }
1038
922
  }
1039
- }
1040
- }
1041
- function keepStringProperties(properties, numericKeys) {
1042
- const props = {};
1043
- for (const key in properties) {
1044
- if (!numericKeys.includes(key)) {
1045
- props[key] = properties[key];
923
+ p = p.next;
924
+ } while (p !== outerNode);
925
+ if (!m)
926
+ return null;
927
+ const stop = m;
928
+ const mx = m.x;
929
+ const my = m.y;
930
+ let tanMin = Infinity;
931
+ let tan;
932
+ p = m;
933
+ do {
934
+ if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
935
+ tan = Math.abs(hy - p.y) / (hx - p.x);
936
+ if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
937
+ m = p;
938
+ tanMin = tan;
939
+ }
1046
940
  }
1047
- }
1048
- return props;
941
+ p = p.next;
942
+ } while (p !== stop);
943
+ return m;
1049
944
  }
1050
- function deduceArrayType(x, constructor) {
1051
- if (constructor === Array || !Number.isFinite(x)) {
1052
- return Array;
1053
- }
1054
- return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
945
+ function sectorContainsSector(m, p) {
946
+ return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
1055
947
  }
1056
-
1057
- // ../gis/src/lib/extract-geometry-info.ts
1058
- function extractGeometryInfo(features) {
1059
- let pointPositionsCount = 0;
1060
- let pointFeaturesCount = 0;
1061
- let linePositionsCount = 0;
1062
- let linePathsCount = 0;
1063
- let lineFeaturesCount = 0;
1064
- let polygonPositionsCount = 0;
1065
- let polygonObjectsCount = 0;
1066
- let polygonRingsCount = 0;
1067
- let polygonFeaturesCount = 0;
1068
- const coordLengths = /* @__PURE__ */ new Set();
1069
- for (const feature of features) {
1070
- const geometry = feature.geometry;
1071
- switch (geometry.type) {
1072
- case "Point":
1073
- pointFeaturesCount++;
1074
- pointPositionsCount++;
1075
- coordLengths.add(geometry.coordinates.length);
1076
- break;
1077
- case "MultiPoint":
1078
- pointFeaturesCount++;
1079
- pointPositionsCount += geometry.coordinates.length;
1080
- for (const point of geometry.coordinates) {
1081
- coordLengths.add(point.length);
1082
- }
1083
- break;
1084
- case "LineString":
1085
- lineFeaturesCount++;
1086
- linePositionsCount += geometry.coordinates.length;
1087
- linePathsCount++;
1088
- for (const coord of geometry.coordinates) {
1089
- coordLengths.add(coord.length);
1090
- }
1091
- break;
1092
- case "MultiLineString":
1093
- lineFeaturesCount++;
1094
- for (const line of geometry.coordinates) {
1095
- linePositionsCount += line.length;
1096
- linePathsCount++;
1097
- for (const coord of line) {
1098
- coordLengths.add(coord.length);
1099
- }
1100
- }
1101
- break;
1102
- case "Polygon":
1103
- polygonFeaturesCount++;
1104
- polygonObjectsCount++;
1105
- polygonRingsCount += geometry.coordinates.length;
1106
- const flattened = geometry.coordinates.flat();
1107
- polygonPositionsCount += flattened.length;
1108
- for (const coord of flattened) {
1109
- coordLengths.add(coord.length);
1110
- }
1111
- break;
1112
- case "MultiPolygon":
1113
- polygonFeaturesCount++;
1114
- for (const polygon of geometry.coordinates) {
1115
- polygonObjectsCount++;
1116
- polygonRingsCount += polygon.length;
1117
- const flattened2 = polygon.flat();
1118
- polygonPositionsCount += flattened2.length;
1119
- for (const coord of flattened2) {
1120
- coordLengths.add(coord.length);
1121
- }
948
+ function indexCurve(start, minX, minY, invSize) {
949
+ let p = start;
950
+ do {
951
+ if (p.z === 0)
952
+ p.z = zOrder(p.x, p.y, minX, minY, invSize);
953
+ p.prevZ = p.prev;
954
+ p.nextZ = p.next;
955
+ p = p.next;
956
+ } while (p !== start);
957
+ p.prevZ.nextZ = null;
958
+ p.prevZ = null;
959
+ sortLinked(p);
960
+ }
961
+ function sortLinked(list) {
962
+ let e;
963
+ let i;
964
+ let inSize = 1;
965
+ let numMerges;
966
+ let p;
967
+ let pSize;
968
+ let q;
969
+ let qSize;
970
+ let tail;
971
+ do {
972
+ p = list;
973
+ list = null;
974
+ tail = null;
975
+ numMerges = 0;
976
+ while (p) {
977
+ numMerges++;
978
+ q = p;
979
+ pSize = 0;
980
+ for (i = 0; i < inSize; i++) {
981
+ pSize++;
982
+ q = q.nextZ;
983
+ if (!q)
984
+ break;
985
+ }
986
+ qSize = inSize;
987
+ while (pSize > 0 || qSize > 0 && q) {
988
+ if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
989
+ e = p;
990
+ p = p.nextZ;
991
+ pSize--;
992
+ } else {
993
+ e = q;
994
+ q = q.nextZ;
995
+ qSize--;
1122
996
  }
1123
- break;
1124
- default:
1125
- throw new Error(`Unsupported geometry type: ${geometry.type}`);
997
+ if (tail)
998
+ tail.nextZ = e;
999
+ else
1000
+ list = e;
1001
+ e.prevZ = tail;
1002
+ tail = e;
1003
+ }
1004
+ p = q;
1126
1005
  }
1127
- }
1128
- return {
1129
- coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
1130
- pointPositionsCount,
1131
- pointFeaturesCount,
1132
- linePositionsCount,
1133
- linePathsCount,
1134
- lineFeaturesCount,
1135
- polygonPositionsCount,
1136
- polygonObjectsCount,
1137
- polygonRingsCount,
1138
- polygonFeaturesCount
1139
- };
1006
+ tail.nextZ = null;
1007
+ inSize *= 2;
1008
+ } while (numMerges > 1);
1009
+ return list;
1140
1010
  }
1141
-
1142
- // ../gis/src/lib/geojson-to-flat-geojson.ts
1143
- function geojsonToFlatGeojson(features, options = { coordLength: 2, fixRingWinding: true }) {
1144
- return features.map((feature) => flattenFeature(feature, options));
1011
+ function zOrder(x, y, minX, minY, invSize) {
1012
+ x = (x - minX) * invSize | 0;
1013
+ y = (y - minY) * invSize | 0;
1014
+ x = (x | x << 8) & 16711935;
1015
+ x = (x | x << 4) & 252645135;
1016
+ x = (x | x << 2) & 858993459;
1017
+ x = (x | x << 1) & 1431655765;
1018
+ y = (y | y << 8) & 16711935;
1019
+ y = (y | y << 4) & 252645135;
1020
+ y = (y | y << 2) & 858993459;
1021
+ y = (y | y << 1) & 1431655765;
1022
+ return x | y << 1;
1145
1023
  }
1146
- function flattenPoint(coordinates, data, indices, options) {
1147
- indices.push(data.length);
1148
- data.push(...coordinates);
1149
- for (let i = coordinates.length; i < options.coordLength; i++) {
1150
- data.push(0);
1151
- }
1024
+ function getLeftmost(start) {
1025
+ let p = start;
1026
+ let leftmost = start;
1027
+ do {
1028
+ if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
1029
+ leftmost = p;
1030
+ p = p.next;
1031
+ } while (p !== start);
1032
+ return leftmost;
1152
1033
  }
1153
- function flattenLineString(coordinates, data, indices, options) {
1154
- indices.push(data.length);
1155
- for (const c of coordinates) {
1156
- data.push(...c);
1157
- for (let i = c.length; i < options.coordLength; i++) {
1158
- data.push(0);
1159
- }
1160
- }
1034
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
1035
+ return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
1161
1036
  }
1162
- function flattenPolygon(coordinates, data, indices, areas, options) {
1163
- let count = 0;
1164
- const ringAreas = [];
1165
- const polygons = [];
1166
- for (const lineString of coordinates) {
1167
- const lineString2d = lineString.map((p) => p.slice(0, 2));
1168
- let area2 = getPolygonSignedArea(lineString2d.flat());
1169
- const ccw = area2 < 0;
1170
- if (options.fixRingWinding && (count === 0 && !ccw || count > 0 && ccw)) {
1171
- lineString.reverse();
1172
- area2 = -area2;
1173
- }
1174
- ringAreas.push(area2);
1175
- flattenLineString(lineString, data, polygons, options);
1176
- count++;
1177
- }
1178
- if (count > 0) {
1179
- areas.push(ringAreas);
1180
- indices.push(polygons);
1181
- }
1037
+ function isValidDiagonal(a, b) {
1038
+ return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && (area(a.prev, a, b.prev) || area(a, b.prev, b)) || equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
1182
1039
  }
1183
- function flattenFeature(feature, options) {
1184
- const { geometry } = feature;
1185
- if (geometry.type === "GeometryCollection") {
1186
- throw new Error("GeometryCollection type not supported");
1187
- }
1188
- const data = [];
1189
- const indices = [];
1190
- let areas;
1191
- let type;
1192
- switch (geometry.type) {
1193
- case "Point":
1194
- type = "Point";
1195
- flattenPoint(geometry.coordinates, data, indices, options);
1196
- break;
1197
- case "MultiPoint":
1198
- type = "Point";
1199
- geometry.coordinates.map((c) => flattenPoint(c, data, indices, options));
1200
- break;
1201
- case "LineString":
1202
- type = "LineString";
1203
- flattenLineString(geometry.coordinates, data, indices, options);
1204
- break;
1205
- case "MultiLineString":
1206
- type = "LineString";
1207
- geometry.coordinates.map((c) => flattenLineString(c, data, indices, options));
1208
- break;
1209
- case "Polygon":
1210
- type = "Polygon";
1211
- areas = [];
1212
- flattenPolygon(geometry.coordinates, data, indices, areas, options);
1213
- break;
1214
- case "MultiPolygon":
1215
- type = "Polygon";
1216
- areas = [];
1217
- geometry.coordinates.map((c) => flattenPolygon(c, data, indices, areas, options));
1218
- break;
1219
- default:
1220
- throw new Error(`Unknown type: ${type}`);
1221
- }
1222
- return { ...feature, geometry: { type, indices, data, areas } };
1040
+ function area(p, q, r) {
1041
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
1223
1042
  }
1224
-
1225
- // ../gis/src/lib/geojson-to-binary.ts
1226
- function geojsonToBinary(features, options = { fixRingWinding: true, triangulate: true }) {
1227
- const geometryInfo = extractGeometryInfo(features);
1228
- const coordLength = geometryInfo.coordLength;
1229
- const { fixRingWinding } = options;
1230
- const flatFeatures = geojsonToFlatGeojson(features, { coordLength, fixRingWinding });
1231
- return flatGeojsonToBinary(flatFeatures, geometryInfo, {
1232
- numericPropKeys: options.numericPropKeys,
1233
- PositionDataType: options.PositionDataType || Float32Array,
1234
- triangulate: options.triangulate
1235
- });
1043
+ function equals(p1, p2) {
1044
+ return p1.x === p2.x && p1.y === p2.y;
1236
1045
  }
1237
-
1238
- // ../schema/src/lib/table/batches/base-table-batch-aggregator.ts
1239
- var DEFAULT_ROW_COUNT = 100;
1240
- var BaseTableBatchAggregator = class {
1241
- constructor(schema, options) {
1242
- this.length = 0;
1243
- this.rows = null;
1244
- this.cursor = 0;
1245
- this._headers = [];
1246
- this.options = options;
1247
- this.schema = schema;
1248
- if (!Array.isArray(schema)) {
1249
- this._headers = [];
1250
- for (const key in schema) {
1251
- this._headers[schema[key].index] = schema[key].name;
1252
- }
1253
- }
1254
- }
1255
- rowCount() {
1256
- return this.length;
1257
- }
1258
- addArrayRow(row, cursor) {
1259
- if (Number.isFinite(cursor)) {
1260
- this.cursor = cursor;
1261
- }
1262
- this.rows = this.rows || new Array(DEFAULT_ROW_COUNT);
1263
- this.rows[this.length] = row;
1264
- this.length++;
1265
- }
1266
- addObjectRow(row, cursor) {
1267
- if (Number.isFinite(cursor)) {
1268
- this.cursor = cursor;
1269
- }
1270
- this.rows = this.rows || new Array(DEFAULT_ROW_COUNT);
1271
- this.rows[this.length] = row;
1272
- this.length++;
1273
- }
1274
- getBatch() {
1275
- let rows = this.rows;
1276
- if (!rows) {
1277
- return null;
1278
- }
1279
- rows = rows.slice(0, this.length);
1280
- this.rows = null;
1281
- const batch = {
1282
- shape: this.options.shape,
1283
- batchType: "data",
1284
- data: rows,
1285
- length: this.length,
1286
- schema: this.schema,
1287
- cursor: this.cursor
1288
- };
1289
- return batch;
1290
- }
1291
- };
1292
-
1293
- // ../schema/src/lib/table/simple-table/row-utils.ts
1294
- function convertToObjectRow(arrayRow, headers) {
1295
- if (!arrayRow) {
1296
- throw new Error("null row");
1297
- }
1298
- if (!headers) {
1299
- throw new Error("no headers");
1300
- }
1301
- const objectRow = {};
1302
- for (let i = 0; i < headers.length; i++) {
1303
- objectRow[headers[i]] = arrayRow[i];
1304
- }
1305
- return objectRow;
1046
+ function intersects(p1, q1, p2, q2) {
1047
+ const o1 = sign(area(p1, q1, p2));
1048
+ const o2 = sign(area(p1, q1, q2));
1049
+ const o3 = sign(area(p2, q2, p1));
1050
+ const o4 = sign(area(p2, q2, q1));
1051
+ if (o1 !== o2 && o3 !== o4)
1052
+ return true;
1053
+ if (o1 === 0 && onSegment(p1, p2, q1))
1054
+ return true;
1055
+ if (o2 === 0 && onSegment(p1, q2, q1))
1056
+ return true;
1057
+ if (o3 === 0 && onSegment(p2, p1, q2))
1058
+ return true;
1059
+ if (o4 === 0 && onSegment(p2, q1, q2))
1060
+ return true;
1061
+ return false;
1062
+ }
1063
+ function onSegment(p, q, r) {
1064
+ return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
1065
+ }
1066
+ function sign(num) {
1067
+ return num > 0 ? 1 : num < 0 ? -1 : 0;
1068
+ }
1069
+ function intersectsPolygon(a, b) {
1070
+ let p = a;
1071
+ do {
1072
+ if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b))
1073
+ return true;
1074
+ p = p.next;
1075
+ } while (p !== a);
1076
+ return false;
1077
+ }
1078
+ function locallyInside(a, b) {
1079
+ return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
1306
1080
  }
1307
- function convertToArrayRow(objectRow, headers) {
1308
- if (!objectRow) {
1309
- throw new Error("null row");
1310
- }
1311
- if (!headers) {
1312
- throw new Error("no headers");
1313
- }
1314
- const arrayRow = new Array(headers.length);
1315
- for (let i = 0; i < headers.length; i++) {
1316
- arrayRow[i] = objectRow[headers[i]];
1317
- }
1318
- return arrayRow;
1081
+ function middleInside(a, b) {
1082
+ let p = a;
1083
+ let inside = false;
1084
+ const px = (a.x + b.x) / 2;
1085
+ const py = (a.y + b.y) / 2;
1086
+ do {
1087
+ if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)
1088
+ inside = !inside;
1089
+ p = p.next;
1090
+ } while (p !== a);
1091
+ return inside;
1319
1092
  }
1320
-
1321
- // ../schema/src/lib/table/batches/row-table-batch-aggregator.ts
1322
- var DEFAULT_ROW_COUNT2 = 100;
1323
- var RowTableBatchAggregator = class {
1324
- constructor(schema, options) {
1325
- this.length = 0;
1326
- this.objectRows = null;
1327
- this.arrayRows = null;
1328
- this.cursor = 0;
1329
- this._headers = [];
1330
- this.options = options;
1331
- this.schema = schema;
1332
- if (!Array.isArray(schema)) {
1333
- this._headers = [];
1334
- for (const key in schema) {
1335
- this._headers[schema[key].index] = schema[key].name;
1336
- }
1337
- }
1338
- }
1339
- rowCount() {
1340
- return this.length;
1341
- }
1342
- addArrayRow(row, cursor) {
1343
- if (Number.isFinite(cursor)) {
1344
- this.cursor = cursor;
1345
- }
1346
- switch (this.options.shape) {
1347
- case "object-row-table":
1348
- const rowObject = convertToObjectRow(row, this._headers);
1349
- this.addObjectRow(rowObject, cursor);
1350
- break;
1351
- case "array-row-table":
1352
- this.arrayRows = this.arrayRows || new Array(DEFAULT_ROW_COUNT2);
1353
- this.arrayRows[this.length] = row;
1354
- this.length++;
1355
- break;
1356
- }
1357
- }
1358
- addObjectRow(row, cursor) {
1359
- if (Number.isFinite(cursor)) {
1360
- this.cursor = cursor;
1361
- }
1362
- switch (this.options.shape) {
1363
- case "array-row-table":
1364
- const rowArray = convertToArrayRow(row, this._headers);
1365
- this.addArrayRow(rowArray, cursor);
1366
- break;
1367
- case "object-row-table":
1368
- this.objectRows = this.objectRows || new Array(DEFAULT_ROW_COUNT2);
1369
- this.objectRows[this.length] = row;
1370
- this.length++;
1371
- break;
1372
- }
1093
+ function splitPolygon(a, b) {
1094
+ const a2 = new Vertex(a.i, a.x, a.y);
1095
+ const b2 = new Vertex(b.i, b.x, b.y);
1096
+ const an = a.next;
1097
+ const bp = b.prev;
1098
+ a.next = b;
1099
+ b.prev = a;
1100
+ a2.next = an;
1101
+ an.prev = a2;
1102
+ b2.next = a2;
1103
+ a2.prev = b2;
1104
+ bp.next = b2;
1105
+ b2.prev = bp;
1106
+ return b2;
1107
+ }
1108
+ function insertNode(i, x, y, last) {
1109
+ const p = new Vertex(i, x, y);
1110
+ if (!last) {
1111
+ p.prev = p;
1112
+ p.next = p;
1113
+ } else {
1114
+ p.next = last.next;
1115
+ p.prev = last;
1116
+ last.next.prev = p;
1117
+ last.next = p;
1373
1118
  }
1374
- getBatch() {
1375
- let rows = this.arrayRows || this.objectRows;
1376
- if (!rows) {
1377
- return null;
1378
- }
1379
- rows = rows.slice(0, this.length);
1380
- this.arrayRows = null;
1381
- this.objectRows = null;
1382
- return {
1383
- shape: this.options.shape,
1384
- batchType: "data",
1385
- data: rows,
1386
- length: this.length,
1387
- schema: this.schema,
1388
- cursor: this.cursor
1389
- };
1119
+ return p;
1120
+ }
1121
+ function removeNode(p) {
1122
+ p.next.prev = p.prev;
1123
+ p.prev.next = p.next;
1124
+ if (p.prevZ)
1125
+ p.prevZ.nextZ = p.nextZ;
1126
+ if (p.nextZ)
1127
+ p.nextZ.prevZ = p.prevZ;
1128
+ }
1129
+ var Vertex = class {
1130
+ constructor(i, x, y) {
1131
+ _defineProperty(this, "i", void 0);
1132
+ _defineProperty(this, "x", void 0);
1133
+ _defineProperty(this, "y", void 0);
1134
+ _defineProperty(this, "prev", null);
1135
+ _defineProperty(this, "next", null);
1136
+ _defineProperty(this, "z", 0);
1137
+ _defineProperty(this, "prevZ", null);
1138
+ _defineProperty(this, "nextZ", null);
1139
+ _defineProperty(this, "steiner", false);
1140
+ this.i = i;
1141
+ this.x = x;
1142
+ this.y = y;
1390
1143
  }
1391
1144
  };
1392
1145
 
1393
- // ../schema/src/lib/table/batches/columnar-table-batch-aggregator.ts
1394
- var DEFAULT_ROW_COUNT3 = 100;
1395
- var ColumnarTableBatchAggregator = class {
1396
- constructor(schema, options) {
1397
- this.length = 0;
1398
- this.allocated = 0;
1399
- this.columns = {};
1400
- this.schema = schema;
1401
- this._reallocateColumns();
1402
- }
1403
- rowCount() {
1404
- return this.length;
1405
- }
1406
- addArrayRow(row) {
1407
- this._reallocateColumns();
1408
- let i = 0;
1409
- for (const fieldName in this.columns) {
1410
- this.columns[fieldName][this.length] = row[i++];
1411
- }
1412
- this.length++;
1413
- }
1414
- addObjectRow(row) {
1415
- this._reallocateColumns();
1416
- for (const fieldName in row) {
1417
- this.columns[fieldName][this.length] = row[fieldName];
1146
+ // ../gis/src/lib/binary-features/flat-geojson-to-binary.ts
1147
+ function flatGeojsonToBinary(features, geometryInfo, options) {
1148
+ const propArrayTypes = extractNumericPropTypes(features);
1149
+ const numericPropKeys = Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array);
1150
+ return fillArrays(
1151
+ features,
1152
+ {
1153
+ propArrayTypes,
1154
+ ...geometryInfo
1155
+ },
1156
+ {
1157
+ numericPropKeys: options && options.numericPropKeys || numericPropKeys,
1158
+ PositionDataType: options ? options.PositionDataType : Float32Array,
1159
+ triangulate: options ? options.triangulate : true
1418
1160
  }
1419
- this.length++;
1420
- }
1421
- getBatch() {
1422
- this._pruneColumns();
1423
- const columns = Array.isArray(this.schema) ? this.columns : {};
1424
- if (!Array.isArray(this.schema)) {
1425
- for (const fieldName in this.schema) {
1426
- const field = this.schema[fieldName];
1427
- columns[field.name] = this.columns[field.index];
1161
+ );
1162
+ }
1163
+ function extractNumericPropTypes(features) {
1164
+ const propArrayTypes = {};
1165
+ for (const feature of features) {
1166
+ if (feature.properties) {
1167
+ for (const key in feature.properties) {
1168
+ const val = feature.properties[key];
1169
+ propArrayTypes[key] = deduceArrayType(val, propArrayTypes[key]);
1428
1170
  }
1429
1171
  }
1430
- this.columns = {};
1431
- const batch = {
1432
- shape: "columnar-table",
1433
- batchType: "data",
1434
- data: columns,
1435
- schema: this.schema,
1436
- length: this.length
1437
- };
1438
- return batch;
1439
1172
  }
1440
- // HELPERS
1441
- _reallocateColumns() {
1442
- if (this.length < this.allocated) {
1443
- return;
1444
- }
1445
- this.allocated = this.allocated > 0 ? this.allocated *= 2 : DEFAULT_ROW_COUNT3;
1446
- this.columns = {};
1447
- for (const fieldName in this.schema) {
1448
- const field = this.schema[fieldName];
1449
- const ArrayType = field.type || Float32Array;
1450
- const oldColumn = this.columns[field.index];
1451
- if (oldColumn && ArrayBuffer.isView(oldColumn)) {
1452
- const typedArray = new ArrayType(this.allocated);
1453
- typedArray.set(oldColumn);
1454
- this.columns[field.index] = typedArray;
1455
- } else if (oldColumn) {
1456
- oldColumn.length = this.allocated;
1457
- this.columns[field.index] = oldColumn;
1458
- } else {
1459
- this.columns[field.index] = new ArrayType(this.allocated);
1460
- }
1173
+ return propArrayTypes;
1174
+ }
1175
+ function fillArrays(features, geometryInfo, options) {
1176
+ const {
1177
+ pointPositionsCount,
1178
+ pointFeaturesCount,
1179
+ linePositionsCount,
1180
+ linePathsCount,
1181
+ lineFeaturesCount,
1182
+ polygonPositionsCount,
1183
+ polygonObjectsCount,
1184
+ polygonRingsCount,
1185
+ polygonFeaturesCount,
1186
+ propArrayTypes,
1187
+ coordLength
1188
+ } = geometryInfo;
1189
+ const { numericPropKeys = [], PositionDataType = Float32Array, triangulate = true } = options;
1190
+ const hasGlobalId = features[0] && "id" in features[0];
1191
+ const GlobalFeatureIdsDataType = features.length > 65535 ? Uint32Array : Uint16Array;
1192
+ const points = {
1193
+ type: "Point",
1194
+ positions: new PositionDataType(pointPositionsCount * coordLength),
1195
+ globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
1196
+ featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
1197
+ numericProps: {},
1198
+ properties: [],
1199
+ fields: []
1200
+ };
1201
+ const lines = {
1202
+ type: "LineString",
1203
+ pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
1204
+ positions: new PositionDataType(linePositionsCount * coordLength),
1205
+ globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
1206
+ featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
1207
+ numericProps: {},
1208
+ properties: [],
1209
+ fields: []
1210
+ };
1211
+ const polygons = {
1212
+ type: "Polygon",
1213
+ polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
1214
+ primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
1215
+ positions: new PositionDataType(polygonPositionsCount * coordLength),
1216
+ globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
1217
+ featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
1218
+ numericProps: {},
1219
+ properties: [],
1220
+ fields: []
1221
+ };
1222
+ if (triangulate) {
1223
+ polygons.triangles = [];
1224
+ }
1225
+ for (const object of [points, lines, polygons]) {
1226
+ for (const propName of numericPropKeys) {
1227
+ const T = propArrayTypes[propName];
1228
+ object.numericProps[propName] = new T(object.positions.length / coordLength);
1461
1229
  }
1462
1230
  }
1463
- _pruneColumns() {
1464
- for (const [columnName, column] of Object.entries(this.columns)) {
1465
- this.columns[columnName] = column.slice(0, this.length);
1231
+ lines.pathIndices[linePathsCount] = linePositionsCount;
1232
+ polygons.polygonIndices[polygonObjectsCount] = polygonPositionsCount;
1233
+ polygons.primitivePolygonIndices[polygonRingsCount] = polygonPositionsCount;
1234
+ const indexMap = {
1235
+ pointPosition: 0,
1236
+ pointFeature: 0,
1237
+ linePosition: 0,
1238
+ linePath: 0,
1239
+ lineFeature: 0,
1240
+ polygonPosition: 0,
1241
+ polygonObject: 0,
1242
+ polygonRing: 0,
1243
+ polygonFeature: 0,
1244
+ feature: 0
1245
+ };
1246
+ for (const feature of features) {
1247
+ const geometry = feature.geometry;
1248
+ const properties = feature.properties || {};
1249
+ switch (geometry.type) {
1250
+ case "Point":
1251
+ handlePoint(geometry, points, indexMap, coordLength, properties);
1252
+ points.properties.push(keepStringProperties(properties, numericPropKeys));
1253
+ if (hasGlobalId) {
1254
+ points.fields.push({ id: feature.id });
1255
+ }
1256
+ indexMap.pointFeature++;
1257
+ break;
1258
+ case "LineString":
1259
+ handleLineString(geometry, lines, indexMap, coordLength, properties);
1260
+ lines.properties.push(keepStringProperties(properties, numericPropKeys));
1261
+ if (hasGlobalId) {
1262
+ lines.fields.push({ id: feature.id });
1263
+ }
1264
+ indexMap.lineFeature++;
1265
+ break;
1266
+ case "Polygon":
1267
+ handlePolygon(geometry, polygons, indexMap, coordLength, properties);
1268
+ polygons.properties.push(keepStringProperties(properties, numericPropKeys));
1269
+ if (hasGlobalId) {
1270
+ polygons.fields.push({ id: feature.id });
1271
+ }
1272
+ indexMap.polygonFeature++;
1273
+ break;
1274
+ default:
1275
+ throw new Error("Invalid geometry type");
1466
1276
  }
1277
+ indexMap.feature++;
1467
1278
  }
1468
- };
1469
-
1470
- // ../schema/src/lib/table/batches/table-batch-builder.ts
1471
- var DEFAULT_OPTIONS = {
1472
- shape: "array-row-table",
1473
- batchSize: "auto",
1474
- batchDebounceMs: 0,
1475
- limit: 0,
1476
- _limitMB: 0
1477
- };
1478
- var ERR_MESSAGE = "TableBatchBuilder";
1479
- var TableBatchBuilder = class {
1480
- constructor(schema, options) {
1481
- this.aggregator = null;
1482
- this.batchCount = 0;
1483
- this.bytesUsed = 0;
1484
- this.isChunkComplete = false;
1485
- this.lastBatchEmittedMs = Date.now();
1486
- this.totalLength = 0;
1487
- this.totalBytes = 0;
1488
- this.rowBytes = 0;
1489
- this.schema = schema;
1490
- this.options = { ...DEFAULT_OPTIONS, ...options };
1279
+ return makeAccessorObjects(points, lines, polygons, coordLength);
1280
+ }
1281
+ function handlePoint(geometry, points, indexMap, coordLength, properties) {
1282
+ points.positions.set(geometry.data, indexMap.pointPosition * coordLength);
1283
+ const nPositions = geometry.data.length / coordLength;
1284
+ fillNumericProperties(points, properties, indexMap.pointPosition, nPositions);
1285
+ points.globalFeatureIds.fill(
1286
+ indexMap.feature,
1287
+ indexMap.pointPosition,
1288
+ indexMap.pointPosition + nPositions
1289
+ );
1290
+ points.featureIds.fill(
1291
+ indexMap.pointFeature,
1292
+ indexMap.pointPosition,
1293
+ indexMap.pointPosition + nPositions
1294
+ );
1295
+ indexMap.pointPosition += nPositions;
1296
+ }
1297
+ function handleLineString(geometry, lines, indexMap, coordLength, properties) {
1298
+ lines.positions.set(geometry.data, indexMap.linePosition * coordLength);
1299
+ const nPositions = geometry.data.length / coordLength;
1300
+ fillNumericProperties(lines, properties, indexMap.linePosition, nPositions);
1301
+ lines.globalFeatureIds.fill(
1302
+ indexMap.feature,
1303
+ indexMap.linePosition,
1304
+ indexMap.linePosition + nPositions
1305
+ );
1306
+ lines.featureIds.fill(
1307
+ indexMap.lineFeature,
1308
+ indexMap.linePosition,
1309
+ indexMap.linePosition + nPositions
1310
+ );
1311
+ for (let i = 0, il = geometry.indices.length; i < il; ++i) {
1312
+ const start = geometry.indices[i];
1313
+ const end = i === il - 1 ? geometry.data.length : geometry.indices[i + 1];
1314
+ lines.pathIndices[indexMap.linePath++] = indexMap.linePosition;
1315
+ indexMap.linePosition += (end - start) / coordLength;
1491
1316
  }
1492
- limitReached() {
1493
- if (Boolean(this.options?.limit) && this.totalLength >= this.options.limit) {
1494
- return true;
1495
- }
1496
- if (Boolean(this.options?._limitMB) && this.totalBytes / 1e6 >= this.options._limitMB) {
1497
- return true;
1317
+ }
1318
+ function handlePolygon(geometry, polygons, indexMap, coordLength, properties) {
1319
+ polygons.positions.set(geometry.data, indexMap.polygonPosition * coordLength);
1320
+ const nPositions = geometry.data.length / coordLength;
1321
+ fillNumericProperties(polygons, properties, indexMap.polygonPosition, nPositions);
1322
+ polygons.globalFeatureIds.fill(
1323
+ indexMap.feature,
1324
+ indexMap.polygonPosition,
1325
+ indexMap.polygonPosition + nPositions
1326
+ );
1327
+ polygons.featureIds.fill(
1328
+ indexMap.polygonFeature,
1329
+ indexMap.polygonPosition,
1330
+ indexMap.polygonPosition + nPositions
1331
+ );
1332
+ for (let l = 0, ll = geometry.indices.length; l < ll; ++l) {
1333
+ const startPosition = indexMap.polygonPosition;
1334
+ polygons.polygonIndices[indexMap.polygonObject++] = startPosition;
1335
+ const areas = geometry.areas[l];
1336
+ const indices = geometry.indices[l];
1337
+ const nextIndices = geometry.indices[l + 1];
1338
+ for (let i = 0, il = indices.length; i < il; ++i) {
1339
+ const start = indices[i];
1340
+ const end = i === il - 1 ? (
1341
+ // last line, so either read to:
1342
+ nextIndices === void 0 ? geometry.data.length : nextIndices[0]
1343
+ ) : indices[i + 1];
1344
+ polygons.primitivePolygonIndices[indexMap.polygonRing++] = indexMap.polygonPosition;
1345
+ indexMap.polygonPosition += (end - start) / coordLength;
1498
1346
  }
1499
- return false;
1347
+ const endPosition = indexMap.polygonPosition;
1348
+ triangulatePolygon(polygons, areas, indices, { startPosition, endPosition, coordLength });
1500
1349
  }
1501
- /** @deprecated Use addArrayRow or addObjectRow */
1502
- addRow(row) {
1503
- if (this.limitReached()) {
1504
- return;
1505
- }
1506
- this.totalLength++;
1507
- this.rowBytes = this.rowBytes || this._estimateRowMB(row);
1508
- this.totalBytes += this.rowBytes;
1509
- if (Array.isArray(row)) {
1510
- this.addArrayRow(row);
1511
- } else {
1512
- this.addObjectRow(row);
1513
- }
1350
+ }
1351
+ function triangulatePolygon(polygons, areas, indices, {
1352
+ startPosition,
1353
+ endPosition,
1354
+ coordLength
1355
+ }) {
1356
+ if (!polygons.triangles) {
1357
+ return;
1514
1358
  }
1515
- /** Add one row to the batch */
1516
- addArrayRow(row) {
1517
- if (!this.aggregator) {
1518
- const TableBatchType = this._getTableBatchType();
1519
- this.aggregator = new TableBatchType(this.schema, this.options);
1520
- }
1521
- this.aggregator.addArrayRow(row);
1359
+ const start = startPosition * coordLength;
1360
+ const end = endPosition * coordLength;
1361
+ const polygonPositions = polygons.positions.subarray(start, end);
1362
+ const offset = indices[0];
1363
+ const holes = indices.slice(1).map((n) => (n - offset) / coordLength);
1364
+ const triangles = earcut(polygonPositions, holes, coordLength, areas);
1365
+ for (let t = 0, tl = triangles.length; t < tl; ++t) {
1366
+ polygons.triangles.push(startPosition + triangles[t]);
1522
1367
  }
1523
- /** Add one row to the batch */
1524
- addObjectRow(row) {
1525
- if (!this.aggregator) {
1526
- const TableBatchType = this._getTableBatchType();
1527
- this.aggregator = new TableBatchType(this.schema, this.options);
1368
+ }
1369
+ function wrapProps(obj, size) {
1370
+ const returnObj = {};
1371
+ for (const key in obj) {
1372
+ returnObj[key] = { value: obj[key], size };
1373
+ }
1374
+ return returnObj;
1375
+ }
1376
+ function makeAccessorObjects(points, lines, polygons, coordLength) {
1377
+ const binaryFeatures = {
1378
+ shape: "binary-feature-collection",
1379
+ points: {
1380
+ ...points,
1381
+ positions: { value: points.positions, size: coordLength },
1382
+ globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
1383
+ featureIds: { value: points.featureIds, size: 1 },
1384
+ numericProps: wrapProps(points.numericProps, 1)
1385
+ },
1386
+ lines: {
1387
+ ...lines,
1388
+ positions: { value: lines.positions, size: coordLength },
1389
+ pathIndices: { value: lines.pathIndices, size: 1 },
1390
+ globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
1391
+ featureIds: { value: lines.featureIds, size: 1 },
1392
+ numericProps: wrapProps(lines.numericProps, 1)
1393
+ },
1394
+ polygons: {
1395
+ ...polygons,
1396
+ positions: { value: polygons.positions, size: coordLength },
1397
+ polygonIndices: { value: polygons.polygonIndices, size: 1 },
1398
+ primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
1399
+ globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
1400
+ featureIds: { value: polygons.featureIds, size: 1 },
1401
+ numericProps: wrapProps(polygons.numericProps, 1)
1528
1402
  }
1529
- this.aggregator.addObjectRow(row);
1403
+ // triangles not expected
1404
+ };
1405
+ if (binaryFeatures.polygons && polygons.triangles) {
1406
+ binaryFeatures.polygons.triangles = { value: new Uint32Array(polygons.triangles), size: 1 };
1530
1407
  }
1531
- /** Mark an incoming raw memory chunk has completed */
1532
- chunkComplete(chunk) {
1533
- if (chunk instanceof ArrayBuffer) {
1534
- this.bytesUsed += chunk.byteLength;
1408
+ return binaryFeatures;
1409
+ }
1410
+ function fillNumericProperties(object, properties, index, length) {
1411
+ for (const numericPropName in object.numericProps) {
1412
+ if (numericPropName in properties) {
1413
+ const value = properties[numericPropName];
1414
+ object.numericProps[numericPropName].fill(value, index, index + length);
1535
1415
  }
1536
- if (typeof chunk === "string") {
1537
- this.bytesUsed += chunk.length;
1416
+ }
1417
+ }
1418
+ function keepStringProperties(properties, numericKeys) {
1419
+ const props = {};
1420
+ for (const key in properties) {
1421
+ if (!numericKeys.includes(key)) {
1422
+ props[key] = properties[key];
1538
1423
  }
1539
- this.isChunkComplete = true;
1540
1424
  }
1541
- getFullBatch(options) {
1542
- return this._isFull() ? this._getBatch(options) : null;
1425
+ return props;
1426
+ }
1427
+ function deduceArrayType(x, constructor) {
1428
+ if (constructor === Array || !Number.isFinite(x)) {
1429
+ return Array;
1543
1430
  }
1544
- getFinalBatch(options) {
1545
- return this._getBatch(options);
1431
+ return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
1432
+ }
1433
+
1434
+ // ../gis/src/lib/binary-features/extract-geometry-info.ts
1435
+ function extractGeometryInfo(features) {
1436
+ let pointPositionsCount = 0;
1437
+ let pointFeaturesCount = 0;
1438
+ let linePositionsCount = 0;
1439
+ let linePathsCount = 0;
1440
+ let lineFeaturesCount = 0;
1441
+ let polygonPositionsCount = 0;
1442
+ let polygonObjectsCount = 0;
1443
+ let polygonRingsCount = 0;
1444
+ let polygonFeaturesCount = 0;
1445
+ const coordLengths = /* @__PURE__ */ new Set();
1446
+ for (const feature of features) {
1447
+ const geometry = feature.geometry;
1448
+ switch (geometry.type) {
1449
+ case "Point":
1450
+ pointFeaturesCount++;
1451
+ pointPositionsCount++;
1452
+ coordLengths.add(geometry.coordinates.length);
1453
+ break;
1454
+ case "MultiPoint":
1455
+ pointFeaturesCount++;
1456
+ pointPositionsCount += geometry.coordinates.length;
1457
+ for (const point of geometry.coordinates) {
1458
+ coordLengths.add(point.length);
1459
+ }
1460
+ break;
1461
+ case "LineString":
1462
+ lineFeaturesCount++;
1463
+ linePositionsCount += geometry.coordinates.length;
1464
+ linePathsCount++;
1465
+ for (const coord of geometry.coordinates) {
1466
+ coordLengths.add(coord.length);
1467
+ }
1468
+ break;
1469
+ case "MultiLineString":
1470
+ lineFeaturesCount++;
1471
+ for (const line of geometry.coordinates) {
1472
+ linePositionsCount += line.length;
1473
+ linePathsCount++;
1474
+ for (const coord of line) {
1475
+ coordLengths.add(coord.length);
1476
+ }
1477
+ }
1478
+ break;
1479
+ case "Polygon":
1480
+ polygonFeaturesCount++;
1481
+ polygonObjectsCount++;
1482
+ polygonRingsCount += geometry.coordinates.length;
1483
+ const flattened = geometry.coordinates.flat();
1484
+ polygonPositionsCount += flattened.length;
1485
+ for (const coord of flattened) {
1486
+ coordLengths.add(coord.length);
1487
+ }
1488
+ break;
1489
+ case "MultiPolygon":
1490
+ polygonFeaturesCount++;
1491
+ for (const polygon of geometry.coordinates) {
1492
+ polygonObjectsCount++;
1493
+ polygonRingsCount += polygon.length;
1494
+ const flattened2 = polygon.flat();
1495
+ polygonPositionsCount += flattened2.length;
1496
+ for (const coord of flattened2) {
1497
+ coordLengths.add(coord.length);
1498
+ }
1499
+ }
1500
+ break;
1501
+ default:
1502
+ throw new Error(`Unsupported geometry type: ${geometry.type}`);
1503
+ }
1546
1504
  }
1547
- // INTERNAL
1548
- _estimateRowMB(row) {
1549
- return Array.isArray(row) ? row.length * 8 : Object.keys(row).length * 8;
1505
+ return {
1506
+ coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
1507
+ pointPositionsCount,
1508
+ pointFeaturesCount,
1509
+ linePositionsCount,
1510
+ linePathsCount,
1511
+ lineFeaturesCount,
1512
+ polygonPositionsCount,
1513
+ polygonObjectsCount,
1514
+ polygonRingsCount,
1515
+ polygonFeaturesCount
1516
+ };
1517
+ }
1518
+
1519
+ // ../gis/src/lib/binary-features/geojson-to-flat-geojson.ts
1520
+ function geojsonToFlatGeojson(features, options = { coordLength: 2, fixRingWinding: true }) {
1521
+ return features.map((feature) => flattenFeature(feature, options));
1522
+ }
1523
+ function flattenPoint(coordinates, data, indices, options) {
1524
+ indices.push(data.length);
1525
+ data.push(...coordinates);
1526
+ for (let i = coordinates.length; i < options.coordLength; i++) {
1527
+ data.push(0);
1550
1528
  }
1551
- _isFull() {
1552
- if (!this.aggregator || this.aggregator.rowCount() === 0) {
1553
- return false;
1554
- }
1555
- if (this.options.batchSize === "auto") {
1556
- if (!this.isChunkComplete) {
1557
- return false;
1558
- }
1559
- } else if (this.options.batchSize > this.aggregator.rowCount()) {
1560
- return false;
1561
- }
1562
- if (this.options.batchDebounceMs > Date.now() - this.lastBatchEmittedMs) {
1563
- return false;
1529
+ }
1530
+ function flattenLineString(coordinates, data, indices, options) {
1531
+ indices.push(data.length);
1532
+ for (const c of coordinates) {
1533
+ data.push(...c);
1534
+ for (let i = c.length; i < options.coordLength; i++) {
1535
+ data.push(0);
1564
1536
  }
1565
- this.isChunkComplete = false;
1566
- this.lastBatchEmittedMs = Date.now();
1567
- return true;
1568
1537
  }
1569
- /**
1570
- * bytesUsed can be set via chunkComplete or via getBatch*
1571
- */
1572
- _getBatch(options) {
1573
- if (!this.aggregator) {
1574
- return null;
1575
- }
1576
- if (options?.bytesUsed) {
1577
- this.bytesUsed = options.bytesUsed;
1538
+ }
1539
+ function flattenPolygon(coordinates, data, indices, areas, options) {
1540
+ let count = 0;
1541
+ const ringAreas = [];
1542
+ const polygons = [];
1543
+ for (const lineString of coordinates) {
1544
+ const lineString2d = lineString.map((p) => p.slice(0, 2));
1545
+ let area2 = getPolygonSignedArea(lineString2d.flat());
1546
+ const ccw = area2 < 0;
1547
+ if (options.fixRingWinding && (count === 0 && !ccw || count > 0 && ccw)) {
1548
+ lineString.reverse();
1549
+ area2 = -area2;
1578
1550
  }
1579
- const normalizedBatch = this.aggregator.getBatch();
1580
- normalizedBatch.count = this.batchCount;
1581
- normalizedBatch.bytesUsed = this.bytesUsed;
1582
- Object.assign(normalizedBatch, options);
1583
- this.batchCount++;
1584
- this.aggregator = null;
1585
- return normalizedBatch;
1551
+ ringAreas.push(area2);
1552
+ flattenLineString(lineString, data, polygons, options);
1553
+ count++;
1586
1554
  }
1587
- _getTableBatchType() {
1588
- switch (this.options.shape) {
1589
- case "row-table":
1590
- return BaseTableBatchAggregator;
1591
- case "array-row-table":
1592
- case "object-row-table":
1593
- return RowTableBatchAggregator;
1594
- case "columnar-table":
1595
- return ColumnarTableBatchAggregator;
1596
- case "arrow-table":
1597
- if (!TableBatchBuilder.ArrowBatch) {
1598
- throw new Error(ERR_MESSAGE);
1599
- }
1600
- return TableBatchBuilder.ArrowBatch;
1601
- default:
1602
- throw new Error(ERR_MESSAGE);
1603
- }
1555
+ if (count > 0) {
1556
+ areas.push(ringAreas);
1557
+ indices.push(polygons);
1604
1558
  }
1605
- };
1559
+ }
1560
+ function flattenFeature(feature, options) {
1561
+ const { geometry } = feature;
1562
+ if (geometry.type === "GeometryCollection") {
1563
+ throw new Error("GeometryCollection type not supported");
1564
+ }
1565
+ const data = [];
1566
+ const indices = [];
1567
+ let areas;
1568
+ let type;
1569
+ switch (geometry.type) {
1570
+ case "Point":
1571
+ type = "Point";
1572
+ flattenPoint(geometry.coordinates, data, indices, options);
1573
+ break;
1574
+ case "MultiPoint":
1575
+ type = "Point";
1576
+ geometry.coordinates.map((c) => flattenPoint(c, data, indices, options));
1577
+ break;
1578
+ case "LineString":
1579
+ type = "LineString";
1580
+ flattenLineString(geometry.coordinates, data, indices, options);
1581
+ break;
1582
+ case "MultiLineString":
1583
+ type = "LineString";
1584
+ geometry.coordinates.map((c) => flattenLineString(c, data, indices, options));
1585
+ break;
1586
+ case "Polygon":
1587
+ type = "Polygon";
1588
+ areas = [];
1589
+ flattenPolygon(geometry.coordinates, data, indices, areas, options);
1590
+ break;
1591
+ case "MultiPolygon":
1592
+ type = "Polygon";
1593
+ areas = [];
1594
+ geometry.coordinates.map((c) => flattenPolygon(c, data, indices, areas, options));
1595
+ break;
1596
+ default:
1597
+ throw new Error(`Unknown type: ${type}`);
1598
+ }
1599
+ return { ...feature, geometry: { type, indices, data, areas } };
1600
+ }
1601
+
1602
+ // ../gis/src/lib/binary-features/geojson-to-binary.ts
1603
+ function geojsonToBinary(features, options = { fixRingWinding: true, triangulate: true }) {
1604
+ const geometryInfo = extractGeometryInfo(features);
1605
+ const coordLength = geometryInfo.coordLength;
1606
+ const { fixRingWinding } = options;
1607
+ const flatFeatures = geojsonToFlatGeojson(features, { coordLength, fixRingWinding });
1608
+ return flatGeojsonToBinary(flatFeatures, geometryInfo, {
1609
+ numericPropKeys: options.numericPropKeys,
1610
+ PositionDataType: options.PositionDataType || Float32Array,
1611
+ triangulate: options.triangulate
1612
+ });
1613
+ }
1606
1614
 
1607
1615
  // src/lib/clarinet/clarinet.ts
1608
1616
  var MAX_BUFFER_LENGTH = Number.MAX_SAFE_INTEGER;
@@ -2417,7 +2425,7 @@ Char: ${this.c}`;
2417
2425
  }
2418
2426
 
2419
2427
  // src/geojson-loader.ts
2420
- var VERSION = true ? "4.0.0" : "latest";
2428
+ var VERSION = true ? "4.0.2" : "latest";
2421
2429
  var GeoJSONWorkerLoader = {
2422
2430
  name: "GeoJSON",
2423
2431
  id: "geojson",