@loaders.gl/tile-converter 4.5.3 → 5.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +14 -3
- package/README.md +464 -0
- package/dist/converter.min.cjs +199 -260
- package/dist/i3s-server/bin/i3s-server.min.cjs +106 -341
- package/dist/index.cjs +38482 -0
- package/dist/index.js +38453 -0
- package/dist/v5/adapters.cjs +1992 -0
- package/dist/v5/adapters.d.ts +22 -0
- package/dist/v5/adapters.js +1972 -0
- package/dist/v5/browser-sink.d.ts +37 -0
- package/dist/v5/browser-source.d.ts +38 -0
- package/dist/v5/browser-tileset-source.d.ts +70 -0
- package/dist/v5/browser.cjs +64 -0
- package/dist/v5/browser.d.ts +34 -0
- package/dist/v5/browser.js +57 -0
- package/dist/v5/conversion-api.d.ts +122 -0
- package/dist/v5/conversion-archive.d.ts +32 -0
- package/dist/v5/core.cjs +863 -0
- package/dist/v5/core.d.ts +16 -0
- package/dist/v5/core.js +845 -0
- package/dist/v5/feature-arrow.d.ts +36 -0
- package/dist/v5/i3s-mesh-conversion.d.ts +26 -0
- package/dist/v5/index.cjs +63 -0
- package/dist/v5/index.d.ts +32 -0
- package/dist/v5/index.js +59 -0
- package/dist/v5/mesh-conversion.d.ts +62 -0
- package/dist/v5/mesh-draco.d.ts +8 -0
- package/dist/v5/mesh-source-features.d.ts +21 -0
- package/dist/v5/mesh-source-texture.d.ts +4 -0
- package/dist/v5/mesh-source.d.ts +34 -0
- package/dist/v5/mesh-tileset-archive.d.ts +18 -0
- package/dist/v5/mesh-tileset-sink.d.ts +51 -0
- package/dist/v5/mesh.d.ts +81 -0
- package/dist/v5/point-cloud-conversion.d.ts +31 -0
- package/dist/v5/point-cloud-source-encoder.d.ts +49 -0
- package/dist/v5/point-cloud-source.d.ts +25 -0
- package/dist/v5/point-cloud.d.ts +24 -0
- package/dist/v5/resource-manifest.d.ts +58 -0
- package/dist/v5/spatial-conversion.d.ts +59 -0
- package/dist/v5/tileset-source.d.ts +21 -0
- package/package.json +53 -27
- package/src/common/README.md +5 -0
- package/src/index.ts +1 -2
- package/src/{3d-tiles-converter → v4/3d-tiles-converter}/3d-tiles-converter.ts +14 -3
- package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/3d-tiles-content-converter.ts +2 -2
- package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +124 -0
- package/src/{3d-tiles-converter → v4/3d-tiles-converter}/json-templates/tileset.ts +4 -4
- package/src/{converter-cli.ts → v4/converter-cli.ts} +4 -4
- package/src/{deps-installer → v4/deps-installer}/deps-installer.ts +10 -7
- package/src/{i3s-converter → v4/i3s-converter}/helpers/attribute-metadata-info.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/helpers/batch-ids-extensions.ts +1 -1
- package/src/v4/i3s-converter/helpers/encode-string-attribute.ts +23 -0
- package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-attributes.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-converter.ts +34 -59
- package/src/{i3s-converter → v4/i3s-converter}/helpers/gltf-attributes.ts +7 -6
- package/src/{i3s-converter → v4/i3s-converter}/helpers/load-3d-tiles.ts +5 -9
- package/src/{i3s-converter → v4/i3s-converter}/helpers/node-debug.ts +5 -6
- package/src/{i3s-converter → v4/i3s-converter}/i3s-converter.ts +16 -19
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/geometry-definitions.ts +4 -4
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/layers.ts +6 -6
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/node.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/scene-server.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/shared-resources.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/store.ts +1 -1
- package/src/{i3s-server → v4/i3s-server}/README.md +2 -2
- package/src/{i3s-server → v4/i3s-server}/controllers/slpk-controller.ts +1 -1
- package/src/{i3s-server → v4/i3s-server}/routes/slpk-router.ts +2 -1
- package/src/v4/index.ts +2 -0
- package/src/{lib → v4/lib}/utils/compress-util.ts +8 -7
- package/src/{lib → v4/lib}/utils/conversion-dump.ts +4 -4
- package/src/{lib → v4/lib}/utils/file-utils.ts +2 -2
- package/src/{lib → v4/lib}/utils/lod-conversion-utils.ts +2 -4
- package/src/v5/adapters.ts +56 -0
- package/src/v5/browser-sink.ts +130 -0
- package/src/v5/browser-source.ts +155 -0
- package/src/v5/browser-tileset-source.ts +328 -0
- package/src/v5/browser.ts +105 -0
- package/src/v5/conversion-api.ts +287 -0
- package/src/v5/conversion-archive.ts +85 -0
- package/src/v5/core.ts +61 -0
- package/src/v5/feature-arrow.ts +429 -0
- package/src/v5/i3s-mesh-conversion.ts +152 -0
- package/src/v5/index.ts +99 -0
- package/src/v5/mesh-conversion.ts +200 -0
- package/src/v5/mesh-draco.ts +138 -0
- package/src/v5/mesh-source-features.ts +232 -0
- package/src/v5/mesh-source-texture.ts +122 -0
- package/src/v5/mesh-source.ts +360 -0
- package/src/v5/mesh-tileset-archive.ts +50 -0
- package/src/v5/mesh-tileset-sink.ts +324 -0
- package/src/v5/mesh.ts +517 -0
- package/src/v5/point-cloud-conversion.ts +80 -0
- package/src/v5/point-cloud-source-encoder.ts +105 -0
- package/src/v5/point-cloud-source.ts +84 -0
- package/src/v5/point-cloud.ts +271 -0
- package/src/v5/resource-manifest.ts +213 -0
- package/src/v5/spatial-conversion.ts +305 -0
- package/src/v5/tileset-source.ts +54 -0
- /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/i3s-obb-to-3d-tiles-obb.ts +0 -0
- /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/load-i3s.ts +0 -0
- /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/texture-atlas.ts +0 -0
- /package/src/{constants.ts → v4/constants.ts} +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/coordinate-converter.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/create-scene-server-path.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/feature-attributes.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-index-document.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-pages.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/preprocess-3d-tiles.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/progress.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/tileset-traversal.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/json-templates/metadata.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/types.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/app.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/bin/www.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/certs/cert.pem +0 -0
- /package/src/{i3s-server → v4/i3s-server}/certs/key.pem +0 -0
- /package/src/{i3s-server → v4/i3s-server}/utils/create-scene-server.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/utils/server-utils.ts +0 -0
- /package/src/{lib → v4/lib}/json-schemas/conversion-dump-json-schema.ts +0 -0
- /package/src/{lib → v4/lib}/utils/cli-utils.ts +0 -0
- /package/src/{lib → v4/lib}/utils/geometry-utils.ts +0 -0
- /package/src/{lib → v4/lib}/utils/queue.ts +0 -0
- /package/src/{lib → v4/lib}/utils/statistic-utils.ts +0 -0
- /package/src/{lib → v4/lib}/utils/write-queue.ts +0 -0
- /package/src/{pgm-loader.ts → v4/pgm-loader.ts} +0 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {ArrowTableBuilder} from '@loaders.gl/schema-utils';
|
|
6
|
+
import type {ArrowTableBatch, DataType, Field, Schema} from '@loaders.gl/schema';
|
|
7
|
+
import {TileConversionError} from '@loaders.gl/tile-converter/v5/core';
|
|
8
|
+
|
|
9
|
+
const DEFAULT_FEATURE_ID_FIELD = 'feature_id';
|
|
10
|
+
const FEATURE_CLASS_METADATA_KEY = 'loaders.gl:feature-class';
|
|
11
|
+
|
|
12
|
+
/** Feature attributes and source identifier ready for Arrow normalization. */
|
|
13
|
+
export interface TileFeatureAttributes {
|
|
14
|
+
/** Stable feature identifier decoded from the source's feature-ID descriptor. */
|
|
15
|
+
readonly featureId: string | number | bigint;
|
|
16
|
+
/** Property values interpreted from the source metadata class. */
|
|
17
|
+
readonly properties: Readonly<Record<string, unknown>>;
|
|
18
|
+
/** Original class or property-table name, kept distinct between output batches. */
|
|
19
|
+
readonly metadataClass: string;
|
|
20
|
+
/** Optional original encoded metadata bytes, preserved without interpretation. */
|
|
21
|
+
readonly rawMetadata?: Uint8Array;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Explicit Arrow mapping and bounded output size for feature attribute batches. */
|
|
25
|
+
export interface FeatureArrowBatchOptions {
|
|
26
|
+
/** Declared output columns and types, including the feature-ID column. */
|
|
27
|
+
readonly schema: Schema;
|
|
28
|
+
/** Schema field receiving stable feature identifiers. Defaults to `feature_id`. */
|
|
29
|
+
readonly featureIdField?: string;
|
|
30
|
+
/** Optional binary field receiving source metadata bytes. */
|
|
31
|
+
readonly rawMetadataField?: string;
|
|
32
|
+
/** Maximum number of features in one emitted Arrow record batch. Defaults to 65,536. */
|
|
33
|
+
readonly batchSize?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Converts decoded feature attributes to bounded Arrow batches using a caller-declared schema.
|
|
38
|
+
*
|
|
39
|
+
* Values retain their source primitive types; nested lists, structs, dictionary enums, and 64-bit
|
|
40
|
+
* identifiers use the corresponding schema field type. Missing schema fields and incompatible
|
|
41
|
+
* identifiers fail explicitly. Unknown properties are rejected so a class mapping cannot silently
|
|
42
|
+
* discard data. Separate metadata classes should be passed separately with their own schema.
|
|
43
|
+
*
|
|
44
|
+
* @param features - Features decoded from one source metadata class.
|
|
45
|
+
* @param options - Explicit Arrow schema and batch configuration.
|
|
46
|
+
* @returns Arrow table batches whose schema metadata records the source metadata class.
|
|
47
|
+
*/
|
|
48
|
+
export function convertFeatureAttributesToArrowBatches(
|
|
49
|
+
features: readonly TileFeatureAttributes[],
|
|
50
|
+
options: FeatureArrowBatchOptions
|
|
51
|
+
): ArrowTableBatch[] {
|
|
52
|
+
const featureIdField = options.featureIdField || DEFAULT_FEATURE_ID_FIELD;
|
|
53
|
+
const batchSize = options.batchSize ?? 65_536;
|
|
54
|
+
if (!Number.isInteger(batchSize) || batchSize <= 0) {
|
|
55
|
+
throw new TileConversionError(
|
|
56
|
+
'INVALID_FEATURE_BATCH_SIZE',
|
|
57
|
+
'Feature Arrow batch size must be a positive integer'
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const featureClasses = new Set(features.map(feature => feature.metadataClass));
|
|
62
|
+
if (featureClasses.size > 1) {
|
|
63
|
+
throw new TileConversionError(
|
|
64
|
+
'MULTIPLE_FEATURE_CLASSES',
|
|
65
|
+
'Build separate Arrow batches for each source metadata class'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
const metadataClass = features[0]?.metadataClass;
|
|
69
|
+
const schema = makeFeatureSchema(
|
|
70
|
+
options.schema,
|
|
71
|
+
featureIdField,
|
|
72
|
+
options.rawMetadataField,
|
|
73
|
+
metadataClass
|
|
74
|
+
);
|
|
75
|
+
const fieldsByName = new Map(schema.fields.map(field => [field.name, field]));
|
|
76
|
+
const propertyFieldNames = new Set(
|
|
77
|
+
schema.fields
|
|
78
|
+
.filter(field => field.name !== featureIdField && field.name !== options.rawMetadataField)
|
|
79
|
+
.map(field => field.name)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
for (const feature of features) {
|
|
83
|
+
validateFeatureIdentifier(feature.featureId, fieldsByName.get(featureIdField)?.type);
|
|
84
|
+
if (feature.rawMetadata && !options.rawMetadataField) {
|
|
85
|
+
throw new TileConversionError(
|
|
86
|
+
'RAW_METADATA_FIELD_REQUIRED',
|
|
87
|
+
'A rawMetadataField must be declared to preserve encoded source metadata'
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
for (const propertyName of Object.keys(feature.properties)) {
|
|
91
|
+
if (!propertyFieldNames.has(propertyName)) {
|
|
92
|
+
throw new TileConversionError(
|
|
93
|
+
'FEATURE_PROPERTY_NOT_MAPPED',
|
|
94
|
+
`Feature property "${propertyName}" is not declared in the Arrow schema`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const batches: ArrowTableBatch[] = [];
|
|
101
|
+
for (let batchStart = 0; batchStart < features.length; batchStart += batchSize) {
|
|
102
|
+
const tableBuilder = new ArrowTableBuilder(schema);
|
|
103
|
+
const batchFeatures = features.slice(batchStart, batchStart + batchSize);
|
|
104
|
+
for (const feature of batchFeatures) {
|
|
105
|
+
const row: Record<string, unknown> = {
|
|
106
|
+
...feature.properties,
|
|
107
|
+
[featureIdField]: feature.featureId
|
|
108
|
+
};
|
|
109
|
+
if (options.rawMetadataField) {
|
|
110
|
+
row[options.rawMetadataField] = feature.rawMetadata || null;
|
|
111
|
+
}
|
|
112
|
+
for (const field of schema.fields) {
|
|
113
|
+
if (row[field.name] === undefined) {
|
|
114
|
+
row[field.name] = null;
|
|
115
|
+
}
|
|
116
|
+
validateFeatureValue(field, row[field.name], field.name);
|
|
117
|
+
}
|
|
118
|
+
tableBuilder.addObjectRow(row);
|
|
119
|
+
}
|
|
120
|
+
const batch = tableBuilder.finishBatch();
|
|
121
|
+
if (batch) {
|
|
122
|
+
batches.push(batch);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return batches;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Adds feature class metadata and validates the required ID and raw metadata mappings. */
|
|
129
|
+
function makeFeatureSchema(
|
|
130
|
+
sourceSchema: Schema,
|
|
131
|
+
featureIdField: string,
|
|
132
|
+
rawMetadataField: string | undefined,
|
|
133
|
+
metadataClass: string | undefined
|
|
134
|
+
): Schema {
|
|
135
|
+
const fieldsByName = new Map(sourceSchema.fields.map(field => [field.name, field]));
|
|
136
|
+
if (fieldsByName.size !== sourceSchema.fields.length) {
|
|
137
|
+
throw new TileConversionError(
|
|
138
|
+
'DUPLICATE_FEATURE_FIELDS',
|
|
139
|
+
'Arrow schema fields must have unique names'
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
for (const field of sourceSchema.fields) {
|
|
143
|
+
validateFeatureSchemaType(field);
|
|
144
|
+
}
|
|
145
|
+
const featureIdType = fieldsByName.get(featureIdField)?.type;
|
|
146
|
+
if (!featureIdType) {
|
|
147
|
+
throw new TileConversionError(
|
|
148
|
+
'FEATURE_ID_FIELD_REQUIRED',
|
|
149
|
+
`Arrow schema must declare the feature identifier field "${featureIdField}"`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
if (rawMetadataField && !fieldsByName.has(rawMetadataField)) {
|
|
153
|
+
throw new TileConversionError(
|
|
154
|
+
'RAW_METADATA_FIELD_NOT_DECLARED',
|
|
155
|
+
`Arrow schema does not declare the raw metadata field "${rawMetadataField}"`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
if (rawMetadataField === featureIdField) {
|
|
159
|
+
throw new TileConversionError(
|
|
160
|
+
'FEATURE_FIELDS_COLLIDE',
|
|
161
|
+
'The feature identifier and raw metadata require separate Arrow fields'
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
if (rawMetadataField && !isBinaryType(fieldsByName.get(rawMetadataField)?.type)) {
|
|
165
|
+
throw new TileConversionError(
|
|
166
|
+
'RAW_METADATA_FIELD_NOT_BINARY',
|
|
167
|
+
`Arrow schema field "${rawMetadataField}" must use binary or fixed-size-binary type`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
...sourceSchema,
|
|
172
|
+
metadata: {
|
|
173
|
+
...(sourceSchema.metadata || {}),
|
|
174
|
+
...(metadataClass ? {[FEATURE_CLASS_METADATA_KEY]: metadataClass} : {})
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Rejects identifier values that the declared Arrow type cannot preserve exactly. */
|
|
180
|
+
function validateFeatureIdentifier(featureId: string | number | bigint, dataType?: DataType): void {
|
|
181
|
+
const isStringIdentifier = typeof featureId === 'string';
|
|
182
|
+
const isIntegerIdentifier = typeof featureId === 'bigint' || Number.isSafeInteger(featureId);
|
|
183
|
+
const isStringType = dataType === 'utf8' || dataType === 'utf8-view';
|
|
184
|
+
if (
|
|
185
|
+
(isStringIdentifier && isStringType) ||
|
|
186
|
+
(isIntegerIdentifier && isIntegerDataType(dataType))
|
|
187
|
+
) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
throw new TileConversionError(
|
|
191
|
+
'FEATURE_ID_TYPE_MISMATCH',
|
|
192
|
+
`Feature identifier ${String(featureId)} is not compatible with the declared Arrow type`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Rejects nulls, implicit coercions, and out-of-range values before Arrow writes a field. */
|
|
197
|
+
function validateFeatureValue(field: Field, value: unknown, fieldPath: string): void {
|
|
198
|
+
if (value === null || value === undefined) {
|
|
199
|
+
if (field.nullable !== true) {
|
|
200
|
+
throw new TileConversionError(
|
|
201
|
+
'FEATURE_VALUE_REQUIRED',
|
|
202
|
+
`Required Arrow field "${fieldPath}" has no value`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const dataType = field.type;
|
|
209
|
+
if (typeof dataType === 'object') {
|
|
210
|
+
if (dataType.type === 'dictionary') {
|
|
211
|
+
validateFeatureValue({...field, type: dataType.dictionary}, value, fieldPath);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (dataType.type === 'list' || dataType.type === 'large-list') {
|
|
215
|
+
if (!Array.isArray(value)) {
|
|
216
|
+
throw createFeatureValueTypeError(fieldPath, 'an array');
|
|
217
|
+
}
|
|
218
|
+
const childField = dataType.children[0];
|
|
219
|
+
for (let index = 0; index < value.length; index++) {
|
|
220
|
+
validateFeatureValue(childField, value[index], `${fieldPath}[${index}]`);
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (dataType.type === 'fixed-size-list') {
|
|
225
|
+
if (!Array.isArray(value) || value.length !== dataType.listSize) {
|
|
226
|
+
throw createFeatureValueTypeError(fieldPath, `an array of length ${dataType.listSize}`);
|
|
227
|
+
}
|
|
228
|
+
const childField = dataType.children[0];
|
|
229
|
+
for (let index = 0; index < value.length; index++) {
|
|
230
|
+
validateFeatureValue(childField, value[index], `${fieldPath}[${index}]`);
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (dataType.type === 'struct') {
|
|
235
|
+
if (!isRecord(value)) {
|
|
236
|
+
throw createFeatureValueTypeError(fieldPath, 'an object');
|
|
237
|
+
}
|
|
238
|
+
const childNames = new Set(dataType.children.map(childField => childField.name));
|
|
239
|
+
const unknownNames = Object.keys(value).filter(name => !childNames.has(name));
|
|
240
|
+
if (unknownNames.length > 0) {
|
|
241
|
+
throw new TileConversionError(
|
|
242
|
+
'FEATURE_PROPERTY_NOT_MAPPED',
|
|
243
|
+
`Nested feature properties "${unknownNames.join(', ')}" are not declared under "${fieldPath}"`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
for (const childField of dataType.children) {
|
|
247
|
+
validateFeatureValue(childField, value[childField.name], `${fieldPath}.${childField.name}`);
|
|
248
|
+
}
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (dataType.type === 'decimal') {
|
|
252
|
+
if (typeof value !== 'bigint') {
|
|
253
|
+
throw createFeatureValueTypeError(fieldPath, 'an unscaled bigint decimal value');
|
|
254
|
+
}
|
|
255
|
+
if (
|
|
256
|
+
value <= -(10n ** BigInt(dataType.precision)) ||
|
|
257
|
+
value >= 10n ** BigInt(dataType.precision)
|
|
258
|
+
) {
|
|
259
|
+
throw new TileConversionError(
|
|
260
|
+
'FEATURE_VALUE_OUT_OF_RANGE',
|
|
261
|
+
`Value for Arrow decimal field "${fieldPath}" exceeds precision ${dataType.precision}`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (dataType.type === 'fixed-size-binary') {
|
|
267
|
+
const byteLength = getByteLength(value);
|
|
268
|
+
if (byteLength !== dataType.byteWidth) {
|
|
269
|
+
throw createFeatureValueTypeError(fieldPath, `exactly ${dataType.byteWidth} bytes`);
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
// Keep future Arrow composites explicit until a lossless runtime mapping is defined.
|
|
274
|
+
throw new TileConversionError(
|
|
275
|
+
'FEATURE_VALUE_MAPPING_UNSUPPORTED',
|
|
276
|
+
`Arrow schema type "${dataType.type}" has no feature value mapping for "${fieldPath}"`
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (isIntegerDataType(dataType)) {
|
|
281
|
+
if (!isIntegerIdentifier(value)) {
|
|
282
|
+
throw createFeatureValueTypeError(fieldPath, 'an integer');
|
|
283
|
+
}
|
|
284
|
+
const [minimum, maximum] = getIntegerBounds(dataType);
|
|
285
|
+
const integerValue = typeof value === 'bigint' ? value : BigInt(value);
|
|
286
|
+
if (integerValue < minimum || integerValue > maximum) {
|
|
287
|
+
throw new TileConversionError(
|
|
288
|
+
'FEATURE_VALUE_OUT_OF_RANGE',
|
|
289
|
+
`Value for Arrow field "${fieldPath}" is outside the range of ${dataType}`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (dataType === 'utf8' || dataType === 'utf8-view') {
|
|
295
|
+
if (typeof value !== 'string') throw createFeatureValueTypeError(fieldPath, 'a string');
|
|
296
|
+
if (new TextDecoder().decode(new TextEncoder().encode(value)) !== value)
|
|
297
|
+
throw createFeatureValueTypeError(fieldPath, 'a valid Unicode string');
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (dataType === 'bool') {
|
|
301
|
+
if (typeof value !== 'boolean') throw createFeatureValueTypeError(fieldPath, 'a boolean');
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (dataType === 'binary' || dataType === 'binary-view') {
|
|
305
|
+
if (getByteLength(value) < 0) throw createFeatureValueTypeError(fieldPath, 'binary data');
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (
|
|
309
|
+
dataType === 'float' ||
|
|
310
|
+
dataType === 'float16' ||
|
|
311
|
+
dataType === 'float32' ||
|
|
312
|
+
dataType === 'float64'
|
|
313
|
+
) {
|
|
314
|
+
if (typeof value !== 'number') throw createFeatureValueTypeError(fieldPath, 'a number');
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
if (dataType === 'null') {
|
|
318
|
+
throw createFeatureValueTypeError(fieldPath, 'null');
|
|
319
|
+
}
|
|
320
|
+
if (
|
|
321
|
+
dataType === 'date-day' ||
|
|
322
|
+
dataType === 'date-millisecond' ||
|
|
323
|
+
dataType.startsWith('timestamp-')
|
|
324
|
+
) {
|
|
325
|
+
if (!(value instanceof Date) || !Number.isFinite(value.getTime())) {
|
|
326
|
+
throw createFeatureValueTypeError(fieldPath, 'a valid Date');
|
|
327
|
+
}
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
throw new TileConversionError(
|
|
331
|
+
'FEATURE_VALUE_MAPPING_UNSUPPORTED',
|
|
332
|
+
`Arrow schema type "${dataType}" has no feature value mapping for "${fieldPath}"`
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Checks whether a feature identifier is exact enough for an integer Arrow field. */
|
|
337
|
+
function isIntegerIdentifier(value: unknown): value is number | bigint {
|
|
338
|
+
return typeof value === 'bigint' || (typeof value === 'number' && Number.isSafeInteger(value));
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** Identifies all Arrow integer primitive types accepted for feature identifiers. */
|
|
342
|
+
function isIntegerDataType(dataType?: DataType): boolean {
|
|
343
|
+
return (
|
|
344
|
+
dataType === 'int8' ||
|
|
345
|
+
dataType === 'int16' ||
|
|
346
|
+
dataType === 'int32' ||
|
|
347
|
+
dataType === 'int64' ||
|
|
348
|
+
dataType === 'uint8' ||
|
|
349
|
+
dataType === 'uint16' ||
|
|
350
|
+
dataType === 'uint32' ||
|
|
351
|
+
dataType === 'uint64'
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** Rejects generic integer types and nested mappings the Arrow table builder cannot materialize. */
|
|
356
|
+
function validateFeatureSchemaType(field: Field): void {
|
|
357
|
+
const dataType = field.type;
|
|
358
|
+
if (dataType === 'int') {
|
|
359
|
+
throw new TileConversionError(
|
|
360
|
+
'FEATURE_INTEGER_TYPE_UNSUPPORTED',
|
|
361
|
+
`Arrow field "${field.name}" must declare an explicit integer width and signedness`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
if (typeof dataType !== 'object') {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
let childFields: readonly Field[] = [];
|
|
368
|
+
if (dataType.type === 'dictionary' && dataType.indices) {
|
|
369
|
+
childFields = [{name: `${field.name} index`, type: dataType.indices, nullable: false}];
|
|
370
|
+
} else if ('children' in dataType) {
|
|
371
|
+
childFields = dataType.children;
|
|
372
|
+
}
|
|
373
|
+
for (const childField of childFields) {
|
|
374
|
+
validateFeatureSchemaType(childField);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** Returns the inclusive numeric limits for the declared integer field. */
|
|
379
|
+
function getIntegerBounds(dataType: DataType): [bigint, bigint] {
|
|
380
|
+
switch (dataType) {
|
|
381
|
+
case 'int8':
|
|
382
|
+
return [-128n, 127n];
|
|
383
|
+
case 'uint8':
|
|
384
|
+
return [0n, 255n];
|
|
385
|
+
case 'int16':
|
|
386
|
+
return [-32768n, 32767n];
|
|
387
|
+
case 'uint16':
|
|
388
|
+
return [0n, 65535n];
|
|
389
|
+
case 'int32':
|
|
390
|
+
return [-2147483648n, 2147483647n];
|
|
391
|
+
case 'uint32':
|
|
392
|
+
return [0n, 4294967295n];
|
|
393
|
+
case 'int64':
|
|
394
|
+
return [-(2n ** 63n), 2n ** 63n - 1n];
|
|
395
|
+
case 'uint64':
|
|
396
|
+
return [0n, 2n ** 64n - 1n];
|
|
397
|
+
default:
|
|
398
|
+
return [-(2n ** 31n), 2n ** 31n - 1n];
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** Creates a typed error that names the field whose schema mapping does not match its value. */
|
|
403
|
+
function createFeatureValueTypeError(fieldPath: string, expected: string): TileConversionError {
|
|
404
|
+
return new TileConversionError(
|
|
405
|
+
'FEATURE_VALUE_TYPE_MISMATCH',
|
|
406
|
+
`Arrow field "${fieldPath}" requires ${expected}`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/** Checks whether a value is a property record rather than an array or scalar. */
|
|
411
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
412
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** Returns the byte length for supported binary value containers. */
|
|
416
|
+
function getByteLength(value: unknown): number {
|
|
417
|
+
if (value instanceof Uint8Array) return value.byteLength;
|
|
418
|
+
if (value instanceof ArrayBuffer) return value.byteLength;
|
|
419
|
+
return -1;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** Checks whether the schema type stores opaque bytes without coercion. */
|
|
423
|
+
function isBinaryType(dataType?: DataType): boolean {
|
|
424
|
+
return (
|
|
425
|
+
dataType === 'binary' ||
|
|
426
|
+
dataType === 'binary-view' ||
|
|
427
|
+
(typeof dataType === 'object' && dataType.type === 'fixed-size-binary')
|
|
428
|
+
);
|
|
429
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {encodeI3SMeshLayer} from '@loaders.gl/i3s';
|
|
6
|
+
import type {EncodedI3SMeshLayer, I3SMeshWriterOptions} from '@loaders.gl/i3s';
|
|
7
|
+
import {TileConversionError} from '@loaders.gl/tile-converter/v5/core';
|
|
8
|
+
import type {TileConversionCodec, TileConversionSink} from '@loaders.gl/tile-converter/v5/core';
|
|
9
|
+
import type {Tiles3DConversionSpatialContext} from '@loaders.gl/tile-converter/v5/core';
|
|
10
|
+
import type {MeshSourceResource} from './mesh-source.js';
|
|
11
|
+
import {validateMeshGeometry} from './mesh.js';
|
|
12
|
+
import {createBoundedMemoryTileConversionSink} from '@loaders.gl/tile-converter/v5/core';
|
|
13
|
+
import type {BrowserTileConversionFile} from '@loaders.gl/tile-converter/v5/core';
|
|
14
|
+
|
|
15
|
+
/** One authored mesh layer, ready for the single-layer sink. */
|
|
16
|
+
export interface I3SMeshConversionResource extends EncodedI3SMeshLayer {
|
|
17
|
+
/** Source placement identifier used for diagnostics. */
|
|
18
|
+
readonly id: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Spatial preparation and required authoring limits for the I3S codec. */
|
|
22
|
+
export interface I3SMeshConversionCodecOptions
|
|
23
|
+
extends Pick<I3SMeshWriterOptions, 'name' | 'maxPositionError' | 'maxResourceBytes'> {
|
|
24
|
+
/** Shared source-to-ECEF context, applied exactly once before I3S geographic encoding. */
|
|
25
|
+
readonly spatialContext: Tiles3DConversionSpatialContext;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Creates a portable source-mesh to I3S layer codec with explicit precision and feature diagnostics. */
|
|
29
|
+
export function createI3SMeshConversionCodec<TInspection = unknown>(
|
|
30
|
+
options: I3SMeshConversionCodecOptions
|
|
31
|
+
): TileConversionCodec<TInspection, MeshSourceResource, I3SMeshConversionResource> {
|
|
32
|
+
const reference = options.spatialContext.spatialReference;
|
|
33
|
+
const height =
|
|
34
|
+
reference.targetHeightReference === 'native'
|
|
35
|
+
? reference.heightReference
|
|
36
|
+
: reference.targetHeightReference;
|
|
37
|
+
if (
|
|
38
|
+
!['native', 'transformed'].includes(reference.status) ||
|
|
39
|
+
(reference.targetCrs || reference.sourceCrs) !== 'EPSG:4978' ||
|
|
40
|
+
height !== 'ellipsoidal' ||
|
|
41
|
+
(reference.status === 'native' &&
|
|
42
|
+
(!['xyz', 'unknown'].includes(reference.axisOrder) ||
|
|
43
|
+
reference.verticalUnitScale !== 1 ||
|
|
44
|
+
reference.units?.some(unit => unit !== 'meter')))
|
|
45
|
+
)
|
|
46
|
+
throw new TileConversionError(
|
|
47
|
+
'I3S_MESH_FRAME_UNSUPPORTED',
|
|
48
|
+
'I3S mesh authoring requires resolved ECEF coordinates and ellipsoidal heights'
|
|
49
|
+
);
|
|
50
|
+
return {
|
|
51
|
+
/** Places a source mesh in ECEF and authors one layer without modifying source arrays. */
|
|
52
|
+
async *convert(resource, _inspection, signal) {
|
|
53
|
+
signal?.throwIfAborted();
|
|
54
|
+
const mesh = validateMeshGeometry(resource.mesh, true);
|
|
55
|
+
const positions = mesh.attributes.POSITION.value;
|
|
56
|
+
mesh.attributes.POSITION = {
|
|
57
|
+
value: options.spatialContext.transformPositions(positions),
|
|
58
|
+
size: 3
|
|
59
|
+
};
|
|
60
|
+
if (mesh.attributes.NORMAL)
|
|
61
|
+
mesh.attributes.NORMAL = {
|
|
62
|
+
value: options.spatialContext.transformNormals(mesh.attributes.NORMAL.value, positions),
|
|
63
|
+
size: 3
|
|
64
|
+
};
|
|
65
|
+
let layer: EncodedI3SMeshLayer;
|
|
66
|
+
try {
|
|
67
|
+
layer = encodeI3SMeshLayer(mesh, {
|
|
68
|
+
...options,
|
|
69
|
+
material: resource.material,
|
|
70
|
+
features: resource.features
|
|
71
|
+
});
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new TileConversionError(
|
|
74
|
+
'I3S_MESH_PROFILE_UNSUPPORTED',
|
|
75
|
+
error instanceof Error ? error.message : String(error)
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
signal?.throwIfAborted();
|
|
79
|
+
yield {id: resource.id, ...layer};
|
|
80
|
+
},
|
|
81
|
+
/** Reports measured precision and explicitly authorized integer representation changes. */
|
|
82
|
+
async validateOutput(resource) {
|
|
83
|
+
return [
|
|
84
|
+
...(resource.maximumPositionError > 0
|
|
85
|
+
? [
|
|
86
|
+
{
|
|
87
|
+
code: 'I3S_MESH_POSITION_ROUNDING',
|
|
88
|
+
message: `I3S positions have up to ${resource.maximumPositionError} meters reconstruction error`,
|
|
89
|
+
severity: 'info' as const,
|
|
90
|
+
resourceId: resource.id
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
: []),
|
|
94
|
+
...resource.decimalStringFields.map(field => ({
|
|
95
|
+
code: 'I3S_INTEGER_DECIMAL_STRING',
|
|
96
|
+
message: `Explicitly represented 64-bit integer field ${field} as exact decimal text`,
|
|
97
|
+
severity: 'info' as const,
|
|
98
|
+
resourceId: resource.id
|
|
99
|
+
}))
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Atomic bounded output for one authored I3S layer. */
|
|
106
|
+
export interface SingleMeshI3SSink extends TileConversionSink<I3SMeshConversionResource> {
|
|
107
|
+
/** Compressed archive-relative files visible only after successful finalization. */
|
|
108
|
+
getFiles(): readonly BrowserTileConversionFile[];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Creates an atomic bounded single-mesh I3S sink; pass finalized files to createTileConversionArchive. */
|
|
112
|
+
export function createSingleMeshI3SSink(options: {
|
|
113
|
+
/** Maximum retained compressed resource bytes; not peak conversion memory. */ readonly maxTotalBytes: number;
|
|
114
|
+
}): SingleMeshI3SSink {
|
|
115
|
+
const memory = createBoundedMemoryTileConversionSink(options);
|
|
116
|
+
let state: 'empty' | 'writing' | 'written' | 'closed' = 'empty';
|
|
117
|
+
let completed = false;
|
|
118
|
+
return {
|
|
119
|
+
/** Exposes resources only after successful finalization. */
|
|
120
|
+
getFiles: () => (completed ? memory.getFiles() : []),
|
|
121
|
+
/** Writes exactly one layer within the retained-resource budget. */
|
|
122
|
+
async write(resource, signal) {
|
|
123
|
+
signal?.throwIfAborted();
|
|
124
|
+
if (state !== 'empty')
|
|
125
|
+
throw new TileConversionError(
|
|
126
|
+
'SINGLE_I3S_MESH_UNAVAILABLE',
|
|
127
|
+
'The initial I3S sink accepts exactly one mesh layer'
|
|
128
|
+
);
|
|
129
|
+
state = 'writing';
|
|
130
|
+
for (const [resourceId, bytes] of Object.entries(resource.files))
|
|
131
|
+
await memory.write({resourceId, parts: [bytes], contentType: 'application/gzip'}, signal);
|
|
132
|
+
state = 'written';
|
|
133
|
+
},
|
|
134
|
+
/** Commits a complete single-layer result. */
|
|
135
|
+
async finalize(report) {
|
|
136
|
+
if (state !== 'written')
|
|
137
|
+
throw new TileConversionError(
|
|
138
|
+
'SINGLE_I3S_MESH_INCOMPLETE',
|
|
139
|
+
'Finalization requires exactly one successfully written layer'
|
|
140
|
+
);
|
|
141
|
+
await memory.finalize(report);
|
|
142
|
+
state = 'closed';
|
|
143
|
+
completed = true;
|
|
144
|
+
},
|
|
145
|
+
/** Discards all resources after any conversion failure. */
|
|
146
|
+
async abort(error) {
|
|
147
|
+
completed = false;
|
|
148
|
+
state = 'closed';
|
|
149
|
+
await memory.abort(error);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
package/src/v5/index.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export {
|
|
2
|
+
convertTileset,
|
|
3
|
+
inspectTileset,
|
|
4
|
+
TileConversionError,
|
|
5
|
+
validateTileset
|
|
6
|
+
} from '@loaders.gl/tile-converter/v5/core';
|
|
7
|
+
export type {
|
|
8
|
+
ConvertTilesetOptions,
|
|
9
|
+
TileConversionCodec,
|
|
10
|
+
TileConversionDiagnostic,
|
|
11
|
+
TileConversionProgress,
|
|
12
|
+
TileConversionReport,
|
|
13
|
+
TileConversionSink,
|
|
14
|
+
TileConversionSource,
|
|
15
|
+
TileValidationReport,
|
|
16
|
+
ValidateTilesetOptions
|
|
17
|
+
} from '@loaders.gl/tile-converter/v5/core';
|
|
18
|
+
export {createTilesetConversionSource} from '@loaders.gl/tile-converter/v5/core';
|
|
19
|
+
export type {TilesetConversionSourceOptions} from '@loaders.gl/tile-converter/v5/core';
|
|
20
|
+
export {
|
|
21
|
+
createI3SConversionSpatialContext,
|
|
22
|
+
createTiles3DConversionSpatialContext
|
|
23
|
+
} from '@loaders.gl/tile-converter/v5/core';
|
|
24
|
+
export type {
|
|
25
|
+
I3SConversionSpatialContext,
|
|
26
|
+
Tiles3DConversionSpatialContext
|
|
27
|
+
} from '@loaders.gl/tile-converter/v5/core';
|
|
28
|
+
export {convertFeatureAttributesToArrowBatches} from '@loaders.gl/tile-converter/v5/adapters';
|
|
29
|
+
export type {
|
|
30
|
+
FeatureArrowBatchOptions,
|
|
31
|
+
TileFeatureAttributes
|
|
32
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
33
|
+
export {encodePointCloudTile} from '@loaders.gl/tile-converter/v5/adapters';
|
|
34
|
+
export type {EncodePointCloudTileOptions} from '@loaders.gl/tile-converter/v5/adapters';
|
|
35
|
+
export {traversePointCloudSource} from '@loaders.gl/tile-converter/v5/core';
|
|
36
|
+
export type {
|
|
37
|
+
PointCloudSourceTile,
|
|
38
|
+
TraversePointCloudSourceOptions
|
|
39
|
+
} from '@loaders.gl/tile-converter/v5/core';
|
|
40
|
+
export {
|
|
41
|
+
encodePointCloudSource,
|
|
42
|
+
encodePointCloudSourceTile
|
|
43
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
44
|
+
export type {
|
|
45
|
+
EncodedPointCloudSourceTile,
|
|
46
|
+
EncodePointCloudSourceOptions
|
|
47
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
48
|
+
export {convertPointCloudSource} from '@loaders.gl/tile-converter/v5/adapters';
|
|
49
|
+
export type {ConvertPointCloudSourceOptions} from '@loaders.gl/tile-converter/v5/adapters';
|
|
50
|
+
export {createManifestBackedTileConversionSink} from '@loaders.gl/tile-converter/v5/core';
|
|
51
|
+
export type {
|
|
52
|
+
ManifestBackedTileConversionSinkOptions,
|
|
53
|
+
TileResourceManifest,
|
|
54
|
+
TileResourceManifestEntry,
|
|
55
|
+
TileResourceManifestStore
|
|
56
|
+
} from '@loaders.gl/tile-converter/v5/core';
|
|
57
|
+
export {encodeMeshTile} from '@loaders.gl/tile-converter/v5/adapters';
|
|
58
|
+
export type {
|
|
59
|
+
MeshTileMaterial,
|
|
60
|
+
MeshTileOptions,
|
|
61
|
+
MeshTileTexture,
|
|
62
|
+
MeshTileSampler,
|
|
63
|
+
MeshTileTextureTransform
|
|
64
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
65
|
+
export {createMeshConversionCodec} from '@loaders.gl/tile-converter/v5/adapters';
|
|
66
|
+
export type {
|
|
67
|
+
MeshConversionInput,
|
|
68
|
+
EncodedMeshConversionResource,
|
|
69
|
+
MeshConversionCodecOptions
|
|
70
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
71
|
+
export {createSingleMeshTilesetSink} from '@loaders.gl/tile-converter/v5/adapters';
|
|
72
|
+
export type {
|
|
73
|
+
SingleMeshTilesetSink,
|
|
74
|
+
SingleMeshTilesetSinkOptions
|
|
75
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
createTileConversionArchive,
|
|
79
|
+
encodeTileConversionArchiveInBatches
|
|
80
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
81
|
+
export type {TileConversionArchiveOptions} from '@loaders.gl/tile-converter/v5/adapters';
|
|
82
|
+
export {createSingleMeshTilesetArchive} from '@loaders.gl/tile-converter/v5/adapters';
|
|
83
|
+
export type {SingleMeshTilesetArchiveOptions} from '@loaders.gl/tile-converter/v5/adapters';
|
|
84
|
+
|
|
85
|
+
export {createMeshTilesetConversionSource} from '@loaders.gl/tile-converter/v5/adapters';
|
|
86
|
+
export type {
|
|
87
|
+
MeshSourceResource,
|
|
88
|
+
MeshTilesetSourceOptions,
|
|
89
|
+
MeshSourceFeatureOptions
|
|
90
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
91
|
+
export {
|
|
92
|
+
createI3SMeshConversionCodec,
|
|
93
|
+
createSingleMeshI3SSink
|
|
94
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|
|
95
|
+
export type {
|
|
96
|
+
I3SMeshConversionResource,
|
|
97
|
+
I3SMeshConversionCodecOptions,
|
|
98
|
+
SingleMeshI3SSink
|
|
99
|
+
} from '@loaders.gl/tile-converter/v5/adapters';
|