@loaders.gl/services 5.0.0-alpha.6 → 5.0.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -991,6 +991,65 @@ var init_convert_geometry_to_wkt = __esm({
991
991
  }
992
992
  });
993
993
 
994
+ // ../schema/src/float16.ts
995
+ function createFloat16Array(length) {
996
+ const ArrayConstructor = (0, import_types.getFloat16ArrayConstructor)();
997
+ return new ArrayConstructor(length);
998
+ }
999
+ function isNativeFloat16Array(value) {
1000
+ return Boolean(import_types.NativeFloat16ArrayConstructor && value instanceof import_types.NativeFloat16ArrayConstructor);
1001
+ }
1002
+ function setFloat16Value(array, index, value) {
1003
+ if (isNativeFloat16Array(array)) {
1004
+ array[index] = value;
1005
+ } else {
1006
+ array[index] = encodeFloat16(value);
1007
+ }
1008
+ }
1009
+ function getFloat16Storage(array) {
1010
+ return isNativeFloat16Array(array) ? new Uint16Array(array.buffer, array.byteOffset, array.length) : array;
1011
+ }
1012
+ function convertColorArrayToFloat16(values, sourceScale) {
1013
+ const result = createFloat16Array(values.length);
1014
+ for (let index = 0; index < values.length; index++) {
1015
+ setFloat16Value(result, index, values[index] / sourceScale);
1016
+ }
1017
+ return result;
1018
+ }
1019
+ function encodeFloat16(value) {
1020
+ if (!Number.isFinite(value)) {
1021
+ return value === Infinity ? 31744 : value === -Infinity ? 64512 : 32256;
1022
+ }
1023
+ const sign = value < 0 || Object.is(value, -0) ? 32768 : 0;
1024
+ const absoluteValue = Math.abs(value);
1025
+ if (absoluteValue === 0) {
1026
+ return sign;
1027
+ }
1028
+ if (absoluteValue >= 65520) {
1029
+ return sign | 31744;
1030
+ }
1031
+ if (absoluteValue >= 65504) {
1032
+ return sign | 31743;
1033
+ }
1034
+ const exponent = Math.floor(Math.log2(absoluteValue));
1035
+ if (exponent < -14) {
1036
+ return sign | Math.round(absoluteValue / 2 ** -24);
1037
+ }
1038
+ const normalizedExponent = exponent + 15;
1039
+ const mantissa = Math.round((absoluteValue / 2 ** exponent - 1) * 1024);
1040
+ if (mantissa === 1024) {
1041
+ return sign | normalizedExponent + 1 << 10;
1042
+ }
1043
+ return sign | normalizedExponent << 10 | mantissa;
1044
+ }
1045
+ var import_types;
1046
+ var init_float16 = __esm({
1047
+ "../schema/src/float16.ts"() {
1048
+ "use strict";
1049
+ import_types = require("@math.gl/types");
1050
+ }
1051
+ });
1052
+
994
1053
  // ../schema/src/metadata.ts
995
1054
  function getMetadataValue(metadata, key) {
996
1055
  return metadata instanceof Map ? metadata.get(key) || null : metadata[key] || null;
@@ -1036,6 +1095,7 @@ var init_category_mesh = __esm({
1036
1095
  var init_src = __esm({
1037
1096
  "../schema/src/index.ts"() {
1038
1097
  "use strict";
1098
+ init_float16();
1039
1099
  init_metadata();
1040
1100
  init_category_mesh();
1041
1101
  }
@@ -1244,6 +1304,9 @@ function getDataTypeFromArray(array) {
1244
1304
  return { type: "null", nullable: true };
1245
1305
  }
1246
1306
  function getDataTypeFromTypedArray(array) {
1307
+ if (typeof Float16Array !== "undefined" && array instanceof Float16Array) {
1308
+ return "float16";
1309
+ }
1247
1310
  switch (array.constructor) {
1248
1311
  case Int8Array:
1249
1312
  return "int8";
@@ -1266,9 +1329,11 @@ function getDataTypeFromTypedArray(array) {
1266
1329
  return "null";
1267
1330
  }
1268
1331
  }
1332
+ var import_types2;
1269
1333
  var init_data_type = __esm({
1270
1334
  "../schema-utils/src/lib/schema/data-type.ts"() {
1271
1335
  "use strict";
1336
+ import_types2 = require("@math.gl/types");
1272
1337
  }
1273
1338
  });
1274
1339
 
@@ -1320,6 +1385,13 @@ function serializeArrowType(arrowType) {
1320
1385
  if (isArrowViewType(arrowType, "Utf8View")) {
1321
1386
  return "utf8-view";
1322
1387
  }
1388
+ if (isOptionalArrowType(arrowType, "LargeList")) {
1389
+ const largeListType = arrowType;
1390
+ return {
1391
+ type: "large-list",
1392
+ children: [serializeArrowField(largeListType.valueField)]
1393
+ };
1394
+ }
1323
1395
  switch (arrowType.constructor) {
1324
1396
  case arrow2.Null:
1325
1397
  return "null";
@@ -1458,12 +1530,6 @@ function serializeArrowType(arrowType) {
1458
1530
  type: "list",
1459
1531
  children: [serializeArrowField(listField)]
1460
1532
  };
1461
- case arrow2.LargeList:
1462
- const largeListType = arrowType;
1463
- return {
1464
- type: "large-list",
1465
- children: [serializeArrowField(largeListType.valueField)]
1466
- };
1467
1533
  case arrow2.FixedSizeList:
1468
1534
  const fixedSizeList = arrowType;
1469
1535
  return {
@@ -1516,7 +1582,13 @@ function deserializeArrowType(dataType, options) {
1516
1582
  }
1517
1583
  case "large-list": {
1518
1584
  const field = deserializeArrowField(dataType.children[0], options);
1519
- return new arrow2.LargeList(field);
1585
+ const LargeList = getOptionalArrowConstructor("LargeList");
1586
+ if (!LargeList) {
1587
+ throw new Error(
1588
+ "LargeList requires an Apache Arrow runtime that exports the LargeList constructor"
1589
+ );
1590
+ }
1591
+ return new LargeList(field);
1520
1592
  }
1521
1593
  case "fixed-size-list": {
1522
1594
  const child = deserializeArrowField(dataType.children[0], options);
@@ -1612,11 +1684,11 @@ function deserializeArrowType(dataType, options) {
1612
1684
  throw new Error("array type not supported");
1613
1685
  }
1614
1686
  }
1615
- function getArrowViewConstructors() {
1616
- return arrow2;
1687
+ function getOptionalArrowConstructor(typeName) {
1688
+ return arrow2[typeName];
1617
1689
  }
1618
1690
  function isArrowViewType(arrowType, viewTypeName) {
1619
- const constructor = getArrowViewConstructors()[viewTypeName];
1691
+ const constructor = getOptionalArrowConstructor(viewTypeName);
1620
1692
  if (constructor && arrowType instanceof constructor) {
1621
1693
  return true;
1622
1694
  }
@@ -1624,12 +1696,16 @@ function isArrowViewType(arrowType, viewTypeName) {
1624
1696
  const guard = viewTypeName === "BinaryView" ? guards.isBinaryView : guards.isUtf8View;
1625
1697
  return Boolean(guard == null ? void 0 : guard(arrowType));
1626
1698
  }
1699
+ function isOptionalArrowType(arrowType, typeName) {
1700
+ const constructor = getOptionalArrowConstructor(typeName);
1701
+ return Boolean(constructor && arrowType instanceof constructor);
1702
+ }
1627
1703
  function makeVariableWidthArrowType(viewTypeName, fallbackType, options) {
1628
1704
  const viewTypeMode = (options == null ? void 0 : options.viewTypes) || "never";
1629
1705
  if (viewTypeMode === "never") {
1630
1706
  return fallbackType;
1631
1707
  }
1632
- const constructor = getArrowViewConstructors()[viewTypeName];
1708
+ const constructor = getOptionalArrowConstructor(viewTypeName);
1633
1709
  if (constructor) {
1634
1710
  return new constructor();
1635
1711
  }
@@ -1641,7 +1717,7 @@ function makeVariableWidthArrowType(viewTypeName, fallbackType, options) {
1641
1717
  return fallbackType;
1642
1718
  }
1643
1719
  function makeRequiredArrowViewType(viewTypeName) {
1644
- const constructor = getArrowViewConstructors()[viewTypeName];
1720
+ const constructor = getOptionalArrowConstructor(viewTypeName);
1645
1721
  if (!constructor) {
1646
1722
  throw new Error(
1647
1723
  `${viewTypeName} requires apache-arrow 21.2.0 or later; the installed runtime does not support it`
@@ -1790,33 +1866,34 @@ var init_mesh_utils = __esm({
1790
1866
  });
1791
1867
 
1792
1868
  // ../schema-utils/src/lib/arrow-utils/arrow-fixed-size-list-utils.ts
1793
- function getFixedSizeListVector(typedArray, stride) {
1794
- const data = getFixedSizeListData(typedArray, stride);
1869
+ function getFixedSizeListVector(typedArray, stride, logicalType) {
1870
+ const data = getFixedSizeListData(typedArray, stride, logicalType);
1795
1871
  return new arrow3.Vector([data]);
1796
1872
  }
1797
- function getFixedSizeListData(typedArray, stride) {
1798
- const listType = getFixedSizeListType(typedArray, stride);
1873
+ function getFixedSizeListData(typedArray, stride, logicalType) {
1874
+ const listType = getFixedSizeListType(typedArray, stride, logicalType);
1799
1875
  const nestedType = listType.children[0].type;
1876
+ const storage = logicalType === "float16" && isNativeFloat16Array(typedArray) ? getFloat16Storage(typedArray) : typedArray;
1800
1877
  const buffers = {
1801
1878
  // valueOffsets: undefined,
1802
- [arrow3.BufferType.DATA]: typedArray
1879
+ [arrow3.BufferType.DATA]: storage
1803
1880
  // values
1804
1881
  // nullBitmap: undefined,
1805
1882
  // typeIds: undefined
1806
1883
  };
1807
- const nestedData = new arrow3.Data(nestedType, 0, typedArray.length, 0, buffers);
1884
+ const nestedData = new arrow3.Data(nestedType, 0, storage.length, 0, buffers);
1808
1885
  const data = new arrow3.Data(
1809
1886
  listType,
1810
1887
  0,
1811
- typedArray.length / stride,
1888
+ storage.length / stride,
1812
1889
  0,
1813
1890
  void 0,
1814
1891
  [nestedData]
1815
1892
  );
1816
1893
  return data;
1817
1894
  }
1818
- function getFixedSizeListType(typedArray, stride) {
1819
- const { type } = getDataTypeFromArray(typedArray);
1895
+ function getFixedSizeListType(typedArray, stride, logicalType) {
1896
+ const type = logicalType || getDataTypeFromArray(typedArray).type;
1820
1897
  const arrowType = deserializeArrowType(type);
1821
1898
  const listType = new arrow3.FixedSizeList(stride, new arrow3.Field("value", arrowType, false));
1822
1899
  return listType;
@@ -1825,6 +1902,7 @@ var arrow3;
1825
1902
  var init_arrow_fixed_size_list_utils = __esm({
1826
1903
  "../schema-utils/src/lib/arrow-utils/arrow-fixed-size-list-utils.ts"() {
1827
1904
  "use strict";
1905
+ init_src();
1828
1906
  arrow3 = __toESM(require("apache-arrow"), 1);
1829
1907
  init_data_type();
1830
1908
  init_convert_arrow_schema();
@@ -1874,9 +1952,11 @@ function makeMeshArrowTable(attributes, options = {}) {
1874
1952
  for (const attributeName of attributeNames) {
1875
1953
  const attribute = attributes[attributeName];
1876
1954
  const { value, size = 1 } = attribute;
1877
- const column = getAttributeArrowVector(value, size);
1955
+ const column = getAttributeArrowVector(value, size, attribute.componentType);
1878
1956
  columns[attributeName] = column;
1879
- fields.push(getAttributeArrowField(options.schema, attributeName, column));
1957
+ fields.push(
1958
+ getAttributeArrowField(options.schema, attributeName, column, attribute.componentType)
1959
+ );
1880
1960
  if (attributeName === "POSITION" && ((_b = (_a2 = options.indices) == null ? void 0 : _a2.value) == null ? void 0 : _b.length)) {
1881
1961
  const indicesField = indexedMeshArrowSchema.fields.find((field) => field.name === "indices");
1882
1962
  columns.indices = getIndicesVector(options.indices.value, column.length, indicesField.type);
@@ -1894,7 +1974,17 @@ function makeMeshArrowTable(attributes, options = {}) {
1894
1974
  indices: options.indices
1895
1975
  };
1896
1976
  }
1897
- function getAttributeArrowVector(value, size) {
1977
+ function getAttributeArrowVector(value, size, componentType) {
1978
+ if (componentType === "float16") {
1979
+ const storage = isNativeFloat16Array(value) ? getFloat16Storage(value) : value;
1980
+ if (size === 1) {
1981
+ const data = new arrow4.Data(new arrow4.Float16(), 0, storage.length, 0, {
1982
+ [arrow4.BufferType.DATA]: storage
1983
+ });
1984
+ return new arrow4.Vector([data]);
1985
+ }
1986
+ return getFixedSizeListVector(value, size, componentType);
1987
+ }
1898
1988
  return size === 1 ? arrow4.makeVector(value) : getFixedSizeListVector(value, size);
1899
1989
  }
1900
1990
  function getOrderedAttributeNames(attributes) {
@@ -1911,7 +2001,7 @@ function hasMeshIndices(mesh) {
1911
2001
  var _a2, _b;
1912
2002
  return Boolean((_b = (_a2 = mesh.indices) == null ? void 0 : _a2.value) == null ? void 0 : _b.length);
1913
2003
  }
1914
- function getAttributeArrowField(schema, attributeName, column) {
2004
+ function getAttributeArrowField(schema, attributeName, column, componentType) {
1915
2005
  if (attributeName === "POSITION" && isMeshPositionColumn(column)) {
1916
2006
  const canonicalField = meshArrowSchema.fields[0];
1917
2007
  const suppliedField = schema == null ? void 0 : schema.fields.find((schemaField) => schemaField.name === attributeName);
@@ -1930,6 +2020,20 @@ function getAttributeArrowField(schema, attributeName, column) {
1930
2020
  );
1931
2021
  }
1932
2022
  const field = schema == null ? void 0 : schema.fields.find((schemaField) => schemaField.name === attributeName);
2023
+ if (componentType === "float16") {
2024
+ const metadata = new Map(Object.entries((field == null ? void 0 : field.metadata) || {}));
2025
+ metadata.set("componentType", "float16");
2026
+ return new arrow4.Field(attributeName, column.type, false, metadata);
2027
+ }
2028
+ if (field && field.type.toString() !== column.type.toString()) {
2029
+ const deserializedField = deserializeArrowField(field);
2030
+ return new arrow4.Field(
2031
+ attributeName,
2032
+ column.type,
2033
+ deserializedField.nullable,
2034
+ deserializedField.metadata
2035
+ );
2036
+ }
1933
2037
  return field ? deserializeArrowField(field) : new arrow4.Field(attributeName, column.type, false);
1934
2038
  }
1935
2039
  function isMeshPositionColumn(column) {
@@ -1985,6 +2089,7 @@ var init_convert_mesh_to_table = __esm({
1985
2089
  "../schema-utils/src/lib/mesh/convert-mesh-to-table.ts"() {
1986
2090
  "use strict";
1987
2091
  init_src();
2092
+ init_src();
1988
2093
  arrow4 = __toESM(require("apache-arrow"), 1);
1989
2094
  init_arrow_fixed_size_list_utils();
1990
2095
  init_convert_arrow_schema();
@@ -1994,7 +2099,7 @@ var init_convert_mesh_to_table = __esm({
1994
2099
 
1995
2100
  // ../schema-utils/src/lib/mesh/deduce-mesh-schema.ts
1996
2101
  function deduceMeshField(name, attribute, optionalMetadata) {
1997
- const type = getDataTypeFromTypedArray(attribute.value);
2102
+ const type = attribute.componentType || getDataTypeFromTypedArray(attribute.value);
1998
2103
  const metadata = optionalMetadata ? optionalMetadata : makeMeshAttributeMetadata(attribute);
1999
2104
  const dataType = attribute.size === 1 ? type : { type: "fixed-size-list", listSize: attribute.size, children: [{ name: "value", type }] };
2000
2105
  return {
@@ -2015,6 +2120,9 @@ function makeMeshAttributeMetadata(attribute) {
2015
2120
  if ("normalized" in attribute) {
2016
2121
  result.normalized = attribute.normalized.toString();
2017
2122
  }
2123
+ if (attribute.componentType) {
2124
+ result.componentType = attribute.componentType;
2125
+ }
2018
2126
  if (attribute.transform) {
2019
2127
  result["loaders.gl.transform"] = JSON.stringify(attribute.transform);
2020
2128
  }
@@ -2135,7 +2243,6 @@ var init_src2 = __esm({
2135
2243
  "../schema-utils/src/index.ts"() {
2136
2244
  "use strict";
2137
2245
  init_convert_arrow_schema();
2138
- init_data_type();
2139
2246
  init_make_table_batch_iterator();
2140
2247
  init_table_accessors();
2141
2248
  init_mesh_utils();
@@ -2197,11 +2304,23 @@ function makeBoxData(values, dimension) {
2197
2304
  }
2198
2305
  function makeListData(child, offsets, fieldName, offsetType) {
2199
2306
  return arrow6.makeData({
2200
- type: offsetType === "int64" ? new arrow6.LargeList(new arrow6.Field(fieldName, child.type, false)) : new arrow6.List(new arrow6.Field(fieldName, child.type, false)),
2307
+ type: offsetType === "int64" ? makeLargeListType(new arrow6.Field(fieldName, child.type, false)) : new arrow6.List(new arrow6.Field(fieldName, child.type, false)),
2201
2308
  valueOffsets: offsets,
2202
2309
  child
2203
2310
  });
2204
2311
  }
2312
+ function makeLargeListType(field) {
2313
+ const LargeList = getOptionalArrowConstructor2("LargeList");
2314
+ if (!LargeList) {
2315
+ throw new Error(
2316
+ "64-bit GeoArrow offsets require an Apache Arrow runtime that exports LargeList"
2317
+ );
2318
+ }
2319
+ return new LargeList(field);
2320
+ }
2321
+ function getOptionalArrowConstructor2(typeName) {
2322
+ return arrow6[typeName];
2323
+ }
2205
2324
  function makeCoordinateBuffers(coordinateCount, dimension, coordinateLayout) {
2206
2325
  if (coordinateLayout === "interleaved") {
2207
2326
  return new Float64Array(coordinateCount * getCoordinateSize2(dimension));
@@ -3317,7 +3436,14 @@ function convertFeaturesToWKBArrowTable(features, options = {}) {
3317
3436
  if (encodingPreference && encodingPreference !== "geoarrow.wkb") {
3318
3437
  return convertFeaturesToGeoArrowTable(features, options);
3319
3438
  }
3320
- const propertyRows = features.map((feature) => normalizeProperties2(feature.properties));
3439
+ const hasFeatureIds = features.some((feature) => feature.id !== void 0);
3440
+ const propertyRows = features.map((feature) => {
3441
+ const properties = normalizeProperties2(feature.properties);
3442
+ if (hasFeatureIds) {
3443
+ properties.id = normalizePropertyValue2(feature.id);
3444
+ }
3445
+ return properties;
3446
+ });
3321
3447
  const propertySchema = getPropertySchema2(propertyRows);
3322
3448
  const schema = buildFeatureArrowSchema(propertySchema, features);
3323
3449
  const arrowTableBuilder = new ArrowTableBuilder(schema);
@@ -3368,9 +3494,12 @@ function getPropertySchema2(propertyRows) {
3368
3494
  return {
3369
3495
  metadata: {},
3370
3496
  fields: fieldNames.map((fieldName) => {
3371
- const inferredType = getDataTypeFromArray(
3372
- propertyRows.map((propertyRow) => propertyRow[fieldName])
3373
- );
3497
+ const values = propertyRows.map((propertyRow) => propertyRow[fieldName]);
3498
+ const firstDefinedValue = values.find((value) => value !== null && value !== void 0);
3499
+ const inferredType = {
3500
+ type: getPropertyDataType(firstDefinedValue),
3501
+ nullable: true
3502
+ };
3374
3503
  return {
3375
3504
  name: fieldName,
3376
3505
  type: inferredType.type === "float32" ? "float64" : inferredType.type,
@@ -3379,6 +3508,18 @@ function getPropertySchema2(propertyRows) {
3379
3508
  })
3380
3509
  };
3381
3510
  }
3511
+ function getPropertyDataType(value) {
3512
+ if (typeof value === "number") {
3513
+ return "float64";
3514
+ }
3515
+ if (typeof value === "boolean") {
3516
+ return "bool";
3517
+ }
3518
+ if (typeof value === "string") {
3519
+ return "utf8";
3520
+ }
3521
+ return "null";
3522
+ }
3382
3523
  function getFieldNames2(propertyRows) {
3383
3524
  const fieldNames = /* @__PURE__ */ new Set();
3384
3525
  for (const propertyRow of propertyRows) {
@@ -4010,6 +4151,7 @@ var init_worker_pool = __esm({
4010
4151
  props = {};
4011
4152
  jobQueue = [];
4012
4153
  idleQueue = [];
4154
+ activeJobs = /* @__PURE__ */ new Set();
4013
4155
  count = 0;
4014
4156
  isDestroyed = false;
4015
4157
  /** Checks if workers are supported on this platform */
@@ -4028,10 +4170,14 @@ var init_worker_pool = __esm({
4028
4170
  this.setProps(props);
4029
4171
  }
4030
4172
  /**
4031
- * Terminates all workers in the pool
4173
+ * Terminates all workers in the pool and aborts active jobs.
4174
+ * @param reason Optional error delivered to active jobs.
4032
4175
  * @note Can free up significant memory
4033
4176
  */
4034
- destroy() {
4177
+ destroy(reason = new Error("Worker pool was destroyed")) {
4178
+ this.activeJobs.forEach((job) => job.abort(reason));
4179
+ const queuedJobs = this.jobQueue.splice(0);
4180
+ queuedJobs.forEach((queuedJob) => queuedJob.onReject(reason));
4035
4181
  this.idleQueue.forEach((worker) => worker.destroy());
4036
4182
  this.isDestroyed = true;
4037
4183
  }
@@ -4054,8 +4200,11 @@ var init_worker_pool = __esm({
4054
4200
  }
4055
4201
  }
4056
4202
  async startJob(name, onMessage2 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
4057
- const startPromise = new Promise((onStart) => {
4058
- this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart });
4203
+ if (this.isDestroyed) {
4204
+ return Promise.reject(new Error("Worker pool was destroyed"));
4205
+ }
4206
+ const startPromise = new Promise((onStart, onReject) => {
4207
+ this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart, onReject });
4059
4208
  return this;
4060
4209
  });
4061
4210
  this._startQueuedJob();
@@ -4083,6 +4232,7 @@ var init_worker_pool = __esm({
4083
4232
  backlog: this.jobQueue.length
4084
4233
  });
4085
4234
  const job = new WorkerJob(queuedJob.name, workerThread);
4235
+ this.activeJobs.add(job);
4086
4236
  workerThread.ref();
4087
4237
  workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload);
4088
4238
  workerThread.onError = (error) => queuedJob.onError(job, error);
@@ -4091,6 +4241,7 @@ var init_worker_pool = __esm({
4091
4241
  await job.result;
4092
4242
  } catch {
4093
4243
  } finally {
4244
+ this.activeJobs.delete(job);
4094
4245
  this.returnWorkerToQueue(workerThread);
4095
4246
  }
4096
4247
  }
@@ -4204,12 +4355,13 @@ var init_worker_farm = __esm({
4204
4355
  this.workerPools = /* @__PURE__ */ new Map();
4205
4356
  }
4206
4357
  /**
4207
- * Terminate all workers in the farm
4358
+ * Terminate all workers in the farm and abort active jobs.
4359
+ * @param reason Optional error delivered to active jobs.
4208
4360
  * @note Can free up significant memory
4209
4361
  */
4210
- destroy() {
4362
+ destroy(reason) {
4211
4363
  for (const workerPool of this.workerPools.values()) {
4212
- workerPool.destroy();
4364
+ workerPool.destroy(reason);
4213
4365
  }
4214
4366
  this.workerPools = /* @__PURE__ */ new Map();
4215
4367
  }
@@ -4682,7 +4834,12 @@ function getCDNOption(cdn, coreCDN) {
4682
4834
  return void 0;
4683
4835
  }
4684
4836
  async function loadLibrary(libraryUrl, moduleName = null, options = {}, libraryName = null) {
4837
+ var _a2;
4685
4838
  if (moduleName) {
4839
+ const injectedLibrary = (_a2 = options.modules) == null ? void 0 : _a2[libraryName || libraryUrl];
4840
+ if (injectedLibrary !== void 0 && typeof injectedLibrary !== "string") {
4841
+ return injectedLibrary;
4842
+ }
4686
4843
  libraryUrl = getLibraryUrl(libraryUrl, moduleName, options, libraryName);
4687
4844
  }
4688
4845
  loadLibraryPromises[libraryUrl] = // eslint-disable-next-line @typescript-eslint/no-misused-promises
@@ -4693,14 +4850,14 @@ function getLibraryUrl(library, moduleName, options = {}, libraryName = null) {
4693
4850
  if (options == null ? void 0 : options.core) {
4694
4851
  throw new Error("loadLibrary: options.core must be pre-normalized");
4695
4852
  }
4696
- if (!options.useLocalLibraries && library.startsWith("http")) {
4697
- return library;
4698
- }
4699
4853
  libraryName = libraryName || library;
4700
4854
  const modules = options.modules || {};
4701
- if (modules[libraryName]) {
4855
+ if (typeof modules[libraryName] === "string") {
4702
4856
  return modules[libraryName];
4703
4857
  }
4858
+ if (!options.useLocalLibraries && library.startsWith("http")) {
4859
+ return library;
4860
+ }
4704
4861
  if (!isBrowser2) {
4705
4862
  return `modules/${moduleName}/dist/libs/${libraryName}`;
4706
4863
  }
@@ -4818,13 +4975,13 @@ var init_src4 = __esm({
4818
4975
 
4819
4976
  // ../loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
4820
4977
  function canParseWithWorker(loader, options) {
4821
- var _a2, _b;
4978
+ var _a2;
4822
4979
  const workerOptions = getWorkerOptions(options);
4823
4980
  const nodeWorkers = workerOptions._nodeWorkers;
4824
4981
  if (!isBrowser2 && !nodeWorkers) {
4825
4982
  return false;
4826
4983
  }
4827
- if (loader.id === "excel" && ((_a2 = options == null ? void 0 : options.excel) == null ? void 0 : _a2.shape) === "arrow-table" || loader.id === "ply" && ((_b = options == null ? void 0 : options.ply) == null ? void 0 : _b.shape) === "arrow-table") {
4984
+ if (loader.id === "las" && (((_a2 = options == null ? void 0 : options.las) == null ? void 0 : _a2.shape) ?? "arrow-table") === "arrow-table") {
4828
4985
  return false;
4829
4986
  }
4830
4987
  if (loader.id === "csv" && !shouldParseCSVWithWorker(options)) {
@@ -7633,6 +7790,36 @@ function hydrateArrowTable(table) {
7633
7790
  );
7634
7791
  return new arrow9.Table(schema, recordBatches);
7635
7792
  }
7793
+ function serializeArrowWorkerResult(result, options) {
7794
+ var _a2;
7795
+ if (!isArrowTableWrapper(result)) {
7796
+ return result;
7797
+ }
7798
+ const workerOptions = options;
7799
+ const bufferCopyMode = ((_a2 = workerOptions == null ? void 0 : workerOptions.core) == null ? void 0 : _a2.workerTransferBufferCopy) ?? (workerOptions == null ? void 0 : workerOptions.workerTransferBufferCopy);
7800
+ return {
7801
+ ...result,
7802
+ data: dehydrateArrowTable(result.data, bufferCopyMode ? { copy: bufferCopyMode } : void 0)
7803
+ };
7804
+ }
7805
+ function deserializeArrowWorkerResult(result) {
7806
+ if (!isDehydratedArrowTableWrapper(result)) {
7807
+ return result;
7808
+ }
7809
+ return { ...result, data: hydrateArrowTable(result.data) };
7810
+ }
7811
+ function isArrowTableWrapper(value) {
7812
+ const table = value;
7813
+ return Boolean(
7814
+ table && table.shape === "arrow-table" && table.data && typeof table.data === "object" && "batches" in table.data
7815
+ );
7816
+ }
7817
+ function isDehydratedArrowTableWrapper(value) {
7818
+ const table = value;
7819
+ return Boolean(
7820
+ table && table.shape === "arrow-table" && table.data && table.data.transport === "arrow-js" && Array.isArray(table.data.batches)
7821
+ );
7822
+ }
7636
7823
  function dehydrateArrowRecordBatch(recordBatch) {
7637
7824
  return { data: dehydrateArrowData(recordBatch.data) };
7638
7825
  }
@@ -8282,9 +8469,9 @@ var init_vector_tile = __esm({
8282
8469
 
8283
8470
  // ../mvt/src/lib/parse-mvt.ts
8284
8471
  function parseMVT(arrayBuffer, options) {
8285
- var _a2, _b, _c, _d;
8472
+ var _a2, _b, _c;
8286
8473
  const mvtOptions = checkOptions(options);
8287
- const shape = ((_a2 = options == null ? void 0 : options.gis) == null ? void 0 : _a2.format) || ((_b = options == null ? void 0 : options.mvt) == null ? void 0 : _b.shape) || (options == null ? void 0 : options.shape);
8474
+ const shape = ((_a2 = options == null ? void 0 : options.mvt) == null ? void 0 : _a2.shape) || (options == null ? void 0 : options.shape) || "arrow-table";
8288
8475
  switch (shape) {
8289
8476
  case "columnar-table":
8290
8477
  return { shape: "columnar-table", data: parseToBinary(arrayBuffer, mvtOptions) };
@@ -8300,7 +8487,7 @@ function parseMVT(arrayBuffer, options) {
8300
8487
  const table = convertFeaturesToWKBArrowTable(
8301
8488
  parseToGeojsonFeatures(arrayBuffer, mvtOptions),
8302
8489
  {
8303
- encodingPreference: ((_c = options == null ? void 0 : options.geoarrow) == null ? void 0 : _c.encodingPreference) || ((_d = mvtOptions.geoarrow) == null ? void 0 : _d.encodingPreference)
8490
+ encodingPreference: ((_b = options == null ? void 0 : options.geoarrow) == null ? void 0 : _b.encodingPreference) || ((_c = mvtOptions.geoarrow) == null ? void 0 : _c.encodingPreference)
8304
8491
  }
8305
8492
  );
8306
8493
  return table;
@@ -8417,19 +8604,14 @@ __export(mvt_loader_with_parser_exports, {
8417
8604
  MVTLoaderWithParser: () => MVTLoaderWithParser,
8418
8605
  MVTWorkerLoaderWithParser: () => MVTWorkerLoaderWithParser
8419
8606
  });
8420
- var _MVTWorkerLoaderPreload, MVTWorkerLoaderMetadataWithoutPreload, _MVTLoaderPreload, MVTLoaderMetadataWithoutPreload, MVTWorkerLoaderWithParser, MVTLoaderWithParser;
8607
+ var _MVTLoaderPreload, MVTLoaderMetadataWithoutPreload, MVTLoaderWithParser, MVTWorkerLoaderWithParser;
8421
8608
  var init_mvt_loader_with_parser = __esm({
8422
8609
  "../mvt/src/mvt-loader-with-parser.ts"() {
8423
8610
  "use strict";
8424
8611
  init_parse_mvt();
8425
8612
  init_mvt_worker_transport();
8426
8613
  init_mvt_loader();
8427
- init_mvt_loader();
8428
- ({ preload: _MVTWorkerLoaderPreload, ...MVTWorkerLoaderMetadataWithoutPreload } = MVTWorkerLoader);
8429
8614
  ({ preload: _MVTLoaderPreload, ...MVTLoaderMetadataWithoutPreload } = MVTLoader);
8430
- MVTWorkerLoaderWithParser = {
8431
- ...MVTWorkerLoaderMetadataWithoutPreload
8432
- };
8433
8615
  MVTLoaderWithParser = {
8434
8616
  ...MVTLoaderMetadataWithoutPreload,
8435
8617
  parse: async (arrayBuffer, options) => parseMVT(arrayBuffer, options),
@@ -8437,6 +8619,7 @@ var init_mvt_loader_with_parser = __esm({
8437
8619
  serializeWorkerResult: serializeMVTWorkerResult,
8438
8620
  deserializeWorkerResult: deserializeMVTWorkerResult
8439
8621
  };
8622
+ MVTWorkerLoaderWithParser = MVTLoaderWithParser;
8440
8623
  }
8441
8624
  });
8442
8625
 
@@ -8445,14 +8628,14 @@ async function preload4() {
8445
8628
  const { MVTLoaderWithParser: MVTLoaderWithParser2 } = await Promise.resolve().then(() => (init_mvt_loader_with_parser(), mvt_loader_with_parser_exports));
8446
8629
  return MVTLoaderWithParser2;
8447
8630
  }
8448
- var VERSION5, MVTWorkerLoader, MVTLoader;
8631
+ var VERSION5, MVTLoader;
8449
8632
  var init_mvt_loader = __esm({
8450
8633
  "../mvt/src/mvt-loader.ts"() {
8451
8634
  "use strict";
8452
8635
  init_mvt_format();
8453
8636
  init_mvt_worker_transport();
8454
8637
  VERSION5 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
8455
- MVTWorkerLoader = {
8638
+ MVTLoader = {
8456
8639
  ...MVTFormat,
8457
8640
  dataType: null,
8458
8641
  batchType: null,
@@ -8460,7 +8643,7 @@ var init_mvt_loader = __esm({
8460
8643
  worker: true,
8461
8644
  options: {
8462
8645
  mvt: {
8463
- shape: "geojson-table",
8646
+ shape: "arrow-table",
8464
8647
  coordinates: "local",
8465
8648
  layerProperty: "layerName",
8466
8649
  layers: void 0,
@@ -8469,12 +8652,8 @@ var init_mvt_loader = __esm({
8469
8652
  },
8470
8653
  serializeWorkerResult: serializeMVTWorkerResult,
8471
8654
  deserializeWorkerResult: deserializeMVTWorkerResult,
8472
- preload: preload4
8473
- };
8474
- MVTLoader = {
8475
- ...MVTWorkerLoader,
8476
- binary: true,
8477
- preload: preload4
8655
+ preload: preload4,
8656
+ binary: true
8478
8657
  };
8479
8658
  }
8480
8659
  });
@@ -8781,6 +8960,7 @@ var init_i3s_loader_options = __esm({
8781
8960
  useDracoGeometry: true,
8782
8961
  useCompressedTextures: true,
8783
8962
  decodeTextures: true,
8963
+ colorFormat: "uint8norm",
8784
8964
  coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS
8785
8965
  };
8786
8966
  }
@@ -9025,10 +9205,9 @@ var init_draco_loader_options = __esm({
9025
9205
  "use strict";
9026
9206
  DRACO_LOADER_DEFAULT_OPTIONS = {
9027
9207
  backend: typeof WebAssembly === "object" ? "wasm" : "javascript",
9028
- decoderType: typeof WebAssembly === "object" ? "wasm" : "js",
9029
9208
  extraAttributes: {},
9030
9209
  attributeNameEntry: void 0,
9031
- shape: "mesh",
9210
+ shape: "arrow-table",
9032
9211
  decoderProfile: "full"
9033
9212
  };
9034
9213
  }
@@ -9801,38 +9980,34 @@ async function preload5(_url, options) {
9801
9980
  }
9802
9981
  }
9803
9982
  function getDracoBackend(options) {
9804
- var _a2, _b;
9983
+ var _a2;
9805
9984
  if ((_a2 = options == null ? void 0 : options.draco) == null ? void 0 : _a2.backend) {
9806
9985
  return options.draco.backend === "js" ? "javascript" : options.draco.backend;
9807
9986
  }
9808
- if ((_b = options == null ? void 0 : options.draco) == null ? void 0 : _b.decoderType) {
9809
- return options.draco.decoderType === "js" ? "javascript" : options.draco.decoderType;
9810
- }
9811
9987
  return DracoLoader.options.draco.backend;
9812
9988
  }
9813
- var DracoWorkerLoader, DracoLoader;
9989
+ var DracoLoader;
9814
9990
  var init_draco_loader = __esm({
9815
9991
  "../draco/src/draco-loader.ts"() {
9816
9992
  "use strict";
9993
+ init_transport();
9817
9994
  init_version3();
9818
9995
  init_draco_format();
9819
9996
  init_draco_loader_options();
9820
- DracoWorkerLoader = {
9997
+ DracoLoader = {
9821
9998
  dataType: null,
9822
9999
  batchType: null,
9823
10000
  ...DracoFormat,
9824
10001
  // shapes: ['mesh'],
9825
10002
  version: VERSION6,
9826
10003
  worker: true,
10004
+ serializeWorkerResult: serializeArrowWorkerResult,
10005
+ deserializeWorkerResult: deserializeArrowWorkerResult,
9827
10006
  options: {
9828
10007
  draco: DRACO_LOADER_DEFAULT_OPTIONS
9829
10008
  },
9830
10009
  preload: preload5
9831
10010
  };
9832
- DracoLoader = {
9833
- ...DracoWorkerLoader,
9834
- preload: preload5
9835
- };
9836
10011
  }
9837
10012
  });
9838
10013
 
@@ -11133,13 +11308,13 @@ async function preload6() {
11133
11308
  const { BasisLoaderWithParser: BasisLoaderWithParser2 } = await Promise.resolve().then(() => (init_basis_loader_with_parser(), basis_loader_with_parser_exports));
11134
11309
  return BasisLoaderWithParser2;
11135
11310
  }
11136
- var BasisWorkerLoader, BasisLoader;
11311
+ var BasisLoader, BasisWorkerLoader;
11137
11312
  var init_basis_loader = __esm({
11138
11313
  "../textures/src/basis-loader.ts"() {
11139
11314
  "use strict";
11140
11315
  init_texture_format();
11141
11316
  init_version4();
11142
- BasisWorkerLoader = {
11317
+ BasisLoader = {
11143
11318
  ...BasisTextureFormat,
11144
11319
  dataType: null,
11145
11320
  batchType: null,
@@ -11160,10 +11335,7 @@ var init_basis_loader = __esm({
11160
11335
  },
11161
11336
  preload: preload6
11162
11337
  };
11163
- BasisLoader = {
11164
- ...BasisWorkerLoader,
11165
- preload: preload6
11166
- };
11338
+ BasisWorkerLoader = BasisLoader;
11167
11339
  }
11168
11340
  });
11169
11341
 
@@ -11492,13 +11664,13 @@ async function preload7() {
11492
11664
  const { CompressedTextureLoaderWithParser: CompressedTextureLoaderWithParser2 } = await Promise.resolve().then(() => (init_compressed_texture_loader_with_parser(), compressed_texture_loader_with_parser_exports));
11493
11665
  return CompressedTextureLoaderWithParser2;
11494
11666
  }
11495
- var CompressedTextureWorkerLoader, CompressedTextureLoader;
11667
+ var CompressedTextureLoader, CompressedTextureWorkerLoader;
11496
11668
  var init_compressed_texture_loader = __esm({
11497
11669
  "../textures/src/compressed-texture-loader.ts"() {
11498
11670
  "use strict";
11499
11671
  init_texture_format();
11500
11672
  init_version4();
11501
- CompressedTextureWorkerLoader = {
11673
+ CompressedTextureLoader = {
11502
11674
  ...CompressedTextureFormat,
11503
11675
  dataType: null,
11504
11676
  batchType: null,
@@ -11536,10 +11708,7 @@ var init_compressed_texture_loader = __esm({
11536
11708
  },
11537
11709
  preload: preload7
11538
11710
  };
11539
- CompressedTextureLoader = {
11540
- ...CompressedTextureWorkerLoader,
11541
- preload: preload7
11542
- };
11711
+ CompressedTextureWorkerLoader = CompressedTextureLoader;
11543
11712
  }
11544
11713
  });
11545
11714
 
@@ -11736,7 +11905,7 @@ var init_tiles_3d_request_priority = __esm({
11736
11905
  }
11737
11906
  });
11738
11907
 
11739
- // ../tiles/src/spatial/get-spatial-coordinate-frame.ts
11908
+ // ../tiles/src/spatial/normalize-crs-identifier.ts
11740
11909
  function normalizeCrsIdentifier(identifier) {
11741
11910
  const normalizedIdentifier = identifier.trim().toUpperCase();
11742
11911
  const ogcMatch = normalizedIdentifier.match(
@@ -11744,20 +11913,27 @@ function normalizeCrsIdentifier(identifier) {
11744
11913
  );
11745
11914
  return ogcMatch ? `${ogcMatch[1]}:${ogcMatch[2]}` : normalizedIdentifier;
11746
11915
  }
11916
+ var WGS84_GEOGRAPHIC_CRS, WGS84_GEOCENTRIC_CRS;
11917
+ var init_normalize_crs_identifier = __esm({
11918
+ "../tiles/src/spatial/normalize-crs-identifier.ts"() {
11919
+ "use strict";
11920
+ WGS84_GEOGRAPHIC_CRS = "EPSG:4326";
11921
+ WGS84_GEOCENTRIC_CRS = "EPSG:4978";
11922
+ }
11923
+ });
11924
+
11925
+ // ../tiles/src/spatial/get-spatial-coordinate-frame.ts
11747
11926
  function getSpatialCoordinateFrame(definition) {
11748
11927
  var _a2, _b;
11749
11928
  if (typeof definition === "string") {
11750
- const normalized = normalizeCrsIdentifier(definition);
11751
- if (normalized === GEOCENTRIC_CRS || /^GEOCCS\s*[\[(]/.test(normalized)) {
11752
- return "geocentric";
11753
- }
11754
- if (normalized === GEOGRAPHIC_CRS || normalized === "EPSG:4490" || normalized === "EPSG:4979" || normalized === "OGC:CRS84" || normalized.includes("+PROJ=LONGLAT") || normalized.includes("+PROJ=LATLONG") || /^(?:GEOGCS|GEOGCRS|GEOGRAPHICCRS|GEOGRAPHIC2DCRS|GEOGRAPHIC3DCRS)\s*[\[(]/.test(normalized)) {
11755
- return "geographic";
11929
+ const representation = (0, import_crs.inferCRSRepresentation)(definition);
11930
+ if (representation === "wkt") {
11931
+ return getWktCoordinateFrame(definition);
11756
11932
  }
11757
- if (/^(?:GEODCRS|GEODETICCRS)\s*[\[(]/.test(normalized)) {
11758
- return /CS\s*[\[(]\s*CARTESIAN/.test(normalized) ? "geocentric" : "geographic";
11933
+ if (representation === "proj-string") {
11934
+ return getProjStringCoordinateFrame(definition);
11759
11935
  }
11760
- return "projected";
11936
+ return getKnownCrsIdentifierCoordinateFrame(definition) || "projected";
11761
11937
  }
11762
11938
  const projJsonDefinition = definition;
11763
11939
  if (projJsonDefinition.type === "BoundCRS" && projJsonDefinition.source_crs) {
@@ -11775,14 +11951,95 @@ function getSpatialCoordinateFrame(definition) {
11775
11951
  if (String(projJsonDefinition.type).includes("Geodetic")) {
11776
11952
  return ((_b = projJsonDefinition.coordinate_system) == null ? void 0 : _b.subtype) === "Cartesian" ? "geocentric" : "geographic";
11777
11953
  }
11778
- return "projected";
11954
+ return "unknown";
11955
+ }
11956
+ function getKnownCrsIdentifierCoordinateFrame(definition) {
11957
+ if (typeof definition !== "string") {
11958
+ return void 0;
11959
+ }
11960
+ const normalized = normalizeCrsIdentifier(definition);
11961
+ if (normalized === WGS84_GEOCENTRIC_CRS) {
11962
+ return "geocentric";
11963
+ }
11964
+ if (normalized === WGS84_GEOGRAPHIC_CRS || normalized === "OGC:CRS84") {
11965
+ return "geographic";
11966
+ }
11967
+ const epsgMatch = /^EPSG:(\d+)$/.exec(normalized);
11968
+ if (!epsgMatch) {
11969
+ return void 0;
11970
+ }
11971
+ const identifier = Number(epsgMatch[1]);
11972
+ if (identifier === 7789) {
11973
+ return "geocentric";
11974
+ }
11975
+ if (identifier === 4490 || identifier === 4979) {
11976
+ return "geographic";
11977
+ }
11978
+ if (identifier === 3857 || identifier >= 32601 && identifier <= 32660 || identifier >= 32701 && identifier <= 32760) {
11979
+ return "projected";
11980
+ }
11981
+ return void 0;
11982
+ }
11983
+ function getWktCoordinateFrame(definition) {
11984
+ let root;
11985
+ try {
11986
+ root = (0, import_crs.parseWKTCRS)(definition).root;
11987
+ } catch {
11988
+ return "unknown";
11989
+ }
11990
+ switch (root.keyword.toUpperCase()) {
11991
+ case "GEOCCS":
11992
+ return "geocentric";
11993
+ case "GEOGCS":
11994
+ case "GEOGCRS":
11995
+ case "GEOGRAPHICCRS":
11996
+ case "GEOGRAPHIC2DCRS":
11997
+ case "GEOGRAPHIC3DCRS":
11998
+ return "geographic";
11999
+ case "PROJCS":
12000
+ case "PROJCRS":
12001
+ case "PROJECTEDCRS":
12002
+ return "projected";
12003
+ case "GEODCRS":
12004
+ case "GEODETICCRS": {
12005
+ const coordinateSystem = root.values.find(
12006
+ (value) => value.type === "node" && value.keyword.toUpperCase() === "CS"
12007
+ );
12008
+ const subtype = coordinateSystem == null ? void 0 : coordinateSystem.values[0];
12009
+ if ((subtype == null ? void 0 : subtype.type) !== "enumeration" && (subtype == null ? void 0 : subtype.type) !== "string") {
12010
+ return "unknown";
12011
+ }
12012
+ return subtype.value.toUpperCase() === "CARTESIAN" ? "geocentric" : subtype.value.toUpperCase() === "ELLIPSOIDAL" ? "geographic" : "unknown";
12013
+ }
12014
+ default:
12015
+ return "unknown";
12016
+ }
12017
+ }
12018
+ function getProjStringCoordinateFrame(definition) {
12019
+ var _a2;
12020
+ try {
12021
+ const projection = (_a2 = (0, import_crs.parsePROJString)(definition).parameters.find(
12022
+ (parameter) => parameter.name.toLowerCase() === "proj"
12023
+ )) == null ? void 0 : _a2.value;
12024
+ switch (projection == null ? void 0 : projection.toLowerCase()) {
12025
+ case "longlat":
12026
+ case "latlong":
12027
+ return "geographic";
12028
+ case "geocent":
12029
+ return "geocentric";
12030
+ default:
12031
+ return projection ? "projected" : "unknown";
12032
+ }
12033
+ } catch {
12034
+ return "unknown";
12035
+ }
11779
12036
  }
11780
- var GEOGRAPHIC_CRS, GEOCENTRIC_CRS;
12037
+ var import_crs;
11781
12038
  var init_get_spatial_coordinate_frame = __esm({
11782
12039
  "../tiles/src/spatial/get-spatial-coordinate-frame.ts"() {
11783
12040
  "use strict";
11784
- GEOGRAPHIC_CRS = "EPSG:4326";
11785
- GEOCENTRIC_CRS = "EPSG:4978";
12041
+ import_crs = require("@math.gl/crs");
12042
+ init_normalize_crs_identifier();
11786
12043
  }
11787
12044
  });
11788
12045
 
@@ -11808,11 +12065,11 @@ function createTilesetSpatialReference(discovered, options = {}) {
11808
12065
  const provenance = hasSourceCrsOverride ? "caller-override" : discovered.provenance || "unknown";
11809
12066
  const coordinateFrame = hasSourceCrsOverride && sourceCrs ? getSpatialCoordinateFrame(sourceCrs) : discovered.coordinateFrame;
11810
12067
  const sourceCrsState = hasSourceCrsOverride ? "explicit" : discovered.sourceCrsState || (sourceCrs ? provenance === "format-default" ? "default" : "explicit" : "absent");
11811
- const spatialReference = (0, import_crs.createSpatialReference)({
12068
+ const spatialReference = (0, import_crs2.createSpatialReference)({
11812
12069
  crs: sourceCrs ? {
11813
12070
  state: sourceCrsState === "default" ? "default" : "explicit",
11814
12071
  definition: sourceCrs,
11815
- representation: !hasSourceCrsOverride && discovered.sourceCrsRepresentation || (0, import_crs.inferCRSRepresentation)(sourceCrs),
12072
+ representation: !hasSourceCrsOverride && discovered.sourceCrsRepresentation || (0, import_crs2.inferCRSRepresentation)(sourceCrs),
11816
12073
  provenance,
11817
12074
  alternatives: hasSourceCrsOverride ? void 0 : discovered.sourceCrsAlternatives
11818
12075
  } : {
@@ -11822,7 +12079,7 @@ function createTilesetSpatialReference(discovered, options = {}) {
11822
12079
  vertical: discovered.verticalCrs ? {
11823
12080
  state: "explicit",
11824
12081
  definition: discovered.verticalCrs,
11825
- representation: (0, import_crs.inferCRSRepresentation)(discovered.verticalCrs),
12082
+ representation: (0, import_crs2.inferCRSRepresentation)(discovered.verticalCrs),
11826
12083
  provenance: discovered.provenance || "metadata"
11827
12084
  } : void 0,
11828
12085
  coordinateEpoch: options.coordinateEpoch ?? discovered.coordinateEpoch,
@@ -11882,11 +12139,11 @@ function getKnownCRSDefinition(reference) {
11882
12139
  return reference.state === "explicit" || reference.state === "default" ? reference.definition : void 0;
11883
12140
  }
11884
12141
  function cloneReadonlyCRSDefinition(definition) {
11885
- const spatialReference = (0, import_crs.createSpatialReference)({
12142
+ const spatialReference = (0, import_crs2.createSpatialReference)({
11886
12143
  crs: {
11887
12144
  state: "explicit",
11888
12145
  definition,
11889
- representation: (0, import_crs.inferCRSRepresentation)(definition),
12146
+ representation: (0, import_crs2.inferCRSRepresentation)(definition),
11890
12147
  provenance: "caller-override"
11891
12148
  }
11892
12149
  });
@@ -11914,34 +12171,87 @@ function markTilesetSpatialReferenceTransformed(spatialReference) {
11914
12171
  }
11915
12172
  return Object.freeze({ ...spatialReference, status: "transformed" });
11916
12173
  }
11917
- var import_crs;
12174
+ var import_crs2;
11918
12175
  var init_spatial_types = __esm({
11919
12176
  "../tiles/src/spatial/spatial-types.ts"() {
11920
12177
  "use strict";
11921
- import_crs = require("@math.gl/crs");
12178
+ import_crs2 = require("@math.gl/crs");
11922
12179
  init_get_spatial_coordinate_frame();
11923
12180
  }
11924
12181
  });
11925
12182
 
12183
+ // ../tiles/src/tileset-3d/common/tile-3d-contracts.ts
12184
+ function getTile3DFeatureIdSets(payload) {
12185
+ const featureIdSets = [];
12186
+ const visited = /* @__PURE__ */ new Set();
12187
+ const visit = (value) => {
12188
+ var _a2, _b;
12189
+ if (!value || typeof value !== "object") {
12190
+ return;
12191
+ }
12192
+ if (visited.has(value)) {
12193
+ return;
12194
+ }
12195
+ visited.add(value);
12196
+ const record = value;
12197
+ const declarations = (_b = (_a2 = record.extensions) == null ? void 0 : _a2.EXT_mesh_features) == null ? void 0 : _b.featureIds;
12198
+ if (Array.isArray(declarations)) {
12199
+ for (const declaration of declarations) {
12200
+ if (!declaration || typeof declaration !== "object") {
12201
+ continue;
12202
+ }
12203
+ const source = declaration.texture ? "texture" : declaration.implicit ? "implicit" : declaration.attribute !== void 0 ? "attribute" : declaration.propertyTable !== void 0 ? "property-table" : "constant";
12204
+ featureIdSets.push({
12205
+ source,
12206
+ attribute: declaration.attribute,
12207
+ propertyTable: declaration.propertyTable,
12208
+ constant: declaration.constant,
12209
+ texture: declaration.texture,
12210
+ implicit: declaration.implicit,
12211
+ values: declaration.values,
12212
+ details: declaration
12213
+ });
12214
+ }
12215
+ }
12216
+ for (const child of Object.values(record)) {
12217
+ visit(child);
12218
+ }
12219
+ };
12220
+ visit(payload);
12221
+ return featureIdSets;
12222
+ }
12223
+ var init_tile_3d_contracts = __esm({
12224
+ "../tiles/src/tileset-3d/common/tile-3d-contracts.ts"() {
12225
+ "use strict";
12226
+ }
12227
+ });
12228
+
11926
12229
  // ../tiles/src/tileset-3d/helpers/bounding-volume.ts
11927
12230
  function defined(x) {
11928
12231
  return x !== void 0 && x !== null;
11929
12232
  }
11930
- function createBoundingVolume(boundingVolumeHeader, transform, result) {
12233
+ function createBoundingVolume(boundingVolumeHeader, transform, result, initialTransform = transform) {
11931
12234
  assert(boundingVolumeHeader, "3D Tile: boundingVolume must be defined");
11932
12235
  if (boundingVolumeHeader.box) {
11933
- return createBox(boundingVolumeHeader.box, transform, result);
12236
+ const boxTransform = boundingVolumeHeader.s2VolumeInfo ? identityTransform : transform;
12237
+ return createBox(boundingVolumeHeader.box, boxTransform, result);
11934
12238
  }
11935
12239
  if (boundingVolumeHeader.region) {
11936
- return (0, import_geospatial.makeOBBFromRegion)(boundingVolumeHeader.region);
12240
+ const boundingVolume = (0, import_geospatial.makeOBBFromRegion)(boundingVolumeHeader.region);
12241
+ const regionTransform = transform.equals(initialTransform) ? identityTransform : transform.clone().multiplyRight(initialTransform.clone().invert());
12242
+ return createBox(
12243
+ [...boundingVolume.center, ...boundingVolume.halfAxes],
12244
+ regionTransform,
12245
+ result
12246
+ );
11937
12247
  }
11938
12248
  if (boundingVolumeHeader.sphere) {
11939
12249
  return createSphere(boundingVolumeHeader.sphere, transform, result);
11940
12250
  }
11941
12251
  throw new Error("3D Tile: boundingVolume must contain a sphere, region, or box");
11942
12252
  }
11943
- function getCartographicBounds(boundingVolumeHeader, boundingVolume) {
11944
- if (boundingVolumeHeader.box) {
12253
+ function getCartographicBounds(boundingVolumeHeader, boundingVolume, isRegionTransformed = false) {
12254
+ if (boundingVolumeHeader.box || boundingVolumeHeader.region && isRegionTransformed) {
11945
12255
  return orientedBoundingBoxToCartographicBounds(boundingVolume);
11946
12256
  }
11947
12257
  if (boundingVolumeHeader.region) {
@@ -12076,7 +12386,7 @@ function addToCartographicBounds(target, cartesian) {
12076
12386
  target[1][1] = Math.max(target[1][1], scratchPoint[1]);
12077
12387
  target[1][2] = Math.max(target[1][2], scratchPoint[2]);
12078
12388
  }
12079
- var import_core3, import_culling2, import_geospatial, scratchPoint, scratchScale;
12389
+ var import_core3, import_culling2, import_geospatial, scratchPoint, scratchScale, identityTransform;
12080
12390
  var init_bounding_volume = __esm({
12081
12391
  "../tiles/src/tileset-3d/helpers/bounding-volume.ts"() {
12082
12392
  "use strict";
@@ -12086,6 +12396,7 @@ var init_bounding_volume = __esm({
12086
12396
  init_src5();
12087
12397
  scratchPoint = new import_core3.Vector3();
12088
12398
  scratchScale = new import_core3.Vector3();
12399
+ identityTransform = new import_core3.Matrix4();
12089
12400
  }
12090
12401
  });
12091
12402
 
@@ -12462,7 +12773,7 @@ var init_tileset_traverser = __esm({
12462
12773
  }
12463
12774
  stack.push(child);
12464
12775
  hasVisibleChild = true;
12465
- } else if (checkRefines || loadSiblings) {
12776
+ } else if ((checkRefines || loadSiblings) && child._inRequestVolume) {
12466
12777
  this.loadTile(child, frameState);
12467
12778
  this.touchTile(child, frameState);
12468
12779
  }
@@ -12650,6 +12961,13 @@ function getContentVisibility(contentVolumes, fallbackVolume, cullingVolume, vis
12650
12961
  }
12651
12962
  return intersectingVolume ? "intersecting" : "inside";
12652
12963
  }
12964
+ function isNestedTilesetPayload(payload) {
12965
+ if (!payload || typeof payload !== "object") {
12966
+ return false;
12967
+ }
12968
+ const record = payload;
12969
+ return record.shape === "tileset3d" || record.type === "tileset3d" || Boolean(record.tileset);
12970
+ }
12653
12971
  function defined2(x) {
12654
12972
  return x !== void 0 && x !== null;
12655
12973
  }
@@ -12659,6 +12977,7 @@ var init_tile_3d = __esm({
12659
12977
  "use strict";
12660
12978
  import_core5 = require("@math.gl/core");
12661
12979
  import_culling3 = require("@math.gl/culling");
12980
+ init_tile_3d_contracts();
12662
12981
  init_constants2();
12663
12982
  init_bounding_volume();
12664
12983
  init_tiles_3d_lod();
@@ -12690,6 +13009,8 @@ var init_tile_3d = __esm({
12690
13009
  * separate ensures transform updates never compound an already-scaled geometric error.
12691
13010
  */
12692
13011
  _unscaledLodMetricValue = 0;
13012
+ /** Whether the source format defines geometric error in transform-local units. */
13013
+ _scaleGeometricError = true;
12693
13014
  /** @todo math.gl is not exporting BoundingVolume base type? */
12694
13015
  boundingVolume = null;
12695
13016
  /**
@@ -12699,6 +13020,14 @@ var init_tile_3d = __esm({
12699
13020
  content = null;
12700
13021
  /** Loaded payloads in the same order as {@link contentUrls}; `content` remains the primary payload. */
12701
13022
  contents = [];
13023
+ /** Ordered renderer-neutral descriptors for each source content entry. */
13024
+ contentEntries = [];
13025
+ /** Raw metadata references inherited by this tile and its content. */
13026
+ metadataContext = {};
13027
+ /** Feature-id declarations normalized from supported content extensions. */
13028
+ featureIdSets = [];
13029
+ /** Decoded 3D Tiles vector topology for the primary loaded content, when present. */
13030
+ vectorContent = null;
12702
13031
  /**
12703
13032
  * Metadata entity attached to this tile in the source tileset, if present.
12704
13033
  *
@@ -12765,6 +13094,7 @@ var init_tile_3d = __esm({
12765
13094
  get viewerRequestVolume() {
12766
13095
  return this._viewerRequestVolume;
12767
13096
  }
13097
+ /** Accumulated tile transforms from the source JSON, excluding the tileset model matrix. */
12768
13098
  _initialTransform = new import_core5.Matrix4();
12769
13099
  // Used by traverser, cannot be marked private
12770
13100
  _priority = 0;
@@ -12806,15 +13136,14 @@ var init_tile_3d = __esm({
12806
13136
  this.type = header.type;
12807
13137
  this.contentUrl = header.contentUrl;
12808
13138
  this.contentUrls = header.contentUrls || (header.contentUrl ? [header.contentUrl] : []);
12809
- this.metadata = header.metadata || null;
12810
- const contentHeaders = Array.isArray(header.content) ? header.content : [header.content];
12811
- this.contentMetadata = contentHeaders.filter(Boolean).map((contentHeader) => contentHeader.metadata || null);
13139
+ this._initializeMetadata(header);
12812
13140
  this.childrenState = header.implicitSubtree ? "unloaded" : "ready";
12813
13141
  this._initializeLodMetric(header);
12814
13142
  this._initializeTransforms(header);
12815
13143
  this._updateLodMetricScale();
12816
13144
  this._initializeBoundingVolumes(header);
12817
13145
  this._initializeContent(header);
13146
+ this._initializeContentEntries(header);
12818
13147
  this._initializeRenderingState(header);
12819
13148
  Object.seal(this);
12820
13149
  }
@@ -12903,12 +13232,16 @@ var init_tile_3d = __esm({
12903
13232
  return this._screenSpaceError;
12904
13233
  }
12905
13234
  /**
12906
- * Get bounding box in cartographic coordinates
13235
+ * Get the current world-space bounding volume in cartographic coordinates.
12907
13236
  * @returns [min, max] each in [longitude, latitude, altitude]
12908
13237
  */
12909
13238
  get boundingBox() {
12910
13239
  if (!this._boundingBox) {
12911
- this._boundingBox = getCartographicBounds(this.header.boundingVolume, this.boundingVolume);
13240
+ this._boundingBox = getCartographicBounds(
13241
+ this.header.boundingVolume,
13242
+ this.boundingVolume,
13243
+ !this.computedTransform.equals(this._initialTransform)
13244
+ );
12912
13245
  }
12913
13246
  return this._boundingBox;
12914
13247
  }
@@ -13016,6 +13349,7 @@ var init_tile_3d = __esm({
13016
13349
  */
13017
13350
  // eslint-disable-next-line max-statements, complexity
13018
13351
  async loadContent() {
13352
+ var _a2;
13019
13353
  if (this.hasEmptyContent) {
13020
13354
  return { loaded: false };
13021
13355
  }
@@ -13041,11 +13375,13 @@ var init_tile_3d = __esm({
13041
13375
  this.contents = loadResult.contents;
13042
13376
  this.content = this.contents[0] || null;
13043
13377
  }
13378
+ this.vectorContent = ((_a2 = this.contents.find((content) => Boolean(content == null ? void 0 : content.vectorContent))) == null ? void 0 : _a2.vectorContent) || null;
13044
13379
  if (this.tileset.options.contentLoader) {
13045
13380
  await this.tileset.options.contentLoader(this);
13046
13381
  }
13047
13382
  this.contentState = TILE_CONTENT_STATE.READY;
13048
13383
  this._onContentLoaded();
13384
+ this._updateContentEntriesAfterLoad(loadResult);
13049
13385
  return loadResult;
13050
13386
  } catch (error) {
13051
13387
  this.contentState = TILE_CONTENT_STATE.FAILED;
@@ -13111,30 +13447,116 @@ var init_tile_3d = __esm({
13111
13447
  /**
13112
13448
  * Replaces a contentless implicit placeholder with its materialized subtree-root header.
13113
13449
  *
13114
- * Transform state is intentionally preserved: the placeholder already owns the composed
13115
- * transform, and reapplying the root transform here would double-transform bounds and geometric
13116
- * error. Content and raw geometric error are reinitialized from the newly available header.
13450
+ * The placeholder transform is preserved when the subtree omits a root transform. An explicit
13451
+ * subtree-root transform replaces it and is recomposed against the runtime parent. Content,
13452
+ * metadata, bounds, and raw geometric error are reinitialized from the available header.
13117
13453
  *
13118
13454
  * @param materializedHeader - Available root header produced from one subtree resource.
13119
13455
  */
13120
13456
  applyImplicitSubtreeHeader(materializedHeader) {
13121
13457
  const existingTransform = this.header.transform;
13122
13458
  const existingTransformMatrix = this.header.transformMatrix;
13459
+ const hasMaterializedTransform = materializedHeader.transform !== void 0;
13123
13460
  this.header = {
13124
13461
  ...this.header,
13125
13462
  ...materializedHeader,
13126
- transform: existingTransform,
13127
- transformMatrix: existingTransformMatrix,
13463
+ transform: hasMaterializedTransform ? materializedHeader.transform : existingTransform,
13464
+ transformMatrix: hasMaterializedTransform ? materializedHeader.transformMatrix : existingTransformMatrix,
13128
13465
  implicitSubtree: void 0
13129
13466
  };
13467
+ if (hasMaterializedTransform) {
13468
+ this._initializeTransforms(this.header);
13469
+ }
13130
13470
  this.refine = this._getRefine(materializedHeader.refine);
13131
13471
  this.type = materializedHeader.type;
13132
13472
  this.contentUrl = materializedHeader.contentUrl;
13133
13473
  this.contentUrls = materializedHeader.contentUrls || (materializedHeader.contentUrl ? [materializedHeader.contentUrl] : []);
13474
+ this._initializeMetadata(this.header);
13134
13475
  this._initializeLodMetric(materializedHeader);
13135
13476
  this._updateLodMetricScale();
13136
13477
  this._initializeBoundingVolumes(this.header);
13478
+ this._boundingBox = void 0;
13137
13479
  this._initializeContent(this.header);
13480
+ this._initializeContentEntries(this.header);
13481
+ }
13482
+ /** Refreshes tile and content metadata from a source or materialized tile header. */
13483
+ _initializeMetadata(header) {
13484
+ var _a2;
13485
+ this.metadata = header.metadata || null;
13486
+ const contentHeaders = Array.isArray(header.content) ? header.content : [header.content];
13487
+ this.contentMetadata = contentHeaders.filter(Boolean).map((contentHeader) => contentHeader.metadata || null);
13488
+ const firstContentHeader = contentHeaders.find(Boolean) || {};
13489
+ const groupReference = firstContentHeader.group;
13490
+ const group = typeof groupReference === "number" ? ((_a2 = this.tileset.groups) == null ? void 0 : _a2[groupReference]) || null : groupReference || null;
13491
+ const metadataContext = {
13492
+ tileset: this.tileset.metadata || null,
13493
+ group,
13494
+ tile: this.metadata,
13495
+ content: this.contentMetadata[0] || null,
13496
+ subtree: header.implicitMetadata || null
13497
+ };
13498
+ if (this.tileset.groups) {
13499
+ metadataContext.groups = this.tileset.groups;
13500
+ }
13501
+ this.metadataContext = metadataContext;
13502
+ }
13503
+ /** Updates payload and renderability while retaining immutable metadata descriptors. */
13504
+ _updateContentEntriesAfterLoad(loadResult) {
13505
+ if (loadResult.contentEntries) {
13506
+ this.contentEntries = loadResult.contentEntries.map((entry, index) => {
13507
+ var _a2;
13508
+ return {
13509
+ ...entry,
13510
+ index,
13511
+ boundingVolume: entry.boundingVolume || this._contentBoundingVolumes[index] || this.boundingVolume,
13512
+ payload: entry.payload ?? this.contents[index] ?? null,
13513
+ featureIds: ((_a2 = entry.featureIds) == null ? void 0 : _a2.length) ? entry.featureIds : getTile3DFeatureIdSets(entry.payload ?? this.contents[index]),
13514
+ renderable: Boolean(
13515
+ entry.renderable !== false && (entry.payload ?? this.contents[index]) && !isNestedTilesetPayload(entry.payload ?? this.contents[index])
13516
+ )
13517
+ };
13518
+ });
13519
+ this.featureIdSets = this.contentEntries.flatMap((entry) => entry.featureIds);
13520
+ return;
13521
+ }
13522
+ this.contentEntries = this.contentEntries.map((entry, index) => ({
13523
+ ...entry,
13524
+ payload: this.contents[index] ?? null,
13525
+ featureIds: getTile3DFeatureIdSets(this.contents[index]),
13526
+ renderable: Boolean(this.contents[index]) && !isNestedTilesetPayload(this.contents[index])
13527
+ }));
13528
+ this.featureIdSets = this.contentEntries.flatMap((entry) => entry.featureIds);
13529
+ }
13530
+ /** Returns one ordered content descriptor, or null when the index is out of range. */
13531
+ getContentEntry(index) {
13532
+ return this.contentEntries[index] || null;
13533
+ }
13534
+ /** Returns whether an ordered content entry currently has renderable payload. */
13535
+ isContentRenderable(index) {
13536
+ var _a2;
13537
+ return Boolean((_a2 = this.contentEntries[index]) == null ? void 0 : _a2.renderable);
13538
+ }
13539
+ /** Initializes additive renderer-neutral descriptors from a normalized tile header. */
13540
+ _initializeContentEntries(tileHeader) {
13541
+ const headers = Array.isArray(tileHeader.content) ? tileHeader.content : tileHeader.content ? [tileHeader.content] : [];
13542
+ this.contentEntries = headers.map((contentHeader, index) => {
13543
+ const normalizedContentHeader = contentHeader || {};
13544
+ return {
13545
+ index,
13546
+ uri: this.contentUrls[index] || normalizedContentHeader.uri || normalizedContentHeader.url,
13547
+ group: normalizedContentHeader.group,
13548
+ type: normalizedContentHeader.type,
13549
+ payload: null,
13550
+ metadata: normalizedContentHeader.metadata || null,
13551
+ boundingVolume: this._contentBoundingVolumes[index] || this.boundingVolume,
13552
+ featureIds: this._getFeatureIdSets(normalizedContentHeader),
13553
+ renderable: false
13554
+ };
13555
+ });
13556
+ }
13557
+ /** Extracts renderer-neutral feature-id declarations without decoding property values. */
13558
+ _getFeatureIdSets(contentHeader) {
13559
+ return getTile3DFeatureIdSets(contentHeader);
13138
13560
  }
13139
13561
  // Unloads the tile's content.
13140
13562
  unloadContent() {
@@ -13145,6 +13567,13 @@ var init_tile_3d = __esm({
13145
13567
  }
13146
13568
  this.contents = [];
13147
13569
  this.content = null;
13570
+ this.vectorContent = null;
13571
+ this.contentEntries = this.contentEntries.map((entry) => ({
13572
+ ...entry,
13573
+ payload: null,
13574
+ renderable: false
13575
+ }));
13576
+ this.featureIdSets = this.contentEntries.flatMap((entry) => entry.featureIds);
13148
13577
  if (this.header.content && this.header.content.destroy) {
13149
13578
  this.header.content.destroy();
13150
13579
  }
@@ -13254,9 +13683,10 @@ var init_tile_3d = __esm({
13254
13683
  * @param frameState Current camera, culling, and optional clipping-plane state.
13255
13684
  * @returns The content visibility classification.
13256
13685
  */
13257
- contentVisibility(frameState) {
13686
+ contentVisibility(frameState, contentIndex) {
13687
+ const contentVolumes = contentIndex === void 0 ? this._contentBoundingVolumes : this._contentBoundingVolumes[contentIndex] ? [this._contentBoundingVolumes[contentIndex]] : [];
13258
13688
  return getContentVisibility(
13259
- this._contentBoundingVolumes,
13689
+ contentVolumes,
13260
13690
  this.boundingVolume,
13261
13691
  frameState.cullingVolume,
13262
13692
  this._visibilityPlaneMask,
@@ -13308,6 +13738,8 @@ var init_tile_3d = __esm({
13308
13738
  // INTERNAL METHODS
13309
13739
  /** Initializes the tile's LOD metric from its header or its nearest available ancestor. */
13310
13740
  _initializeLodMetric(header) {
13741
+ var _a2;
13742
+ this._scaleGeometricError = typeof header._scaleGeometricError === "boolean" ? header._scaleGeometricError : ((_a2 = this.parent) == null ? void 0 : _a2._scaleGeometricError) ?? true;
13311
13743
  if ("lodMetricType" in header) {
13312
13744
  this.lodMetricType = header.lodMetricType;
13313
13745
  } else {
@@ -13345,7 +13777,7 @@ var init_tile_3d = __esm({
13345
13777
  * I3S `maxScreenThreshold` is already a screen-space metric and must not be transform-scaled.
13346
13778
  */
13347
13779
  _updateLodMetricScale() {
13348
- if (this.lodMetricType !== "geometricError" /* GEOMETRIC_ERROR */) {
13780
+ if (this.lodMetricType !== "geometricError" /* GEOMETRIC_ERROR */ || !this._scaleGeometricError) {
13349
13781
  this.lodMetricValue = this._unscaledLodMetricValue;
13350
13782
  return;
13351
13783
  }
@@ -13427,16 +13859,19 @@ var init_tile_3d = __esm({
13427
13859
  }
13428
13860
  }
13429
13861
  _updateBoundingVolume(header) {
13862
+ this._boundingBox = void 0;
13430
13863
  this.boundingVolume = createBoundingVolume(
13431
13864
  header.boundingVolume,
13432
13865
  this.computedTransform,
13433
- this.boundingVolume
13866
+ this.boundingVolume,
13867
+ this._initialTransform
13434
13868
  );
13435
13869
  if (header.viewerRequestVolume) {
13436
13870
  this._viewerRequestVolume = createBoundingVolume(
13437
13871
  header.viewerRequestVolume,
13438
13872
  this.computedTransform,
13439
- this._viewerRequestVolume
13873
+ this._viewerRequestVolume,
13874
+ this._initialTransform
13440
13875
  );
13441
13876
  }
13442
13877
  const content = header.content;
@@ -13445,7 +13880,12 @@ var init_tile_3d = __esm({
13445
13880
  }
13446
13881
  const contentHeaders = content ? Array.isArray(content) ? content : [content] : this._contentBoundingVolumeHeaders;
13447
13882
  this._contentBoundingVolumes = contentHeaders.length ? contentHeaders.map(
13448
- (headerEntry) => (headerEntry == null ? void 0 : headerEntry.boundingVolume) ? createBoundingVolume(headerEntry.boundingVolume, this.computedTransform) : this.boundingVolume
13883
+ (headerEntry) => (headerEntry == null ? void 0 : headerEntry.boundingVolume) ? createBoundingVolume(
13884
+ headerEntry.boundingVolume,
13885
+ this.computedTransform,
13886
+ void 0,
13887
+ this._initialTransform
13888
+ ) : this.boundingVolume
13449
13889
  ) : [this.boundingVolume];
13450
13890
  this._contentBoundingVolume = this._contentBoundingVolumes[0] || null;
13451
13891
  }
@@ -13586,7 +14026,7 @@ function getI3SSpatialReference(layer) {
13586
14026
  const verticalUnitScale = getI3SVerticalUnitScale(verticalUnit, layer.ZFactor);
13587
14027
  const heightReference = heightModel === "ellipsoidal" ? "ellipsoidal" : heightModel === "gravity_related_height" ? "orthometric" : "unknown";
13588
14028
  const sourceIdentifier = getCrsIdentifier(spatialReference);
13589
- const coordinateFrame = sourceIdentifier === void 0 ? getWktCoordinateFrame(spatialReference == null ? void 0 : spatialReference.wkt) : getIdentifierCoordinateFrame(sourceIdentifier);
14029
+ const coordinateFrame = sourceIdentifier === void 0 ? sourceCrs ? getSpatialCoordinateFrame(sourceCrs) : "unknown" : getSpatialCoordinateFrame(`EPSG:${sourceIdentifier}`);
13590
14030
  const units = getI3SCoordinateUnits(coordinateFrame, verticalUnit, layer.ZFactor);
13591
14031
  const warnings = [];
13592
14032
  const elevationMode = getI3SElevationMode((_e = layer.elevationInfo) == null ? void 0 : _e.mode);
@@ -13660,57 +14100,315 @@ function getI3SVerticalCrsDefinition(spatialReference) {
13660
14100
  function getCrsIdentifier(spatialReference) {
13661
14101
  return (spatialReference == null ? void 0 : spatialReference.latestWkid) ?? (spatialReference == null ? void 0 : spatialReference.wkid);
13662
14102
  }
13663
- function getIdentifierCoordinateFrame(identifier) {
13664
- if (identifier === 4978) {
13665
- return "geocentric";
13666
- }
13667
- if (identifier === 4326 || identifier === 4490 || identifier === 4979) {
13668
- return "geographic";
13669
- }
13670
- return "projected";
13671
- }
13672
- function getWktCoordinateFrame(wkt) {
13673
- var _a2;
13674
- if (!wkt) {
13675
- return "unknown";
13676
- }
13677
- const normalizedWkt = wkt.trim().toUpperCase();
13678
- const rootKeyword = (_a2 = normalizedWkt.match(/^([A-Z][A-Z0-9_]*)\s*[\[(]/)) == null ? void 0 : _a2[1];
13679
- if (rootKeyword === "GEOCCS") {
13680
- return "geocentric";
13681
- }
13682
- if (rootKeyword === "GEOGCS" || rootKeyword === "GEOGRAPHICCRS" || rootKeyword === "GEOGRAPHIC2DCRS" || rootKeyword === "GEOGRAPHIC3DCRS") {
13683
- return "geographic";
13684
- }
13685
- if (rootKeyword === "PROJCS" || rootKeyword === "PROJCRS" || rootKeyword === "PROJECTEDCRS") {
13686
- return "projected";
13687
- }
13688
- if (rootKeyword === "GEODCRS" || rootKeyword === "GEODETICCRS") {
13689
- if (/\bCS\s*[\[(]\s*CARTESIAN\s*,\s*3\b/.test(normalizedWkt)) {
13690
- return "geocentric";
13691
- }
13692
- if (/\bCS\s*[\[(]\s*ELLIPSOIDAL\s*,\s*[23]\b/.test(normalizedWkt)) {
13693
- return "geographic";
13694
- }
13695
- }
13696
- return "unknown";
13697
- }
13698
14103
  var init_format_spatial_reference = __esm({
13699
14104
  "../tiles/src/spatial/format-spatial-reference.ts"() {
13700
14105
  "use strict";
13701
14106
  init_i3s_elevation();
14107
+ init_get_spatial_coordinate_frame();
13702
14108
  init_spatial_types();
13703
14109
  }
13704
14110
  });
13705
14111
 
13706
- // ../tiles/src/tileset-3d/format-i3s/i3s-pending-tiles-register.ts
13707
- var I3SPendingTilesRegister;
13708
- var init_i3s_pending_tiles_register = __esm({
13709
- "../tiles/src/tileset-3d/format-i3s/i3s-pending-tiles-register.ts"() {
13710
- "use strict";
13711
- I3SPendingTilesRegister = class {
13712
- frameNumberMap = /* @__PURE__ */ new Map();
13713
- /**
14112
+ // ../tiles/src/spatial/spatial-resource-registry.ts
14113
+ function getGeoidModel(name) {
14114
+ return geoidModels.get(name);
14115
+ }
14116
+ var import_geoid, import_proj4, geoidModels;
14117
+ var init_spatial_resource_registry = __esm({
14118
+ "../tiles/src/spatial/spatial-resource-registry.ts"() {
14119
+ "use strict";
14120
+ import_geoid = require("@math.gl/geoid");
14121
+ import_proj4 = require("@math.gl/proj4");
14122
+ geoidModels = /* @__PURE__ */ new Map();
14123
+ }
14124
+ });
14125
+
14126
+ // ../tiles/src/spatial/spatial-coordinate-transformer.ts
14127
+ function getFiniteDifferenceJacobian(transformer, position, epsilon) {
14128
+ const columns = [];
14129
+ for (let axis = 0; axis < 3; axis++) {
14130
+ const plus = position.slice();
14131
+ const minus = position.slice();
14132
+ plus[axis] += epsilon;
14133
+ minus[axis] -= epsilon;
14134
+ const plusPosition = transformer.transformPosition(plus);
14135
+ const minusPosition = transformer.transformPosition(minus);
14136
+ columns.push([
14137
+ (plusPosition[0] - minusPosition[0]) / (2 * epsilon),
14138
+ (plusPosition[1] - minusPosition[1]) / (2 * epsilon),
14139
+ (plusPosition[2] - minusPosition[2]) / (2 * epsilon)
14140
+ ]);
14141
+ }
14142
+ return columns;
14143
+ }
14144
+ function inverseTransposeMultiply(jacobianColumns, vector) {
14145
+ const [a, b, c] = jacobianColumns;
14146
+ const determinant = a[0] * (b[1] * c[2] - b[2] * c[1]) - b[0] * (a[1] * c[2] - a[2] * c[1]) + c[0] * (a[1] * b[2] - a[2] * b[1]);
14147
+ if (!Number.isFinite(determinant) || Math.abs(determinant) < 1e-15) {
14148
+ return vector;
14149
+ }
14150
+ const inverseTranspose = [
14151
+ [b[1] * c[2] - b[2] * c[1], a[2] * c[1] - a[1] * c[2], a[1] * b[2] - a[2] * b[1]],
14152
+ [b[2] * c[0] - b[0] * c[2], a[0] * c[2] - a[2] * c[0], a[2] * b[0] - a[0] * b[2]],
14153
+ [b[0] * c[1] - b[1] * c[0], a[1] * c[0] - a[0] * c[1], a[0] * b[1] - a[1] * b[0]]
14154
+ ];
14155
+ return inverseTranspose.map(
14156
+ (row) => (row[0] * vector[0] + row[1] * vector[1] + row[2] * vector[2]) / determinant
14157
+ );
14158
+ }
14159
+ function getHorizontalProj4Definition(definition) {
14160
+ if (!definition) {
14161
+ throw new Error("Cannot construct a projection because the CRS is unknown");
14162
+ }
14163
+ return (0, import_proj42.toProj4CRSDefinition)(definition, { mode: "horizontal" });
14164
+ }
14165
+ function validateTransformRequest(spatialReference) {
14166
+ if (spatialReference.outputCoordinates === "local-enu") {
14167
+ throw new Error(
14168
+ "local-enu output requires a dataset-derived local origin and must be created by a tileset source"
14169
+ );
14170
+ }
14171
+ if (spatialReference.outputCoordinates === "target-crs" && !spatialReference.targetCrs) {
14172
+ throw new Error("target-crs output requires targetCrs");
14173
+ }
14174
+ if (!spatialReference.sourceCrs && spatialReference.status === "unresolved") {
14175
+ throw new Error("Cannot transform coordinates because the source CRS is unknown");
14176
+ }
14177
+ if (requiresHeightTransformation(spatialReference) && spatialReference.heightReference === "unknown") {
14178
+ throw new Error("Cannot convert heights because the source height reference is unknown");
14179
+ }
14180
+ if (spatialReference.coordinateFrame === "geocentric" && !isWgs84Geocentric(spatialReference.sourceCrs)) {
14181
+ throw new Error(
14182
+ "Only EPSG:4978 geocentric coordinates are supported by the current spatial transformer"
14183
+ );
14184
+ }
14185
+ if (spatialReference.status === "unresolved") {
14186
+ throw new Error("The requested spatial output cannot be resolved from the available metadata");
14187
+ }
14188
+ }
14189
+ function isWgs84Geocentric(definition) {
14190
+ return typeof definition === "string" && normalizeCrsIdentifier(definition) === WGS84_GEOCENTRIC_CRS;
14191
+ }
14192
+ function isWgs84Geographic(definition) {
14193
+ if (typeof definition !== "string") {
14194
+ return false;
14195
+ }
14196
+ const identifier = normalizeCrsIdentifier(definition);
14197
+ return identifier === WGS84_GEOGRAPHIC_CRS || identifier === "EPSG:4979" || identifier === "OGC:CRS84";
14198
+ }
14199
+ function requiresHeightTransformation(spatialReference) {
14200
+ const target = spatialReference.targetHeightReference;
14201
+ return target !== "native" && target !== spatialReference.heightReference;
14202
+ }
14203
+ function resolveGeoid(model) {
14204
+ return typeof model === "string" ? getGeoidModel(model) : model;
14205
+ }
14206
+ function transformHeight(height, geoidUndulation, source, target) {
14207
+ if (source === target || target === "native") {
14208
+ return height;
14209
+ }
14210
+ if (source === "orthometric" && target === "ellipsoidal") {
14211
+ return height + geoidUndulation;
14212
+ }
14213
+ if (source === "ellipsoidal" && target === "orthometric") {
14214
+ return height - geoidUndulation;
14215
+ }
14216
+ throw new Error(`Unsupported height conversion from ${source} to ${target}`);
14217
+ }
14218
+ var import_core7, import_geospatial4, import_proj42, SpatialCoordinateTransformer;
14219
+ var init_spatial_coordinate_transformer = __esm({
14220
+ "../tiles/src/spatial/spatial-coordinate-transformer.ts"() {
14221
+ "use strict";
14222
+ import_core7 = require("@math.gl/core");
14223
+ import_geospatial4 = require("@math.gl/geospatial");
14224
+ import_proj42 = require("@math.gl/proj4");
14225
+ init_spatial_resource_registry();
14226
+ init_normalize_crs_identifier();
14227
+ init_get_spatial_coordinate_frame();
14228
+ SpatialCoordinateTransformer = class {
14229
+ /** Normalized spatial metadata describing this transformation. */
14230
+ spatialReference;
14231
+ /** Projection from the source CRS directly to the requested horizontal target CRS. */
14232
+ horizontalProjection;
14233
+ /** Projection from the source CRS to geographic longitude, latitude, and ellipsoidal height. */
14234
+ geographicProjection;
14235
+ /** Projection from adjusted geographic coordinates to the requested output CRS. */
14236
+ heightOutputProjection;
14237
+ /** Whether source coordinates use the WGS84 geocentric frame handled by math.gl. */
14238
+ sourceIsGeocentric;
14239
+ /** Whether output coordinates use the WGS84 geocentric frame handled by math.gl. */
14240
+ outputIsGeocentric;
14241
+ /** Whether source coordinates already use conventional WGS84 longitude/latitude order. */
14242
+ sourceIsGeographic;
14243
+ /** Whether output coordinates use conventional WGS84 longitude/latitude order. */
14244
+ outputIsGeographic;
14245
+ /** Geoid model used to convert between ellipsoidal and orthometric heights. */
14246
+ geoid;
14247
+ /**
14248
+ * Creates a coordinate transformer.
14249
+ *
14250
+ * @param spatialReference - Format-discovered and option-normalized spatial metadata.
14251
+ * @param options - Application options containing an optional geoid model.
14252
+ */
14253
+ constructor(spatialReference, options = {}) {
14254
+ this.spatialReference = spatialReference;
14255
+ validateTransformRequest(spatialReference);
14256
+ const outputCrs = spatialReference.targetCrs || spatialReference.sourceCrs;
14257
+ this.sourceIsGeocentric = isWgs84Geocentric(spatialReference.sourceCrs);
14258
+ this.outputIsGeocentric = isWgs84Geocentric(outputCrs);
14259
+ this.sourceIsGeographic = isWgs84Geographic(spatialReference.sourceCrs);
14260
+ this.outputIsGeographic = isWgs84Geographic(outputCrs);
14261
+ if (spatialReference.sourceCrs && spatialReference.targetCrs && !this.sourceIsGeocentric && !this.outputIsGeocentric) {
14262
+ this.horizontalProjection = new import_proj42.Proj4Projection({
14263
+ from: getHorizontalProj4Definition(spatialReference.sourceCrs),
14264
+ to: getHorizontalProj4Definition(spatialReference.targetCrs),
14265
+ enforceAxis: false
14266
+ });
14267
+ }
14268
+ if (requiresHeightTransformation(spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
14269
+ if (!this.sourceIsGeographic && !this.sourceIsGeocentric) {
14270
+ this.geographicProjection = new import_proj42.Proj4Projection({
14271
+ from: getHorizontalProj4Definition(spatialReference.sourceCrs),
14272
+ to: WGS84_GEOGRAPHIC_CRS,
14273
+ enforceAxis: false
14274
+ });
14275
+ }
14276
+ if (!this.outputIsGeographic && !this.outputIsGeocentric) {
14277
+ this.heightOutputProjection = new import_proj42.Proj4Projection({
14278
+ from: WGS84_GEOGRAPHIC_CRS,
14279
+ to: getHorizontalProj4Definition(outputCrs),
14280
+ enforceAxis: false
14281
+ });
14282
+ }
14283
+ }
14284
+ if (requiresHeightTransformation(spatialReference)) {
14285
+ this.geoid = resolveGeoid(options.geoidModel);
14286
+ if (!this.geoid) {
14287
+ const modelName = typeof options.geoidModel === "string" ? ` "${options.geoidModel}"` : "";
14288
+ throw new Error(
14289
+ `Height conversion requires a registered geoid model${modelName}; call registerGeoidModel() or pass a parsed Geoid instance`
14290
+ );
14291
+ }
14292
+ }
14293
+ }
14294
+ /**
14295
+ * Transforms one `[x, y, z?]` coordinate while retaining additional components.
14296
+ *
14297
+ * @param coordinate - Source coordinate in the format adapter's normalized `x/y/z` order.
14298
+ * @returns A new transformed coordinate array.
14299
+ */
14300
+ transformPosition(coordinate) {
14301
+ if (coordinate.length < 2) {
14302
+ throw new Error("A spatial coordinate must contain at least x and y components");
14303
+ }
14304
+ const result = [...coordinate];
14305
+ if (requiresHeightTransformation(this.spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
14306
+ if (result.length < 3 || !Number.isFinite(result[2])) {
14307
+ throw new Error("Three-dimensional CRS conversion requires a finite z coordinate");
14308
+ }
14309
+ const geographic = this.toGeographic(result);
14310
+ if (requiresHeightTransformation(this.spatialReference)) {
14311
+ const geoidUndulation = this.geoid.getHeight(geographic[1], geographic[0]);
14312
+ geographic[2] = transformHeight(
14313
+ geographic[2],
14314
+ geoidUndulation,
14315
+ this.spatialReference.heightReference,
14316
+ this.spatialReference.targetHeightReference
14317
+ );
14318
+ }
14319
+ const projected = this.fromGeographic(geographic);
14320
+ result.splice(0, projected.length, ...projected);
14321
+ return result;
14322
+ }
14323
+ if (this.horizontalProjection) {
14324
+ const projected = this.horizontalProjection.project(result.slice(0, 3));
14325
+ result.splice(0, projected.length, ...projected);
14326
+ }
14327
+ return result;
14328
+ }
14329
+ /** Transform a packed sequence of xyz positions, preserving the input array type only when safe. */
14330
+ transformPositions(positions) {
14331
+ if (positions.length % 3 !== 0) {
14332
+ throw new Error("Packed spatial positions must contain a multiple of three components");
14333
+ }
14334
+ const transformedPositions = new Float64Array(positions.length);
14335
+ for (let index = 0; index < positions.length; index += 3) {
14336
+ const transformed = this.transformPosition([
14337
+ Number(positions[index]),
14338
+ Number(positions[index + 1]),
14339
+ Number(positions[index + 2])
14340
+ ]);
14341
+ transformedPositions[index] = transformed[0];
14342
+ transformedPositions[index + 1] = transformed[1];
14343
+ transformedPositions[index + 2] = transformed[2];
14344
+ }
14345
+ return transformedPositions;
14346
+ }
14347
+ /** Transform packed xyz normals using a local finite-difference tangent approximation. */
14348
+ transformNormals(normals, positions) {
14349
+ if (normals.length !== positions.length || normals.length % 3 !== 0) {
14350
+ throw new Error("Spatial normals and positions must have matching xyz component counts");
14351
+ }
14352
+ const transformedNormals = new Float32Array(normals.length);
14353
+ const epsilon = 1e-5;
14354
+ for (let index = 0; index < normals.length; index += 3) {
14355
+ const position = [
14356
+ Number(positions[index]),
14357
+ Number(positions[index + 1]),
14358
+ Number(positions[index + 2])
14359
+ ];
14360
+ const normal = [
14361
+ Number(normals[index]),
14362
+ Number(normals[index + 1]),
14363
+ Number(normals[index + 2])
14364
+ ];
14365
+ const jacobian = getFiniteDifferenceJacobian(this, position, epsilon);
14366
+ const transformedNormal = inverseTransposeMultiply(jacobian, normal);
14367
+ const length = Math.hypot(...transformedNormal);
14368
+ if (length > 0 && Number.isFinite(length)) {
14369
+ transformedNormals[index] = transformedNormal[0] / length;
14370
+ transformedNormals[index + 1] = transformedNormal[1] / length;
14371
+ transformedNormals[index + 2] = transformedNormal[2] / length;
14372
+ } else {
14373
+ transformedNormals[index] = normal[0];
14374
+ transformedNormals[index + 1] = normal[1];
14375
+ transformedNormals[index + 2] = normal[2];
14376
+ }
14377
+ }
14378
+ return transformedNormals;
14379
+ }
14380
+ /** Convert one source coordinate to conventional WGS84 longitude, latitude, and height. */
14381
+ toGeographic(coordinate) {
14382
+ if (this.sourceIsGeocentric) {
14383
+ return Array.from(import_geospatial4.Ellipsoid.WGS84.cartesianToCartographic(new import_core7.Vector3(coordinate)));
14384
+ }
14385
+ if (this.sourceIsGeographic) {
14386
+ return coordinate.slice(0, 3);
14387
+ }
14388
+ return this.geographicProjection.project(coordinate.slice(0, 3));
14389
+ }
14390
+ /** Convert one conventional WGS84 geographic coordinate to the selected output CRS. */
14391
+ fromGeographic(coordinate) {
14392
+ if (this.outputIsGeocentric) {
14393
+ return Array.from(import_geospatial4.Ellipsoid.WGS84.cartographicToCartesian(new import_core7.Vector3(coordinate)));
14394
+ }
14395
+ if (this.outputIsGeographic) {
14396
+ return coordinate.slice(0, 3);
14397
+ }
14398
+ return this.heightOutputProjection.project(coordinate.slice(0, 3));
14399
+ }
14400
+ };
14401
+ }
14402
+ });
14403
+
14404
+ // ../tiles/src/tileset-3d/format-i3s/i3s-pending-tiles-register.ts
14405
+ var I3SPendingTilesRegister;
14406
+ var init_i3s_pending_tiles_register = __esm({
14407
+ "../tiles/src/tileset-3d/format-i3s/i3s-pending-tiles-register.ts"() {
14408
+ "use strict";
14409
+ I3SPendingTilesRegister = class {
14410
+ frameNumberMap = /* @__PURE__ */ new Map();
14411
+ /**
13714
14412
  * Register a new pending tile header for the particular frameNumber
13715
14413
  * @param viewportId
13716
14414
  * @param frameNumber
@@ -13924,223 +14622,6 @@ var init_i3s_tileset_traverser = __esm({
13924
14622
  }
13925
14623
  });
13926
14624
 
13927
- // ../tiles/src/spatial/spatial-resource-registry.ts
13928
- function getGeoidModel(name) {
13929
- return geoidModels.get(name);
13930
- }
13931
- var import_geoid, import_proj4, geoidModels;
13932
- var init_spatial_resource_registry = __esm({
13933
- "../tiles/src/spatial/spatial-resource-registry.ts"() {
13934
- "use strict";
13935
- import_geoid = require("@math.gl/geoid");
13936
- import_proj4 = require("@math.gl/proj4");
13937
- geoidModels = /* @__PURE__ */ new Map();
13938
- }
13939
- });
13940
-
13941
- // ../tiles/src/spatial/spatial-coordinate-transformer.ts
13942
- function getHorizontalProj4Definition(definition) {
13943
- if (!definition) {
13944
- throw new Error("Cannot construct a projection because the CRS is unknown");
13945
- }
13946
- return (0, import_proj42.toProj4CRSDefinition)(definition, { mode: "horizontal" });
13947
- }
13948
- function validateTransformRequest(spatialReference) {
13949
- if (spatialReference.outputCoordinates === "local-enu") {
13950
- throw new Error(
13951
- "local-enu output requires a dataset-derived local origin and must be created by a tileset source"
13952
- );
13953
- }
13954
- if (spatialReference.outputCoordinates === "target-crs" && !spatialReference.targetCrs) {
13955
- throw new Error("target-crs output requires targetCrs");
13956
- }
13957
- if (!spatialReference.sourceCrs && spatialReference.status === "unresolved") {
13958
- throw new Error("Cannot transform coordinates because the source CRS is unknown");
13959
- }
13960
- if (requiresHeightTransformation(spatialReference) && spatialReference.heightReference === "unknown") {
13961
- throw new Error("Cannot convert heights because the source height reference is unknown");
13962
- }
13963
- if (spatialReference.coordinateFrame === "geocentric" && !isWgs84Geocentric(spatialReference.sourceCrs)) {
13964
- throw new Error(
13965
- "Only EPSG:4978 geocentric coordinates are supported by the current spatial transformer"
13966
- );
13967
- }
13968
- if (spatialReference.status === "unresolved") {
13969
- throw new Error("The requested spatial output cannot be resolved from the available metadata");
13970
- }
13971
- }
13972
- function isWgs84Geocentric(definition) {
13973
- return typeof definition === "string" && normalizeCrsIdentifier2(definition) === GEOCENTRIC_CRS2;
13974
- }
13975
- function isWgs84Geographic(definition) {
13976
- if (typeof definition !== "string") {
13977
- return false;
13978
- }
13979
- const identifier = normalizeCrsIdentifier2(definition);
13980
- return identifier === GEOGRAPHIC_CRS2 || identifier === "EPSG:4979" || identifier === "OGC:CRS84";
13981
- }
13982
- function normalizeCrsIdentifier2(identifier) {
13983
- const normalizedIdentifier = identifier.trim().toUpperCase();
13984
- const ogcMatch = normalizedIdentifier.match(
13985
- /(?:\/DEF\/CRS\/|URN:OGC:DEF:CRS:)([A-Z0-9_-]+)(?:\/|::)(?:[^/:]*[/:])?([A-Z0-9_.-]+)$/
13986
- );
13987
- return ogcMatch ? `${ogcMatch[1]}:${ogcMatch[2]}` : normalizedIdentifier;
13988
- }
13989
- function requiresHeightTransformation(spatialReference) {
13990
- const target = spatialReference.targetHeightReference;
13991
- return target !== "native" && target !== spatialReference.heightReference;
13992
- }
13993
- function resolveGeoid(model) {
13994
- return typeof model === "string" ? getGeoidModel(model) : model;
13995
- }
13996
- function transformHeight(height, geoidUndulation, source, target) {
13997
- if (source === target || target === "native") {
13998
- return height;
13999
- }
14000
- if (source === "orthometric" && target === "ellipsoidal") {
14001
- return height + geoidUndulation;
14002
- }
14003
- if (source === "ellipsoidal" && target === "orthometric") {
14004
- return height - geoidUndulation;
14005
- }
14006
- throw new Error(`Unsupported height conversion from ${source} to ${target}`);
14007
- }
14008
- var import_core7, import_geospatial4, import_proj42, GEOGRAPHIC_CRS2, GEOCENTRIC_CRS2, SpatialCoordinateTransformer;
14009
- var init_spatial_coordinate_transformer = __esm({
14010
- "../tiles/src/spatial/spatial-coordinate-transformer.ts"() {
14011
- "use strict";
14012
- import_core7 = require("@math.gl/core");
14013
- import_geospatial4 = require("@math.gl/geospatial");
14014
- import_proj42 = require("@math.gl/proj4");
14015
- init_spatial_resource_registry();
14016
- init_get_spatial_coordinate_frame();
14017
- GEOGRAPHIC_CRS2 = "EPSG:4326";
14018
- GEOCENTRIC_CRS2 = "EPSG:4978";
14019
- SpatialCoordinateTransformer = class {
14020
- /** Normalized spatial metadata describing this transformation. */
14021
- spatialReference;
14022
- /** Projection from the source CRS directly to the requested horizontal target CRS. */
14023
- horizontalProjection;
14024
- /** Projection from the source CRS to geographic longitude, latitude, and ellipsoidal height. */
14025
- geographicProjection;
14026
- /** Projection from adjusted geographic coordinates to the requested output CRS. */
14027
- heightOutputProjection;
14028
- /** Whether source coordinates use the WGS84 geocentric frame handled by math.gl. */
14029
- sourceIsGeocentric;
14030
- /** Whether output coordinates use the WGS84 geocentric frame handled by math.gl. */
14031
- outputIsGeocentric;
14032
- /** Whether source coordinates already use conventional WGS84 longitude/latitude order. */
14033
- sourceIsGeographic;
14034
- /** Whether output coordinates use conventional WGS84 longitude/latitude order. */
14035
- outputIsGeographic;
14036
- /** Geoid model used to convert between ellipsoidal and orthometric heights. */
14037
- geoid;
14038
- /**
14039
- * Creates a coordinate transformer.
14040
- *
14041
- * @param spatialReference - Format-discovered and option-normalized spatial metadata.
14042
- * @param options - Application options containing an optional geoid model.
14043
- */
14044
- constructor(spatialReference, options = {}) {
14045
- this.spatialReference = spatialReference;
14046
- validateTransformRequest(spatialReference);
14047
- const outputCrs = spatialReference.targetCrs || spatialReference.sourceCrs;
14048
- this.sourceIsGeocentric = isWgs84Geocentric(spatialReference.sourceCrs);
14049
- this.outputIsGeocentric = isWgs84Geocentric(outputCrs);
14050
- this.sourceIsGeographic = isWgs84Geographic(spatialReference.sourceCrs);
14051
- this.outputIsGeographic = isWgs84Geographic(outputCrs);
14052
- if (spatialReference.sourceCrs && spatialReference.targetCrs && !this.sourceIsGeocentric && !this.outputIsGeocentric) {
14053
- this.horizontalProjection = new import_proj42.Proj4Projection({
14054
- from: getHorizontalProj4Definition(spatialReference.sourceCrs),
14055
- to: getHorizontalProj4Definition(spatialReference.targetCrs),
14056
- enforceAxis: false
14057
- });
14058
- }
14059
- if (requiresHeightTransformation(spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
14060
- if (!this.sourceIsGeographic && !this.sourceIsGeocentric) {
14061
- this.geographicProjection = new import_proj42.Proj4Projection({
14062
- from: getHorizontalProj4Definition(spatialReference.sourceCrs),
14063
- to: GEOGRAPHIC_CRS2,
14064
- enforceAxis: false
14065
- });
14066
- }
14067
- if (!this.outputIsGeographic && !this.outputIsGeocentric) {
14068
- this.heightOutputProjection = new import_proj42.Proj4Projection({
14069
- from: GEOGRAPHIC_CRS2,
14070
- to: getHorizontalProj4Definition(outputCrs),
14071
- enforceAxis: false
14072
- });
14073
- }
14074
- }
14075
- if (requiresHeightTransformation(spatialReference)) {
14076
- this.geoid = resolveGeoid(options.geoidModel);
14077
- if (!this.geoid) {
14078
- const modelName = typeof options.geoidModel === "string" ? ` "${options.geoidModel}"` : "";
14079
- throw new Error(
14080
- `Height conversion requires a registered geoid model${modelName}; call registerGeoidModel() or pass a parsed Geoid instance`
14081
- );
14082
- }
14083
- }
14084
- }
14085
- /**
14086
- * Transforms one `[x, y, z?]` coordinate while retaining additional components.
14087
- *
14088
- * @param coordinate - Source coordinate in the format adapter's normalized `x/y/z` order.
14089
- * @returns A new transformed coordinate array.
14090
- */
14091
- transformPosition(coordinate) {
14092
- if (coordinate.length < 2) {
14093
- throw new Error("A spatial coordinate must contain at least x and y components");
14094
- }
14095
- const result = [...coordinate];
14096
- if (requiresHeightTransformation(this.spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
14097
- if (result.length < 3 || !Number.isFinite(result[2])) {
14098
- throw new Error("Three-dimensional CRS conversion requires a finite z coordinate");
14099
- }
14100
- const geographic = this.toGeographic(result);
14101
- if (requiresHeightTransformation(this.spatialReference)) {
14102
- const geoidUndulation = this.geoid.getHeight(geographic[1], geographic[0]);
14103
- geographic[2] = transformHeight(
14104
- geographic[2],
14105
- geoidUndulation,
14106
- this.spatialReference.heightReference,
14107
- this.spatialReference.targetHeightReference
14108
- );
14109
- }
14110
- const projected = this.fromGeographic(geographic);
14111
- result.splice(0, projected.length, ...projected);
14112
- return result;
14113
- }
14114
- if (this.horizontalProjection) {
14115
- const projected = this.horizontalProjection.project(result.slice(0, 3));
14116
- result.splice(0, projected.length, ...projected);
14117
- }
14118
- return result;
14119
- }
14120
- /** Convert one source coordinate to conventional WGS84 longitude, latitude, and height. */
14121
- toGeographic(coordinate) {
14122
- if (this.sourceIsGeocentric) {
14123
- return Array.from(import_geospatial4.Ellipsoid.WGS84.cartesianToCartographic(new import_core7.Vector3(coordinate)));
14124
- }
14125
- if (this.sourceIsGeographic) {
14126
- return coordinate.slice(0, 3);
14127
- }
14128
- return this.geographicProjection.project(coordinate.slice(0, 3));
14129
- }
14130
- /** Convert one conventional WGS84 geographic coordinate to the selected output CRS. */
14131
- fromGeographic(coordinate) {
14132
- if (this.outputIsGeocentric) {
14133
- return Array.from(import_geospatial4.Ellipsoid.WGS84.cartographicToCartesian(new import_core7.Vector3(coordinate)));
14134
- }
14135
- if (this.outputIsGeographic) {
14136
- return coordinate.slice(0, 3);
14137
- }
14138
- return this.heightOutputProjection.project(coordinate.slice(0, 3));
14139
- }
14140
- };
14141
- }
14142
- });
14143
-
14144
14625
  // ../tiles/src/spatial/i3s-spatial-transformer.ts
14145
14626
  function getElevationProvider(mode, options) {
14146
14627
  return mode === "relativeToScene" ? options.sceneElevationProvider : requiresElevationSurface(mode) ? options.terrainElevationProvider : void 0;
@@ -15449,7 +15930,7 @@ async function loadI3STexture(textureUrl, textureFormat, tileOptions, options, c
15449
15930
  };
15450
15931
  }
15451
15932
  async function parseI3SNodeGeometry(arrayBuffer, content, tileOptions, tilesetOptions, options, context) {
15452
- var _a2, _b, _c, _d, _e;
15933
+ var _a2, _b, _c, _d, _e, _f;
15453
15934
  const contentByteLength = arrayBuffer.byteLength;
15454
15935
  let attributes;
15455
15936
  let vertexCount;
@@ -15463,6 +15944,8 @@ async function parseI3SNodeGeometry(arrayBuffer, content, tileOptions, tilesetOp
15463
15944
  DracoLoader,
15464
15945
  {
15465
15946
  draco: {
15947
+ // I3S geometry processing consumes the legacy mesh contract.
15948
+ shape: "mesh",
15466
15949
  attributeNameEntry: I3S_ATTRIBUTE_TYPE
15467
15950
  }
15468
15951
  },
@@ -15572,8 +16055,7 @@ async function parseI3SNodeGeometry(arrayBuffer, content, tileOptions, tilesetOp
15572
16055
  content.attributes = {
15573
16056
  positions: attributes.position,
15574
16057
  normals: attributes.normal,
15575
- colors: normalizeAttribute(attributes.color),
15576
- // Normalize from UInt8
16058
+ colors: normalizeAttribute(attributes.color, ((_f = options == null ? void 0 : options.i3s) == null ? void 0 : _f.colorFormat) || "uint8norm"),
15577
16059
  uvRegions: normalizeAttribute(attributes.uvRegion || attributes.region)
15578
16060
  // Normalize from UInt16
15579
16061
  };
@@ -15684,12 +16166,26 @@ function updateAttributesMetadata(attributes, decompressedGeometry) {
15684
16166
  function concatAttributes(normalizedVertexAttributes, normalizedFeatureAttributes) {
15685
16167
  return { ...normalizedVertexAttributes, ...normalizedFeatureAttributes };
15686
16168
  }
15687
- function normalizeAttribute(attribute) {
16169
+ function normalizeAttribute(attribute, colorFormat = "uint8norm") {
15688
16170
  if (!attribute) {
15689
16171
  return attribute;
15690
16172
  }
15691
- attribute.normalized = true;
15692
- return attribute;
16173
+ if (colorFormat === "float16" && !attribute.componentType) {
16174
+ return {
16175
+ ...attribute,
16176
+ value: convertColorArrayToFloat16(attribute.value, 255),
16177
+ normalized: false,
16178
+ componentType: "float16"
16179
+ };
16180
+ }
16181
+ if (colorFormat === "float32" && !attribute.componentType) {
16182
+ return {
16183
+ ...attribute,
16184
+ value: Float32Array.from(attribute.value, (value) => value / 255),
16185
+ normalized: false
16186
+ };
16187
+ }
16188
+ return { ...attribute, normalized: true };
15693
16189
  }
15694
16190
  function parseHeaders(arrayBuffer, geometrySchema) {
15695
16191
  let byteOffset = 0;
@@ -15965,6 +16461,7 @@ var import_core10, import_geospatial7, scratchVector3, I3S_ATTRIBUTE_TYPE;
15965
16461
  var init_parse_i3s_tile_content = __esm({
15966
16462
  "../i3s/src/lib/parsers/parse-i3s-tile-content.ts"() {
15967
16463
  "use strict";
16464
+ init_src();
15968
16465
  import_core10 = require("@math.gl/core");
15969
16466
  import_geospatial7 = require("@math.gl/geospatial");
15970
16467
  init_src5();
@@ -21827,13 +22324,14 @@ var ArcGISVectorSource = class extends DataSource {
21827
22324
  getFeaturesURL(parameters) {
21828
22325
  var _a2;
21829
22326
  const defaultParameters = ((_a2 = this.options["arcgis-feature-server"]) == null ? void 0 : _a2.queryParameters) || {};
21830
- const spatialReference = normalizeArcGISSpatialReference(parameters.crs) || 4326;
22327
+ const outputSpatialReference = normalizeArcGISSpatialReference(parameters.crs) || 4326;
22328
+ const requestSpatialReference = normalizeArcGISSpatialReference(parameters.requestCrs) || outputSpatialReference;
21831
22329
  const queryParameters = {
21832
22330
  returnGeometry: true,
21833
22331
  where: "1=1",
21834
22332
  outFields: "*",
21835
- outSR: spatialReference,
21836
- inSR: spatialReference,
22333
+ outSR: outputSpatialReference,
22334
+ inSR: requestSpatialReference,
21837
22335
  f: "geojson",
21838
22336
  ...defaultParameters
21839
22337
  };
@@ -21992,10 +22490,10 @@ var ArcGISImageSource = class extends DataSource {
21992
22490
  }
21993
22491
  /** Requests an image from generic ImageSource parameters. */
21994
22492
  async getImage(parameters) {
21995
- const { boundingBox, bbox, width, height, crs, format, signal } = parameters;
22493
+ const { boundingBox, width, height, crs, format, signal } = parameters;
21996
22494
  const spatialReference = normalizeArcGISSpatialReference2(crs) || "4326";
21997
22495
  const imageParameters = {
21998
- bbox: boundingBox ? [...boundingBox[0], ...boundingBox[1]] : bbox,
22496
+ bbox: [...boundingBox[0], ...boundingBox[1]],
21999
22497
  bboxSR: spatialReference,
22000
22498
  imageSR: spatialReference,
22001
22499
  width,
@@ -22573,6 +23071,7 @@ init_src5();
22573
23071
  // ../i3s/src/i3s-point-cloud-source.ts
22574
23072
  init_src5();
22575
23073
  init_src2();
23074
+ init_src();
22576
23075
  var import_core12 = require("@math.gl/core");
22577
23076
  var import_geospatial9 = require("@math.gl/geospatial");
22578
23077
  init_src9();
@@ -22717,6 +23216,7 @@ var I3SPointCloudSource = class extends DataSource {
22717
23216
  const descriptors = this.getAttributeDescriptors();
22718
23217
  await Promise.all(
22719
23218
  descriptors.map(async (descriptor) => {
23219
+ var _a3, _b2;
22720
23220
  const bytes = await this.readBinaryOptional(
22721
23221
  this.resourceCandidates(
22722
23222
  `nodes/${resourceId}/attributes/${descriptor.key || descriptor.name || ""}/${descriptor.resource ?? 0}`,
@@ -22733,10 +23233,16 @@ var I3SPointCloudSource = class extends DataSource {
22733
23233
  );
22734
23234
  }
22735
23235
  const attributeName = this.getAttributeName(descriptor, decoded.kind);
22736
- attributes[attributeName] = {
22737
- value: decoded.value,
22738
- size: decoded.size
22739
- };
23236
+ attributes[attributeName] = attributeName === "COLOR_0" && ((_a3 = this.options.i3s) == null ? void 0 : _a3.colorFormat) === "float16" ? {
23237
+ value: convertColorArrayToFloat16(decoded.value, 255),
23238
+ size: decoded.size,
23239
+ normalized: false,
23240
+ componentType: "float16"
23241
+ } : attributeName === "COLOR_0" && ((_b2 = this.options.i3s) == null ? void 0 : _b2.colorFormat) === "float32" ? {
23242
+ value: Float32Array.from(decoded.value, (value) => value / 255),
23243
+ size: decoded.size,
23244
+ normalized: false
23245
+ } : { value: decoded.value, size: decoded.size };
22740
23246
  })
22741
23247
  );
22742
23248
  const volume = tile.spatialBoundingVolume || tile.boundingVolume;