@loaders.gl/json 3.1.0 → 3.1.4

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.
@@ -159,83 +159,509 @@
159
159
  }
160
160
  }
161
161
 
162
- // ../gis/src/lib/geojson-to-binary.ts
163
- function geojsonToBinary(features, options = {}) {
164
- const firstPassData = firstPass(features);
165
- return secondPass(features, firstPassData, {
166
- coordLength: options.coordLength || firstPassData.coordLength,
167
- numericPropKeys: options.numericPropKeys || firstPassData.numericPropKeys,
168
- PositionDataType: options.PositionDataType || Float32Array
169
- });
162
+ // ../../node_modules/@math.gl/polygon/dist/esm/polygon-utils.js
163
+ function getPolygonSignedArea(points, options = {}) {
164
+ const {
165
+ start = 0,
166
+ end = points.length
167
+ } = options;
168
+ const dim = options.size || 2;
169
+ let area2 = 0;
170
+ for (let i = start, j = end - dim; i < end; i += dim) {
171
+ area2 += (points[i] - points[j]) * (points[i + 1] + points[j + 1]);
172
+ j = i;
173
+ }
174
+ return area2 / 2;
170
175
  }
171
- function firstPass(features) {
172
- let pointPositionsCount = 0;
173
- let pointFeaturesCount = 0;
174
- let linePositionsCount = 0;
175
- let linePathsCount = 0;
176
- let lineFeaturesCount = 0;
177
- let polygonPositionsCount = 0;
178
- let polygonObjectsCount = 0;
179
- let polygonRingsCount = 0;
180
- let polygonFeaturesCount = 0;
181
- const coordLengths = new Set();
182
- const propArrayTypes = {};
183
- for (const feature of features) {
184
- const geometry = feature.geometry;
185
- switch (geometry.type) {
186
- case "Point":
187
- pointFeaturesCount++;
188
- pointPositionsCount++;
189
- coordLengths.add(geometry.coordinates.length);
190
- break;
191
- case "MultiPoint":
192
- pointFeaturesCount++;
193
- pointPositionsCount += geometry.coordinates.length;
194
- for (const point of geometry.coordinates) {
195
- coordLengths.add(point.length);
196
- }
197
- break;
198
- case "LineString":
199
- lineFeaturesCount++;
200
- linePositionsCount += geometry.coordinates.length;
201
- linePathsCount++;
202
- for (const coord of geometry.coordinates) {
203
- coordLengths.add(coord.length);
204
- }
205
- break;
206
- case "MultiLineString":
207
- lineFeaturesCount++;
208
- for (const line of geometry.coordinates) {
209
- linePositionsCount += line.length;
210
- linePathsCount++;
211
- for (const coord of line) {
212
- coordLengths.add(coord.length);
213
- }
214
- }
176
+
177
+ // ../../node_modules/@math.gl/polygon/dist/esm/earcut.js
178
+ function earcut(data, holeIndices, dim, areas) {
179
+ dim = dim || 2;
180
+ const hasHoles = holeIndices && holeIndices.length;
181
+ const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
182
+ let outerNode = linkedList(data, 0, outerLen, dim, true, areas && areas[0]);
183
+ const triangles = [];
184
+ if (!outerNode || outerNode.next === outerNode.prev)
185
+ return triangles;
186
+ let invSize;
187
+ let maxX;
188
+ let maxY;
189
+ let minX;
190
+ let minY;
191
+ let x;
192
+ let y;
193
+ if (hasHoles)
194
+ outerNode = eliminateHoles(data, holeIndices, outerNode, dim, areas);
195
+ if (data.length > 80 * dim) {
196
+ minX = maxX = data[0];
197
+ minY = maxY = data[1];
198
+ for (let i = dim; i < outerLen; i += dim) {
199
+ x = data[i];
200
+ y = data[i + 1];
201
+ if (x < minX)
202
+ minX = x;
203
+ if (y < minY)
204
+ minY = y;
205
+ if (x > maxX)
206
+ maxX = x;
207
+ if (y > maxY)
208
+ maxY = y;
209
+ }
210
+ invSize = Math.max(maxX - minX, maxY - minY);
211
+ invSize = invSize !== 0 ? 1 / invSize : 0;
212
+ }
213
+ earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
214
+ return triangles;
215
+ }
216
+ function linkedList(data, start, end, dim, clockwise, area2) {
217
+ let i;
218
+ let last;
219
+ if (area2 === void 0) {
220
+ area2 = getPolygonSignedArea(data, {
221
+ start,
222
+ end,
223
+ size: dim
224
+ });
225
+ }
226
+ if (clockwise === area2 < 0) {
227
+ for (i = start; i < end; i += dim)
228
+ last = insertNode(i, data[i], data[i + 1], last);
229
+ } else {
230
+ for (i = end - dim; i >= start; i -= dim)
231
+ last = insertNode(i, data[i], data[i + 1], last);
232
+ }
233
+ if (last && equals(last, last.next)) {
234
+ removeNode(last);
235
+ last = last.next;
236
+ }
237
+ return last;
238
+ }
239
+ function filterPoints(start, end) {
240
+ if (!start)
241
+ return start;
242
+ if (!end)
243
+ end = start;
244
+ let p = start;
245
+ let again;
246
+ do {
247
+ again = false;
248
+ if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
249
+ removeNode(p);
250
+ p = end = p.prev;
251
+ if (p === p.next)
215
252
  break;
216
- case "Polygon":
217
- polygonFeaturesCount++;
218
- polygonObjectsCount++;
219
- polygonRingsCount += geometry.coordinates.length;
220
- polygonPositionsCount += flatten(geometry.coordinates).length;
221
- for (const coord of flatten(geometry.coordinates)) {
222
- coordLengths.add(coord.length);
253
+ again = true;
254
+ } else {
255
+ p = p.next;
256
+ }
257
+ } while (again || p !== end);
258
+ return end;
259
+ }
260
+ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
261
+ if (!ear)
262
+ return;
263
+ if (!pass && invSize)
264
+ indexCurve(ear, minX, minY, invSize);
265
+ let stop = ear;
266
+ let prev;
267
+ let next;
268
+ while (ear.prev !== ear.next) {
269
+ prev = ear.prev;
270
+ next = ear.next;
271
+ if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
272
+ triangles.push(prev.i / dim);
273
+ triangles.push(ear.i / dim);
274
+ triangles.push(next.i / dim);
275
+ removeNode(ear);
276
+ ear = next.next;
277
+ stop = next.next;
278
+ continue;
279
+ }
280
+ ear = next;
281
+ if (ear === stop) {
282
+ if (!pass) {
283
+ earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
284
+ } else if (pass === 1) {
285
+ ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
286
+ earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
287
+ } else if (pass === 2) {
288
+ splitEarcut(ear, triangles, dim, minX, minY, invSize);
289
+ }
290
+ break;
291
+ }
292
+ }
293
+ }
294
+ function isEar(ear) {
295
+ const a = ear.prev;
296
+ const b = ear;
297
+ const c = ear.next;
298
+ if (area(a, b, c) >= 0)
299
+ return false;
300
+ let p = ear.next.next;
301
+ while (p !== ear.prev) {
302
+ if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0)
303
+ return false;
304
+ p = p.next;
305
+ }
306
+ return true;
307
+ }
308
+ function isEarHashed(ear, minX, minY, invSize) {
309
+ const a = ear.prev;
310
+ const b = ear;
311
+ const c = ear.next;
312
+ if (area(a, b, c) >= 0)
313
+ return false;
314
+ const minTX = a.x < b.x ? a.x < c.x ? a.x : c.x : b.x < c.x ? b.x : c.x;
315
+ const minTY = a.y < b.y ? a.y < c.y ? a.y : c.y : b.y < c.y ? b.y : c.y;
316
+ const maxTX = a.x > b.x ? a.x > c.x ? a.x : c.x : b.x > c.x ? b.x : c.x;
317
+ const maxTY = a.y > b.y ? a.y > c.y ? a.y : c.y : b.y > c.y ? b.y : c.y;
318
+ const minZ = zOrder(minTX, minTY, minX, minY, invSize);
319
+ const maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
320
+ let p = ear.prevZ;
321
+ let n = ear.nextZ;
322
+ while (p && p.z >= minZ && n && n.z <= maxZ) {
323
+ if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0)
324
+ return false;
325
+ p = p.prevZ;
326
+ if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0)
327
+ return false;
328
+ n = n.nextZ;
329
+ }
330
+ while (p && p.z >= minZ) {
331
+ if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0)
332
+ return false;
333
+ p = p.prevZ;
334
+ }
335
+ while (n && n.z <= maxZ) {
336
+ if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0)
337
+ return false;
338
+ n = n.nextZ;
339
+ }
340
+ return true;
341
+ }
342
+ function cureLocalIntersections(start, triangles, dim) {
343
+ let p = start;
344
+ do {
345
+ const a = p.prev;
346
+ const b = p.next.next;
347
+ if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
348
+ triangles.push(a.i / dim);
349
+ triangles.push(p.i / dim);
350
+ triangles.push(b.i / dim);
351
+ removeNode(p);
352
+ removeNode(p.next);
353
+ p = start = b;
354
+ }
355
+ p = p.next;
356
+ } while (p !== start);
357
+ return filterPoints(p);
358
+ }
359
+ function splitEarcut(start, triangles, dim, minX, minY, invSize) {
360
+ let a = start;
361
+ do {
362
+ let b = a.next.next;
363
+ while (b !== a.prev) {
364
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
365
+ let c = splitPolygon(a, b);
366
+ a = filterPoints(a, a.next);
367
+ c = filterPoints(c, c.next);
368
+ earcutLinked(a, triangles, dim, minX, minY, invSize);
369
+ earcutLinked(c, triangles, dim, minX, minY, invSize);
370
+ return;
371
+ }
372
+ b = b.next;
373
+ }
374
+ a = a.next;
375
+ } while (a !== start);
376
+ }
377
+ function eliminateHoles(data, holeIndices, outerNode, dim, areas) {
378
+ const queue = [];
379
+ let i;
380
+ let len;
381
+ let start;
382
+ let end;
383
+ let list;
384
+ for (i = 0, len = holeIndices.length; i < len; i++) {
385
+ start = holeIndices[i] * dim;
386
+ end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
387
+ list = linkedList(data, start, end, dim, false, areas && areas[i + 1]);
388
+ if (list === list.next)
389
+ list.steiner = true;
390
+ queue.push(getLeftmost(list));
391
+ }
392
+ queue.sort(compareX);
393
+ for (i = 0; i < queue.length; i++) {
394
+ eliminateHole(queue[i], outerNode);
395
+ outerNode = filterPoints(outerNode, outerNode.next);
396
+ }
397
+ return outerNode;
398
+ }
399
+ function compareX(a, b) {
400
+ return a.x - b.x;
401
+ }
402
+ function eliminateHole(hole, outerNode) {
403
+ outerNode = findHoleBridge(hole, outerNode);
404
+ if (outerNode) {
405
+ const b = splitPolygon(outerNode, hole);
406
+ filterPoints(outerNode, outerNode.next);
407
+ filterPoints(b, b.next);
408
+ }
409
+ }
410
+ function findHoleBridge(hole, outerNode) {
411
+ let p = outerNode;
412
+ const hx = hole.x;
413
+ const hy = hole.y;
414
+ let qx = -Infinity;
415
+ let m;
416
+ do {
417
+ if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
418
+ const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
419
+ if (x <= hx && x > qx) {
420
+ qx = x;
421
+ if (x === hx) {
422
+ if (hy === p.y)
423
+ return p;
424
+ if (hy === p.next.y)
425
+ return p.next;
223
426
  }
224
- break;
225
- case "MultiPolygon":
226
- polygonFeaturesCount++;
227
- for (const polygon of geometry.coordinates) {
228
- polygonObjectsCount++;
229
- polygonRingsCount += polygon.length;
230
- polygonPositionsCount += flatten(polygon).length;
231
- for (const coord of flatten(polygon)) {
232
- coordLengths.add(coord.length);
233
- }
427
+ m = p.x < p.next.x ? p : p.next;
428
+ }
429
+ }
430
+ p = p.next;
431
+ } while (p !== outerNode);
432
+ if (!m)
433
+ return null;
434
+ if (hx === qx)
435
+ return m;
436
+ const stop = m;
437
+ const mx = m.x;
438
+ const my = m.y;
439
+ let tanMin = Infinity;
440
+ let tan;
441
+ p = m;
442
+ do {
443
+ 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)) {
444
+ tan = Math.abs(hy - p.y) / (hx - p.x);
445
+ if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
446
+ m = p;
447
+ tanMin = tan;
448
+ }
449
+ }
450
+ p = p.next;
451
+ } while (p !== stop);
452
+ return m;
453
+ }
454
+ function sectorContainsSector(m, p) {
455
+ return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
456
+ }
457
+ function indexCurve(start, minX, minY, invSize) {
458
+ let p = start;
459
+ do {
460
+ if (p.z === null)
461
+ p.z = zOrder(p.x, p.y, minX, minY, invSize);
462
+ p.prevZ = p.prev;
463
+ p.nextZ = p.next;
464
+ p = p.next;
465
+ } while (p !== start);
466
+ p.prevZ.nextZ = null;
467
+ p.prevZ = null;
468
+ sortLinked(p);
469
+ }
470
+ function sortLinked(list) {
471
+ let e;
472
+ let i;
473
+ let inSize = 1;
474
+ let numMerges;
475
+ let p;
476
+ let pSize;
477
+ let q;
478
+ let qSize;
479
+ let tail;
480
+ do {
481
+ p = list;
482
+ list = null;
483
+ tail = null;
484
+ numMerges = 0;
485
+ while (p) {
486
+ numMerges++;
487
+ q = p;
488
+ pSize = 0;
489
+ for (i = 0; i < inSize; i++) {
490
+ pSize++;
491
+ q = q.nextZ;
492
+ if (!q)
493
+ break;
494
+ }
495
+ qSize = inSize;
496
+ while (pSize > 0 || qSize > 0 && q) {
497
+ if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
498
+ e = p;
499
+ p = p.nextZ;
500
+ pSize--;
501
+ } else {
502
+ e = q;
503
+ q = q.nextZ;
504
+ qSize--;
234
505
  }
235
- break;
236
- default:
237
- throw new Error(`Unsupported geometry type: ${geometry.type}`);
506
+ if (tail)
507
+ tail.nextZ = e;
508
+ else
509
+ list = e;
510
+ e.prevZ = tail;
511
+ tail = e;
512
+ }
513
+ p = q;
238
514
  }
515
+ tail.nextZ = null;
516
+ inSize *= 2;
517
+ } while (numMerges > 1);
518
+ return list;
519
+ }
520
+ function zOrder(x, y, minX, minY, invSize) {
521
+ x = 32767 * (x - minX) * invSize;
522
+ y = 32767 * (y - minY) * invSize;
523
+ x = (x | x << 8) & 16711935;
524
+ x = (x | x << 4) & 252645135;
525
+ x = (x | x << 2) & 858993459;
526
+ x = (x | x << 1) & 1431655765;
527
+ y = (y | y << 8) & 16711935;
528
+ y = (y | y << 4) & 252645135;
529
+ y = (y | y << 2) & 858993459;
530
+ y = (y | y << 1) & 1431655765;
531
+ return x | y << 1;
532
+ }
533
+ function getLeftmost(start) {
534
+ let p = start;
535
+ let leftmost = start;
536
+ do {
537
+ if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
538
+ leftmost = p;
539
+ p = p.next;
540
+ } while (p !== start);
541
+ return leftmost;
542
+ }
543
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
544
+ return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
545
+ }
546
+ function isValidDiagonal(a, b) {
547
+ 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);
548
+ }
549
+ function area(p, q, r) {
550
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
551
+ }
552
+ function equals(p1, p2) {
553
+ return p1.x === p2.x && p1.y === p2.y;
554
+ }
555
+ function intersects(p1, q1, p2, q2) {
556
+ const o1 = sign(area(p1, q1, p2));
557
+ const o2 = sign(area(p1, q1, q2));
558
+ const o3 = sign(area(p2, q2, p1));
559
+ const o4 = sign(area(p2, q2, q1));
560
+ if (o1 !== o2 && o3 !== o4)
561
+ return true;
562
+ if (o1 === 0 && onSegment(p1, p2, q1))
563
+ return true;
564
+ if (o2 === 0 && onSegment(p1, q2, q1))
565
+ return true;
566
+ if (o3 === 0 && onSegment(p2, p1, q2))
567
+ return true;
568
+ if (o4 === 0 && onSegment(p2, q1, q2))
569
+ return true;
570
+ return false;
571
+ }
572
+ function onSegment(p, q, r) {
573
+ 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);
574
+ }
575
+ function sign(num) {
576
+ return num > 0 ? 1 : num < 0 ? -1 : 0;
577
+ }
578
+ function intersectsPolygon(a, b) {
579
+ let p = a;
580
+ do {
581
+ 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))
582
+ return true;
583
+ p = p.next;
584
+ } while (p !== a);
585
+ return false;
586
+ }
587
+ function locallyInside(a, b) {
588
+ 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;
589
+ }
590
+ function middleInside(a, b) {
591
+ let p = a;
592
+ let inside = false;
593
+ const px = (a.x + b.x) / 2;
594
+ const py = (a.y + b.y) / 2;
595
+ do {
596
+ 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)
597
+ inside = !inside;
598
+ p = p.next;
599
+ } while (p !== a);
600
+ return inside;
601
+ }
602
+ function splitPolygon(a, b) {
603
+ const a2 = new Node(a.i, a.x, a.y);
604
+ const b2 = new Node(b.i, b.x, b.y);
605
+ const an = a.next;
606
+ const bp = b.prev;
607
+ a.next = b;
608
+ b.prev = a;
609
+ a2.next = an;
610
+ an.prev = a2;
611
+ b2.next = a2;
612
+ a2.prev = b2;
613
+ bp.next = b2;
614
+ b2.prev = bp;
615
+ return b2;
616
+ }
617
+ function insertNode(i, x, y, last) {
618
+ const p = new Node(i, x, y);
619
+ if (!last) {
620
+ p.prev = p;
621
+ p.next = p;
622
+ } else {
623
+ p.next = last.next;
624
+ p.prev = last;
625
+ last.next.prev = p;
626
+ last.next = p;
627
+ }
628
+ return p;
629
+ }
630
+ function removeNode(p) {
631
+ p.next.prev = p.prev;
632
+ p.prev.next = p.next;
633
+ if (p.prevZ)
634
+ p.prevZ.nextZ = p.nextZ;
635
+ if (p.nextZ)
636
+ p.nextZ.prevZ = p.prevZ;
637
+ }
638
+ function Node(i, x, y) {
639
+ this.i = i;
640
+ this.x = x;
641
+ this.y = y;
642
+ this.prev = null;
643
+ this.next = null;
644
+ this.z = null;
645
+ this.prevZ = null;
646
+ this.nextZ = null;
647
+ this.steiner = false;
648
+ }
649
+
650
+ // ../gis/src/lib/flat-geojson-to-binary.ts
651
+ function flatGeojsonToBinary(features, geometryInfo, options) {
652
+ const propArrayTypes = extractNumericPropTypes(features);
653
+ const numericPropKeys = Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array);
654
+ return fillArrays(features, {
655
+ propArrayTypes,
656
+ ...geometryInfo
657
+ }, {
658
+ numericPropKeys: options && options.numericPropKeys || numericPropKeys,
659
+ PositionDataType: options ? options.PositionDataType : Float32Array
660
+ });
661
+ }
662
+ function extractNumericPropTypes(features) {
663
+ const propArrayTypes = {};
664
+ for (const feature of features) {
239
665
  if (feature.properties) {
240
666
  for (const key in feature.properties) {
241
667
  const val = feature.properties[key];
@@ -243,22 +669,9 @@
243
669
  }
244
670
  }
245
671
  }
246
- return {
247
- coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
248
- pointPositionsCount,
249
- pointFeaturesCount,
250
- linePositionsCount,
251
- linePathsCount,
252
- lineFeaturesCount,
253
- polygonPositionsCount,
254
- polygonObjectsCount,
255
- polygonRingsCount,
256
- polygonFeaturesCount,
257
- numericPropKeys: Object.keys(propArrayTypes).filter((k) => propArrayTypes[k] !== Array),
258
- propArrayTypes
259
- };
672
+ return propArrayTypes;
260
673
  }
261
- function secondPass(features, firstPassData, options) {
674
+ function fillArrays(features, geometryInfo, options) {
262
675
  const {
263
676
  pointPositionsCount,
264
677
  pointFeaturesCount,
@@ -268,42 +681,48 @@
268
681
  polygonPositionsCount,
269
682
  polygonObjectsCount,
270
683
  polygonRingsCount,
684
+ polygonFeaturesCount,
271
685
  propArrayTypes,
272
- polygonFeaturesCount
273
- } = firstPassData;
274
- const { coordLength, numericPropKeys, PositionDataType = Float32Array } = options;
686
+ coordLength
687
+ } = geometryInfo;
688
+ const { numericPropKeys = [], PositionDataType = Float32Array } = options;
689
+ const hasGlobalId = features[0] && "id" in features[0];
275
690
  const GlobalFeatureIdsDataType = features.length > 65535 ? Uint32Array : Uint16Array;
276
691
  const points = {
692
+ type: "Point",
277
693
  positions: new PositionDataType(pointPositionsCount * coordLength),
278
694
  globalFeatureIds: new GlobalFeatureIdsDataType(pointPositionsCount),
279
695
  featureIds: pointFeaturesCount > 65535 ? new Uint32Array(pointPositionsCount) : new Uint16Array(pointPositionsCount),
280
696
  numericProps: {},
281
- properties: Array(),
282
- fields: Array()
697
+ properties: [],
698
+ fields: []
283
699
  };
284
700
  const lines = {
285
- positions: new PositionDataType(linePositionsCount * coordLength),
701
+ type: "LineString",
286
702
  pathIndices: linePositionsCount > 65535 ? new Uint32Array(linePathsCount + 1) : new Uint16Array(linePathsCount + 1),
703
+ positions: new PositionDataType(linePositionsCount * coordLength),
287
704
  globalFeatureIds: new GlobalFeatureIdsDataType(linePositionsCount),
288
705
  featureIds: lineFeaturesCount > 65535 ? new Uint32Array(linePositionsCount) : new Uint16Array(linePositionsCount),
289
706
  numericProps: {},
290
- properties: Array(),
291
- fields: Array()
707
+ properties: [],
708
+ fields: []
292
709
  };
293
710
  const polygons = {
294
- positions: new PositionDataType(polygonPositionsCount * coordLength),
711
+ type: "Polygon",
295
712
  polygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonObjectsCount + 1) : new Uint16Array(polygonObjectsCount + 1),
296
713
  primitivePolygonIndices: polygonPositionsCount > 65535 ? new Uint32Array(polygonRingsCount + 1) : new Uint16Array(polygonRingsCount + 1),
714
+ positions: new PositionDataType(polygonPositionsCount * coordLength),
715
+ triangles: [],
297
716
  globalFeatureIds: new GlobalFeatureIdsDataType(polygonPositionsCount),
298
717
  featureIds: polygonFeaturesCount > 65535 ? new Uint32Array(polygonPositionsCount) : new Uint16Array(polygonPositionsCount),
299
718
  numericProps: {},
300
- properties: Array(),
301
- fields: Array()
719
+ properties: [],
720
+ fields: []
302
721
  };
303
722
  for (const object of [points, lines, polygons]) {
304
- for (const propName of numericPropKeys || []) {
305
- const TypedArray = propArrayTypes[propName];
306
- object.numericProps[propName] = new TypedArray(object.positions.length / coordLength);
723
+ for (const propName of numericPropKeys) {
724
+ const T = propArrayTypes[propName];
725
+ object.numericProps[propName] = new T(object.positions.length / coordLength);
307
726
  }
308
727
  }
309
728
  lines.pathIndices[linePathsCount] = linePositionsCount;
@@ -326,33 +745,27 @@
326
745
  const properties = feature.properties || {};
327
746
  switch (geometry.type) {
328
747
  case "Point":
329
- handlePoint(geometry.coordinates, points, indexMap, coordLength, properties);
330
- points.properties.push(keepStringProperties(properties, numericPropKeys));
331
- indexMap.pointFeature++;
332
- break;
333
- case "MultiPoint":
334
- handleMultiPoint(geometry.coordinates, points, indexMap, coordLength, properties);
748
+ handlePoint(geometry, points, indexMap, coordLength, properties);
335
749
  points.properties.push(keepStringProperties(properties, numericPropKeys));
750
+ if (hasGlobalId) {
751
+ points.fields.push({ id: feature.id });
752
+ }
336
753
  indexMap.pointFeature++;
337
754
  break;
338
755
  case "LineString":
339
- handleLineString(geometry.coordinates, lines, indexMap, coordLength, properties);
340
- lines.properties.push(keepStringProperties(properties, numericPropKeys));
341
- indexMap.lineFeature++;
342
- break;
343
- case "MultiLineString":
344
- handleMultiLineString(geometry.coordinates, lines, indexMap, coordLength, properties);
756
+ handleLineString(geometry, lines, indexMap, coordLength, properties);
345
757
  lines.properties.push(keepStringProperties(properties, numericPropKeys));
758
+ if (hasGlobalId) {
759
+ lines.fields.push({ id: feature.id });
760
+ }
346
761
  indexMap.lineFeature++;
347
762
  break;
348
763
  case "Polygon":
349
- handlePolygon(geometry.coordinates, polygons, indexMap, coordLength, properties);
350
- polygons.properties.push(keepStringProperties(properties, numericPropKeys));
351
- indexMap.polygonFeature++;
352
- break;
353
- case "MultiPolygon":
354
- handleMultiPolygon(geometry.coordinates, polygons, indexMap, coordLength, properties);
764
+ handlePolygon(geometry, polygons, indexMap, coordLength, properties);
355
765
  polygons.properties.push(keepStringProperties(properties, numericPropKeys));
766
+ if (hasGlobalId) {
767
+ polygons.fields.push({ id: feature.id });
768
+ }
356
769
  indexMap.polygonFeature++;
357
770
  break;
358
771
  default:
@@ -362,93 +775,105 @@
362
775
  }
363
776
  return makeAccessorObjects(points, lines, polygons, coordLength);
364
777
  }
365
- function handlePoint(coords, points, indexMap, coordLength, properties) {
366
- points.positions.set(coords, indexMap.pointPosition * coordLength);
367
- points.globalFeatureIds[indexMap.pointPosition] = indexMap.feature;
368
- points.featureIds[indexMap.pointPosition] = indexMap.pointFeature;
369
- fillNumericProperties(points, properties, indexMap.pointPosition, 1);
370
- indexMap.pointPosition++;
371
- }
372
- function handleMultiPoint(coords, points, indexMap, coordLength, properties) {
373
- for (const point of coords) {
374
- handlePoint(point, points, indexMap, coordLength, properties);
375
- }
778
+ function handlePoint(geometry, points, indexMap, coordLength, properties) {
779
+ points.positions.set(geometry.data, indexMap.pointPosition * coordLength);
780
+ const nPositions = geometry.data.length / coordLength;
781
+ fillNumericProperties(points, properties, indexMap.pointPosition, nPositions);
782
+ points.globalFeatureIds.fill(indexMap.feature, indexMap.pointPosition, indexMap.pointPosition + nPositions);
783
+ points.featureIds.fill(indexMap.pointFeature, indexMap.pointPosition, indexMap.pointPosition + nPositions);
784
+ indexMap.pointPosition += nPositions;
376
785
  }
377
- function handleLineString(coords, lines, indexMap, coordLength, properties) {
378
- lines.pathIndices[indexMap.linePath] = indexMap.linePosition;
379
- indexMap.linePath++;
380
- fillCoords(lines.positions, coords, indexMap.linePosition, coordLength);
381
- const nPositions = coords.length;
786
+ function handleLineString(geometry, lines, indexMap, coordLength, properties) {
787
+ lines.positions.set(geometry.data, indexMap.linePosition * coordLength);
788
+ const nPositions = geometry.data.length / coordLength;
382
789
  fillNumericProperties(lines, properties, indexMap.linePosition, nPositions);
383
- lines.globalFeatureIds.set(new Uint32Array(nPositions).fill(indexMap.feature), indexMap.linePosition);
384
- lines.featureIds.set(new Uint32Array(nPositions).fill(indexMap.lineFeature), indexMap.linePosition);
385
- indexMap.linePosition += nPositions;
790
+ lines.globalFeatureIds.fill(indexMap.feature, indexMap.linePosition, indexMap.linePosition + nPositions);
791
+ lines.featureIds.fill(indexMap.lineFeature, indexMap.linePosition, indexMap.linePosition + nPositions);
792
+ for (let i = 0, il = geometry.indices.length; i < il; ++i) {
793
+ const start = geometry.indices[i];
794
+ const end = i === il - 1 ? geometry.data.length : geometry.indices[i + 1];
795
+ lines.pathIndices[indexMap.linePath++] = indexMap.linePosition;
796
+ indexMap.linePosition += (end - start) / coordLength;
797
+ }
386
798
  }
387
- function handleMultiLineString(coords, lines, indexMap, coordLength, properties) {
388
- for (const line of coords) {
389
- handleLineString(line, lines, indexMap, coordLength, properties);
799
+ function handlePolygon(geometry, polygons, indexMap, coordLength, properties) {
800
+ polygons.positions.set(geometry.data, indexMap.polygonPosition * coordLength);
801
+ const nPositions = geometry.data.length / coordLength;
802
+ fillNumericProperties(polygons, properties, indexMap.polygonPosition, nPositions);
803
+ polygons.globalFeatureIds.fill(indexMap.feature, indexMap.polygonPosition, indexMap.polygonPosition + nPositions);
804
+ polygons.featureIds.fill(indexMap.polygonFeature, indexMap.polygonPosition, indexMap.polygonPosition + nPositions);
805
+ for (let l = 0, ll = geometry.indices.length; l < ll; ++l) {
806
+ const startPosition = indexMap.polygonPosition;
807
+ polygons.polygonIndices[indexMap.polygonObject++] = startPosition;
808
+ const areas = geometry.areas[l];
809
+ const indices = geometry.indices[l];
810
+ const nextIndices = geometry.indices[l + 1];
811
+ for (let i = 0, il = indices.length; i < il; ++i) {
812
+ const start = indices[i];
813
+ const end = i === il - 1 ? nextIndices === void 0 ? geometry.data.length : nextIndices[0] : indices[i + 1];
814
+ polygons.primitivePolygonIndices[indexMap.polygonRing++] = indexMap.polygonPosition;
815
+ indexMap.polygonPosition += (end - start) / coordLength;
816
+ }
817
+ const endPosition = indexMap.polygonPosition;
818
+ triangulatePolygon(polygons, areas, indices, { startPosition, endPosition, coordLength });
390
819
  }
391
820
  }
392
- function handlePolygon(coords, polygons, indexMap, coordLength, properties) {
393
- polygons.polygonIndices[indexMap.polygonObject] = indexMap.polygonPosition;
394
- indexMap.polygonObject++;
395
- for (const ring of coords) {
396
- polygons.primitivePolygonIndices[indexMap.polygonRing] = indexMap.polygonPosition;
397
- indexMap.polygonRing++;
398
- fillCoords(polygons.positions, ring, indexMap.polygonPosition, coordLength);
399
- const nPositions = ring.length;
400
- fillNumericProperties(polygons, properties, indexMap.polygonPosition, nPositions);
401
- polygons.globalFeatureIds.set(new Uint32Array(nPositions).fill(indexMap.feature), indexMap.polygonPosition);
402
- polygons.featureIds.set(new Uint32Array(nPositions).fill(indexMap.polygonFeature), indexMap.polygonPosition);
403
- indexMap.polygonPosition += nPositions;
821
+ function triangulatePolygon(polygons, areas, indices, {
822
+ startPosition,
823
+ endPosition,
824
+ coordLength
825
+ }) {
826
+ const start = startPosition * coordLength;
827
+ const end = endPosition * coordLength;
828
+ const polygonPositions = polygons.positions.subarray(start, end);
829
+ const offset = indices[0];
830
+ const holes = indices.slice(1).map((n) => (n - offset) / coordLength);
831
+ const triangles = earcut(polygonPositions, holes, coordLength, areas);
832
+ for (let t = 0, tl = triangles.length; t < tl; ++t) {
833
+ polygons.triangles.push(startPosition + triangles[t]);
404
834
  }
405
835
  }
406
- function handleMultiPolygon(coords, polygons, indexMap, coordLength, properties) {
407
- for (const polygon of coords) {
408
- handlePolygon(polygon, polygons, indexMap, coordLength, properties);
836
+ function wrapProps(obj, size) {
837
+ const returnObj = {};
838
+ for (const key in obj) {
839
+ returnObj[key] = { value: obj[key], size };
409
840
  }
841
+ return returnObj;
410
842
  }
411
843
  function makeAccessorObjects(points, lines, polygons, coordLength) {
412
- const returnObj = {
844
+ return {
413
845
  points: {
414
846
  ...points,
415
847
  positions: { value: points.positions, size: coordLength },
416
848
  globalFeatureIds: { value: points.globalFeatureIds, size: 1 },
417
849
  featureIds: { value: points.featureIds, size: 1 },
418
- type: "Point"
850
+ numericProps: wrapProps(points.numericProps, 1)
419
851
  },
420
852
  lines: {
421
853
  ...lines,
422
- pathIndices: { value: lines.pathIndices, size: 1 },
423
854
  positions: { value: lines.positions, size: coordLength },
855
+ pathIndices: { value: lines.pathIndices, size: 1 },
424
856
  globalFeatureIds: { value: lines.globalFeatureIds, size: 1 },
425
857
  featureIds: { value: lines.featureIds, size: 1 },
426
- type: "LineString"
858
+ numericProps: wrapProps(lines.numericProps, 1)
427
859
  },
428
860
  polygons: {
429
861
  ...polygons,
862
+ positions: { value: polygons.positions, size: coordLength },
430
863
  polygonIndices: { value: polygons.polygonIndices, size: 1 },
431
864
  primitivePolygonIndices: { value: polygons.primitivePolygonIndices, size: 1 },
432
- positions: { value: polygons.positions, size: coordLength },
865
+ triangles: { value: new Uint32Array(polygons.triangles), size: 1 },
433
866
  globalFeatureIds: { value: polygons.globalFeatureIds, size: 1 },
434
867
  featureIds: { value: polygons.featureIds, size: 1 },
435
- type: "Polygon"
868
+ numericProps: wrapProps(polygons.numericProps, 1)
436
869
  }
437
870
  };
438
- for (const geomType in returnObj) {
439
- for (const numericProp in returnObj[geomType].numericProps) {
440
- returnObj[geomType].numericProps[numericProp] = {
441
- value: returnObj[geomType].numericProps[numericProp],
442
- size: 1
443
- };
444
- }
445
- }
446
- return returnObj;
447
871
  }
448
872
  function fillNumericProperties(object, properties, index, length) {
449
873
  for (const numericPropName in object.numericProps) {
450
874
  if (numericPropName in properties) {
451
- object.numericProps[numericPropName].set(new Array(length).fill(properties[numericPropName]), index);
875
+ const value = properties[numericPropName];
876
+ object.numericProps[numericPropName].fill(value, index, index + length);
452
877
  }
453
878
  }
454
879
  }
@@ -461,16 +886,6 @@
461
886
  }
462
887
  return props;
463
888
  }
464
- function fillCoords(array, coords, startVertex, coordLength) {
465
- let index = startVertex * coordLength;
466
- for (const coord of coords) {
467
- array.set(coord, index);
468
- index += coordLength;
469
- }
470
- }
471
- function flatten(arrays) {
472
- return [].concat(...arrays);
473
- }
474
889
  function deduceArrayType(x, constructor) {
475
890
  if (constructor === Array || !Number.isFinite(x)) {
476
891
  return Array;
@@ -478,6 +893,186 @@
478
893
  return constructor === Float64Array || Math.fround(x) !== x ? Float64Array : Float32Array;
479
894
  }
480
895
 
896
+ // ../gis/src/lib/extract-geometry-info.ts
897
+ function extractGeometryInfo(features) {
898
+ let pointPositionsCount = 0;
899
+ let pointFeaturesCount = 0;
900
+ let linePositionsCount = 0;
901
+ let linePathsCount = 0;
902
+ let lineFeaturesCount = 0;
903
+ let polygonPositionsCount = 0;
904
+ let polygonObjectsCount = 0;
905
+ let polygonRingsCount = 0;
906
+ let polygonFeaturesCount = 0;
907
+ const coordLengths = new Set();
908
+ for (const feature of features) {
909
+ const geometry = feature.geometry;
910
+ switch (geometry.type) {
911
+ case "Point":
912
+ pointFeaturesCount++;
913
+ pointPositionsCount++;
914
+ coordLengths.add(geometry.coordinates.length);
915
+ break;
916
+ case "MultiPoint":
917
+ pointFeaturesCount++;
918
+ pointPositionsCount += geometry.coordinates.length;
919
+ for (const point of geometry.coordinates) {
920
+ coordLengths.add(point.length);
921
+ }
922
+ break;
923
+ case "LineString":
924
+ lineFeaturesCount++;
925
+ linePositionsCount += geometry.coordinates.length;
926
+ linePathsCount++;
927
+ for (const coord of geometry.coordinates) {
928
+ coordLengths.add(coord.length);
929
+ }
930
+ break;
931
+ case "MultiLineString":
932
+ lineFeaturesCount++;
933
+ for (const line of geometry.coordinates) {
934
+ linePositionsCount += line.length;
935
+ linePathsCount++;
936
+ for (const coord of line) {
937
+ coordLengths.add(coord.length);
938
+ }
939
+ }
940
+ break;
941
+ case "Polygon":
942
+ polygonFeaturesCount++;
943
+ polygonObjectsCount++;
944
+ polygonRingsCount += geometry.coordinates.length;
945
+ const flattened = geometry.coordinates.flat();
946
+ polygonPositionsCount += flattened.length;
947
+ for (const coord of flattened) {
948
+ coordLengths.add(coord.length);
949
+ }
950
+ break;
951
+ case "MultiPolygon":
952
+ polygonFeaturesCount++;
953
+ for (const polygon of geometry.coordinates) {
954
+ polygonObjectsCount++;
955
+ polygonRingsCount += polygon.length;
956
+ const flattened2 = polygon.flat();
957
+ polygonPositionsCount += flattened2.length;
958
+ for (const coord of flattened2) {
959
+ coordLengths.add(coord.length);
960
+ }
961
+ }
962
+ break;
963
+ default:
964
+ throw new Error(`Unsupported geometry type: ${geometry.type}`);
965
+ }
966
+ }
967
+ return {
968
+ coordLength: coordLengths.size > 0 ? Math.max(...coordLengths) : 2,
969
+ pointPositionsCount,
970
+ pointFeaturesCount,
971
+ linePositionsCount,
972
+ linePathsCount,
973
+ lineFeaturesCount,
974
+ polygonPositionsCount,
975
+ polygonObjectsCount,
976
+ polygonRingsCount,
977
+ polygonFeaturesCount
978
+ };
979
+ }
980
+
981
+ // ../gis/src/lib/geojson-to-flat-geojson.ts
982
+ function geojsonToFlatGeojson(features, options = { coordLength: 2, fixRingWinding: true }) {
983
+ return features.map((feature) => flattenFeature(feature, options));
984
+ }
985
+ function flattenPoint(coordinates, data, indices, options) {
986
+ indices.push(data.length);
987
+ data.push(...coordinates);
988
+ for (let i = coordinates.length; i < options.coordLength; i++) {
989
+ data.push(0);
990
+ }
991
+ }
992
+ function flattenLineString(coordinates, data, indices, options) {
993
+ indices.push(data.length);
994
+ for (const c of coordinates) {
995
+ data.push(...c);
996
+ for (let i = c.length; i < options.coordLength; i++) {
997
+ data.push(0);
998
+ }
999
+ }
1000
+ }
1001
+ function flattenPolygon(coordinates, data, indices, areas, options) {
1002
+ let count = 0;
1003
+ const ringAreas = [];
1004
+ const polygons = [];
1005
+ for (const lineString of coordinates) {
1006
+ const lineString2d = lineString.map((p) => p.slice(0, 2));
1007
+ let area2 = getPolygonSignedArea(lineString2d.flat());
1008
+ const ccw = area2 < 0;
1009
+ if (options.fixRingWinding && (count === 0 && !ccw || count > 0 && ccw)) {
1010
+ lineString.reverse();
1011
+ area2 = -area2;
1012
+ }
1013
+ ringAreas.push(area2);
1014
+ flattenLineString(lineString, data, polygons, options);
1015
+ count++;
1016
+ }
1017
+ if (count > 0) {
1018
+ areas.push(ringAreas);
1019
+ indices.push(polygons);
1020
+ }
1021
+ }
1022
+ function flattenFeature(feature, options) {
1023
+ const { geometry } = feature;
1024
+ if (geometry.type === "GeometryCollection") {
1025
+ throw new Error("GeometryCollection type not supported");
1026
+ }
1027
+ const data = [];
1028
+ const indices = [];
1029
+ let areas;
1030
+ let type;
1031
+ switch (geometry.type) {
1032
+ case "Point":
1033
+ type = "Point";
1034
+ flattenPoint(geometry.coordinates, data, indices, options);
1035
+ break;
1036
+ case "MultiPoint":
1037
+ type = "Point";
1038
+ geometry.coordinates.map((c) => flattenPoint(c, data, indices, options));
1039
+ break;
1040
+ case "LineString":
1041
+ type = "LineString";
1042
+ flattenLineString(geometry.coordinates, data, indices, options);
1043
+ break;
1044
+ case "MultiLineString":
1045
+ type = "LineString";
1046
+ geometry.coordinates.map((c) => flattenLineString(c, data, indices, options));
1047
+ break;
1048
+ case "Polygon":
1049
+ type = "Polygon";
1050
+ areas = [];
1051
+ flattenPolygon(geometry.coordinates, data, indices, areas, options);
1052
+ break;
1053
+ case "MultiPolygon":
1054
+ type = "Polygon";
1055
+ areas = [];
1056
+ geometry.coordinates.map((c) => flattenPolygon(c, data, indices, areas, options));
1057
+ break;
1058
+ default:
1059
+ throw new Error(`Unknown type: ${type}`);
1060
+ }
1061
+ return { ...feature, geometry: { type, indices, data, areas } };
1062
+ }
1063
+
1064
+ // ../gis/src/lib/geojson-to-binary.ts
1065
+ function geojsonToBinary(features, options = { fixRingWinding: true }) {
1066
+ const geometryInfo = extractGeometryInfo(features);
1067
+ const coordLength = geometryInfo.coordLength;
1068
+ const { fixRingWinding } = options;
1069
+ const flatFeatures = geojsonToFlatGeojson(features, { coordLength, fixRingWinding });
1070
+ return flatGeojsonToBinary(flatFeatures, geometryInfo, {
1071
+ numericPropKeys: options.numericPropKeys,
1072
+ PositionDataType: options.PositionDataType || Float32Array
1073
+ });
1074
+ }
1075
+
481
1076
  // src/lib/parse-json.ts
482
1077
  function parseJSONSync(jsonText, options) {
483
1078
  try {
@@ -1640,7 +2235,7 @@ Char: ${this.c}`;
1640
2235
  }
1641
2236
 
1642
2237
  // src/geojson-loader.ts
1643
- var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
2238
+ var VERSION = true ? "3.1.4" : "latest";
1644
2239
  var DEFAULT_GEOJSON_LOADER_OPTIONS = {
1645
2240
  geojson: {
1646
2241
  shape: "object-row-table"