@loaders.gl/arrow 4.3.0-alpha.8 → 4.3.0-beta.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.
Files changed (132) hide show
  1. package/dist/arrow-loader.d.ts +6 -38
  2. package/dist/arrow-loader.d.ts.map +1 -1
  3. package/dist/arrow-loader.js +2 -29
  4. package/dist/arrow-worker.js +2654 -1710
  5. package/dist/arrow-writer.d.ts +1 -1
  6. package/dist/arrow-writer.d.ts.map +1 -1
  7. package/dist/arrow-writer.js +2 -2
  8. package/dist/dist.dev.js +1863 -1768
  9. package/dist/dist.min.js +5 -5
  10. package/dist/exports/arrow-loader.d.ts +34 -0
  11. package/dist/exports/arrow-loader.d.ts.map +1 -0
  12. package/dist/exports/arrow-loader.js +30 -0
  13. package/dist/exports/geoarrow-loader.d.ts +27 -0
  14. package/dist/exports/geoarrow-loader.d.ts.map +1 -0
  15. package/dist/exports/geoarrow-loader.js +13 -0
  16. package/dist/geoarrow-loader.d.ts +3 -27
  17. package/dist/geoarrow-loader.d.ts.map +1 -1
  18. package/dist/geoarrow-loader.js +2 -12
  19. package/dist/geoarrow-writer.d.ts +2 -2
  20. package/dist/geoarrow-writer.d.ts.map +1 -1
  21. package/dist/geoarrow-writer.js +2 -2
  22. package/dist/index.cjs +426 -387
  23. package/dist/index.cjs.map +4 -4
  24. package/dist/index.d.ts +14 -13
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +16 -12
  27. package/dist/lib/encoders/encode-arrow.d.ts.map +1 -0
  28. package/dist/lib/encoders/encode-geoarrow.d.ts.map +1 -0
  29. package/dist/lib/geoarrow/convert-geoarrow-to-binary-geometry.d.ts.map +1 -0
  30. package/dist/lib/geoarrow/convert-geoarrow-to-geojson-geometry.d.ts.map +1 -0
  31. package/dist/lib/geoarrow/get-arrow-bounds.d.ts.map +1 -0
  32. package/dist/lib/parsers/parse-arrow.d.ts +9 -0
  33. package/dist/lib/parsers/parse-arrow.d.ts.map +1 -0
  34. package/dist/{parsers/parse-arrow-in-batches.js → lib/parsers/parse-arrow.js} +7 -3
  35. package/dist/lib/parsers/parse-geoarrow.d.ts +9 -0
  36. package/dist/lib/parsers/parse-geoarrow.d.ts.map +1 -0
  37. package/dist/{parsers/parse-geoarrow-sync.js → lib/parsers/parse-geoarrow.js} +9 -3
  38. package/dist/{schema → lib/tables}/convert-arrow-schema.d.ts +4 -0
  39. package/dist/lib/tables/convert-arrow-schema.d.ts.map +1 -0
  40. package/dist/{schema → lib/tables}/convert-arrow-schema.js +8 -0
  41. package/dist/lib/tables/convert-arrow-to-table.d.ts +15 -0
  42. package/dist/lib/tables/convert-arrow-to-table.d.ts.map +1 -0
  43. package/dist/lib/tables/convert-arrow-to-table.js +104 -0
  44. package/dist/lib/tables/convert-table-to-arrow.d.ts +16 -0
  45. package/dist/lib/tables/convert-table-to-arrow.d.ts.map +1 -0
  46. package/dist/lib/tables/convert-table-to-arrow.js +56 -0
  47. package/dist/lib/types.d.ts.map +1 -0
  48. package/dist/{lib → schema}/arrow-table-batch.d.ts +2 -1
  49. package/dist/schema/arrow-table-batch.d.ts.map +1 -0
  50. package/dist/{lib → schema}/arrow-table-batch.js +1 -0
  51. package/dist/{lib/arrow-table.d.ts → schema/arrow-table-type.d.ts} +3 -1
  52. package/dist/schema/arrow-table-type.d.ts.map +1 -0
  53. package/dist/triangulate-on-worker.js +1 -1
  54. package/dist/triangulation-worker.js +13 -5
  55. package/dist/workers/triangulation-worker.js +1 -1
  56. package/package.json +11 -7
  57. package/src/arrow-loader.ts +6 -57
  58. package/src/arrow-writer.ts +1 -2
  59. package/src/exports/arrow-loader.ts +49 -0
  60. package/src/exports/geoarrow-loader.ts +24 -0
  61. package/src/geoarrow-loader.ts +6 -22
  62. package/src/geoarrow-writer.ts +1 -1
  63. package/src/index.ts +23 -23
  64. package/src/{parsers/parse-arrow-in-batches.ts → lib/parsers/parse-arrow.ts} +11 -5
  65. package/src/lib/parsers/parse-geoarrow.ts +32 -0
  66. package/src/{schema → lib/tables}/convert-arrow-schema.ts +10 -0
  67. package/src/lib/tables/convert-arrow-to-table.ts +144 -0
  68. package/src/lib/tables/convert-table-to-arrow.ts +72 -0
  69. package/src/{lib → schema}/arrow-table-batch.ts +2 -1
  70. package/src/{lib/arrow-table.ts → schema/arrow-table-type.ts} +2 -0
  71. package/src/workers/triangulation-worker.ts +1 -1
  72. package/dist/geoarrow/convert-geoarrow-to-binary-geometry.d.ts.map +0 -1
  73. package/dist/geoarrow/convert-geoarrow-to-geojson-geometry.d.ts.map +0 -1
  74. package/dist/geoarrow/get-arrow-bounds.d.ts.map +0 -1
  75. package/dist/lib/arrow-table-batch.d.ts.map +0 -1
  76. package/dist/lib/arrow-table.d.ts.map +0 -1
  77. package/dist/lib/encode-arrow.d.ts.map +0 -1
  78. package/dist/lib/encode-geoarrow.d.ts.map +0 -1
  79. package/dist/parsers/parse-arrow-in-batches.d.ts +0 -6
  80. package/dist/parsers/parse-arrow-in-batches.d.ts.map +0 -1
  81. package/dist/parsers/parse-arrow-sync.d.ts +0 -6
  82. package/dist/parsers/parse-arrow-sync.d.ts.map +0 -1
  83. package/dist/parsers/parse-arrow-sync.js +0 -32
  84. package/dist/parsers/parse-geoarrow-in-batches.d.ts +0 -6
  85. package/dist/parsers/parse-geoarrow-in-batches.d.ts.map +0 -1
  86. package/dist/parsers/parse-geoarrow-in-batches.js +0 -10
  87. package/dist/parsers/parse-geoarrow-sync.d.ts +0 -6
  88. package/dist/parsers/parse-geoarrow-sync.d.ts.map +0 -1
  89. package/dist/schema/arrow-type-utils.d.ts +0 -5
  90. package/dist/schema/arrow-type-utils.d.ts.map +0 -1
  91. package/dist/schema/arrow-type-utils.js +0 -51
  92. package/dist/schema/convert-arrow-schema.d.ts.map +0 -1
  93. package/dist/tables/convert-arrow-to-columnar-table.d.ts +0 -8
  94. package/dist/tables/convert-arrow-to-columnar-table.d.ts.map +0 -1
  95. package/dist/tables/convert-arrow-to-columnar-table.js +0 -24
  96. package/dist/tables/convert-arrow-to-geojson-table.d.ts +0 -16
  97. package/dist/tables/convert-arrow-to-geojson-table.d.ts.map +0 -1
  98. package/dist/tables/convert-arrow-to-geojson-table.js +0 -54
  99. package/dist/tables/convert-columnar-to-row-table.d.ts +0 -7
  100. package/dist/tables/convert-columnar-to-row-table.d.ts.map +0 -1
  101. package/dist/tables/convert-columnar-to-row-table.js +0 -25
  102. package/dist/tables/convert-table-to-arrow.d.ts +0 -42
  103. package/dist/tables/convert-table-to-arrow.d.ts.map +0 -1
  104. package/dist/tables/convert-table-to-arrow.js +0 -59
  105. package/dist/types.d.ts.map +0 -1
  106. package/src/parsers/parse-arrow-sync.ts +0 -44
  107. package/src/parsers/parse-geoarrow-in-batches.ts +0 -16
  108. package/src/parsers/parse-geoarrow-sync.ts +0 -23
  109. package/src/schema/arrow-type-utils.ts +0 -55
  110. package/src/tables/convert-arrow-to-columnar-table.ts +0 -31
  111. package/src/tables/convert-arrow-to-geojson-table.ts +0 -66
  112. package/src/tables/convert-columnar-to-row-table.ts +0 -31
  113. package/src/tables/convert-table-to-arrow.ts +0 -61
  114. /package/dist/lib/{encode-arrow.d.ts → encoders/encode-arrow.d.ts} +0 -0
  115. /package/dist/lib/{encode-arrow.js → encoders/encode-arrow.js} +0 -0
  116. /package/dist/lib/{encode-geoarrow.d.ts → encoders/encode-geoarrow.d.ts} +0 -0
  117. /package/dist/lib/{encode-geoarrow.js → encoders/encode-geoarrow.js} +0 -0
  118. /package/dist/{geoarrow → lib/geoarrow}/convert-geoarrow-to-binary-geometry.d.ts +0 -0
  119. /package/dist/{geoarrow → lib/geoarrow}/convert-geoarrow-to-binary-geometry.js +0 -0
  120. /package/dist/{geoarrow → lib/geoarrow}/convert-geoarrow-to-geojson-geometry.d.ts +0 -0
  121. /package/dist/{geoarrow → lib/geoarrow}/convert-geoarrow-to-geojson-geometry.js +0 -0
  122. /package/dist/{geoarrow → lib/geoarrow}/get-arrow-bounds.d.ts +0 -0
  123. /package/dist/{geoarrow → lib/geoarrow}/get-arrow-bounds.js +0 -0
  124. /package/dist/{types.d.ts → lib/types.d.ts} +0 -0
  125. /package/dist/{types.js → lib/types.js} +0 -0
  126. /package/dist/{lib/arrow-table.js → schema/arrow-table-type.js} +0 -0
  127. /package/src/lib/{encode-arrow.ts → encoders/encode-arrow.ts} +0 -0
  128. /package/src/lib/{encode-geoarrow.ts → encoders/encode-geoarrow.ts} +0 -0
  129. /package/src/{geoarrow → lib/geoarrow}/convert-geoarrow-to-binary-geometry.ts +0 -0
  130. /package/src/{geoarrow → lib/geoarrow}/convert-geoarrow-to-geojson-geometry.ts +0 -0
  131. /package/src/{geoarrow → lib/geoarrow}/get-arrow-bounds.ts +0 -0
  132. /package/src/{types.ts → lib/types.ts} +0 -0
package/dist/dist.dev.js CHANGED
@@ -60,12 +60,14 @@ var __exports__ = (() => {
60
60
  GeoArrowWorkerLoader: () => GeoArrowWorkerLoader,
61
61
  TriangulationWorker: () => TriangulationWorker,
62
62
  VECTOR_TYPES: () => VECTOR_TYPES,
63
- convertArrowToGeoJSONTable: () => convertArrowToGeoJSONTable,
63
+ convertArrowToSchema: () => convertArrowToSchema,
64
+ convertArrowToTable: () => convertArrowToTable,
65
+ convertSchemaToArrow: () => convertSchemaToArrow,
66
+ convertTableToArrow: () => convertTableToArrow,
64
67
  deserializeArrowField: () => deserializeArrowField,
65
68
  deserializeArrowMetadata: () => deserializeArrowMetadata,
66
69
  deserializeArrowSchema: () => deserializeArrowSchema,
67
70
  deserializeArrowType: () => deserializeArrowType,
68
- getArrowType: () => getArrowType,
69
71
  getBinaryGeometriesFromArrow: () => getBinaryGeometriesFromArrow,
70
72
  getBinaryGeometryTemplate: () => getBinaryGeometryTemplate,
71
73
  getMeanCentersFromBinaryGeometries: () => getMeanCentersFromBinaryGeometries,
@@ -82,6 +84,13 @@ var __exports__ = (() => {
82
84
  });
83
85
  __reExport(bundle_exports, __toESM(require_core(), 1));
84
86
 
87
+ // src/lib/types.ts
88
+ var VECTOR_TYPES = /* @__PURE__ */ ((VECTOR_TYPES2) => {
89
+ VECTOR_TYPES2[VECTOR_TYPES2["FLOAT"] = 0] = "FLOAT";
90
+ VECTOR_TYPES2[VECTOR_TYPES2["DATE"] = 1] = "DATE";
91
+ return VECTOR_TYPES2;
92
+ })(VECTOR_TYPES || {});
93
+
85
94
  // ../schema/src/lib/table/simple-table/data-type.ts
86
95
  function getDataTypeFromValue(value, defaultNumberType = "float32") {
87
96
  if (value instanceof Date) {
@@ -575,6 +584,29 @@ var __exports__ = (() => {
575
584
  throw new Error("table");
576
585
  }
577
586
  }
587
+ function getTableNumCols(table) {
588
+ if (table.schema) {
589
+ return table.schema.fields.length;
590
+ }
591
+ if (getTableLength(table) === 0) {
592
+ throw new Error("empty table");
593
+ }
594
+ switch (table.shape) {
595
+ case "array-row-table":
596
+ return table.data[0].length;
597
+ case "object-row-table":
598
+ return Object.keys(table.data[0]).length;
599
+ case "geojson-table":
600
+ return Object.keys(table.features[0]).length;
601
+ case "columnar-table":
602
+ return Object.keys(table.data).length;
603
+ case "arrow-table":
604
+ const arrowTable = table.data;
605
+ return arrowTable.numCols;
606
+ default:
607
+ throw new Error("table");
608
+ }
609
+ }
578
610
  function getTableCell(table, rowIndex, columnName) {
579
611
  switch (table.shape) {
580
612
  case "array-row-table":
@@ -597,6 +629,27 @@ var __exports__ = (() => {
597
629
  throw new Error("todo");
598
630
  }
599
631
  }
632
+ function getTableCellAt(table, rowIndex, columnIndex) {
633
+ switch (table.shape) {
634
+ case "array-row-table":
635
+ return table.data[rowIndex][columnIndex];
636
+ case "object-row-table":
637
+ const columnName1 = getTableColumnName(table, columnIndex);
638
+ return table.data[rowIndex][columnName1];
639
+ case "geojson-table":
640
+ const columnName2 = getTableColumnName(table, columnIndex);
641
+ return table.features[rowIndex][columnName2];
642
+ case "columnar-table":
643
+ const columnName3 = getTableColumnName(table, columnIndex);
644
+ const column = table.data[columnName3];
645
+ return column[rowIndex];
646
+ case "arrow-table":
647
+ const arrowTable = table.data;
648
+ return arrowTable.getChildAt(columnIndex)?.get(rowIndex);
649
+ default:
650
+ throw new Error("todo");
651
+ }
652
+ }
600
653
  function getTableColumnIndex(table, columnName) {
601
654
  const columnIndex = table.schema?.fields.findIndex((field) => field.name === columnName);
602
655
  if (columnIndex === void 0) {
@@ -604,6 +657,13 @@ var __exports__ = (() => {
604
657
  }
605
658
  return columnIndex;
606
659
  }
660
+ function getTableColumnName(table, columnIndex) {
661
+ const columnName = table.schema?.fields[columnIndex]?.name;
662
+ if (!columnName) {
663
+ throw new Error(`${columnIndex}`);
664
+ }
665
+ return columnName;
666
+ }
607
667
  function getTableRowAsObject(table, rowIndex, target, copy2) {
608
668
  switch (table.shape) {
609
669
  case "object-row-table":
@@ -923,16 +983,24 @@ var __exports__ = (() => {
923
983
  if (!Symbol.asyncIterator)
924
984
  throw new TypeError("Symbol.asyncIterator is not defined.");
925
985
  var g = generator.apply(thisArg, _arguments || []), i, q = [];
926
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
986
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
927
987
  return this;
928
988
  }, i;
929
- function verb(n) {
930
- if (g[n])
989
+ function awaitReturn(f) {
990
+ return function(v) {
991
+ return Promise.resolve(v).then(f, reject);
992
+ };
993
+ }
994
+ function verb(n, f) {
995
+ if (g[n]) {
931
996
  i[n] = function(v) {
932
997
  return new Promise(function(a, b) {
933
998
  q.push([n, v, a, b]) > 1 || resume(n, v);
934
999
  });
935
1000
  };
1001
+ if (f)
1002
+ i[n] = f(i[n]);
1003
+ }
936
1004
  }
937
1005
  function resume(n, v) {
938
1006
  try {
@@ -12711,7 +12779,7 @@ return true;`);
12711
12779
  RecordBatchFileWriter["throughDOM"] = recordBatchWriterThroughDOMStream;
12712
12780
  RecordBatchStreamWriter["throughDOM"] = recordBatchWriterThroughDOMStream;
12713
12781
 
12714
- // src/lib/arrow-table-batch.ts
12782
+ // src/schema/arrow-table-batch.ts
12715
12783
  var ArrowTableBatchAggregator = class extends ColumnarTableBatchAggregator {
12716
12784
  arrowSchema;
12717
12785
  constructor(schema, options) {
@@ -12770,594 +12838,182 @@ return true;`);
12770
12838
  return arrowVectors;
12771
12839
  }
12772
12840
 
12773
- // src/schema/arrow-type-utils.ts
12774
- function getArrowType(array) {
12775
- switch (array.constructor) {
12776
- case Int8Array:
12777
- return new Int8();
12778
- case Uint8Array:
12779
- return new Uint8();
12780
- case Int16Array:
12781
- return new Int16();
12782
- case Uint16Array:
12783
- return new Uint16();
12784
- case Int32Array:
12785
- return new Int32();
12786
- case Uint32Array:
12787
- return new Uint32();
12788
- case Float32Array:
12789
- return new Float32();
12790
- case Float64Array:
12791
- return new Float64();
12792
- default:
12793
- throw new Error("array type not supported");
12841
+ // src/exports/arrow-loader.ts
12842
+ var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
12843
+ var ArrowWorkerLoader = {
12844
+ dataType: null,
12845
+ batchType: null,
12846
+ name: "Apache Arrow",
12847
+ id: "arrow",
12848
+ module: "arrow",
12849
+ version: VERSION,
12850
+ // worker: true,
12851
+ category: "table",
12852
+ extensions: ["arrow", "feather"],
12853
+ mimeTypes: [
12854
+ "application/vnd.apache.arrow.file",
12855
+ "application/vnd.apache.arrow.stream",
12856
+ "application/octet-stream"
12857
+ ],
12858
+ binary: true,
12859
+ tests: ["ARROW"],
12860
+ options: {
12861
+ arrow: {
12862
+ shape: "columnar-table"
12863
+ }
12794
12864
  }
12795
- }
12796
-
12797
- // src/types.ts
12798
- var VECTOR_TYPES = /* @__PURE__ */ ((VECTOR_TYPES2) => {
12799
- VECTOR_TYPES2[VECTOR_TYPES2["FLOAT"] = 0] = "FLOAT";
12800
- VECTOR_TYPES2[VECTOR_TYPES2["DATE"] = 1] = "DATE";
12801
- return VECTOR_TYPES2;
12802
- })(VECTOR_TYPES || {});
12865
+ };
12803
12866
 
12804
- // src/tables/convert-arrow-to-columnar-table.ts
12805
- function convertArrowToColumnarTable(table) {
12806
- const arrowTable = table.data;
12807
- const columnarTable = {};
12808
- for (const field of arrowTable.schema.fields) {
12809
- const arrowColumn = arrowTable.getChild(field.name);
12810
- const values = arrowColumn?.toArray();
12811
- columnarTable[field.name] = values;
12867
+ // ../gis/src/lib/geo/geoarrow-metadata.ts
12868
+ var GEOARROW_ENCODINGS = [
12869
+ "geoarrow.multipolygon",
12870
+ "geoarrow.polygon",
12871
+ "geoarrow.multilinestring",
12872
+ "geoarrow.linestring",
12873
+ "geoarrow.multipoint",
12874
+ "geoarrow.point",
12875
+ "geoarrow.wkb",
12876
+ "geoarrow.wkt"
12877
+ ];
12878
+ var GEOARROW_COLUMN_METADATA_ENCODING = "ARROW:extension:name";
12879
+ var GEOARROW_COLUMN_METADATA_METADATA = "ARROW:extension:metadata";
12880
+ function getGeometryColumnsFromSchema(schema) {
12881
+ const geometryColumns = {};
12882
+ for (const field of schema.fields) {
12883
+ const metadata = getGeometryMetadataForField(field);
12884
+ if (metadata) {
12885
+ geometryColumns[field.name] = metadata;
12886
+ }
12812
12887
  }
12813
- return {
12814
- shape: "columnar-table",
12815
- schema: table.schema,
12816
- data: columnarTable
12817
- };
12888
+ return geometryColumns;
12889
+ }
12890
+ function getGeometryMetadataForField(field) {
12891
+ let metadata = null;
12892
+ let geoEncoding = field.metadata?.[GEOARROW_COLUMN_METADATA_ENCODING];
12893
+ if (geoEncoding) {
12894
+ geoEncoding = geoEncoding.toLowerCase();
12895
+ if (geoEncoding === "wkb") {
12896
+ geoEncoding = "geoarrow.wkb";
12897
+ }
12898
+ if (geoEncoding === "wkt") {
12899
+ geoEncoding = "geoarrow.wkt";
12900
+ }
12901
+ if (!GEOARROW_ENCODINGS.includes(geoEncoding)) {
12902
+ console.warn(`Invalid GeoArrow encoding: ${geoEncoding}`);
12903
+ } else {
12904
+ metadata = metadata || {};
12905
+ metadata.encoding = geoEncoding;
12906
+ }
12907
+ }
12908
+ const columnMetadata = field.metadata?.[GEOARROW_COLUMN_METADATA_METADATA];
12909
+ if (columnMetadata) {
12910
+ try {
12911
+ metadata = JSON.parse(columnMetadata);
12912
+ } catch (error) {
12913
+ console.warn("Failed to parse GeoArrow metadata", error);
12914
+ }
12915
+ }
12916
+ return metadata || null;
12818
12917
  }
12819
12918
 
12820
- // src/schema/convert-arrow-schema.ts
12821
- function serializeArrowSchema(arrowSchema) {
12822
- return {
12823
- fields: arrowSchema.fields.map((arrowField) => serializeArrowField(arrowField)),
12824
- metadata: serializeArrowMetadata(arrowSchema.metadata)
12825
- };
12919
+ // ../../node_modules/@math.gl/polygon/dist/polygon-utils.js
12920
+ var DimIndex = {
12921
+ x: 0,
12922
+ y: 1,
12923
+ z: 2
12924
+ };
12925
+ function getPolygonSignedArea(points, options = {}) {
12926
+ const { start = 0, end = points.length, plane = "xy" } = options;
12927
+ const dim = options.size || 2;
12928
+ let area2 = 0;
12929
+ const i0 = DimIndex[plane[0]];
12930
+ const i1 = DimIndex[plane[1]];
12931
+ for (let i = start, j = end - dim; i < end; i += dim) {
12932
+ area2 += (points[i + i0] - points[j + i0]) * (points[i + i1] + points[j + i1]);
12933
+ j = i;
12934
+ }
12935
+ return area2 / 2;
12826
12936
  }
12827
- function deserializeArrowSchema(schema) {
12828
- return new Schema2(
12829
- schema.fields.map((field) => deserializeArrowField(field)),
12830
- deserializeArrowMetadata(schema.metadata)
12831
- );
12937
+
12938
+ // ../../node_modules/@math.gl/polygon/dist/earcut.js
12939
+ function earcut(positions, holeIndices, dim = 2, areas, plane = "xy") {
12940
+ const hasHoles = holeIndices && holeIndices.length;
12941
+ const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
12942
+ let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0], plane);
12943
+ const triangles = [];
12944
+ if (!outerNode || outerNode.next === outerNode.prev)
12945
+ return triangles;
12946
+ let invSize;
12947
+ let maxX;
12948
+ let maxY;
12949
+ let minX;
12950
+ let minY;
12951
+ let x;
12952
+ let y;
12953
+ if (hasHoles)
12954
+ outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas, plane);
12955
+ if (positions.length > 80 * dim) {
12956
+ minX = maxX = positions[0];
12957
+ minY = maxY = positions[1];
12958
+ for (let i = dim; i < outerLen; i += dim) {
12959
+ x = positions[i];
12960
+ y = positions[i + 1];
12961
+ if (x < minX)
12962
+ minX = x;
12963
+ if (y < minY)
12964
+ minY = y;
12965
+ if (x > maxX)
12966
+ maxX = x;
12967
+ if (y > maxY)
12968
+ maxY = y;
12969
+ }
12970
+ invSize = Math.max(maxX - minX, maxY - minY);
12971
+ invSize = invSize !== 0 ? 32767 / invSize : 0;
12972
+ }
12973
+ earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
12974
+ return triangles;
12832
12975
  }
12833
- function serializeArrowMetadata(arrowMetadata) {
12834
- return Object.fromEntries(arrowMetadata);
12976
+ function linkedList(data, start, end, dim, clockwise, area2, plane) {
12977
+ let i;
12978
+ let last;
12979
+ if (area2 === void 0) {
12980
+ area2 = getPolygonSignedArea(data, { start, end, size: dim, plane });
12981
+ }
12982
+ let i0 = DimIndex[plane[0]];
12983
+ let i1 = DimIndex[plane[1]];
12984
+ if (clockwise === area2 < 0) {
12985
+ for (i = start; i < end; i += dim)
12986
+ last = insertNode(i, data[i + i0], data[i + i1], last);
12987
+ } else {
12988
+ for (i = end - dim; i >= start; i -= dim)
12989
+ last = insertNode(i, data[i + i0], data[i + i1], last);
12990
+ }
12991
+ if (last && equals(last, last.next)) {
12992
+ removeNode(last);
12993
+ last = last.next;
12994
+ }
12995
+ return last;
12835
12996
  }
12836
- function deserializeArrowMetadata(metadata) {
12837
- return metadata ? new Map(Object.entries(metadata)) : /* @__PURE__ */ new Map();
12838
- }
12839
- function serializeArrowField(field) {
12840
- return {
12841
- name: field.name,
12842
- type: serializeArrowType(field.type),
12843
- nullable: field.nullable,
12844
- metadata: serializeArrowMetadata(field.metadata)
12845
- };
12846
- }
12847
- function deserializeArrowField(field) {
12848
- return new Field2(
12849
- field.name,
12850
- deserializeArrowType(field.type),
12851
- field.nullable,
12852
- deserializeArrowMetadata(field.metadata)
12853
- );
12854
- }
12855
- function serializeArrowType(arrowType) {
12856
- switch (arrowType.constructor) {
12857
- case Null2:
12858
- return "null";
12859
- case Binary2:
12860
- return "binary";
12861
- case Bool2:
12862
- return "bool";
12863
- case Int_:
12864
- const intType = arrowType;
12865
- return `${intType.isSigned ? "u" : ""}int${intType.bitWidth}`;
12866
- case Int8:
12867
- return "int8";
12868
- case Int16:
12869
- return "int16";
12870
- case Int32:
12871
- return "int32";
12872
- case Int64:
12873
- return "int64";
12874
- case Uint8:
12875
- return "uint8";
12876
- case Uint16:
12877
- return "uint16";
12878
- case Uint32:
12879
- return "uint32";
12880
- case Uint64:
12881
- return "uint64";
12882
- case Float:
12883
- const precision = arrowType.precision;
12884
- switch (precision) {
12885
- case Precision.HALF:
12886
- return "float16";
12887
- case Precision.SINGLE:
12888
- return "float32";
12889
- case Precision.DOUBLE:
12890
- return "float64";
12891
- default:
12892
- return "float16";
12893
- }
12894
- case Float16:
12895
- return "float16";
12896
- case Float32:
12897
- return "float32";
12898
- case Float64:
12899
- return "float64";
12900
- case Utf82:
12901
- return "utf8";
12902
- case Decimal2:
12903
- const decimal = arrowType;
12904
- return {
12905
- type: "decimal",
12906
- bitWidth: decimal.bitWidth,
12907
- precision: decimal.precision,
12908
- scale: decimal.scale
12909
- };
12910
- case Date_:
12911
- const dateUnit = arrowType.unit;
12912
- return dateUnit === DateUnit.DAY ? "date-day" : "date-millisecond";
12913
- case DateDay:
12914
- return "date-day";
12915
- case DateMillisecond:
12916
- return "date-millisecond";
12917
- case Time_:
12918
- const timeUnit = arrowType.unit;
12919
- switch (timeUnit) {
12920
- case TimeUnit.SECOND:
12921
- return "time-second";
12922
- case TimeUnit.MILLISECOND:
12923
- return "time-millisecond";
12924
- case TimeUnit.MICROSECOND:
12925
- return "time-microsecond";
12926
- case TimeUnit.NANOSECOND:
12927
- return "time-nanosecond";
12928
- default:
12929
- return "time-second";
12930
- }
12931
- case TimeMillisecond:
12932
- return "time-millisecond";
12933
- case TimeSecond:
12934
- return "time-second";
12935
- case TimeMicrosecond:
12936
- return "time-microsecond";
12937
- case TimeNanosecond:
12938
- return "time-nanosecond";
12939
- case Timestamp_:
12940
- const timeStampUnit = arrowType.unit;
12941
- switch (timeStampUnit) {
12942
- case TimeUnit.SECOND:
12943
- return "timestamp-second";
12944
- case TimeUnit.MILLISECOND:
12945
- return "timestamp-millisecond";
12946
- case TimeUnit.MICROSECOND:
12947
- return "timestamp-microsecond";
12948
- case TimeUnit.NANOSECOND:
12949
- return "timestamp-nanosecond";
12950
- default:
12951
- return "timestamp-second";
12952
- }
12953
- case TimestampSecond:
12954
- return "timestamp-second";
12955
- case TimestampMillisecond:
12956
- return "timestamp-millisecond";
12957
- case TimestampMicrosecond:
12958
- return "timestamp-microsecond";
12959
- case TimestampNanosecond:
12960
- return "timestamp-nanosecond";
12961
- case Interval_:
12962
- const intervalUnit = arrowType.unit;
12963
- switch (intervalUnit) {
12964
- case IntervalUnit.DAY_TIME:
12965
- return "interval-daytime";
12966
- case IntervalUnit.YEAR_MONTH:
12967
- return "interval-yearmonth";
12968
- default:
12969
- return "interval-daytime";
12970
- }
12971
- case IntervalDayTime:
12972
- return "interval-daytime";
12973
- case IntervalYearMonth:
12974
- return "interval-yearmonth";
12975
- case Map_:
12976
- const mapType = arrowType;
12977
- return {
12978
- type: "map",
12979
- keysSorted: mapType.keysSorted,
12980
- children: mapType.children.map((arrowField) => serializeArrowField(arrowField))
12981
- };
12982
- case List2:
12983
- const listType = arrowType;
12984
- const listField = listType.valueField;
12985
- return {
12986
- type: "list",
12987
- children: [serializeArrowField(listField)]
12988
- };
12989
- case FixedSizeList2:
12990
- const fixedSizeList = arrowType;
12991
- return {
12992
- type: "fixed-size-list",
12993
- listSize: fixedSizeList.listSize,
12994
- children: [serializeArrowField(fixedSizeList.children[0])]
12995
- };
12996
- case Struct:
12997
- const structType = arrowType;
12998
- return {
12999
- type: "struct",
13000
- children: structType.children.map((arrowField) => serializeArrowField(arrowField))
13001
- };
13002
- default:
13003
- throw new Error(`arrow type not supported: ${arrowType.constructor.name}`);
13004
- }
13005
- }
13006
- function deserializeArrowType(dataType) {
13007
- if (typeof dataType === "object") {
13008
- switch (dataType.type) {
13009
- case "decimal":
13010
- return new Decimal2(dataType.precision, dataType.scale, dataType.bitWidth);
13011
- case "map":
13012
- let children = dataType.children.map((arrowField) => deserializeArrowField(arrowField));
13013
- return new Map_(children, dataType.keysSorted);
13014
- case "list":
13015
- const field = deserializeArrowField(dataType.children[0]);
13016
- return new List2(field);
13017
- case "fixed-size-list":
13018
- const child = deserializeArrowField(dataType.children[0]);
13019
- return new FixedSizeList2(dataType.listSize, child);
13020
- case "struct":
13021
- children = dataType.children.map((arrowField) => deserializeArrowField(arrowField));
13022
- return new Struct(children);
13023
- default:
13024
- throw new Error("array type not supported");
13025
- }
13026
- }
13027
- switch (dataType) {
13028
- case "null":
13029
- return new Null2();
13030
- case "binary":
13031
- return new Binary2();
13032
- case "bool":
13033
- return new Bool2();
13034
- case "int8":
13035
- return new Int8();
13036
- case "int16":
13037
- return new Int16();
13038
- case "int32":
13039
- return new Int32();
13040
- case "int64":
13041
- return new Int64();
13042
- case "uint8":
13043
- return new Uint8();
13044
- case "uint16":
13045
- return new Uint16();
13046
- case "uint32":
13047
- return new Uint32();
13048
- case "uint64":
13049
- return new Uint64();
13050
- case "float16":
13051
- return new Float16();
13052
- case "float32":
13053
- return new Float32();
13054
- case "float64":
13055
- return new Float64();
13056
- case "utf8":
13057
- return new Utf82();
13058
- case "date-day":
13059
- return new DateDay();
13060
- case "date-millisecond":
13061
- return new DateMillisecond();
13062
- case "time-second":
13063
- return new TimeSecond();
13064
- case "time-millisecond":
13065
- return new TimeMillisecond();
13066
- case "time-microsecond":
13067
- return new TimeMicrosecond();
13068
- case "time-nanosecond":
13069
- return new TimeNanosecond();
13070
- case "timestamp-second":
13071
- return new TimestampSecond();
13072
- case "timestamp-millisecond":
13073
- return new TimestampMillisecond();
13074
- case "timestamp-microsecond":
13075
- return new TimestampMicrosecond();
13076
- case "timestamp-nanosecond":
13077
- return new TimestampNanosecond();
13078
- case "interval-daytime":
13079
- return new IntervalDayTime();
13080
- case "interval-yearmonth":
13081
- return new IntervalYearMonth();
13082
- default:
13083
- throw new Error("array type not supported");
13084
- }
13085
- }
13086
-
13087
- // src/parsers/parse-arrow-sync.ts
13088
- function parseArrowSync(arrayBuffer, options) {
13089
- const apacheArrowTable = tableFromIPC([new Uint8Array(arrayBuffer)]);
13090
- const arrowTable = {
13091
- shape: "arrow-table",
13092
- schema: serializeArrowSchema(apacheArrowTable.schema),
13093
- data: apacheArrowTable
13094
- };
13095
- const shape = options?.shape || "arrow-table";
13096
- switch (shape) {
13097
- case "arrow-table":
13098
- return arrowTable;
13099
- case "columnar-table":
13100
- return convertArrowToColumnarTable(arrowTable);
13101
- case "object-row-table":
13102
- let columnarTable = convertArrowToColumnarTable(arrowTable);
13103
- return convertTable(columnarTable, "object-row-table");
13104
- case "array-row-table":
13105
- columnarTable = convertArrowToColumnarTable(arrowTable);
13106
- return convertTable(columnarTable, "array-row-table");
13107
- default:
13108
- throw new Error(shape);
13109
- }
13110
- }
13111
-
13112
- // src/parsers/parse-arrow-in-batches.ts
13113
- function parseArrowInBatches(asyncIterator, options) {
13114
- async function* makeArrowAsyncIterator() {
13115
- const readers = RecordBatchReader.readAll(asyncIterator);
13116
- for await (const reader of readers) {
13117
- for await (const recordBatch of reader) {
13118
- if (options?.arrow?.batchDebounceMs !== void 0 && options?.arrow?.batchDebounceMs > 0) {
13119
- await new Promise((resolve) => setTimeout(resolve, options.arrow?.batchDebounceMs || 0));
13120
- }
13121
- const arrowTabledBatch = {
13122
- shape: "arrow-table",
13123
- batchType: "data",
13124
- data: new Table([recordBatch]),
13125
- length: recordBatch.data.length
13126
- };
13127
- yield arrowTabledBatch;
13128
- }
13129
- break;
13130
- }
13131
- }
13132
- return makeArrowAsyncIterator();
13133
- }
13134
-
13135
- // src/arrow-loader.ts
13136
- var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
13137
- var ArrowWorkerLoader = {
13138
- dataType: null,
13139
- batchType: null,
13140
- name: "Apache Arrow",
13141
- id: "arrow",
13142
- module: "arrow",
13143
- version: VERSION,
13144
- // worker: true,
13145
- category: "table",
13146
- extensions: ["arrow", "feather"],
13147
- mimeTypes: [
13148
- "application/vnd.apache.arrow.file",
13149
- "application/vnd.apache.arrow.stream",
13150
- "application/octet-stream"
13151
- ],
13152
- binary: true,
13153
- tests: ["ARROW"],
13154
- options: {
13155
- arrow: {
13156
- shape: "columnar-table"
13157
- }
13158
- }
13159
- };
13160
- var ArrowLoader = {
13161
- ...ArrowWorkerLoader,
13162
- parse: async (arraybuffer, options) => parseArrowSync(arraybuffer, options?.arrow),
13163
- parseSync: (arraybuffer, options) => parseArrowSync(arraybuffer, options?.arrow),
13164
- parseInBatches: parseArrowInBatches
13165
- };
13166
-
13167
- // src/lib/encode-arrow.ts
13168
- function encodeArrowSync(data) {
13169
- const vectors = {};
13170
- for (const arrayData of data) {
13171
- const arrayVector = createVector(arrayData.array, arrayData.type);
13172
- vectors[arrayData.name] = arrayVector;
13173
- }
13174
- const table = new Table(vectors);
13175
- const arrowBuffer = tableToIPC(table);
13176
- return arrowBuffer;
13177
- }
13178
- function createVector(array, type) {
13179
- switch (type) {
13180
- case 1 /* DATE */:
13181
- return vectorFromArray(array);
13182
- case 0 /* FLOAT */:
13183
- default:
13184
- return vectorFromArray(array);
13185
- }
13186
- }
13187
-
13188
- // src/arrow-writer.ts
13189
- var VERSION2 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
13190
- var ArrowWriter = {
13191
- name: "Apache Arrow",
13192
- id: "arrow",
13193
- module: "arrow",
13194
- version: VERSION2,
13195
- extensions: ["arrow", "feather"],
13196
- mimeTypes: [
13197
- "application/vnd.apache.arrow.file",
13198
- "application/vnd.apache.arrow.stream",
13199
- "application/octet-stream"
13200
- ],
13201
- binary: true,
13202
- options: {},
13203
- encode: async function encodeArrow(data, options) {
13204
- return encodeArrowSync(data);
13205
- },
13206
- encodeSync(data, options) {
13207
- return encodeArrowSync(data);
13208
- }
13209
- };
13210
-
13211
- // ../gis/src/lib/geo/geoarrow-metadata.ts
13212
- var GEOARROW_ENCODINGS = [
13213
- "geoarrow.multipolygon",
13214
- "geoarrow.polygon",
13215
- "geoarrow.multilinestring",
13216
- "geoarrow.linestring",
13217
- "geoarrow.multipoint",
13218
- "geoarrow.point",
13219
- "geoarrow.wkb",
13220
- "geoarrow.wkt"
13221
- ];
13222
- var GEOARROW_COLUMN_METADATA_ENCODING = "ARROW:extension:name";
13223
- var GEOARROW_COLUMN_METADATA_METADATA = "ARROW:extension:metadata";
13224
- function getGeometryColumnsFromSchema(schema) {
13225
- const geometryColumns = {};
13226
- for (const field of schema.fields) {
13227
- const metadata = getGeometryMetadataForField(field);
13228
- if (metadata) {
13229
- geometryColumns[field.name] = metadata;
13230
- }
13231
- }
13232
- return geometryColumns;
13233
- }
13234
- function getGeometryMetadataForField(field) {
13235
- let metadata = null;
13236
- let geoEncoding = field.metadata?.[GEOARROW_COLUMN_METADATA_ENCODING];
13237
- if (geoEncoding) {
13238
- geoEncoding = geoEncoding.toLowerCase();
13239
- if (geoEncoding === "wkb") {
13240
- geoEncoding = "geoarrow.wkb";
13241
- }
13242
- if (geoEncoding === "wkt") {
13243
- geoEncoding = "geoarrow.wkt";
13244
- }
13245
- if (!GEOARROW_ENCODINGS.includes(geoEncoding)) {
13246
- console.warn(`Invalid GeoArrow encoding: ${geoEncoding}`);
13247
- } else {
13248
- metadata = metadata || {};
13249
- metadata.encoding = geoEncoding;
13250
- }
13251
- }
13252
- const columnMetadata = field.metadata?.[GEOARROW_COLUMN_METADATA_METADATA];
13253
- if (columnMetadata) {
13254
- try {
13255
- metadata = JSON.parse(columnMetadata);
13256
- } catch (error) {
13257
- console.warn("Failed to parse GeoArrow metadata", error);
13258
- }
13259
- }
13260
- return metadata || null;
13261
- }
13262
-
13263
- // ../../node_modules/@math.gl/polygon/dist/polygon-utils.js
13264
- var DimIndex = {
13265
- x: 0,
13266
- y: 1,
13267
- z: 2
13268
- };
13269
- function getPolygonSignedArea(points, options = {}) {
13270
- const { start = 0, end = points.length, plane = "xy" } = options;
13271
- const dim = options.size || 2;
13272
- let area2 = 0;
13273
- const i0 = DimIndex[plane[0]];
13274
- const i1 = DimIndex[plane[1]];
13275
- for (let i = start, j = end - dim; i < end; i += dim) {
13276
- area2 += (points[i + i0] - points[j + i0]) * (points[i + i1] + points[j + i1]);
13277
- j = i;
13278
- }
13279
- return area2 / 2;
13280
- }
13281
-
13282
- // ../../node_modules/@math.gl/polygon/dist/earcut.js
13283
- function earcut(positions, holeIndices, dim = 2, areas, plane = "xy") {
13284
- const hasHoles = holeIndices && holeIndices.length;
13285
- const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
13286
- let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0], plane);
13287
- const triangles = [];
13288
- if (!outerNode || outerNode.next === outerNode.prev)
13289
- return triangles;
13290
- let invSize;
13291
- let maxX;
13292
- let maxY;
13293
- let minX;
13294
- let minY;
13295
- let x;
13296
- let y;
13297
- if (hasHoles)
13298
- outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas, plane);
13299
- if (positions.length > 80 * dim) {
13300
- minX = maxX = positions[0];
13301
- minY = maxY = positions[1];
13302
- for (let i = dim; i < outerLen; i += dim) {
13303
- x = positions[i];
13304
- y = positions[i + 1];
13305
- if (x < minX)
13306
- minX = x;
13307
- if (y < minY)
13308
- minY = y;
13309
- if (x > maxX)
13310
- maxX = x;
13311
- if (y > maxY)
13312
- maxY = y;
13313
- }
13314
- invSize = Math.max(maxX - minX, maxY - minY);
13315
- invSize = invSize !== 0 ? 32767 / invSize : 0;
13316
- }
13317
- earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
13318
- return triangles;
13319
- }
13320
- function linkedList(data, start, end, dim, clockwise, area2, plane) {
13321
- let i;
13322
- let last;
13323
- if (area2 === void 0) {
13324
- area2 = getPolygonSignedArea(data, { start, end, size: dim, plane });
13325
- }
13326
- let i0 = DimIndex[plane[0]];
13327
- let i1 = DimIndex[plane[1]];
13328
- if (clockwise === area2 < 0) {
13329
- for (i = start; i < end; i += dim)
13330
- last = insertNode(i, data[i + i0], data[i + i1], last);
13331
- } else {
13332
- for (i = end - dim; i >= start; i -= dim)
13333
- last = insertNode(i, data[i + i0], data[i + i1], last);
13334
- }
13335
- if (last && equals(last, last.next)) {
13336
- removeNode(last);
13337
- last = last.next;
13338
- }
13339
- return last;
13340
- }
13341
- function filterPoints(start, end) {
13342
- if (!start)
13343
- return start;
13344
- if (!end)
13345
- end = start;
13346
- let p = start;
13347
- let again;
13348
- do {
13349
- again = false;
13350
- if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
13351
- removeNode(p);
13352
- p = end = p.prev;
13353
- if (p === p.next)
13354
- break;
13355
- again = true;
13356
- } else {
13357
- p = p.next;
13358
- }
13359
- } while (again || p !== end);
13360
- return end;
12997
+ function filterPoints(start, end) {
12998
+ if (!start)
12999
+ return start;
13000
+ if (!end)
13001
+ end = start;
13002
+ let p = start;
13003
+ let again;
13004
+ do {
13005
+ again = false;
13006
+ if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
13007
+ removeNode(p);
13008
+ p = end = p.prev;
13009
+ if (p === p.next)
13010
+ break;
13011
+ again = true;
13012
+ } else {
13013
+ p = p.next;
13014
+ }
13015
+ } while (again || p !== end);
13016
+ return end;
13361
13017
  }
13362
13018
  function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
13363
13019
  if (!ear)
@@ -13622,605 +13278,505 @@ return true;`);
13622
13278
  e.prevZ = tail;
13623
13279
  tail = e;
13624
13280
  }
13625
- p = q;
13626
- }
13627
- tail.nextZ = null;
13628
- inSize *= 2;
13629
- } while (numMerges > 1);
13630
- return list;
13631
- }
13632
- function zOrder(x, y, minX, minY, invSize) {
13633
- x = (x - minX) * invSize | 0;
13634
- y = (y - minY) * invSize | 0;
13635
- x = (x | x << 8) & 16711935;
13636
- x = (x | x << 4) & 252645135;
13637
- x = (x | x << 2) & 858993459;
13638
- x = (x | x << 1) & 1431655765;
13639
- y = (y | y << 8) & 16711935;
13640
- y = (y | y << 4) & 252645135;
13641
- y = (y | y << 2) & 858993459;
13642
- y = (y | y << 1) & 1431655765;
13643
- return x | y << 1;
13644
- }
13645
- function getLeftmost(start) {
13646
- let p = start;
13647
- let leftmost = start;
13648
- do {
13649
- if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
13650
- leftmost = p;
13651
- p = p.next;
13652
- } while (p !== start);
13653
- return leftmost;
13654
- }
13655
- function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
13656
- 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);
13657
- }
13658
- function isValidDiagonal(a, b) {
13659
- return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
13660
- (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
13661
- (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
13662
- equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
13663
- }
13664
- function area(p, q, r) {
13665
- return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
13666
- }
13667
- function equals(p1, p2) {
13668
- return p1.x === p2.x && p1.y === p2.y;
13669
- }
13670
- function intersects(p1, q1, p2, q2) {
13671
- const o1 = sign(area(p1, q1, p2));
13672
- const o2 = sign(area(p1, q1, q2));
13673
- const o3 = sign(area(p2, q2, p1));
13674
- const o4 = sign(area(p2, q2, q1));
13675
- if (o1 !== o2 && o3 !== o4)
13676
- return true;
13677
- if (o1 === 0 && onSegment(p1, p2, q1))
13678
- return true;
13679
- if (o2 === 0 && onSegment(p1, q2, q1))
13680
- return true;
13681
- if (o3 === 0 && onSegment(p2, p1, q2))
13682
- return true;
13683
- if (o4 === 0 && onSegment(p2, q1, q2))
13684
- return true;
13685
- return false;
13686
- }
13687
- function onSegment(p, q, r) {
13688
- 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);
13689
- }
13690
- function sign(num) {
13691
- return num > 0 ? 1 : num < 0 ? -1 : 0;
13692
- }
13693
- function intersectsPolygon(a, b) {
13694
- let p = a;
13695
- do {
13696
- 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))
13697
- return true;
13698
- p = p.next;
13699
- } while (p !== a);
13700
- return false;
13701
- }
13702
- function locallyInside(a, b) {
13703
- 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;
13704
- }
13705
- function middleInside(a, b) {
13706
- let p = a;
13707
- let inside = false;
13708
- const px = (a.x + b.x) / 2;
13709
- const py = (a.y + b.y) / 2;
13710
- do {
13711
- 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)
13712
- inside = !inside;
13713
- p = p.next;
13714
- } while (p !== a);
13715
- return inside;
13716
- }
13717
- function splitPolygon(a, b) {
13718
- const a2 = new Vertex(a.i, a.x, a.y);
13719
- const b2 = new Vertex(b.i, b.x, b.y);
13720
- const an = a.next;
13721
- const bp = b.prev;
13722
- a.next = b;
13723
- b.prev = a;
13724
- a2.next = an;
13725
- an.prev = a2;
13726
- b2.next = a2;
13727
- a2.prev = b2;
13728
- bp.next = b2;
13729
- b2.prev = bp;
13730
- return b2;
13731
- }
13732
- function insertNode(i, x, y, last) {
13733
- const p = new Vertex(i, x, y);
13734
- if (!last) {
13735
- p.prev = p;
13736
- p.next = p;
13737
- } else {
13738
- p.next = last.next;
13739
- p.prev = last;
13740
- last.next.prev = p;
13741
- last.next = p;
13742
- }
13743
- return p;
13744
- }
13745
- function removeNode(p) {
13746
- p.next.prev = p.prev;
13747
- p.prev.next = p.next;
13748
- if (p.prevZ)
13749
- p.prevZ.nextZ = p.nextZ;
13750
- if (p.nextZ)
13751
- p.nextZ.prevZ = p.prevZ;
13752
- }
13753
- var Vertex = class {
13754
- constructor(i, x, y) {
13755
- this.prev = null;
13756
- this.next = null;
13757
- this.z = 0;
13758
- this.prevZ = null;
13759
- this.nextZ = null;
13760
- this.steiner = false;
13761
- this.i = i;
13762
- this.x = x;
13763
- this.y = y;
13764
- }
13765
- };
13766
-
13767
- // ../gis/src/lib/binary-features/binary-to-geojson.ts
13768
- function binaryToGeometry(data, startIndex, endIndex) {
13769
- switch (data.type) {
13770
- case "Point":
13771
- return pointToGeoJson(data, startIndex, endIndex);
13772
- case "LineString":
13773
- return lineStringToGeoJson(data, startIndex, endIndex);
13774
- case "Polygon":
13775
- return polygonToGeoJson(data, startIndex, endIndex);
13776
- default:
13777
- const unexpectedInput = data;
13778
- throw new Error(`Unsupported geometry type: ${unexpectedInput?.type}`);
13779
- }
13780
- }
13781
- function polygonToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
13782
- const { positions } = data;
13783
- const polygonIndices = data.polygonIndices.value.filter((x) => x >= startIndex && x <= endIndex);
13784
- const primitivePolygonIndices = data.primitivePolygonIndices.value.filter(
13785
- (x) => x >= startIndex && x <= endIndex
13786
- );
13787
- const multi = polygonIndices.length > 2;
13788
- if (!multi) {
13789
- const coordinates2 = [];
13790
- for (let i = 0; i < primitivePolygonIndices.length - 1; i++) {
13791
- const startRingIndex = primitivePolygonIndices[i];
13792
- const endRingIndex = primitivePolygonIndices[i + 1];
13793
- const ringCoordinates = ringToGeoJson(positions, startRingIndex, endRingIndex);
13794
- coordinates2.push(ringCoordinates);
13281
+ p = q;
13795
13282
  }
13796
- return { type: "Polygon", coordinates: coordinates2 };
13797
- }
13798
- const coordinates = [];
13799
- for (let i = 0; i < polygonIndices.length - 1; i++) {
13800
- const startPolygonIndex = polygonIndices[i];
13801
- const endPolygonIndex = polygonIndices[i + 1];
13802
- const polygonCoordinates = polygonToGeoJson(
13803
- data,
13804
- startPolygonIndex,
13805
- endPolygonIndex
13806
- ).coordinates;
13807
- coordinates.push(polygonCoordinates);
13808
- }
13809
- return { type: "MultiPolygon", coordinates };
13283
+ tail.nextZ = null;
13284
+ inSize *= 2;
13285
+ } while (numMerges > 1);
13286
+ return list;
13810
13287
  }
13811
- function lineStringToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
13812
- const { positions } = data;
13813
- const pathIndices = data.pathIndices.value.filter((x) => x >= startIndex && x <= endIndex);
13814
- const multi = pathIndices.length > 2;
13815
- if (!multi) {
13816
- const coordinates2 = ringToGeoJson(positions, pathIndices[0], pathIndices[1]);
13817
- return { type: "LineString", coordinates: coordinates2 };
13818
- }
13819
- const coordinates = [];
13820
- for (let i = 0; i < pathIndices.length - 1; i++) {
13821
- const ringCoordinates = ringToGeoJson(positions, pathIndices[i], pathIndices[i + 1]);
13822
- coordinates.push(ringCoordinates);
13823
- }
13824
- return { type: "MultiLineString", coordinates };
13288
+ function zOrder(x, y, minX, minY, invSize) {
13289
+ x = (x - minX) * invSize | 0;
13290
+ y = (y - minY) * invSize | 0;
13291
+ x = (x | x << 8) & 16711935;
13292
+ x = (x | x << 4) & 252645135;
13293
+ x = (x | x << 2) & 858993459;
13294
+ x = (x | x << 1) & 1431655765;
13295
+ y = (y | y << 8) & 16711935;
13296
+ y = (y | y << 4) & 252645135;
13297
+ y = (y | y << 2) & 858993459;
13298
+ y = (y | y << 1) & 1431655765;
13299
+ return x | y << 1;
13825
13300
  }
13826
- function pointToGeoJson(data, startIndex, endIndex) {
13827
- const { positions } = data;
13828
- const coordinates = ringToGeoJson(positions, startIndex, endIndex);
13829
- const multi = coordinates.length > 1;
13830
- if (multi) {
13831
- return { type: "MultiPoint", coordinates };
13832
- }
13833
- return { type: "Point", coordinates: coordinates[0] };
13301
+ function getLeftmost(start) {
13302
+ let p = start;
13303
+ let leftmost = start;
13304
+ do {
13305
+ if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
13306
+ leftmost = p;
13307
+ p = p.next;
13308
+ } while (p !== start);
13309
+ return leftmost;
13834
13310
  }
13835
- function ringToGeoJson(positions, startIndex, endIndex) {
13836
- startIndex = startIndex || 0;
13837
- endIndex = endIndex || positions.value.length / positions.size;
13838
- const ringCoordinates = [];
13839
- for (let j = startIndex; j < endIndex; j++) {
13840
- const coord = Array();
13841
- for (let k = j * positions.size; k < (j + 1) * positions.size; k++) {
13842
- coord.push(Number(positions.value[k]));
13843
- }
13844
- ringCoordinates.push(coord);
13845
- }
13846
- return ringCoordinates;
13311
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
13312
+ 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);
13847
13313
  }
13848
-
13849
- // src/tables/convert-arrow-to-geojson-table.ts
13850
- function convertArrowToGeoJSONTable(table) {
13851
- const arrowTable = table.data;
13852
- const schema = serializeArrowSchema(arrowTable.schema);
13853
- const geometryColumns = getGeometryColumnsFromSchema(schema);
13854
- const encoding = geometryColumns.geometry.encoding;
13855
- const features = [];
13856
- const propertyColumnNames = arrowTable.schema.fields.map((field) => field.name).filter((name) => !(name in geometryColumns));
13857
- const propertiesTable = arrowTable.select(propertyColumnNames);
13858
- const arrowGeometryColumn = arrowTable.getChild("geometry");
13859
- for (let row = 0; row < arrowTable.numRows; row++) {
13860
- const arrowGeometry = arrowGeometryColumn?.get(row);
13861
- const feature = parseGeometryFromArrow(arrowGeometry, encoding);
13862
- if (feature) {
13863
- const properties = propertiesTable.get(row)?.toJSON() || {};
13864
- features.push({ type: "Feature", geometry: feature, properties });
13865
- }
13866
- }
13867
- return {
13868
- shape: "geojson-table",
13869
- type: "FeatureCollection",
13870
- schema: table.schema,
13871
- features
13872
- };
13314
+ function isValidDiagonal(a, b) {
13315
+ return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
13316
+ (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
13317
+ (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
13318
+ equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
13873
13319
  }
13874
-
13875
- // src/parsers/parse-geoarrow-sync.ts
13876
- function parseGeoArrowSync(arrayBuffer, options) {
13877
- const table = parseArrowSync(arrayBuffer, { shape: "arrow-table" });
13878
- switch (options?.shape) {
13879
- case "geojson-table":
13880
- return convertArrowToGeoJSONTable(table);
13881
- default:
13882
- return table;
13883
- }
13320
+ function area(p, q, r) {
13321
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
13884
13322
  }
13885
-
13886
- // src/parsers/parse-geoarrow-in-batches.ts
13887
- function parseGeoArrowInBatches(asyncIterator) {
13888
- return parseArrowInBatches(asyncIterator);
13323
+ function equals(p1, p2) {
13324
+ return p1.x === p2.x && p1.y === p2.y;
13889
13325
  }
13890
-
13891
- // src/geoarrow-loader.ts
13892
- var GeoArrowWorkerLoader = {
13893
- ...ArrowWorkerLoader,
13894
- options: {
13895
- arrow: {
13896
- shape: "arrow-table"
13897
- }
13898
- }
13899
- };
13900
- var GeoArrowLoader = {
13901
- ...GeoArrowWorkerLoader,
13902
- parse: async (arraybuffer, options) => parseGeoArrowSync(arraybuffer, options?.arrow),
13903
- parseSync: (arraybuffer, options) => parseGeoArrowSync(arraybuffer, options?.arrow),
13904
- parseInBatches: parseGeoArrowInBatches
13905
- };
13906
-
13907
- // src/geoarrow/get-arrow-bounds.ts
13908
- function updateBoundsFromGeoArrowSamples(flatCoords, nDim, bounds, sampleSize = 100) {
13909
- const numberOfFeatures = flatCoords.length / nDim;
13910
- const sampleStep = Math.max(Math.floor(numberOfFeatures / sampleSize), 1);
13911
- const newBounds = [...bounds];
13912
- for (let i = 0; i < numberOfFeatures; i += sampleStep) {
13913
- const lng = flatCoords[i * nDim];
13914
- const lat = flatCoords[i * nDim + 1];
13915
- if (lng < newBounds[0]) {
13916
- newBounds[0] = lng;
13917
- }
13918
- if (lat < newBounds[1]) {
13919
- newBounds[1] = lat;
13920
- }
13921
- if (lng > newBounds[2]) {
13922
- newBounds[2] = lng;
13923
- }
13924
- if (lat > newBounds[3]) {
13925
- newBounds[3] = lat;
13926
- }
13927
- }
13928
- return newBounds;
13326
+ function intersects(p1, q1, p2, q2) {
13327
+ const o1 = sign(area(p1, q1, p2));
13328
+ const o2 = sign(area(p1, q1, q2));
13329
+ const o3 = sign(area(p2, q2, p1));
13330
+ const o4 = sign(area(p2, q2, q1));
13331
+ if (o1 !== o2 && o3 !== o4)
13332
+ return true;
13333
+ if (o1 === 0 && onSegment(p1, p2, q1))
13334
+ return true;
13335
+ if (o2 === 0 && onSegment(p1, q2, q1))
13336
+ return true;
13337
+ if (o3 === 0 && onSegment(p2, p1, q2))
13338
+ return true;
13339
+ if (o4 === 0 && onSegment(p2, q1, q2))
13340
+ return true;
13341
+ return false;
13929
13342
  }
13930
-
13931
- // src/geoarrow/convert-geoarrow-to-binary-geometry.ts
13932
- function getBinaryGeometryTemplate() {
13933
- return {
13934
- globalFeatureIds: { value: new Uint32Array(0), size: 1 },
13935
- positions: { value: new Float32Array(0), size: 2 },
13936
- properties: [],
13937
- numericProps: {},
13938
- featureIds: { value: new Uint32Array(0), size: 1 }
13939
- };
13343
+ function onSegment(p, q, r) {
13344
+ 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);
13940
13345
  }
13941
- function getBinaryGeometriesFromArrow(geoColumn, geoEncoding, options) {
13942
- const featureTypes = {
13943
- polygon: geoEncoding === "geoarrow.multipolygon" || geoEncoding === "geoarrow.polygon",
13944
- point: geoEncoding === "geoarrow.multipoint" || geoEncoding === "geoarrow.point",
13945
- line: geoEncoding === "geoarrow.multilinestring" || geoEncoding === "geoarrow.linestring"
13946
- };
13947
- const chunks = options?.chunkIndex !== void 0 && options?.chunkIndex >= 0 ? [geoColumn.data[options?.chunkIndex]] : geoColumn.data;
13948
- let bounds = [Infinity, Infinity, -Infinity, -Infinity];
13949
- let globalFeatureIdOffset = options?.chunkOffset || 0;
13950
- const binaryGeometries = [];
13951
- chunks.forEach((chunk) => {
13952
- const { featureIds, flatCoordinateArray, nDim, geomOffset, triangles } = getBinaryGeometriesFromChunk(chunk, geoEncoding, options);
13953
- const globalFeatureIds = new Uint32Array(featureIds.length);
13954
- for (let i = 0; i < featureIds.length; i++) {
13955
- globalFeatureIds[i] = featureIds[i] + globalFeatureIdOffset;
13956
- }
13957
- const binaryContent = {
13958
- globalFeatureIds: { value: globalFeatureIds, size: 1 },
13959
- positions: {
13960
- value: flatCoordinateArray,
13961
- size: nDim
13962
- },
13963
- featureIds: { value: featureIds, size: 1 },
13964
- // eslint-disable-next-line no-loop-func
13965
- properties: [...Array(chunk.length).keys()].map((i) => ({
13966
- index: i + globalFeatureIdOffset
13967
- }))
13968
- };
13969
- globalFeatureIdOffset += chunk.length;
13970
- binaryGeometries.push({
13971
- shape: "binary-feature-collection",
13972
- points: {
13973
- type: "Point",
13974
- ...getBinaryGeometryTemplate(),
13975
- ...featureTypes.point ? binaryContent : {}
13976
- },
13977
- lines: {
13978
- type: "LineString",
13979
- ...getBinaryGeometryTemplate(),
13980
- ...featureTypes.line ? binaryContent : {},
13981
- pathIndices: { value: featureTypes.line ? geomOffset : new Uint16Array(0), size: 1 }
13982
- },
13983
- polygons: {
13984
- type: "Polygon",
13985
- ...getBinaryGeometryTemplate(),
13986
- ...featureTypes.polygon ? binaryContent : {},
13987
- polygonIndices: {
13988
- // use geomOffset as polygonIndices same as primitivePolygonIndices since we are using earcut to get triangule indices
13989
- value: featureTypes.polygon ? geomOffset : new Uint16Array(0),
13990
- size: 1
13991
- },
13992
- primitivePolygonIndices: {
13993
- value: featureTypes.polygon ? geomOffset : new Uint16Array(0),
13994
- size: 1
13995
- },
13996
- ...triangles ? { triangles: { value: triangles, size: 1 } } : {}
13997
- }
13998
- });
13999
- bounds = updateBoundsFromGeoArrowSamples(flatCoordinateArray, nDim, bounds);
14000
- });
14001
- return {
14002
- binaryGeometries,
14003
- bounds,
14004
- featureTypes,
14005
- ...options?.calculateMeanCenters ? { meanCenters: getMeanCentersFromBinaryGeometries(binaryGeometries) } : {}
14006
- };
13346
+ function sign(num) {
13347
+ return num > 0 ? 1 : num < 0 ? -1 : 0;
13348
+ }
13349
+ function intersectsPolygon(a, b) {
13350
+ let p = a;
13351
+ do {
13352
+ 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))
13353
+ return true;
13354
+ p = p.next;
13355
+ } while (p !== a);
13356
+ return false;
14007
13357
  }
14008
- function getMeanCentersFromBinaryGeometries(binaryGeometries) {
14009
- const globalMeanCenters = [];
14010
- binaryGeometries.forEach((binaryGeometry) => {
14011
- let binaryGeometryType = null;
14012
- if (binaryGeometry.points && binaryGeometry.points.positions.value.length > 0) {
14013
- binaryGeometryType = "points" /* points */;
14014
- } else if (binaryGeometry.lines && binaryGeometry.lines.positions.value.length > 0) {
14015
- binaryGeometryType = "lines" /* lines */;
14016
- } else if (binaryGeometry.polygons && binaryGeometry.polygons.positions.value.length > 0) {
14017
- binaryGeometryType = "polygons" /* polygons */;
14018
- }
14019
- const binaryContent = binaryGeometryType ? binaryGeometry[binaryGeometryType] : null;
14020
- if (binaryContent && binaryGeometryType !== null) {
14021
- const featureIds = binaryContent.featureIds.value;
14022
- const flatCoordinateArray = binaryContent.positions.value;
14023
- const nDim = binaryContent.positions.size;
14024
- const primitivePolygonIndices = binaryContent.type === "Polygon" ? binaryContent.primitivePolygonIndices?.value : void 0;
14025
- const meanCenters = getMeanCentersFromGeometry(
14026
- featureIds,
14027
- flatCoordinateArray,
14028
- nDim,
14029
- binaryGeometryType,
14030
- primitivePolygonIndices
14031
- );
14032
- meanCenters.forEach((center) => {
14033
- globalMeanCenters.push(center);
14034
- });
14035
- }
14036
- });
14037
- return globalMeanCenters;
13358
+ function locallyInside(a, b) {
13359
+ 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;
14038
13360
  }
14039
- function getMeanCentersFromGeometry(featureIds, flatCoordinateArray, nDim, geometryType, primitivePolygonIndices) {
14040
- const meanCenters = [];
14041
- const vertexCount = flatCoordinateArray.length;
14042
- let vertexIndex = 0;
14043
- let coordIdx = 0;
14044
- let primitiveIdx = 0;
14045
- while (vertexIndex < vertexCount) {
14046
- const featureId = featureIds[vertexIndex / nDim];
14047
- const center = [0, 0];
14048
- let vertexCountInFeature = 0;
14049
- while (vertexIndex < vertexCount && featureIds[coordIdx] === featureId) {
14050
- if (geometryType === "polygons" /* polygons */ && primitivePolygonIndices?.[primitiveIdx] === coordIdx) {
14051
- vertexIndex += nDim;
14052
- primitiveIdx++;
14053
- } else {
14054
- center[0] += flatCoordinateArray[vertexIndex];
14055
- center[1] += flatCoordinateArray[vertexIndex + 1];
14056
- vertexIndex += nDim;
14057
- vertexCountInFeature++;
14058
- }
14059
- coordIdx += 1;
14060
- }
14061
- center[0] /= vertexCountInFeature;
14062
- center[1] /= vertexCountInFeature;
14063
- meanCenters.push(center);
13361
+ function middleInside(a, b) {
13362
+ let p = a;
13363
+ let inside = false;
13364
+ const px = (a.x + b.x) / 2;
13365
+ const py = (a.y + b.y) / 2;
13366
+ do {
13367
+ 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)
13368
+ inside = !inside;
13369
+ p = p.next;
13370
+ } while (p !== a);
13371
+ return inside;
13372
+ }
13373
+ function splitPolygon(a, b) {
13374
+ const a2 = new Vertex(a.i, a.x, a.y);
13375
+ const b2 = new Vertex(b.i, b.x, b.y);
13376
+ const an = a.next;
13377
+ const bp = b.prev;
13378
+ a.next = b;
13379
+ b.prev = a;
13380
+ a2.next = an;
13381
+ an.prev = a2;
13382
+ b2.next = a2;
13383
+ a2.prev = b2;
13384
+ bp.next = b2;
13385
+ b2.prev = bp;
13386
+ return b2;
13387
+ }
13388
+ function insertNode(i, x, y, last) {
13389
+ const p = new Vertex(i, x, y);
13390
+ if (!last) {
13391
+ p.prev = p;
13392
+ p.next = p;
13393
+ } else {
13394
+ p.next = last.next;
13395
+ p.prev = last;
13396
+ last.next.prev = p;
13397
+ last.next = p;
14064
13398
  }
14065
- return meanCenters;
13399
+ return p;
14066
13400
  }
14067
- function getBinaryGeometriesFromChunk(chunk, geoEncoding, options) {
14068
- switch (geoEncoding) {
14069
- case "geoarrow.point":
14070
- case "geoarrow.multipoint":
14071
- return getBinaryPointsFromChunk(chunk, geoEncoding);
14072
- case "geoarrow.linestring":
14073
- case "geoarrow.multilinestring":
14074
- return getBinaryLinesFromChunk(chunk, geoEncoding);
14075
- case "geoarrow.polygon":
14076
- case "geoarrow.multipolygon":
14077
- return getBinaryPolygonsFromChunk(chunk, geoEncoding, options);
13401
+ function removeNode(p) {
13402
+ p.next.prev = p.prev;
13403
+ p.prev.next = p.next;
13404
+ if (p.prevZ)
13405
+ p.prevZ.nextZ = p.nextZ;
13406
+ if (p.nextZ)
13407
+ p.nextZ.prevZ = p.prevZ;
13408
+ }
13409
+ var Vertex = class {
13410
+ constructor(i, x, y) {
13411
+ this.prev = null;
13412
+ this.next = null;
13413
+ this.z = 0;
13414
+ this.prevZ = null;
13415
+ this.nextZ = null;
13416
+ this.steiner = false;
13417
+ this.i = i;
13418
+ this.x = x;
13419
+ this.y = y;
13420
+ }
13421
+ };
13422
+
13423
+ // ../gis/src/lib/binary-features/binary-to-geojson.ts
13424
+ function binaryToGeometry(data, startIndex, endIndex) {
13425
+ switch (data.type) {
13426
+ case "Point":
13427
+ return pointToGeoJson(data, startIndex, endIndex);
13428
+ case "LineString":
13429
+ return lineStringToGeoJson(data, startIndex, endIndex);
13430
+ case "Polygon":
13431
+ return polygonToGeoJson(data, startIndex, endIndex);
14078
13432
  default:
14079
- throw Error("invalid geoarrow encoding");
13433
+ const unexpectedInput = data;
13434
+ throw new Error(`Unsupported geometry type: ${unexpectedInput?.type}`);
14080
13435
  }
14081
13436
  }
14082
- function getTriangleIndices(polygonIndices, primitivePolygonIndices, flatCoordinateArray, nDim) {
14083
- try {
14084
- let primitiveIndex = 0;
14085
- const triangles = [];
14086
- for (let i = 0; i < polygonIndices.length - 1; i++) {
14087
- const startIdx = polygonIndices[i];
14088
- const endIdx = polygonIndices[i + 1];
14089
- const slicedFlatCoords = flatCoordinateArray.subarray(startIdx * nDim, endIdx * nDim);
14090
- const holeIndices = [];
14091
- while (primitivePolygonIndices[primitiveIndex] < endIdx) {
14092
- if (primitivePolygonIndices[primitiveIndex] > startIdx) {
14093
- holeIndices.push(primitivePolygonIndices[primitiveIndex] - startIdx);
14094
- }
14095
- primitiveIndex++;
14096
- }
14097
- const triangleIndices = earcut(
14098
- slicedFlatCoords,
14099
- holeIndices.length > 0 ? holeIndices : void 0,
14100
- nDim
14101
- );
14102
- if (triangleIndices.length === 0) {
14103
- throw Error("earcut failed e.g. invalid polygon");
14104
- }
14105
- for (let j = 0; j < triangleIndices.length; j++) {
14106
- triangles.push(triangleIndices[j] + startIdx);
14107
- }
14108
- }
14109
- const trianglesUint32 = new Uint32Array(triangles.length);
14110
- for (let i = 0; i < triangles.length; i++) {
14111
- trianglesUint32[i] = triangles[i];
13437
+ function polygonToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
13438
+ const { positions } = data;
13439
+ const polygonIndices = data.polygonIndices.value.filter((x) => x >= startIndex && x <= endIndex);
13440
+ const primitivePolygonIndices = data.primitivePolygonIndices.value.filter(
13441
+ (x) => x >= startIndex && x <= endIndex
13442
+ );
13443
+ const multi = polygonIndices.length > 2;
13444
+ if (!multi) {
13445
+ const coordinates2 = [];
13446
+ for (let i = 0; i < primitivePolygonIndices.length - 1; i++) {
13447
+ const startRingIndex = primitivePolygonIndices[i];
13448
+ const endRingIndex = primitivePolygonIndices[i + 1];
13449
+ const ringCoordinates = ringToGeoJson(positions, startRingIndex, endRingIndex);
13450
+ coordinates2.push(ringCoordinates);
14112
13451
  }
14113
- return trianglesUint32;
14114
- } catch (error) {
14115
- return null;
13452
+ return { type: "Polygon", coordinates: coordinates2 };
14116
13453
  }
13454
+ const coordinates = [];
13455
+ for (let i = 0; i < polygonIndices.length - 1; i++) {
13456
+ const startPolygonIndex = polygonIndices[i];
13457
+ const endPolygonIndex = polygonIndices[i + 1];
13458
+ const polygonCoordinates = polygonToGeoJson(
13459
+ data,
13460
+ startPolygonIndex,
13461
+ endPolygonIndex
13462
+ ).coordinates;
13463
+ coordinates.push(polygonCoordinates);
13464
+ }
13465
+ return { type: "MultiPolygon", coordinates };
14117
13466
  }
14118
- function getBinaryPolygonsFromChunk(chunk, geoEncoding, options) {
14119
- const isMultiPolygon = geoEncoding === "geoarrow.multipolygon";
14120
- const polygonData = isMultiPolygon ? chunk.children[0] : chunk;
14121
- const polygonOffset = polygonData.valueOffsets;
14122
- const partData = isMultiPolygon ? chunk.valueOffsets.map((i) => polygonOffset.at(i) || i) : chunk.valueOffsets;
14123
- const ringData = polygonData.children[0];
14124
- const pointData = ringData.children[0];
14125
- const coordData = pointData.children[0];
14126
- const nDim = pointData.stride;
14127
- const geomOffset = ringData.valueOffsets;
14128
- const flatCoordinateArray = coordData.values;
14129
- const geometryIndicies = new Uint16Array(polygonOffset.length);
14130
- for (let i = 0; i < polygonOffset.length; i++) {
14131
- geometryIndicies[i] = geomOffset[polygonOffset[i]];
13467
+ function lineStringToGeoJson(data, startIndex = -Infinity, endIndex = Infinity) {
13468
+ const { positions } = data;
13469
+ const pathIndices = data.pathIndices.value.filter((x) => x >= startIndex && x <= endIndex);
13470
+ const multi = pathIndices.length > 2;
13471
+ if (!multi) {
13472
+ const coordinates2 = ringToGeoJson(positions, pathIndices[0], pathIndices[1]);
13473
+ return { type: "LineString", coordinates: coordinates2 };
14132
13474
  }
14133
- const numOfVertices = flatCoordinateArray.length / nDim;
14134
- const featureIds = new Uint32Array(numOfVertices);
14135
- for (let i = 0; i < partData.length - 1; i++) {
14136
- const startIdx = geomOffset[partData[i]];
14137
- const endIdx = geomOffset[partData[i + 1]];
14138
- for (let j = startIdx; j < endIdx; j++) {
14139
- featureIds[j] = i;
13475
+ const coordinates = [];
13476
+ for (let i = 0; i < pathIndices.length - 1; i++) {
13477
+ const ringCoordinates = ringToGeoJson(positions, pathIndices[i], pathIndices[i + 1]);
13478
+ coordinates.push(ringCoordinates);
13479
+ }
13480
+ return { type: "MultiLineString", coordinates };
13481
+ }
13482
+ function pointToGeoJson(data, startIndex, endIndex) {
13483
+ const { positions } = data;
13484
+ const coordinates = ringToGeoJson(positions, startIndex, endIndex);
13485
+ const multi = coordinates.length > 1;
13486
+ if (multi) {
13487
+ return { type: "MultiPoint", coordinates };
13488
+ }
13489
+ return { type: "Point", coordinates: coordinates[0] };
13490
+ }
13491
+ function ringToGeoJson(positions, startIndex, endIndex) {
13492
+ startIndex = startIndex || 0;
13493
+ endIndex = endIndex || positions.value.length / positions.size;
13494
+ const ringCoordinates = [];
13495
+ for (let j = startIndex; j < endIndex; j++) {
13496
+ const coord = Array();
13497
+ for (let k = j * positions.size; k < (j + 1) * positions.size; k++) {
13498
+ coord.push(Number(positions.value[k]));
14140
13499
  }
13500
+ ringCoordinates.push(coord);
14141
13501
  }
14142
- const triangles = options?.triangulate ? getTriangleIndices(geometryIndicies, geomOffset, flatCoordinateArray, nDim) : null;
13502
+ return ringCoordinates;
13503
+ }
13504
+
13505
+ // src/lib/tables/convert-arrow-schema.ts
13506
+ function convertArrowToSchema(arrowSchema) {
13507
+ return serializeArrowSchema(arrowSchema);
13508
+ }
13509
+ function convertSchemaToArrow(schema) {
13510
+ return deserializeArrowSchema(schema);
13511
+ }
13512
+ function serializeArrowSchema(arrowSchema) {
14143
13513
  return {
14144
- featureIds,
14145
- nDim,
14146
- flatCoordinateArray,
14147
- geomOffset,
14148
- geometryIndicies,
14149
- ...options?.triangulate && triangles ? { triangles } : {}
13514
+ fields: arrowSchema.fields.map((arrowField) => serializeArrowField(arrowField)),
13515
+ metadata: serializeArrowMetadata(arrowSchema.metadata)
14150
13516
  };
14151
13517
  }
14152
- function getBinaryLinesFromChunk(chunk, geoEncoding) {
14153
- const isMultiLineString = geoEncoding === "geoarrow.multilinestring";
14154
- const lineData = isMultiLineString ? chunk.children[0] : chunk;
14155
- const pointData = lineData.children[0];
14156
- const coordData = pointData.children[0];
14157
- const nDim = pointData.stride;
14158
- const geomOffset = lineData.valueOffsets;
14159
- const flatCoordinateArray = coordData.values;
14160
- const geometryIndicies = new Uint16Array(0);
14161
- const numOfVertices = flatCoordinateArray.length / nDim;
14162
- const featureIds = new Uint32Array(numOfVertices);
14163
- if (isMultiLineString) {
14164
- const partData = chunk.valueOffsets;
14165
- for (let i = 0; i < partData.length - 1; i++) {
14166
- const startIdx = geomOffset[partData[i]];
14167
- const endIdx = geomOffset[partData[i + 1]];
14168
- for (let j = startIdx; j < endIdx; j++) {
14169
- featureIds[j] = i;
14170
- }
14171
- }
14172
- } else {
14173
- for (let i = 0; i < chunk.length; i++) {
14174
- const startIdx = geomOffset[i];
14175
- const endIdx = geomOffset[i + 1];
14176
- for (let j = startIdx; j < endIdx; j++) {
14177
- featureIds[j] = i;
14178
- }
14179
- }
14180
- }
13518
+ function deserializeArrowSchema(schema) {
13519
+ return new Schema2(
13520
+ schema.fields.map((field) => deserializeArrowField(field)),
13521
+ deserializeArrowMetadata(schema.metadata)
13522
+ );
13523
+ }
13524
+ function serializeArrowMetadata(arrowMetadata) {
13525
+ return Object.fromEntries(arrowMetadata);
13526
+ }
13527
+ function deserializeArrowMetadata(metadata) {
13528
+ return metadata ? new Map(Object.entries(metadata)) : /* @__PURE__ */ new Map();
13529
+ }
13530
+ function serializeArrowField(field) {
14181
13531
  return {
14182
- featureIds,
14183
- flatCoordinateArray,
14184
- nDim,
14185
- geomOffset,
14186
- geometryIndicies
13532
+ name: field.name,
13533
+ type: serializeArrowType(field.type),
13534
+ nullable: field.nullable,
13535
+ metadata: serializeArrowMetadata(field.metadata)
14187
13536
  };
14188
13537
  }
14189
- function getBinaryPointsFromChunk(chunk, geoEncoding) {
14190
- const isMultiPoint = geoEncoding === "geoarrow.multipoint";
14191
- const pointData = isMultiPoint ? chunk.children[0] : chunk;
14192
- const coordData = pointData.children[0];
14193
- const nDim = pointData.stride;
14194
- const flatCoordinateArray = coordData.values;
14195
- const geometryIndicies = new Uint16Array(0);
14196
- const geomOffset = new Int32Array(0);
14197
- const numOfVertices = flatCoordinateArray.length / nDim;
14198
- const featureIds = new Uint32Array(numOfVertices);
14199
- if (isMultiPoint) {
14200
- const partData = chunk.valueOffsets;
14201
- for (let i = 0; i < partData.length - 1; i++) {
14202
- const startIdx = partData[i];
14203
- const endIdx = partData[i + 1];
14204
- for (let j = startIdx; j < endIdx; j++) {
14205
- featureIds[j] = i;
13538
+ function deserializeArrowField(field) {
13539
+ return new Field2(
13540
+ field.name,
13541
+ deserializeArrowType(field.type),
13542
+ field.nullable,
13543
+ deserializeArrowMetadata(field.metadata)
13544
+ );
13545
+ }
13546
+ function serializeArrowType(arrowType) {
13547
+ switch (arrowType.constructor) {
13548
+ case Null2:
13549
+ return "null";
13550
+ case Binary2:
13551
+ return "binary";
13552
+ case Bool2:
13553
+ return "bool";
13554
+ case Int_:
13555
+ const intType = arrowType;
13556
+ return `${intType.isSigned ? "u" : ""}int${intType.bitWidth}`;
13557
+ case Int8:
13558
+ return "int8";
13559
+ case Int16:
13560
+ return "int16";
13561
+ case Int32:
13562
+ return "int32";
13563
+ case Int64:
13564
+ return "int64";
13565
+ case Uint8:
13566
+ return "uint8";
13567
+ case Uint16:
13568
+ return "uint16";
13569
+ case Uint32:
13570
+ return "uint32";
13571
+ case Uint64:
13572
+ return "uint64";
13573
+ case Float:
13574
+ const precision = arrowType.precision;
13575
+ switch (precision) {
13576
+ case Precision.HALF:
13577
+ return "float16";
13578
+ case Precision.SINGLE:
13579
+ return "float32";
13580
+ case Precision.DOUBLE:
13581
+ return "float64";
13582
+ default:
13583
+ return "float16";
14206
13584
  }
14207
- }
14208
- } else {
14209
- for (let i = 0; i < chunk.length; i++) {
14210
- featureIds[i] = i;
13585
+ case Float16:
13586
+ return "float16";
13587
+ case Float32:
13588
+ return "float32";
13589
+ case Float64:
13590
+ return "float64";
13591
+ case Utf82:
13592
+ return "utf8";
13593
+ case Decimal2:
13594
+ const decimal = arrowType;
13595
+ return {
13596
+ type: "decimal",
13597
+ bitWidth: decimal.bitWidth,
13598
+ precision: decimal.precision,
13599
+ scale: decimal.scale
13600
+ };
13601
+ case Date_:
13602
+ const dateUnit = arrowType.unit;
13603
+ return dateUnit === DateUnit.DAY ? "date-day" : "date-millisecond";
13604
+ case DateDay:
13605
+ return "date-day";
13606
+ case DateMillisecond:
13607
+ return "date-millisecond";
13608
+ case Time_:
13609
+ const timeUnit = arrowType.unit;
13610
+ switch (timeUnit) {
13611
+ case TimeUnit.SECOND:
13612
+ return "time-second";
13613
+ case TimeUnit.MILLISECOND:
13614
+ return "time-millisecond";
13615
+ case TimeUnit.MICROSECOND:
13616
+ return "time-microsecond";
13617
+ case TimeUnit.NANOSECOND:
13618
+ return "time-nanosecond";
13619
+ default:
13620
+ return "time-second";
13621
+ }
13622
+ case TimeMillisecond:
13623
+ return "time-millisecond";
13624
+ case TimeSecond:
13625
+ return "time-second";
13626
+ case TimeMicrosecond:
13627
+ return "time-microsecond";
13628
+ case TimeNanosecond:
13629
+ return "time-nanosecond";
13630
+ case Timestamp_:
13631
+ const timeStampUnit = arrowType.unit;
13632
+ switch (timeStampUnit) {
13633
+ case TimeUnit.SECOND:
13634
+ return "timestamp-second";
13635
+ case TimeUnit.MILLISECOND:
13636
+ return "timestamp-millisecond";
13637
+ case TimeUnit.MICROSECOND:
13638
+ return "timestamp-microsecond";
13639
+ case TimeUnit.NANOSECOND:
13640
+ return "timestamp-nanosecond";
13641
+ default:
13642
+ return "timestamp-second";
13643
+ }
13644
+ case TimestampSecond:
13645
+ return "timestamp-second";
13646
+ case TimestampMillisecond:
13647
+ return "timestamp-millisecond";
13648
+ case TimestampMicrosecond:
13649
+ return "timestamp-microsecond";
13650
+ case TimestampNanosecond:
13651
+ return "timestamp-nanosecond";
13652
+ case Interval_:
13653
+ const intervalUnit = arrowType.unit;
13654
+ switch (intervalUnit) {
13655
+ case IntervalUnit.DAY_TIME:
13656
+ return "interval-daytime";
13657
+ case IntervalUnit.YEAR_MONTH:
13658
+ return "interval-yearmonth";
13659
+ default:
13660
+ return "interval-daytime";
13661
+ }
13662
+ case IntervalDayTime:
13663
+ return "interval-daytime";
13664
+ case IntervalYearMonth:
13665
+ return "interval-yearmonth";
13666
+ case Map_:
13667
+ const mapType = arrowType;
13668
+ return {
13669
+ type: "map",
13670
+ keysSorted: mapType.keysSorted,
13671
+ children: mapType.children.map((arrowField) => serializeArrowField(arrowField))
13672
+ };
13673
+ case List2:
13674
+ const listType = arrowType;
13675
+ const listField = listType.valueField;
13676
+ return {
13677
+ type: "list",
13678
+ children: [serializeArrowField(listField)]
13679
+ };
13680
+ case FixedSizeList2:
13681
+ const fixedSizeList = arrowType;
13682
+ return {
13683
+ type: "fixed-size-list",
13684
+ listSize: fixedSizeList.listSize,
13685
+ children: [serializeArrowField(fixedSizeList.children[0])]
13686
+ };
13687
+ case Struct:
13688
+ const structType = arrowType;
13689
+ return {
13690
+ type: "struct",
13691
+ children: structType.children.map((arrowField) => serializeArrowField(arrowField))
13692
+ };
13693
+ default:
13694
+ throw new Error(`arrow type not supported: ${arrowType.constructor.name}`);
13695
+ }
13696
+ }
13697
+ function deserializeArrowType(dataType) {
13698
+ if (typeof dataType === "object") {
13699
+ switch (dataType.type) {
13700
+ case "decimal":
13701
+ return new Decimal2(dataType.precision, dataType.scale, dataType.bitWidth);
13702
+ case "map":
13703
+ let children = dataType.children.map((arrowField) => deserializeArrowField(arrowField));
13704
+ return new Map_(children, dataType.keysSorted);
13705
+ case "list":
13706
+ const field = deserializeArrowField(dataType.children[0]);
13707
+ return new List2(field);
13708
+ case "fixed-size-list":
13709
+ const child = deserializeArrowField(dataType.children[0]);
13710
+ return new FixedSizeList2(dataType.listSize, child);
13711
+ case "struct":
13712
+ children = dataType.children.map((arrowField) => deserializeArrowField(arrowField));
13713
+ return new Struct(children);
13714
+ default:
13715
+ throw new Error("array type not supported");
14211
13716
  }
14212
13717
  }
14213
- return {
14214
- featureIds,
14215
- flatCoordinateArray,
14216
- nDim,
14217
- geomOffset,
14218
- geometryIndicies
14219
- };
13718
+ switch (dataType) {
13719
+ case "null":
13720
+ return new Null2();
13721
+ case "binary":
13722
+ return new Binary2();
13723
+ case "bool":
13724
+ return new Bool2();
13725
+ case "int8":
13726
+ return new Int8();
13727
+ case "int16":
13728
+ return new Int16();
13729
+ case "int32":
13730
+ return new Int32();
13731
+ case "int64":
13732
+ return new Int64();
13733
+ case "uint8":
13734
+ return new Uint8();
13735
+ case "uint16":
13736
+ return new Uint16();
13737
+ case "uint32":
13738
+ return new Uint32();
13739
+ case "uint64":
13740
+ return new Uint64();
13741
+ case "float16":
13742
+ return new Float16();
13743
+ case "float32":
13744
+ return new Float32();
13745
+ case "float64":
13746
+ return new Float64();
13747
+ case "utf8":
13748
+ return new Utf82();
13749
+ case "date-day":
13750
+ return new DateDay();
13751
+ case "date-millisecond":
13752
+ return new DateMillisecond();
13753
+ case "time-second":
13754
+ return new TimeSecond();
13755
+ case "time-millisecond":
13756
+ return new TimeMillisecond();
13757
+ case "time-microsecond":
13758
+ return new TimeMicrosecond();
13759
+ case "time-nanosecond":
13760
+ return new TimeNanosecond();
13761
+ case "timestamp-second":
13762
+ return new TimestampSecond();
13763
+ case "timestamp-millisecond":
13764
+ return new TimestampMillisecond();
13765
+ case "timestamp-microsecond":
13766
+ return new TimestampMicrosecond();
13767
+ case "timestamp-nanosecond":
13768
+ return new TimestampNanosecond();
13769
+ case "interval-daytime":
13770
+ return new IntervalDayTime();
13771
+ case "interval-yearmonth":
13772
+ return new IntervalYearMonth();
13773
+ default:
13774
+ throw new Error("array type not supported");
13775
+ }
14220
13776
  }
14221
13777
 
14222
13778
  // ../wkt/src/lib/utils/version.ts
14223
- var VERSION3 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
13779
+ var VERSION2 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
14224
13780
 
14225
13781
  // ../wkt/src/lib/parse-wkt.ts
14226
13782
  var numberRegexp = /[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/;
@@ -14238,747 +13794,1286 @@ return true;`);
14238
13794
  function isWKT(input) {
14239
13795
  return WKT_MAGIC_STRINGS.some((magicString) => input.startsWith(magicString));
14240
13796
  }
14241
- function parseWKT(input, options) {
14242
- return parseWKTToGeometry(input, options);
13797
+ function parseWKT(input, options) {
13798
+ return parseWKTToGeometry(input, options);
13799
+ }
13800
+ function parseWKTToGeometry(input, options) {
13801
+ const parts = input.split(";");
13802
+ let _ = parts.pop();
13803
+ const srid = (parts.shift() || "").split("=").pop();
13804
+ const state = { parts, _, i: 0 };
13805
+ const geometry = parseGeometry(state);
13806
+ return options?.wkt?.crs ? addCRS(geometry, srid) : geometry;
13807
+ }
13808
+ function parseGeometry(state) {
13809
+ return parsePoint(state) || parseLineString(state) || parsePolygon(state) || parseMultiPoint(state) || parseMultiLineString(state) || parseMultiPolygon(state) || parseGeometryCollection(state);
13810
+ }
13811
+ function addCRS(obj, srid) {
13812
+ if (obj && srid?.match(/\d+/)) {
13813
+ const crs = {
13814
+ type: "name",
13815
+ properties: {
13816
+ name: "urn:ogc:def:crs:EPSG::" + srid
13817
+ }
13818
+ };
13819
+ obj.crs = crs;
13820
+ }
13821
+ return obj;
13822
+ }
13823
+ function parsePoint(state) {
13824
+ if (!$(/^(POINT(\sz)?)/i, state)) {
13825
+ return null;
13826
+ }
13827
+ white(state);
13828
+ if (!$(/^(\()/, state)) {
13829
+ return null;
13830
+ }
13831
+ const c = coords(state);
13832
+ if (!c) {
13833
+ return null;
13834
+ }
13835
+ white(state);
13836
+ if (!$(/^(\))/, state)) {
13837
+ return null;
13838
+ }
13839
+ return {
13840
+ type: "Point",
13841
+ coordinates: c[0]
13842
+ };
13843
+ }
13844
+ function parseMultiPoint(state) {
13845
+ if (!$(/^(MULTIPOINT)/i, state)) {
13846
+ return null;
13847
+ }
13848
+ white(state);
13849
+ const newCoordsFormat = state._?.substring(state._?.indexOf("(") + 1, state._.length - 1).replace(/\(/g, "").replace(/\)/g, "");
13850
+ state._ = "MULTIPOINT (" + newCoordsFormat + ")";
13851
+ const c = multicoords(state);
13852
+ if (!c) {
13853
+ return null;
13854
+ }
13855
+ white(state);
13856
+ return {
13857
+ type: "MultiPoint",
13858
+ coordinates: c
13859
+ };
13860
+ }
13861
+ function parseLineString(state) {
13862
+ if (!$(/^(LINESTRING(\sz)?)/i, state)) {
13863
+ return null;
13864
+ }
13865
+ white(state);
13866
+ if (!$(/^(\()/, state)) {
13867
+ return null;
13868
+ }
13869
+ const c = coords(state);
13870
+ if (!c) {
13871
+ return null;
13872
+ }
13873
+ if (!$(/^(\))/, state)) {
13874
+ return null;
13875
+ }
13876
+ return {
13877
+ type: "LineString",
13878
+ coordinates: c
13879
+ };
13880
+ }
13881
+ function parseMultiLineString(state) {
13882
+ if (!$(/^(MULTILINESTRING)/i, state))
13883
+ return null;
13884
+ white(state);
13885
+ const c = multicoords(state);
13886
+ if (!c) {
13887
+ return null;
13888
+ }
13889
+ white(state);
13890
+ return {
13891
+ // @ts-ignore
13892
+ type: "MultiLineString",
13893
+ // @ts-expect-error
13894
+ coordinates: c
13895
+ };
13896
+ }
13897
+ function parsePolygon(state) {
13898
+ if (!$(/^(POLYGON(\sz)?)/i, state)) {
13899
+ return null;
13900
+ }
13901
+ white(state);
13902
+ const c = multicoords(state);
13903
+ if (!c) {
13904
+ return null;
13905
+ }
13906
+ return {
13907
+ // @ts-ignore
13908
+ type: "Polygon",
13909
+ // @ts-expect-error
13910
+ coordinates: c
13911
+ };
13912
+ }
13913
+ function parseMultiPolygon(state) {
13914
+ if (!$(/^(MULTIPOLYGON)/i, state)) {
13915
+ return null;
13916
+ }
13917
+ white(state);
13918
+ const c = multicoords(state);
13919
+ if (!c) {
13920
+ return null;
13921
+ }
13922
+ return {
13923
+ type: "MultiPolygon",
13924
+ // @ts-expect-error
13925
+ coordinates: c
13926
+ };
13927
+ }
13928
+ function parseGeometryCollection(state) {
13929
+ const geometries = [];
13930
+ let geometry;
13931
+ if (!$(/^(GEOMETRYCOLLECTION)/i, state)) {
13932
+ return null;
13933
+ }
13934
+ white(state);
13935
+ if (!$(/^(\()/, state)) {
13936
+ return null;
13937
+ }
13938
+ while (geometry = parseGeometry(state)) {
13939
+ geometries.push(geometry);
13940
+ white(state);
13941
+ $(/^(,)/, state);
13942
+ white(state);
13943
+ }
13944
+ if (!$(/^(\))/, state)) {
13945
+ return null;
13946
+ }
13947
+ return {
13948
+ type: "GeometryCollection",
13949
+ geometries
13950
+ };
13951
+ }
13952
+ function multicoords(state) {
13953
+ white(state);
13954
+ let depth = 0;
13955
+ const rings = [];
13956
+ const stack = [rings];
13957
+ let pointer = rings;
13958
+ let elem;
13959
+ while (elem = $(/^(\()/, state) || $(/^(\))/, state) || $(/^(,)/, state) || $(tuples, state)) {
13960
+ if (elem === "(") {
13961
+ stack.push(pointer);
13962
+ pointer = [];
13963
+ stack[stack.length - 1].push(pointer);
13964
+ depth++;
13965
+ } else if (elem === ")") {
13966
+ if (pointer.length === 0)
13967
+ return null;
13968
+ pointer = stack.pop();
13969
+ if (!pointer)
13970
+ return null;
13971
+ depth--;
13972
+ if (depth === 0)
13973
+ break;
13974
+ } else if (elem === ",") {
13975
+ pointer = [];
13976
+ stack[stack.length - 1].push(pointer);
13977
+ } else if (!elem.split(/\s/g).some(isNaN)) {
13978
+ Array.prototype.push.apply(pointer, elem.split(/\s/g).map(parseFloat));
13979
+ } else {
13980
+ return null;
13981
+ }
13982
+ white(state);
13983
+ }
13984
+ if (depth !== 0)
13985
+ return null;
13986
+ return rings;
13987
+ }
13988
+ function coords(state) {
13989
+ const list = [];
13990
+ let item;
13991
+ let pt;
13992
+ while (pt = $(tuples, state) || $(/^(,)/, state)) {
13993
+ if (pt === ",") {
13994
+ list.push(item);
13995
+ item = [];
13996
+ } else if (!pt.split(/\s/g).some(isNaN)) {
13997
+ if (!item)
13998
+ item = [];
13999
+ Array.prototype.push.apply(item, pt.split(/\s/g).map(parseFloat));
14000
+ }
14001
+ white(state);
14002
+ }
14003
+ if (item)
14004
+ list.push(item);
14005
+ else
14006
+ return null;
14007
+ return list.length ? list : null;
14243
14008
  }
14244
- function parseWKTToGeometry(input, options) {
14245
- const parts = input.split(";");
14246
- let _ = parts.pop();
14247
- const srid = (parts.shift() || "").split("=").pop();
14248
- const state = { parts, _, i: 0 };
14249
- const geometry = parseGeometry(state);
14250
- return options?.wkt?.crs ? addCRS(geometry, srid) : geometry;
14009
+ function $(regexp, state) {
14010
+ const match = state._?.substring(state.i).match(regexp);
14011
+ if (!match)
14012
+ return null;
14013
+ else {
14014
+ state.i += match[0].length;
14015
+ return match[0];
14016
+ }
14251
14017
  }
14252
- function parseGeometry(state) {
14253
- return parsePoint(state) || parseLineString(state) || parsePolygon(state) || parseMultiPoint(state) || parseMultiLineString(state) || parseMultiPolygon(state) || parseGeometryCollection(state);
14018
+ function white(state) {
14019
+ $(/^\s*/, state);
14254
14020
  }
14255
- function addCRS(obj, srid) {
14256
- if (obj && srid?.match(/\d+/)) {
14257
- const crs = {
14258
- type: "name",
14259
- properties: {
14260
- name: "urn:ogc:def:crs:EPSG::" + srid
14261
- }
14262
- };
14263
- obj.crs = crs;
14021
+
14022
+ // ../wkt/src/wkt-loader.ts
14023
+ var WKTWorkerLoader = {
14024
+ dataType: null,
14025
+ batchType: null,
14026
+ name: "WKT (Well-Known Text)",
14027
+ id: "wkt",
14028
+ module: "wkt",
14029
+ version: VERSION2,
14030
+ worker: true,
14031
+ extensions: ["wkt"],
14032
+ mimeTypes: ["text/plain"],
14033
+ category: "geometry",
14034
+ text: true,
14035
+ tests: WKT_MAGIC_STRINGS,
14036
+ testText: isWKT,
14037
+ options: {
14038
+ wkt: {
14039
+ shape: "geojson-geometry",
14040
+ crs: true
14041
+ }
14264
14042
  }
14265
- return obj;
14043
+ };
14044
+ var WKTLoader = {
14045
+ ...WKTWorkerLoader,
14046
+ parse: async (arrayBuffer, options) => parseWKT(new TextDecoder().decode(arrayBuffer), options),
14047
+ parseTextSync: (string, options) => parseWKT(string, options)
14048
+ };
14049
+
14050
+ // ../wkt/src/lib/parse-wkb-header.ts
14051
+ var EWKB_FLAG_Z = 2147483648;
14052
+ var EWKB_FLAG_M = 1073741824;
14053
+ var EWKB_FLAG_SRID = 536870912;
14054
+ var MAX_SRID = 1e4;
14055
+ function isWKB(arrayBuffer) {
14056
+ const dataView = new DataView(arrayBuffer);
14057
+ let byteOffset = 0;
14058
+ const endianness = dataView.getUint8(byteOffset);
14059
+ byteOffset += 1;
14060
+ if (endianness > 1) {
14061
+ return false;
14062
+ }
14063
+ const littleEndian = endianness === 1;
14064
+ const geometry = dataView.getUint32(byteOffset, littleEndian);
14065
+ byteOffset += 4;
14066
+ const geometryType = geometry & 7;
14067
+ if (geometryType === 0 || geometryType > 7) {
14068
+ return false;
14069
+ }
14070
+ const geometryFlags = geometry - geometryType;
14071
+ if (geometryFlags === 0 || geometryFlags === 1e3 || geometryFlags === 2e3 || geometryFlags === 3e3) {
14072
+ return true;
14073
+ }
14074
+ if ((geometryFlags & ~(EWKB_FLAG_Z | EWKB_FLAG_M | EWKB_FLAG_SRID)) !== 0) {
14075
+ return false;
14076
+ }
14077
+ if (geometryFlags & EWKB_FLAG_SRID) {
14078
+ const srid = dataView.getUint32(byteOffset, littleEndian);
14079
+ byteOffset += 4;
14080
+ if (srid > MAX_SRID) {
14081
+ return false;
14082
+ }
14083
+ }
14084
+ return true;
14266
14085
  }
14267
- function parsePoint(state) {
14268
- if (!$(/^(POINT(\sz)?)/i, state)) {
14269
- return null;
14086
+ function parseWKBHeader(dataView, target) {
14087
+ const wkbHeader = Object.assign(target || {}, {
14088
+ type: "wkb",
14089
+ geometryType: 1,
14090
+ dimensions: 2,
14091
+ coordinates: "xy",
14092
+ littleEndian: true,
14093
+ byteOffset: 0
14094
+ });
14095
+ wkbHeader.littleEndian = dataView.getUint8(wkbHeader.byteOffset) === 1;
14096
+ wkbHeader.byteOffset++;
14097
+ const geometryCode = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
14098
+ wkbHeader.byteOffset += 4;
14099
+ wkbHeader.geometryType = geometryCode & 7;
14100
+ const isoType = (geometryCode - wkbHeader.geometryType) / 1e3;
14101
+ switch (isoType) {
14102
+ case 0:
14103
+ break;
14104
+ case 1:
14105
+ wkbHeader.type = "iso-wkb";
14106
+ wkbHeader.dimensions = 3;
14107
+ wkbHeader.coordinates = "xyz";
14108
+ break;
14109
+ case 2:
14110
+ wkbHeader.type = "iso-wkb";
14111
+ wkbHeader.dimensions = 3;
14112
+ wkbHeader.coordinates = "xym";
14113
+ break;
14114
+ case 3:
14115
+ wkbHeader.type = "iso-wkb";
14116
+ wkbHeader.dimensions = 4;
14117
+ wkbHeader.coordinates = "xyzm";
14118
+ break;
14119
+ default:
14120
+ throw new Error(`WKB: Unsupported iso-wkb type: ${isoType}`);
14270
14121
  }
14271
- white(state);
14272
- if (!$(/^(\()/, state)) {
14273
- return null;
14122
+ const ewkbZ = geometryCode & EWKB_FLAG_Z;
14123
+ const ewkbM = geometryCode & EWKB_FLAG_M;
14124
+ const ewkbSRID = geometryCode & EWKB_FLAG_SRID;
14125
+ if (ewkbZ && ewkbM) {
14126
+ wkbHeader.type = "ewkb";
14127
+ wkbHeader.dimensions = 4;
14128
+ wkbHeader.coordinates = "xyzm";
14129
+ } else if (ewkbZ) {
14130
+ wkbHeader.type = "ewkb";
14131
+ wkbHeader.dimensions = 3;
14132
+ wkbHeader.coordinates = "xyz";
14133
+ } else if (ewkbM) {
14134
+ wkbHeader.type = "ewkb";
14135
+ wkbHeader.dimensions = 3;
14136
+ wkbHeader.coordinates = "xym";
14274
14137
  }
14275
- const c = coords(state);
14276
- if (!c) {
14277
- return null;
14138
+ if (ewkbSRID) {
14139
+ wkbHeader.type = "ewkb";
14140
+ wkbHeader.srid = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
14141
+ wkbHeader.byteOffset += 4;
14278
14142
  }
14279
- white(state);
14280
- if (!$(/^(\))/, state)) {
14281
- return null;
14143
+ return wkbHeader;
14144
+ }
14145
+
14146
+ // ../wkt/src/lib/parse-wkb.ts
14147
+ function parseWKB(arrayBuffer, options) {
14148
+ const binaryGeometry = parseWKBToBinary(arrayBuffer, options);
14149
+ const shape = options?.wkb?.shape || "binary-geometry";
14150
+ switch (shape) {
14151
+ case "binary-geometry":
14152
+ return binaryGeometry;
14153
+ case "geojson-geometry":
14154
+ return binaryToGeometry(binaryGeometry);
14155
+ case "geometry":
14156
+ console.error('WKBLoader: "geometry" shape is deprecated, use "binary-geometry" instead');
14157
+ return binaryToGeometry(binaryGeometry);
14158
+ default:
14159
+ throw new Error(shape);
14282
14160
  }
14283
- return {
14284
- type: "Point",
14285
- coordinates: c[0]
14286
- };
14287
14161
  }
14288
- function parseMultiPoint(state) {
14289
- if (!$(/^(MULTIPOINT)/i, state)) {
14290
- return null;
14162
+ function parseWKBToBinary(arrayBuffer, options) {
14163
+ const dataView = new DataView(arrayBuffer);
14164
+ const wkbHeader = parseWKBHeader(dataView);
14165
+ const { geometryType, dimensions, littleEndian } = wkbHeader;
14166
+ const offset = wkbHeader.byteOffset;
14167
+ switch (geometryType) {
14168
+ case 1 /* Point */:
14169
+ const point = parsePoint2(dataView, offset, dimensions, littleEndian);
14170
+ return point.geometry;
14171
+ case 2 /* LineString */:
14172
+ const line = parseLineString2(dataView, offset, dimensions, littleEndian);
14173
+ return line.geometry;
14174
+ case 3 /* Polygon */:
14175
+ const polygon = parsePolygon2(dataView, offset, dimensions, littleEndian);
14176
+ return polygon.geometry;
14177
+ case 4 /* MultiPoint */:
14178
+ const multiPoint = parseMultiPoint2(dataView, offset, dimensions, littleEndian);
14179
+ multiPoint.type = "Point";
14180
+ return multiPoint;
14181
+ case 5 /* MultiLineString */:
14182
+ const multiLine = parseMultiLineString2(dataView, offset, dimensions, littleEndian);
14183
+ multiLine.type = "LineString";
14184
+ return multiLine;
14185
+ case 6 /* MultiPolygon */:
14186
+ const multiPolygon = parseMultiPolygon2(dataView, offset, dimensions, littleEndian);
14187
+ multiPolygon.type = "Polygon";
14188
+ return multiPolygon;
14189
+ default:
14190
+ throw new Error(`WKB: Unsupported geometry type: ${geometryType}`);
14291
14191
  }
14292
- white(state);
14293
- const newCoordsFormat = state._?.substring(state._?.indexOf("(") + 1, state._.length - 1).replace(/\(/g, "").replace(/\)/g, "");
14294
- state._ = "MULTIPOINT (" + newCoordsFormat + ")";
14295
- const c = multicoords(state);
14296
- if (!c) {
14297
- return null;
14192
+ }
14193
+ function parsePoint2(dataView, offset, dimension, littleEndian) {
14194
+ const positions = new Float64Array(dimension);
14195
+ for (let i = 0; i < dimension; i++) {
14196
+ positions[i] = dataView.getFloat64(offset, littleEndian);
14197
+ offset += 8;
14298
14198
  }
14299
- white(state);
14300
14199
  return {
14301
- type: "MultiPoint",
14302
- coordinates: c
14200
+ geometry: { type: "Point", positions: { value: positions, size: dimension } },
14201
+ offset
14303
14202
  };
14304
14203
  }
14305
- function parseLineString(state) {
14306
- if (!$(/^(LINESTRING(\sz)?)/i, state)) {
14307
- return null;
14308
- }
14309
- white(state);
14310
- if (!$(/^(\()/, state)) {
14311
- return null;
14312
- }
14313
- const c = coords(state);
14314
- if (!c) {
14315
- return null;
14204
+ function parseLineString2(dataView, offset, dimension, littleEndian) {
14205
+ const nPoints = dataView.getUint32(offset, littleEndian);
14206
+ offset += 4;
14207
+ const positions = new Float64Array(nPoints * dimension);
14208
+ for (let i = 0; i < nPoints * dimension; i++) {
14209
+ positions[i] = dataView.getFloat64(offset, littleEndian);
14210
+ offset += 8;
14316
14211
  }
14317
- if (!$(/^(\))/, state)) {
14318
- return null;
14212
+ const pathIndices = [0];
14213
+ if (nPoints > 0) {
14214
+ pathIndices.push(nPoints);
14319
14215
  }
14320
14216
  return {
14321
- type: "LineString",
14322
- coordinates: c
14217
+ geometry: {
14218
+ type: "LineString",
14219
+ positions: { value: positions, size: dimension },
14220
+ pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
14221
+ },
14222
+ offset
14323
14223
  };
14324
14224
  }
14325
- function parseMultiLineString(state) {
14326
- if (!$(/^(MULTILINESTRING)/i, state))
14327
- return null;
14328
- white(state);
14329
- const c = multicoords(state);
14330
- if (!c) {
14331
- return null;
14225
+ var cumulativeSum = (sum) => (value) => sum += value;
14226
+ function parsePolygon2(dataView, offset, dimension, littleEndian) {
14227
+ const nRings = dataView.getUint32(offset, littleEndian);
14228
+ offset += 4;
14229
+ const rings = [];
14230
+ for (let i = 0; i < nRings; i++) {
14231
+ const parsed = parseLineString2(dataView, offset, dimension, littleEndian);
14232
+ const { positions } = parsed.geometry;
14233
+ offset = parsed.offset;
14234
+ rings.push(positions.value);
14332
14235
  }
14333
- white(state);
14236
+ const concatenatedPositions = new Float64Array(concatTypedArrays(rings).buffer);
14237
+ const polygonIndices = [0];
14238
+ if (concatenatedPositions.length > 0) {
14239
+ polygonIndices.push(concatenatedPositions.length / dimension);
14240
+ }
14241
+ const primitivePolygonIndices = rings.map((l) => l.length / dimension).map(cumulativeSum(0));
14242
+ primitivePolygonIndices.unshift(0);
14334
14243
  return {
14335
- // @ts-ignore
14336
- type: "MultiLineString",
14337
- // @ts-expect-error
14338
- coordinates: c
14244
+ geometry: {
14245
+ type: "Polygon",
14246
+ positions: { value: concatenatedPositions, size: dimension },
14247
+ polygonIndices: {
14248
+ value: new Uint32Array(polygonIndices),
14249
+ size: 1
14250
+ },
14251
+ primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
14252
+ },
14253
+ offset
14339
14254
  };
14340
14255
  }
14341
- function parsePolygon(state) {
14342
- if (!$(/^(POLYGON(\sz)?)/i, state)) {
14343
- return null;
14256
+ function parseMultiPoint2(dataView, offset, dimension, littleEndian) {
14257
+ const nPoints = dataView.getUint32(offset, littleEndian);
14258
+ offset += 4;
14259
+ const binaryPointGeometries = [];
14260
+ for (let i = 0; i < nPoints; i++) {
14261
+ const littleEndianPoint = dataView.getUint8(offset) === 1;
14262
+ offset++;
14263
+ if (dataView.getUint32(offset, littleEndianPoint) % 1e3 !== 1) {
14264
+ throw new Error("WKB: Inner geometries of MultiPoint not of type Point");
14265
+ }
14266
+ offset += 4;
14267
+ const parsed = parsePoint2(dataView, offset, dimension, littleEndianPoint);
14268
+ offset = parsed.offset;
14269
+ binaryPointGeometries.push(parsed.geometry);
14344
14270
  }
14345
- white(state);
14346
- const c = multicoords(state);
14347
- if (!c) {
14348
- return null;
14271
+ return concatenateBinaryPointGeometries(binaryPointGeometries, dimension);
14272
+ }
14273
+ function parseMultiLineString2(dataView, offset, dimension, littleEndian) {
14274
+ const nLines = dataView.getUint32(offset, littleEndian);
14275
+ offset += 4;
14276
+ const binaryLineGeometries = [];
14277
+ for (let i = 0; i < nLines; i++) {
14278
+ const littleEndianLine = dataView.getUint8(offset) === 1;
14279
+ offset++;
14280
+ if (dataView.getUint32(offset, littleEndianLine) % 1e3 !== 2) {
14281
+ throw new Error("WKB: Inner geometries of MultiLineString not of type LineString");
14282
+ }
14283
+ offset += 4;
14284
+ const parsed = parseLineString2(dataView, offset, dimension, littleEndianLine);
14285
+ offset = parsed.offset;
14286
+ binaryLineGeometries.push(parsed.geometry);
14287
+ }
14288
+ return concatenateBinaryLineGeometries(binaryLineGeometries, dimension);
14289
+ }
14290
+ function parseMultiPolygon2(dataView, offset, dimension, littleEndian) {
14291
+ const nPolygons = dataView.getUint32(offset, littleEndian);
14292
+ offset += 4;
14293
+ const binaryPolygonGeometries = [];
14294
+ for (let i = 0; i < nPolygons; i++) {
14295
+ const littleEndianPolygon = dataView.getUint8(offset) === 1;
14296
+ offset++;
14297
+ if (dataView.getUint32(offset, littleEndianPolygon) % 1e3 !== 3) {
14298
+ throw new Error("WKB: Inner geometries of MultiPolygon not of type Polygon");
14299
+ }
14300
+ offset += 4;
14301
+ const parsed = parsePolygon2(dataView, offset, dimension, littleEndianPolygon);
14302
+ offset = parsed.offset;
14303
+ binaryPolygonGeometries.push(parsed.geometry);
14349
14304
  }
14305
+ return concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension);
14306
+ }
14307
+ function concatenateBinaryPointGeometries(binaryPointGeometries, dimension) {
14308
+ const positions = binaryPointGeometries.map((geometry) => geometry.positions.value);
14309
+ const concatenatedPositions = new Float64Array(concatTypedArrays(positions).buffer);
14350
14310
  return {
14351
- // @ts-ignore
14352
- type: "Polygon",
14353
- // @ts-expect-error
14354
- coordinates: c
14311
+ type: "Point",
14312
+ positions: { value: concatenatedPositions, size: dimension }
14355
14313
  };
14356
14314
  }
14357
- function parseMultiPolygon(state) {
14358
- if (!$(/^(MULTIPOLYGON)/i, state)) {
14359
- return null;
14360
- }
14361
- white(state);
14362
- const c = multicoords(state);
14363
- if (!c) {
14364
- return null;
14365
- }
14315
+ function concatenateBinaryLineGeometries(binaryLineGeometries, dimension) {
14316
+ const lines = binaryLineGeometries.map((geometry) => geometry.positions.value);
14317
+ const concatenatedPositions = new Float64Array(concatTypedArrays(lines).buffer);
14318
+ const pathIndices = lines.map((line) => line.length / dimension).map(cumulativeSum(0));
14319
+ pathIndices.unshift(0);
14366
14320
  return {
14367
- type: "MultiPolygon",
14368
- // @ts-expect-error
14369
- coordinates: c
14321
+ type: "LineString",
14322
+ positions: { value: concatenatedPositions, size: dimension },
14323
+ pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
14370
14324
  };
14371
14325
  }
14372
- function parseGeometryCollection(state) {
14373
- const geometries = [];
14374
- let geometry;
14375
- if (!$(/^(GEOMETRYCOLLECTION)/i, state)) {
14376
- return null;
14377
- }
14378
- white(state);
14379
- if (!$(/^(\()/, state)) {
14380
- return null;
14381
- }
14382
- while (geometry = parseGeometry(state)) {
14383
- geometries.push(geometry);
14384
- white(state);
14385
- $(/^(,)/, state);
14386
- white(state);
14326
+ function concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension) {
14327
+ const polygons = [];
14328
+ const primitivePolygons = [];
14329
+ for (const binaryPolygon of binaryPolygonGeometries) {
14330
+ const { positions, primitivePolygonIndices: primitivePolygonIndices2 } = binaryPolygon;
14331
+ polygons.push(positions.value);
14332
+ primitivePolygons.push(primitivePolygonIndices2.value);
14387
14333
  }
14388
- if (!$(/^(\))/, state)) {
14389
- return null;
14334
+ const concatenatedPositions = new Float64Array(concatTypedArrays(polygons).buffer);
14335
+ const polygonIndices = polygons.map((p) => p.length / dimension).map(cumulativeSum(0));
14336
+ polygonIndices.unshift(0);
14337
+ const primitivePolygonIndices = [0];
14338
+ for (const primitivePolygon of primitivePolygons) {
14339
+ primitivePolygonIndices.push(
14340
+ ...primitivePolygon.filter((x) => x > 0).map((x) => x + primitivePolygonIndices[primitivePolygonIndices.length - 1])
14341
+ );
14390
14342
  }
14391
14343
  return {
14392
- type: "GeometryCollection",
14393
- geometries
14344
+ type: "Polygon",
14345
+ positions: { value: concatenatedPositions, size: dimension },
14346
+ polygonIndices: { value: new Uint32Array(polygonIndices), size: 1 },
14347
+ primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
14394
14348
  };
14395
14349
  }
14396
- function multicoords(state) {
14397
- white(state);
14398
- let depth = 0;
14399
- const rings = [];
14400
- const stack = [rings];
14401
- let pointer = rings;
14402
- let elem;
14403
- while (elem = $(/^(\()/, state) || $(/^(\))/, state) || $(/^(,)/, state) || $(tuples, state)) {
14404
- if (elem === "(") {
14405
- stack.push(pointer);
14406
- pointer = [];
14407
- stack[stack.length - 1].push(pointer);
14408
- depth++;
14409
- } else if (elem === ")") {
14410
- if (pointer.length === 0)
14411
- return null;
14412
- pointer = stack.pop();
14413
- if (!pointer)
14414
- return null;
14415
- depth--;
14416
- if (depth === 0)
14417
- break;
14418
- } else if (elem === ",") {
14419
- pointer = [];
14420
- stack[stack.length - 1].push(pointer);
14421
- } else if (!elem.split(/\s/g).some(isNaN)) {
14422
- Array.prototype.push.apply(pointer, elem.split(/\s/g).map(parseFloat));
14423
- } else {
14424
- return null;
14425
- }
14426
- white(state);
14350
+ function concatTypedArrays(arrays) {
14351
+ let byteLength = 0;
14352
+ for (let i = 0; i < arrays.length; ++i) {
14353
+ byteLength += arrays[i].byteLength;
14427
14354
  }
14428
- if (depth !== 0)
14429
- return null;
14430
- return rings;
14431
- }
14432
- function coords(state) {
14433
- const list = [];
14434
- let item;
14435
- let pt;
14436
- while (pt = $(tuples, state) || $(/^(,)/, state)) {
14437
- if (pt === ",") {
14438
- list.push(item);
14439
- item = [];
14440
- } else if (!pt.split(/\s/g).some(isNaN)) {
14441
- if (!item)
14442
- item = [];
14443
- Array.prototype.push.apply(item, pt.split(/\s/g).map(parseFloat));
14355
+ const buffer = new Uint8Array(byteLength);
14356
+ let byteOffset = 0;
14357
+ for (let i = 0; i < arrays.length; ++i) {
14358
+ const data = new Uint8Array(arrays[i].buffer);
14359
+ byteLength = data.length;
14360
+ for (let j = 0; j < byteLength; ++j) {
14361
+ buffer[byteOffset++] = data[j];
14444
14362
  }
14445
- white(state);
14446
- }
14447
- if (item)
14448
- list.push(item);
14449
- else
14450
- return null;
14451
- return list.length ? list : null;
14452
- }
14453
- function $(regexp, state) {
14454
- const match = state._?.substring(state.i).match(regexp);
14455
- if (!match)
14456
- return null;
14457
- else {
14458
- state.i += match[0].length;
14459
- return match[0];
14460
14363
  }
14461
- }
14462
- function white(state) {
14463
- $(/^\s*/, state);
14364
+ return buffer;
14464
14365
  }
14465
14366
 
14466
- // ../wkt/src/wkt-loader.ts
14467
- var WKTWorkerLoader = {
14367
+ // ../wkt/src/wkb-loader.ts
14368
+ var WKBWorkerLoader = {
14468
14369
  dataType: null,
14469
14370
  batchType: null,
14470
- name: "WKT (Well-Known Text)",
14471
- id: "wkt",
14371
+ name: "WKB",
14372
+ id: "wkb",
14472
14373
  module: "wkt",
14473
- version: VERSION3,
14374
+ version: VERSION2,
14474
14375
  worker: true,
14475
- extensions: ["wkt"],
14476
- mimeTypes: ["text/plain"],
14477
14376
  category: "geometry",
14478
- text: true,
14479
- tests: WKT_MAGIC_STRINGS,
14480
- testText: isWKT,
14377
+ extensions: ["wkb"],
14378
+ mimeTypes: [],
14379
+ // TODO can we define static, serializable tests, eg. some binary strings?
14380
+ tests: [isWKB],
14481
14381
  options: {
14482
- wkt: {
14483
- shape: "geojson-geometry",
14484
- crs: true
14382
+ wkb: {
14383
+ shape: "binary-geometry"
14384
+ // 'geojson-geometry'
14485
14385
  }
14486
14386
  }
14487
14387
  };
14488
- var WKTLoader = {
14489
- ...WKTWorkerLoader,
14490
- parse: async (arrayBuffer, options) => parseWKT(new TextDecoder().decode(arrayBuffer), options),
14491
- parseTextSync: (string, options) => parseWKT(string, options)
14388
+ var WKBLoader = {
14389
+ ...WKBWorkerLoader,
14390
+ parse: async (arrayBuffer) => parseWKB(arrayBuffer),
14391
+ parseSync: parseWKB
14492
14392
  };
14493
14393
 
14494
- // ../wkt/src/lib/parse-wkb-header.ts
14495
- var EWKB_FLAG_Z = 2147483648;
14496
- var EWKB_FLAG_M = 1073741824;
14497
- var EWKB_FLAG_SRID = 536870912;
14498
- var MAX_SRID = 1e4;
14499
- function isWKB(arrayBuffer) {
14500
- const dataView = new DataView(arrayBuffer);
14501
- let byteOffset = 0;
14502
- const endianness = dataView.getUint8(byteOffset);
14503
- byteOffset += 1;
14504
- if (endianness > 1) {
14505
- return false;
14506
- }
14507
- const littleEndian = endianness === 1;
14508
- const geometry = dataView.getUint32(byteOffset, littleEndian);
14509
- byteOffset += 4;
14510
- const geometryType = geometry & 7;
14511
- if (geometryType === 0 || geometryType > 7) {
14512
- return false;
14394
+ // src/lib/geoarrow/convert-geoarrow-to-geojson-geometry.ts
14395
+ function parseGeometryFromArrow(arrowCellValue, encoding) {
14396
+ encoding = encoding?.toLowerCase();
14397
+ if (!encoding || !arrowCellValue) {
14398
+ return null;
14513
14399
  }
14514
- const geometryFlags = geometry - geometryType;
14515
- if (geometryFlags === 0 || geometryFlags === 1e3 || geometryFlags === 2e3 || geometryFlags === 3e3) {
14516
- return true;
14400
+ let geometry;
14401
+ switch (encoding) {
14402
+ case "geoarrow.multipolygon":
14403
+ geometry = arrowMultiPolygonToFeature(arrowCellValue);
14404
+ break;
14405
+ case "geoarrow.polygon":
14406
+ geometry = arrowPolygonToFeature(arrowCellValue);
14407
+ break;
14408
+ case "geoarrow.multipoint":
14409
+ geometry = arrowMultiPointToFeature(arrowCellValue);
14410
+ break;
14411
+ case "geoarrow.point":
14412
+ geometry = arrowPointToFeature(arrowCellValue);
14413
+ break;
14414
+ case "geoarrow.multilinestring":
14415
+ geometry = arrowMultiLineStringToFeature(arrowCellValue);
14416
+ break;
14417
+ case "geoarrow.linestring":
14418
+ geometry = arrowLineStringToFeature(arrowCellValue);
14419
+ break;
14420
+ case "geoarrow.wkb":
14421
+ geometry = arrowWKBToFeature(arrowCellValue);
14422
+ break;
14423
+ case "geoarrow.wkt":
14424
+ geometry = arrowWKTToFeature(arrowCellValue);
14425
+ break;
14426
+ default: {
14427
+ throw Error(`GeoArrow encoding not supported ${encoding}`);
14428
+ }
14517
14429
  }
14518
- if ((geometryFlags & ~(EWKB_FLAG_Z | EWKB_FLAG_M | EWKB_FLAG_SRID)) !== 0) {
14519
- return false;
14430
+ return geometry;
14431
+ }
14432
+ function arrowWKBToFeature(arrowCellValue) {
14433
+ const arrayBuffer = arrowCellValue.buffer.slice(
14434
+ arrowCellValue.byteOffset,
14435
+ arrowCellValue.byteOffset + arrowCellValue.byteLength
14436
+ );
14437
+ const binaryGeometry = WKBLoader.parseSync?.(arrayBuffer);
14438
+ const geometry = binaryToGeometry(binaryGeometry);
14439
+ return geometry;
14440
+ }
14441
+ function arrowWKTToFeature(arrowCellValue) {
14442
+ const string = arrowCellValue;
14443
+ return WKTLoader.parseTextSync?.(string);
14444
+ }
14445
+ function arrowMultiPolygonToFeature(arrowMultiPolygon) {
14446
+ const multiPolygon = [];
14447
+ for (let m = 0; m < arrowMultiPolygon.length; m++) {
14448
+ const arrowPolygon = arrowMultiPolygon.get(m);
14449
+ const polygon = [];
14450
+ for (let i = 0; arrowPolygon && i < arrowPolygon?.length; i++) {
14451
+ const arrowRing = arrowPolygon?.get(i);
14452
+ const ring = [];
14453
+ for (let j = 0; arrowRing && j < arrowRing.length; j++) {
14454
+ const arrowCoord = arrowRing.get(j);
14455
+ const coord = Array.from(arrowCoord);
14456
+ ring.push(coord);
14457
+ }
14458
+ polygon.push(ring);
14459
+ }
14460
+ multiPolygon.push(polygon);
14520
14461
  }
14521
- if (geometryFlags & EWKB_FLAG_SRID) {
14522
- const srid = dataView.getUint32(byteOffset, littleEndian);
14523
- byteOffset += 4;
14524
- if (srid > MAX_SRID) {
14525
- return false;
14462
+ const geometry = {
14463
+ type: "MultiPolygon",
14464
+ coordinates: multiPolygon
14465
+ };
14466
+ return geometry;
14467
+ }
14468
+ function arrowPolygonToFeature(arrowPolygon) {
14469
+ const polygon = [];
14470
+ for (let i = 0; arrowPolygon && i < arrowPolygon.length; i++) {
14471
+ const arrowRing = arrowPolygon.get(i);
14472
+ const ring = [];
14473
+ for (let j = 0; arrowRing && j < arrowRing.length; j++) {
14474
+ const arrowCoord = arrowRing.get(j);
14475
+ const coords2 = Array.from(arrowCoord);
14476
+ ring.push(coords2);
14526
14477
  }
14478
+ polygon.push(ring);
14527
14479
  }
14528
- return true;
14480
+ const geometry = {
14481
+ type: "Polygon",
14482
+ coordinates: polygon
14483
+ };
14484
+ return geometry;
14529
14485
  }
14530
- function parseWKBHeader(dataView, target) {
14531
- const wkbHeader = Object.assign(target || {}, {
14532
- type: "wkb",
14533
- geometryType: 1,
14534
- dimensions: 2,
14535
- coordinates: "xy",
14536
- littleEndian: true,
14537
- byteOffset: 0
14538
- });
14539
- wkbHeader.littleEndian = dataView.getUint8(wkbHeader.byteOffset) === 1;
14540
- wkbHeader.byteOffset++;
14541
- const geometryCode = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
14542
- wkbHeader.byteOffset += 4;
14543
- wkbHeader.geometryType = geometryCode & 7;
14544
- const isoType = (geometryCode - wkbHeader.geometryType) / 1e3;
14545
- switch (isoType) {
14546
- case 0:
14547
- break;
14548
- case 1:
14549
- wkbHeader.type = "iso-wkb";
14550
- wkbHeader.dimensions = 3;
14551
- wkbHeader.coordinates = "xyz";
14552
- break;
14553
- case 2:
14554
- wkbHeader.type = "iso-wkb";
14555
- wkbHeader.dimensions = 3;
14556
- wkbHeader.coordinates = "xym";
14557
- break;
14558
- case 3:
14559
- wkbHeader.type = "iso-wkb";
14560
- wkbHeader.dimensions = 4;
14561
- wkbHeader.coordinates = "xyzm";
14562
- break;
14563
- default:
14564
- throw new Error(`WKB: Unsupported iso-wkb type: ${isoType}`);
14486
+ function arrowMultiPointToFeature(arrowMultiPoint) {
14487
+ const multiPoint = [];
14488
+ for (let i = 0; arrowMultiPoint && i < arrowMultiPoint.length; i++) {
14489
+ const arrowPoint = arrowMultiPoint.get(i);
14490
+ if (arrowPoint) {
14491
+ const coord = Array.from(arrowPoint);
14492
+ multiPoint.push(coord);
14493
+ }
14565
14494
  }
14566
- const ewkbZ = geometryCode & EWKB_FLAG_Z;
14567
- const ewkbM = geometryCode & EWKB_FLAG_M;
14568
- const ewkbSRID = geometryCode & EWKB_FLAG_SRID;
14569
- if (ewkbZ && ewkbM) {
14570
- wkbHeader.type = "ewkb";
14571
- wkbHeader.dimensions = 4;
14572
- wkbHeader.coordinates = "xyzm";
14573
- } else if (ewkbZ) {
14574
- wkbHeader.type = "ewkb";
14575
- wkbHeader.dimensions = 3;
14576
- wkbHeader.coordinates = "xyz";
14577
- } else if (ewkbM) {
14578
- wkbHeader.type = "ewkb";
14579
- wkbHeader.dimensions = 3;
14580
- wkbHeader.coordinates = "xym";
14495
+ return {
14496
+ type: "MultiPoint",
14497
+ coordinates: multiPoint
14498
+ };
14499
+ }
14500
+ function arrowPointToFeature(arrowPoint) {
14501
+ const point = Array.from(arrowPoint);
14502
+ return {
14503
+ type: "Point",
14504
+ coordinates: point
14505
+ };
14506
+ }
14507
+ function arrowMultiLineStringToFeature(arrowMultiLineString) {
14508
+ const multiLineString = [];
14509
+ for (let i = 0; arrowMultiLineString && i < arrowMultiLineString.length; i++) {
14510
+ const arrowLineString = arrowMultiLineString.get(i);
14511
+ const lineString = [];
14512
+ for (let j = 0; arrowLineString && j < arrowLineString.length; j++) {
14513
+ const arrowCoord = arrowLineString.get(j);
14514
+ if (arrowCoord) {
14515
+ const coords2 = Array.from(arrowCoord);
14516
+ lineString.push(coords2);
14517
+ }
14518
+ }
14519
+ multiLineString.push(lineString);
14581
14520
  }
14582
- if (ewkbSRID) {
14583
- wkbHeader.type = "ewkb";
14584
- wkbHeader.srid = dataView.getUint32(wkbHeader.byteOffset, wkbHeader.littleEndian);
14585
- wkbHeader.byteOffset += 4;
14521
+ return {
14522
+ type: "MultiLineString",
14523
+ coordinates: multiLineString
14524
+ };
14525
+ }
14526
+ function arrowLineStringToFeature(arrowLineString) {
14527
+ const lineString = [];
14528
+ for (let i = 0; arrowLineString && i < arrowLineString.length; i++) {
14529
+ const arrowCoord = arrowLineString.get(i);
14530
+ if (arrowCoord) {
14531
+ const coords2 = Array.from(arrowCoord);
14532
+ lineString.push(coords2);
14533
+ }
14586
14534
  }
14587
- return wkbHeader;
14535
+ return {
14536
+ type: "LineString",
14537
+ coordinates: lineString
14538
+ };
14588
14539
  }
14589
14540
 
14590
- // ../wkt/src/lib/parse-wkb.ts
14591
- function parseWKB(arrayBuffer, options) {
14592
- const binaryGeometry = parseWKBToBinary(arrayBuffer, options);
14593
- const shape = options?.wkb?.shape || "binary-geometry";
14541
+ // src/lib/tables/convert-arrow-to-table.ts
14542
+ function convertArrowToTable(arrowTable, shape) {
14594
14543
  switch (shape) {
14595
- case "binary-geometry":
14596
- return binaryGeometry;
14597
- case "geojson-geometry":
14598
- return binaryToGeometry(binaryGeometry);
14599
- case "geometry":
14600
- console.error('WKBLoader: "geometry" shape is deprecated, use "binary-geometry" instead');
14601
- return binaryToGeometry(binaryGeometry);
14544
+ case "arrow-table":
14545
+ return convertArrowToArrowTable(arrowTable);
14546
+ case "array-row-table":
14547
+ return convertArrowToArrayRowTable(arrowTable);
14548
+ case "object-row-table":
14549
+ return convertArrowToObjectRowTable(arrowTable);
14550
+ case "columnar-table":
14551
+ return convertArrowToColumnarTable(arrowTable);
14552
+ case "geojson-table":
14553
+ return convertArrowToGeoJSONTable(arrowTable);
14602
14554
  default:
14603
14555
  throw new Error(shape);
14604
14556
  }
14605
14557
  }
14606
- function parseWKBToBinary(arrayBuffer, options) {
14607
- const dataView = new DataView(arrayBuffer);
14608
- const wkbHeader = parseWKBHeader(dataView);
14609
- const { geometryType, dimensions, littleEndian } = wkbHeader;
14610
- const offset = wkbHeader.byteOffset;
14611
- switch (geometryType) {
14612
- case 1 /* Point */:
14613
- const point = parsePoint2(dataView, offset, dimensions, littleEndian);
14614
- return point.geometry;
14615
- case 2 /* LineString */:
14616
- const line = parseLineString2(dataView, offset, dimensions, littleEndian);
14617
- return line.geometry;
14618
- case 3 /* Polygon */:
14619
- const polygon = parsePolygon2(dataView, offset, dimensions, littleEndian);
14620
- return polygon.geometry;
14621
- case 4 /* MultiPoint */:
14622
- const multiPoint = parseMultiPoint2(dataView, offset, dimensions, littleEndian);
14623
- multiPoint.type = "Point";
14624
- return multiPoint;
14625
- case 5 /* MultiLineString */:
14626
- const multiLine = parseMultiLineString2(dataView, offset, dimensions, littleEndian);
14627
- multiLine.type = "LineString";
14628
- return multiLine;
14629
- case 6 /* MultiPolygon */:
14630
- const multiPolygon = parseMultiPolygon2(dataView, offset, dimensions, littleEndian);
14631
- multiPolygon.type = "Polygon";
14632
- return multiPolygon;
14633
- default:
14634
- throw new Error(`WKB: Unsupported geometry type: ${geometryType}`);
14635
- }
14558
+ function convertArrowToArrowTable(arrowTable) {
14559
+ return {
14560
+ shape: "arrow-table",
14561
+ schema: convertArrowToSchema(arrowTable.schema),
14562
+ data: arrowTable
14563
+ };
14636
14564
  }
14637
- function parsePoint2(dataView, offset, dimension, littleEndian) {
14638
- const positions = new Float64Array(dimension);
14639
- for (let i = 0; i < dimension; i++) {
14640
- positions[i] = dataView.getFloat64(offset, littleEndian);
14641
- offset += 8;
14565
+ function convertArrowToArrayRowTable(arrowTable) {
14566
+ const columnarTable = convertArrowToColumnarTable(arrowTable);
14567
+ return convertTable(columnarTable, "array-row-table");
14568
+ }
14569
+ function convertArrowToObjectRowTable(arrowTable) {
14570
+ const columnarTable = convertArrowToColumnarTable(arrowTable);
14571
+ return convertTable(columnarTable, "object-row-table");
14572
+ }
14573
+ function convertArrowToColumnarTable(arrowTable) {
14574
+ const columns = {};
14575
+ for (const field of arrowTable.schema.fields) {
14576
+ const arrowColumn = arrowTable.getChild(field.name);
14577
+ const values = arrowColumn?.toArray();
14578
+ columns[field.name] = values;
14642
14579
  }
14580
+ const schema = convertArrowToSchema(arrowTable.schema);
14643
14581
  return {
14644
- geometry: { type: "Point", positions: { value: positions, size: dimension } },
14645
- offset
14582
+ shape: "columnar-table",
14583
+ schema,
14584
+ data: columns
14646
14585
  };
14647
14586
  }
14648
- function parseLineString2(dataView, offset, dimension, littleEndian) {
14649
- const nPoints = dataView.getUint32(offset, littleEndian);
14650
- offset += 4;
14651
- const positions = new Float64Array(nPoints * dimension);
14652
- for (let i = 0; i < nPoints * dimension; i++) {
14653
- positions[i] = dataView.getFloat64(offset, littleEndian);
14654
- offset += 8;
14655
- }
14656
- const pathIndices = [0];
14657
- if (nPoints > 0) {
14658
- pathIndices.push(nPoints);
14587
+ function convertArrowToGeoJSONTable(arrowTable) {
14588
+ const schema = convertArrowToSchema(arrowTable.schema);
14589
+ const geometryColumns = getGeometryColumnsFromSchema(schema);
14590
+ const encoding = geometryColumns.geometry.encoding;
14591
+ const features = [];
14592
+ const propertyColumnNames = arrowTable.schema.fields.map((field) => field.name).filter((name) => !(name in geometryColumns));
14593
+ const propertiesTable = arrowTable.select(propertyColumnNames);
14594
+ const arrowGeometryColumn = arrowTable.getChild("geometry");
14595
+ for (let row = 0; row < arrowTable.numRows; row++) {
14596
+ const arrowGeometry = arrowGeometryColumn?.get(row);
14597
+ const feature = parseGeometryFromArrow(arrowGeometry, encoding);
14598
+ if (feature) {
14599
+ const properties = propertiesTable.get(row)?.toJSON() || {};
14600
+ features.push({ type: "Feature", geometry: feature, properties });
14601
+ }
14659
14602
  }
14660
14603
  return {
14661
- geometry: {
14662
- type: "LineString",
14663
- positions: { value: positions, size: dimension },
14664
- pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
14665
- },
14666
- offset
14604
+ shape: "geojson-table",
14605
+ type: "FeatureCollection",
14606
+ schema,
14607
+ features
14667
14608
  };
14668
14609
  }
14669
- var cumulativeSum = (sum) => (value) => sum += value;
14670
- function parsePolygon2(dataView, offset, dimension, littleEndian) {
14671
- const nRings = dataView.getUint32(offset, littleEndian);
14672
- offset += 4;
14673
- const rings = [];
14674
- for (let i = 0; i < nRings; i++) {
14675
- const parsed = parseLineString2(dataView, offset, dimension, littleEndian);
14676
- const { positions } = parsed.geometry;
14677
- offset = parsed.offset;
14678
- rings.push(positions.value);
14610
+
14611
+ // src/lib/parsers/parse-arrow.ts
14612
+ function parseArrowSync(arrayBuffer, options) {
14613
+ const shape = options?.shape || "arrow-table";
14614
+ const arrowTable = tableFromIPC([new Uint8Array(arrayBuffer)]);
14615
+ return convertArrowToTable(arrowTable, shape);
14616
+ }
14617
+ function parseArrowInBatches(asyncIterator, options) {
14618
+ async function* makeArrowAsyncIterator() {
14619
+ const readers = RecordBatchReader.readAll(asyncIterator);
14620
+ for await (const reader of readers) {
14621
+ for await (const recordBatch of reader) {
14622
+ if (options?.arrow?.batchDebounceMs !== void 0 && options?.arrow?.batchDebounceMs > 0) {
14623
+ await new Promise((resolve) => setTimeout(resolve, options.arrow?.batchDebounceMs || 0));
14624
+ }
14625
+ const arrowTabledBatch = {
14626
+ shape: "arrow-table",
14627
+ batchType: "data",
14628
+ data: new Table([recordBatch]),
14629
+ length: recordBatch.data.length
14630
+ };
14631
+ yield arrowTabledBatch;
14632
+ }
14633
+ break;
14634
+ }
14679
14635
  }
14680
- const concatenatedPositions = new Float64Array(concatTypedArrays(rings).buffer);
14681
- const polygonIndices = [0];
14682
- if (concatenatedPositions.length > 0) {
14683
- polygonIndices.push(concatenatedPositions.length / dimension);
14636
+ return makeArrowAsyncIterator();
14637
+ }
14638
+
14639
+ // src/arrow-loader.ts
14640
+ var ArrowLoader = {
14641
+ ...ArrowWorkerLoader,
14642
+ parse: async (arraybuffer, options) => parseArrowSync(arraybuffer, options?.arrow),
14643
+ parseSync: (arraybuffer, options) => parseArrowSync(arraybuffer, options?.arrow),
14644
+ parseInBatches: parseArrowInBatches
14645
+ };
14646
+
14647
+ // src/lib/encoders/encode-arrow.ts
14648
+ function encodeArrowSync(data) {
14649
+ const vectors = {};
14650
+ for (const arrayData of data) {
14651
+ const arrayVector = createVector(arrayData.array, arrayData.type);
14652
+ vectors[arrayData.name] = arrayVector;
14684
14653
  }
14685
- const primitivePolygonIndices = rings.map((l) => l.length / dimension).map(cumulativeSum(0));
14686
- primitivePolygonIndices.unshift(0);
14687
- return {
14688
- geometry: {
14689
- type: "Polygon",
14690
- positions: { value: concatenatedPositions, size: dimension },
14691
- polygonIndices: {
14692
- value: new Uint32Array(polygonIndices),
14693
- size: 1
14694
- },
14695
- primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
14696
- },
14697
- offset
14698
- };
14654
+ const table = new Table(vectors);
14655
+ const arrowBuffer = tableToIPC(table);
14656
+ return arrowBuffer;
14699
14657
  }
14700
- function parseMultiPoint2(dataView, offset, dimension, littleEndian) {
14701
- const nPoints = dataView.getUint32(offset, littleEndian);
14702
- offset += 4;
14703
- const binaryPointGeometries = [];
14704
- for (let i = 0; i < nPoints; i++) {
14705
- const littleEndianPoint = dataView.getUint8(offset) === 1;
14706
- offset++;
14707
- if (dataView.getUint32(offset, littleEndianPoint) % 1e3 !== 1) {
14708
- throw new Error("WKB: Inner geometries of MultiPoint not of type Point");
14658
+ function createVector(array, type) {
14659
+ switch (type) {
14660
+ case 1 /* DATE */:
14661
+ return vectorFromArray(array);
14662
+ case 0 /* FLOAT */:
14663
+ default:
14664
+ return vectorFromArray(array);
14665
+ }
14666
+ }
14667
+
14668
+ // src/arrow-writer.ts
14669
+ var VERSION3 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
14670
+ var ArrowWriter = {
14671
+ name: "Apache Arrow",
14672
+ id: "arrow",
14673
+ module: "arrow",
14674
+ version: VERSION3,
14675
+ extensions: ["arrow", "feather"],
14676
+ mimeTypes: [
14677
+ "application/vnd.apache.arrow.file",
14678
+ "application/vnd.apache.arrow.stream",
14679
+ "application/octet-stream"
14680
+ ],
14681
+ binary: true,
14682
+ options: {},
14683
+ encode: async function encodeArrow(data, options) {
14684
+ return encodeArrowSync(data);
14685
+ },
14686
+ encodeSync(data, options) {
14687
+ return encodeArrowSync(data);
14688
+ }
14689
+ };
14690
+
14691
+ // src/exports/geoarrow-loader.ts
14692
+ var GeoArrowWorkerLoader = {
14693
+ ...ArrowWorkerLoader,
14694
+ options: {
14695
+ arrow: {
14696
+ shape: "arrow-table"
14709
14697
  }
14710
- offset += 4;
14711
- const parsed = parsePoint2(dataView, offset, dimension, littleEndianPoint);
14712
- offset = parsed.offset;
14713
- binaryPointGeometries.push(parsed.geometry);
14714
14698
  }
14715
- return concatenateBinaryPointGeometries(binaryPointGeometries, dimension);
14699
+ };
14700
+
14701
+ // src/lib/parsers/parse-geoarrow.ts
14702
+ function parseGeoArrowSync(arrayBuffer, options) {
14703
+ const table = parseArrowSync(arrayBuffer, { shape: "arrow-table" });
14704
+ switch (options?.shape) {
14705
+ case "geojson-table":
14706
+ return convertArrowToTable(table.data, "geojson-table");
14707
+ default:
14708
+ return table;
14709
+ }
14710
+ }
14711
+ function parseGeoArrowInBatches(asyncIterator) {
14712
+ return parseArrowInBatches(asyncIterator);
14713
+ }
14714
+
14715
+ // src/geoarrow-loader.ts
14716
+ var GeoArrowLoader = {
14717
+ ...GeoArrowWorkerLoader,
14718
+ parse: async (arraybuffer, options) => parseGeoArrowSync(arraybuffer, options?.arrow),
14719
+ parseSync: (arraybuffer, options) => parseGeoArrowSync(arraybuffer, options?.arrow),
14720
+ parseInBatches: parseGeoArrowInBatches
14721
+ };
14722
+
14723
+ // src/lib/tables/convert-table-to-arrow.ts
14724
+ function convertTableToArrow(table, options) {
14725
+ switch (table.shape) {
14726
+ case "arrow-table":
14727
+ return table.data;
14728
+ case "columnar-table":
14729
+ default:
14730
+ const arrowBatchIterator = makeTableToArrowBatchesIterator(table, options);
14731
+ return new Table(arrowBatchIterator);
14732
+ }
14716
14733
  }
14717
- function parseMultiLineString2(dataView, offset, dimension, littleEndian) {
14718
- const nLines = dataView.getUint32(offset, littleEndian);
14719
- offset += 4;
14720
- const binaryLineGeometries = [];
14721
- for (let i = 0; i < nLines; i++) {
14722
- const littleEndianLine = dataView.getUint8(offset) === 1;
14723
- offset++;
14724
- if (dataView.getUint32(offset, littleEndianLine) % 1e3 !== 2) {
14725
- throw new Error("WKB: Inner geometries of MultiLineString not of type LineString");
14734
+ function* makeTableToArrowBatchesIterator(table, options) {
14735
+ const arrowSchema = deserializeArrowSchema(table.schema);
14736
+ const length = getTableLength(table);
14737
+ const numColumns = getTableNumCols(table);
14738
+ const batchSize = options?.batchSize || length;
14739
+ const builders = arrowSchema?.fields.map((arrowField) => makeBuilder(arrowField));
14740
+ const structField = new Struct(arrowSchema.fields);
14741
+ let batchLength = 0;
14742
+ for (let rowIndex = 0; rowIndex < length; rowIndex++) {
14743
+ for (let columnIndex = 0; columnIndex < numColumns; ++columnIndex) {
14744
+ const value = getTableCellAt(table, rowIndex, columnIndex);
14745
+ const builder = builders[columnIndex];
14746
+ builder.append(value);
14747
+ batchLength++;
14748
+ if (batchLength >= batchSize) {
14749
+ const datas = builders.map((builder2) => builder2.flush());
14750
+ const structData = new Data(structField, 0, batchLength, 0, void 0, datas);
14751
+ yield new RecordBatch2(arrowSchema, structData);
14752
+ batchLength = 0;
14753
+ }
14726
14754
  }
14727
- offset += 4;
14728
- const parsed = parseLineString2(dataView, offset, dimension, littleEndianLine);
14729
- offset = parsed.offset;
14730
- binaryLineGeometries.push(parsed.geometry);
14731
14755
  }
14732
- return concatenateBinaryLineGeometries(binaryLineGeometries, dimension);
14756
+ if (batchLength > 0) {
14757
+ const datas = builders.map((builder) => builder.flush());
14758
+ const structData = new Data(structField, 0, batchLength, 0, void 0, datas);
14759
+ yield new RecordBatch2(arrowSchema, structData);
14760
+ batchLength = 0;
14761
+ }
14762
+ builders.map((builder) => builder.finish());
14733
14763
  }
14734
- function parseMultiPolygon2(dataView, offset, dimension, littleEndian) {
14735
- const nPolygons = dataView.getUint32(offset, littleEndian);
14736
- offset += 4;
14737
- const binaryPolygonGeometries = [];
14738
- for (let i = 0; i < nPolygons; i++) {
14739
- const littleEndianPolygon = dataView.getUint8(offset) === 1;
14740
- offset++;
14741
- if (dataView.getUint32(offset, littleEndianPolygon) % 1e3 !== 3) {
14742
- throw new Error("WKB: Inner geometries of MultiPolygon not of type Polygon");
14764
+
14765
+ // src/lib/geoarrow/get-arrow-bounds.ts
14766
+ function updateBoundsFromGeoArrowSamples(flatCoords, nDim, bounds, sampleSize = 100) {
14767
+ const numberOfFeatures = flatCoords.length / nDim;
14768
+ const sampleStep = Math.max(Math.floor(numberOfFeatures / sampleSize), 1);
14769
+ const newBounds = [...bounds];
14770
+ for (let i = 0; i < numberOfFeatures; i += sampleStep) {
14771
+ const lng = flatCoords[i * nDim];
14772
+ const lat = flatCoords[i * nDim + 1];
14773
+ if (lng < newBounds[0]) {
14774
+ newBounds[0] = lng;
14775
+ }
14776
+ if (lat < newBounds[1]) {
14777
+ newBounds[1] = lat;
14778
+ }
14779
+ if (lng > newBounds[2]) {
14780
+ newBounds[2] = lng;
14781
+ }
14782
+ if (lat > newBounds[3]) {
14783
+ newBounds[3] = lat;
14743
14784
  }
14744
- offset += 4;
14745
- const parsed = parsePolygon2(dataView, offset, dimension, littleEndianPolygon);
14746
- offset = parsed.offset;
14747
- binaryPolygonGeometries.push(parsed.geometry);
14748
14785
  }
14749
- return concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension);
14786
+ return newBounds;
14750
14787
  }
14751
- function concatenateBinaryPointGeometries(binaryPointGeometries, dimension) {
14752
- const positions = binaryPointGeometries.map((geometry) => geometry.positions.value);
14753
- const concatenatedPositions = new Float64Array(concatTypedArrays(positions).buffer);
14788
+
14789
+ // src/lib/geoarrow/convert-geoarrow-to-binary-geometry.ts
14790
+ function getBinaryGeometryTemplate() {
14754
14791
  return {
14755
- type: "Point",
14756
- positions: { value: concatenatedPositions, size: dimension }
14792
+ globalFeatureIds: { value: new Uint32Array(0), size: 1 },
14793
+ positions: { value: new Float32Array(0), size: 2 },
14794
+ properties: [],
14795
+ numericProps: {},
14796
+ featureIds: { value: new Uint32Array(0), size: 1 }
14757
14797
  };
14758
14798
  }
14759
- function concatenateBinaryLineGeometries(binaryLineGeometries, dimension) {
14760
- const lines = binaryLineGeometries.map((geometry) => geometry.positions.value);
14761
- const concatenatedPositions = new Float64Array(concatTypedArrays(lines).buffer);
14762
- const pathIndices = lines.map((line) => line.length / dimension).map(cumulativeSum(0));
14763
- pathIndices.unshift(0);
14764
- return {
14765
- type: "LineString",
14766
- positions: { value: concatenatedPositions, size: dimension },
14767
- pathIndices: { value: new Uint32Array(pathIndices), size: 1 }
14799
+ function getBinaryGeometriesFromArrow(geoColumn, geoEncoding, options) {
14800
+ const featureTypes = {
14801
+ polygon: geoEncoding === "geoarrow.multipolygon" || geoEncoding === "geoarrow.polygon",
14802
+ point: geoEncoding === "geoarrow.multipoint" || geoEncoding === "geoarrow.point",
14803
+ line: geoEncoding === "geoarrow.multilinestring" || geoEncoding === "geoarrow.linestring"
14768
14804
  };
14769
- }
14770
- function concatenateBinaryPolygonGeometries(binaryPolygonGeometries, dimension) {
14771
- const polygons = [];
14772
- const primitivePolygons = [];
14773
- for (const binaryPolygon of binaryPolygonGeometries) {
14774
- const { positions, primitivePolygonIndices: primitivePolygonIndices2 } = binaryPolygon;
14775
- polygons.push(positions.value);
14776
- primitivePolygons.push(primitivePolygonIndices2.value);
14777
- }
14778
- const concatenatedPositions = new Float64Array(concatTypedArrays(polygons).buffer);
14779
- const polygonIndices = polygons.map((p) => p.length / dimension).map(cumulativeSum(0));
14780
- polygonIndices.unshift(0);
14781
- const primitivePolygonIndices = [0];
14782
- for (const primitivePolygon of primitivePolygons) {
14783
- primitivePolygonIndices.push(
14784
- ...primitivePolygon.filter((x) => x > 0).map((x) => x + primitivePolygonIndices[primitivePolygonIndices.length - 1])
14785
- );
14786
- }
14805
+ const chunks = options?.chunkIndex !== void 0 && options?.chunkIndex >= 0 ? [geoColumn.data[options?.chunkIndex]] : geoColumn.data;
14806
+ let bounds = [Infinity, Infinity, -Infinity, -Infinity];
14807
+ let globalFeatureIdOffset = options?.chunkOffset || 0;
14808
+ const binaryGeometries = [];
14809
+ chunks.forEach((chunk) => {
14810
+ const { featureIds, flatCoordinateArray, nDim, geomOffset, triangles } = getBinaryGeometriesFromChunk(chunk, geoEncoding, options);
14811
+ const globalFeatureIds = new Uint32Array(featureIds.length);
14812
+ for (let i = 0; i < featureIds.length; i++) {
14813
+ globalFeatureIds[i] = featureIds[i] + globalFeatureIdOffset;
14814
+ }
14815
+ const binaryContent = {
14816
+ globalFeatureIds: { value: globalFeatureIds, size: 1 },
14817
+ positions: {
14818
+ value: flatCoordinateArray,
14819
+ size: nDim
14820
+ },
14821
+ featureIds: { value: featureIds, size: 1 },
14822
+ // eslint-disable-next-line no-loop-func
14823
+ properties: [...Array(chunk.length).keys()].map((i) => ({
14824
+ index: i + globalFeatureIdOffset
14825
+ }))
14826
+ };
14827
+ globalFeatureIdOffset += chunk.length;
14828
+ binaryGeometries.push({
14829
+ shape: "binary-feature-collection",
14830
+ points: {
14831
+ type: "Point",
14832
+ ...getBinaryGeometryTemplate(),
14833
+ ...featureTypes.point ? binaryContent : {}
14834
+ },
14835
+ lines: {
14836
+ type: "LineString",
14837
+ ...getBinaryGeometryTemplate(),
14838
+ ...featureTypes.line ? binaryContent : {},
14839
+ pathIndices: { value: featureTypes.line ? geomOffset : new Uint16Array(0), size: 1 }
14840
+ },
14841
+ polygons: {
14842
+ type: "Polygon",
14843
+ ...getBinaryGeometryTemplate(),
14844
+ ...featureTypes.polygon ? binaryContent : {},
14845
+ polygonIndices: {
14846
+ // use geomOffset as polygonIndices same as primitivePolygonIndices since we are using earcut to get triangule indices
14847
+ value: featureTypes.polygon ? geomOffset : new Uint16Array(0),
14848
+ size: 1
14849
+ },
14850
+ primitivePolygonIndices: {
14851
+ value: featureTypes.polygon ? geomOffset : new Uint16Array(0),
14852
+ size: 1
14853
+ },
14854
+ ...triangles ? { triangles: { value: triangles, size: 1 } } : {}
14855
+ }
14856
+ });
14857
+ bounds = updateBoundsFromGeoArrowSamples(flatCoordinateArray, nDim, bounds);
14858
+ });
14787
14859
  return {
14788
- type: "Polygon",
14789
- positions: { value: concatenatedPositions, size: dimension },
14790
- polygonIndices: { value: new Uint32Array(polygonIndices), size: 1 },
14791
- primitivePolygonIndices: { value: new Uint32Array(primitivePolygonIndices), size: 1 }
14860
+ binaryGeometries,
14861
+ bounds,
14862
+ featureTypes,
14863
+ ...options?.calculateMeanCenters ? { meanCenters: getMeanCentersFromBinaryGeometries(binaryGeometries) } : {}
14792
14864
  };
14793
14865
  }
14794
- function concatTypedArrays(arrays) {
14795
- let byteLength = 0;
14796
- for (let i = 0; i < arrays.length; ++i) {
14797
- byteLength += arrays[i].byteLength;
14798
- }
14799
- const buffer = new Uint8Array(byteLength);
14800
- let byteOffset = 0;
14801
- for (let i = 0; i < arrays.length; ++i) {
14802
- const data = new Uint8Array(arrays[i].buffer);
14803
- byteLength = data.length;
14804
- for (let j = 0; j < byteLength; ++j) {
14805
- buffer[byteOffset++] = data[j];
14866
+ function getMeanCentersFromBinaryGeometries(binaryGeometries) {
14867
+ const globalMeanCenters = [];
14868
+ binaryGeometries.forEach((binaryGeometry) => {
14869
+ let binaryGeometryType = null;
14870
+ if (binaryGeometry.points && binaryGeometry.points.positions.value.length > 0) {
14871
+ binaryGeometryType = "points" /* points */;
14872
+ } else if (binaryGeometry.lines && binaryGeometry.lines.positions.value.length > 0) {
14873
+ binaryGeometryType = "lines" /* lines */;
14874
+ } else if (binaryGeometry.polygons && binaryGeometry.polygons.positions.value.length > 0) {
14875
+ binaryGeometryType = "polygons" /* polygons */;
14806
14876
  }
14807
- }
14808
- return buffer;
14809
- }
14810
-
14811
- // ../wkt/src/wkb-loader.ts
14812
- var WKBWorkerLoader = {
14813
- dataType: null,
14814
- batchType: null,
14815
- name: "WKB",
14816
- id: "wkb",
14817
- module: "wkt",
14818
- version: VERSION3,
14819
- worker: true,
14820
- category: "geometry",
14821
- extensions: ["wkb"],
14822
- mimeTypes: [],
14823
- // TODO can we define static, serializable tests, eg. some binary strings?
14824
- tests: [isWKB],
14825
- options: {
14826
- wkb: {
14827
- shape: "binary-geometry"
14828
- // 'geojson-geometry'
14877
+ const binaryContent = binaryGeometryType ? binaryGeometry[binaryGeometryType] : null;
14878
+ if (binaryContent && binaryGeometryType !== null) {
14879
+ const featureIds = binaryContent.featureIds.value;
14880
+ const flatCoordinateArray = binaryContent.positions.value;
14881
+ const nDim = binaryContent.positions.size;
14882
+ const primitivePolygonIndices = binaryContent.type === "Polygon" ? binaryContent.primitivePolygonIndices?.value : void 0;
14883
+ const meanCenters = getMeanCentersFromGeometry(
14884
+ featureIds,
14885
+ flatCoordinateArray,
14886
+ nDim,
14887
+ binaryGeometryType,
14888
+ primitivePolygonIndices
14889
+ );
14890
+ meanCenters.forEach((center) => {
14891
+ globalMeanCenters.push(center);
14892
+ });
14829
14893
  }
14894
+ });
14895
+ return globalMeanCenters;
14896
+ }
14897
+ function getMeanCentersFromGeometry(featureIds, flatCoordinateArray, nDim, geometryType, primitivePolygonIndices) {
14898
+ const meanCenters = [];
14899
+ const vertexCount = flatCoordinateArray.length;
14900
+ let vertexIndex = 0;
14901
+ let coordIdx = 0;
14902
+ let primitiveIdx = 0;
14903
+ while (vertexIndex < vertexCount) {
14904
+ const featureId = featureIds[vertexIndex / nDim];
14905
+ const center = [0, 0];
14906
+ let vertexCountInFeature = 0;
14907
+ while (vertexIndex < vertexCount && featureIds[coordIdx] === featureId) {
14908
+ if (geometryType === "polygons" /* polygons */ && primitivePolygonIndices?.[primitiveIdx] === coordIdx) {
14909
+ vertexIndex += nDim;
14910
+ primitiveIdx++;
14911
+ } else {
14912
+ center[0] += flatCoordinateArray[vertexIndex];
14913
+ center[1] += flatCoordinateArray[vertexIndex + 1];
14914
+ vertexIndex += nDim;
14915
+ vertexCountInFeature++;
14916
+ }
14917
+ coordIdx += 1;
14918
+ }
14919
+ center[0] /= vertexCountInFeature;
14920
+ center[1] /= vertexCountInFeature;
14921
+ meanCenters.push(center);
14830
14922
  }
14831
- };
14832
- var WKBLoader = {
14833
- ...WKBWorkerLoader,
14834
- parse: async (arrayBuffer) => parseWKB(arrayBuffer),
14835
- parseSync: parseWKB
14836
- };
14837
-
14838
- // src/geoarrow/convert-geoarrow-to-geojson-geometry.ts
14839
- function parseGeometryFromArrow(arrowCellValue, encoding) {
14840
- encoding = encoding?.toLowerCase();
14841
- if (!encoding || !arrowCellValue) {
14842
- return null;
14843
- }
14844
- let geometry;
14845
- switch (encoding) {
14846
- case "geoarrow.multipolygon":
14847
- geometry = arrowMultiPolygonToFeature(arrowCellValue);
14848
- break;
14849
- case "geoarrow.polygon":
14850
- geometry = arrowPolygonToFeature(arrowCellValue);
14851
- break;
14852
- case "geoarrow.multipoint":
14853
- geometry = arrowMultiPointToFeature(arrowCellValue);
14854
- break;
14923
+ return meanCenters;
14924
+ }
14925
+ function getBinaryGeometriesFromChunk(chunk, geoEncoding, options) {
14926
+ switch (geoEncoding) {
14855
14927
  case "geoarrow.point":
14856
- geometry = arrowPointToFeature(arrowCellValue);
14857
- break;
14858
- case "geoarrow.multilinestring":
14859
- geometry = arrowMultiLineStringToFeature(arrowCellValue);
14860
- break;
14928
+ case "geoarrow.multipoint":
14929
+ return getBinaryPointsFromChunk(chunk, geoEncoding);
14861
14930
  case "geoarrow.linestring":
14862
- geometry = arrowLineStringToFeature(arrowCellValue);
14863
- break;
14864
- case "geoarrow.wkb":
14865
- geometry = arrowWKBToFeature(arrowCellValue);
14866
- break;
14867
- case "geoarrow.wkt":
14868
- geometry = arrowWKTToFeature(arrowCellValue);
14869
- break;
14870
- default: {
14871
- throw Error(`GeoArrow encoding not supported ${encoding}`);
14872
- }
14931
+ case "geoarrow.multilinestring":
14932
+ return getBinaryLinesFromChunk(chunk, geoEncoding);
14933
+ case "geoarrow.polygon":
14934
+ case "geoarrow.multipolygon":
14935
+ return getBinaryPolygonsFromChunk(chunk, geoEncoding, options);
14936
+ default:
14937
+ throw Error("invalid geoarrow encoding");
14873
14938
  }
14874
- return geometry;
14875
- }
14876
- function arrowWKBToFeature(arrowCellValue) {
14877
- const arrayBuffer = arrowCellValue.buffer.slice(
14878
- arrowCellValue.byteOffset,
14879
- arrowCellValue.byteOffset + arrowCellValue.byteLength
14880
- );
14881
- const binaryGeometry = WKBLoader.parseSync?.(arrayBuffer);
14882
- const geometry = binaryToGeometry(binaryGeometry);
14883
- return geometry;
14884
- }
14885
- function arrowWKTToFeature(arrowCellValue) {
14886
- const string = arrowCellValue;
14887
- return WKTLoader.parseTextSync?.(string);
14888
14939
  }
14889
- function arrowMultiPolygonToFeature(arrowMultiPolygon) {
14890
- const multiPolygon = [];
14891
- for (let m = 0; m < arrowMultiPolygon.length; m++) {
14892
- const arrowPolygon = arrowMultiPolygon.get(m);
14893
- const polygon = [];
14894
- for (let i = 0; arrowPolygon && i < arrowPolygon?.length; i++) {
14895
- const arrowRing = arrowPolygon?.get(i);
14896
- const ring = [];
14897
- for (let j = 0; arrowRing && j < arrowRing.length; j++) {
14898
- const arrowCoord = arrowRing.get(j);
14899
- const coord = Array.from(arrowCoord);
14900
- ring.push(coord);
14940
+ function getTriangleIndices(polygonIndices, primitivePolygonIndices, flatCoordinateArray, nDim) {
14941
+ try {
14942
+ let primitiveIndex = 0;
14943
+ const triangles = [];
14944
+ for (let i = 0; i < polygonIndices.length - 1; i++) {
14945
+ const startIdx = polygonIndices[i];
14946
+ const endIdx = polygonIndices[i + 1];
14947
+ const slicedFlatCoords = flatCoordinateArray.subarray(startIdx * nDim, endIdx * nDim);
14948
+ const holeIndices = [];
14949
+ while (primitivePolygonIndices[primitiveIndex] < endIdx) {
14950
+ if (primitivePolygonIndices[primitiveIndex] > startIdx) {
14951
+ holeIndices.push(primitivePolygonIndices[primitiveIndex] - startIdx);
14952
+ }
14953
+ primitiveIndex++;
14954
+ }
14955
+ const triangleIndices = earcut(
14956
+ slicedFlatCoords,
14957
+ holeIndices.length > 0 ? holeIndices : void 0,
14958
+ nDim
14959
+ );
14960
+ if (triangleIndices.length === 0) {
14961
+ throw Error("earcut failed e.g. invalid polygon");
14962
+ }
14963
+ for (let j = 0; j < triangleIndices.length; j++) {
14964
+ triangles.push(triangleIndices[j] + startIdx);
14901
14965
  }
14902
- polygon.push(ring);
14903
14966
  }
14904
- multiPolygon.push(polygon);
14905
- }
14906
- const geometry = {
14907
- type: "MultiPolygon",
14908
- coordinates: multiPolygon
14909
- };
14910
- return geometry;
14911
- }
14912
- function arrowPolygonToFeature(arrowPolygon) {
14913
- const polygon = [];
14914
- for (let i = 0; arrowPolygon && i < arrowPolygon.length; i++) {
14915
- const arrowRing = arrowPolygon.get(i);
14916
- const ring = [];
14917
- for (let j = 0; arrowRing && j < arrowRing.length; j++) {
14918
- const arrowCoord = arrowRing.get(j);
14919
- const coords2 = Array.from(arrowCoord);
14920
- ring.push(coords2);
14967
+ const trianglesUint32 = new Uint32Array(triangles.length);
14968
+ for (let i = 0; i < triangles.length; i++) {
14969
+ trianglesUint32[i] = triangles[i];
14921
14970
  }
14922
- polygon.push(ring);
14971
+ return trianglesUint32;
14972
+ } catch (error) {
14973
+ return null;
14923
14974
  }
14924
- const geometry = {
14925
- type: "Polygon",
14926
- coordinates: polygon
14927
- };
14928
- return geometry;
14929
14975
  }
14930
- function arrowMultiPointToFeature(arrowMultiPoint) {
14931
- const multiPoint = [];
14932
- for (let i = 0; arrowMultiPoint && i < arrowMultiPoint.length; i++) {
14933
- const arrowPoint = arrowMultiPoint.get(i);
14934
- if (arrowPoint) {
14935
- const coord = Array.from(arrowPoint);
14936
- multiPoint.push(coord);
14976
+ function getBinaryPolygonsFromChunk(chunk, geoEncoding, options) {
14977
+ const isMultiPolygon = geoEncoding === "geoarrow.multipolygon";
14978
+ const polygonData = isMultiPolygon ? chunk.children[0] : chunk;
14979
+ const polygonOffset = polygonData.valueOffsets;
14980
+ const partData = isMultiPolygon ? chunk.valueOffsets.map((i) => polygonOffset.at(i) || i) : chunk.valueOffsets;
14981
+ const ringData = polygonData.children[0];
14982
+ const pointData = ringData.children[0];
14983
+ const coordData = pointData.children[0];
14984
+ const nDim = pointData.stride;
14985
+ const geomOffset = ringData.valueOffsets;
14986
+ const flatCoordinateArray = coordData.values;
14987
+ const geometryIndicies = new Uint16Array(polygonOffset.length);
14988
+ for (let i = 0; i < polygonOffset.length; i++) {
14989
+ geometryIndicies[i] = geomOffset[polygonOffset[i]];
14990
+ }
14991
+ const numOfVertices = flatCoordinateArray.length / nDim;
14992
+ const featureIds = new Uint32Array(numOfVertices);
14993
+ for (let i = 0; i < partData.length - 1; i++) {
14994
+ const startIdx = geomOffset[partData[i]];
14995
+ const endIdx = geomOffset[partData[i + 1]];
14996
+ for (let j = startIdx; j < endIdx; j++) {
14997
+ featureIds[j] = i;
14937
14998
  }
14938
14999
  }
15000
+ const triangles = options?.triangulate ? getTriangleIndices(geometryIndicies, geomOffset, flatCoordinateArray, nDim) : null;
14939
15001
  return {
14940
- type: "MultiPoint",
14941
- coordinates: multiPoint
14942
- };
14943
- }
14944
- function arrowPointToFeature(arrowPoint) {
14945
- const point = Array.from(arrowPoint);
14946
- return {
14947
- type: "Point",
14948
- coordinates: point
15002
+ featureIds,
15003
+ nDim,
15004
+ flatCoordinateArray,
15005
+ geomOffset,
15006
+ geometryIndicies,
15007
+ ...options?.triangulate && triangles ? { triangles } : {}
14949
15008
  };
14950
15009
  }
14951
- function arrowMultiLineStringToFeature(arrowMultiLineString) {
14952
- const multiLineString = [];
14953
- for (let i = 0; arrowMultiLineString && i < arrowMultiLineString.length; i++) {
14954
- const arrowLineString = arrowMultiLineString.get(i);
14955
- const lineString = [];
14956
- for (let j = 0; arrowLineString && j < arrowLineString.length; j++) {
14957
- const arrowCoord = arrowLineString.get(j);
14958
- if (arrowCoord) {
14959
- const coords2 = Array.from(arrowCoord);
14960
- lineString.push(coords2);
15010
+ function getBinaryLinesFromChunk(chunk, geoEncoding) {
15011
+ const isMultiLineString = geoEncoding === "geoarrow.multilinestring";
15012
+ const lineData = isMultiLineString ? chunk.children[0] : chunk;
15013
+ const pointData = lineData.children[0];
15014
+ const coordData = pointData.children[0];
15015
+ const nDim = pointData.stride;
15016
+ const geomOffset = lineData.valueOffsets;
15017
+ const flatCoordinateArray = coordData.values;
15018
+ const geometryIndicies = new Uint16Array(0);
15019
+ const numOfVertices = flatCoordinateArray.length / nDim;
15020
+ const featureIds = new Uint32Array(numOfVertices);
15021
+ if (isMultiLineString) {
15022
+ const partData = chunk.valueOffsets;
15023
+ for (let i = 0; i < partData.length - 1; i++) {
15024
+ const startIdx = geomOffset[partData[i]];
15025
+ const endIdx = geomOffset[partData[i + 1]];
15026
+ for (let j = startIdx; j < endIdx; j++) {
15027
+ featureIds[j] = i;
15028
+ }
15029
+ }
15030
+ } else {
15031
+ for (let i = 0; i < chunk.length; i++) {
15032
+ const startIdx = geomOffset[i];
15033
+ const endIdx = geomOffset[i + 1];
15034
+ for (let j = startIdx; j < endIdx; j++) {
15035
+ featureIds[j] = i;
14961
15036
  }
14962
15037
  }
14963
- multiLineString.push(lineString);
14964
15038
  }
14965
15039
  return {
14966
- type: "MultiLineString",
14967
- coordinates: multiLineString
15040
+ featureIds,
15041
+ flatCoordinateArray,
15042
+ nDim,
15043
+ geomOffset,
15044
+ geometryIndicies
14968
15045
  };
14969
15046
  }
14970
- function arrowLineStringToFeature(arrowLineString) {
14971
- const lineString = [];
14972
- for (let i = 0; arrowLineString && i < arrowLineString.length; i++) {
14973
- const arrowCoord = arrowLineString.get(i);
14974
- if (arrowCoord) {
14975
- const coords2 = Array.from(arrowCoord);
14976
- lineString.push(coords2);
15047
+ function getBinaryPointsFromChunk(chunk, geoEncoding) {
15048
+ const isMultiPoint = geoEncoding === "geoarrow.multipoint";
15049
+ const pointData = isMultiPoint ? chunk.children[0] : chunk;
15050
+ const coordData = pointData.children[0];
15051
+ const nDim = pointData.stride;
15052
+ const flatCoordinateArray = coordData.values;
15053
+ const geometryIndicies = new Uint16Array(0);
15054
+ const geomOffset = new Int32Array(0);
15055
+ const numOfVertices = flatCoordinateArray.length / nDim;
15056
+ const featureIds = new Uint32Array(numOfVertices);
15057
+ if (isMultiPoint) {
15058
+ const partData = chunk.valueOffsets;
15059
+ for (let i = 0; i < partData.length - 1; i++) {
15060
+ const startIdx = partData[i];
15061
+ const endIdx = partData[i + 1];
15062
+ for (let j = startIdx; j < endIdx; j++) {
15063
+ featureIds[j] = i;
15064
+ }
15065
+ }
15066
+ } else {
15067
+ for (let i = 0; i < chunk.length; i++) {
15068
+ featureIds[i] = i;
14977
15069
  }
14978
15070
  }
14979
15071
  return {
14980
- type: "LineString",
14981
- coordinates: lineString
15072
+ featureIds,
15073
+ flatCoordinateArray,
15074
+ nDim,
15075
+ geomOffset,
15076
+ geometryIndicies
14982
15077
  };
14983
15078
  }
14984
15079