@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,24 @@
|
|
|
1
|
+
import type { Mesh, MeshArrowTable } from '@loaders.gl/schema';
|
|
2
|
+
/** Options for encoding one Arrow or mesh point batch as a 3D Tiles point tile. */
|
|
3
|
+
export interface EncodePointCloudTileOptions {
|
|
4
|
+
/** Optional origin subtracted from absolute positions and stored as the PNTS RTC_CENTER. */
|
|
5
|
+
readonly rtcCenter?: readonly [number, number, number];
|
|
6
|
+
/** Optional source-wide RGBA color stored as the PNTS CONSTANT_RGBA property. */
|
|
7
|
+
readonly constantRGBA?: readonly number[];
|
|
8
|
+
/** Optional per-point values indexed by the tile's `BATCH_ID` attribute. */
|
|
9
|
+
readonly batchTableJson?: Readonly<Record<string, readonly (string | number)[]>>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Encodes one mesh or Mesh Arrow point batch as a PNTS resource.
|
|
13
|
+
*
|
|
14
|
+
* The input position field must be named `POSITION` and contain xyz values. `COLOR_0` or `COLOR`
|
|
15
|
+
* is written when present; `constantRGBA` supplies a fallback PNTS `CONSTANT_RGBA` feature-table
|
|
16
|
+
* property. `NORMAL` and `BATCH_ID` are also written when present. Arrow batches should be passed
|
|
17
|
+
* one at a time so callers can bound memory and apply their own tiling and output policy.
|
|
18
|
+
* Unsupported attributes, including a second color attribute, fail instead of being discarded.
|
|
19
|
+
*
|
|
20
|
+
* @param pointBatch - Point data produced by a LAS, COPC, I3S, or other point source.
|
|
21
|
+
* @param options - Optional RTC center and batch-table values.
|
|
22
|
+
* @returns A 3D Tiles PNTS resource.
|
|
23
|
+
*/
|
|
24
|
+
export declare function encodePointCloudTile(pointBatch: Mesh | MeshArrowTable, options?: EncodePointCloudTileOptions): ArrayBuffer;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { TileConversionReport, TileConversionSink } from './conversion-api.js';
|
|
2
|
+
/** Durable record for one successfully written, deterministic output resource. */
|
|
3
|
+
export interface TileResourceManifestEntry {
|
|
4
|
+
/** Stable resource identifier supplied by the output profile. */
|
|
5
|
+
readonly resourceId: string;
|
|
6
|
+
/** Byte length of the output resource. */
|
|
7
|
+
readonly byteLength: number;
|
|
8
|
+
/** Stable caller-computed content fingerprint, such as a SHA-256 digest. */
|
|
9
|
+
readonly fingerprint: string;
|
|
10
|
+
}
|
|
11
|
+
/** Versioned progress record used to resume deterministic output packaging. */
|
|
12
|
+
export interface TileResourceManifest {
|
|
13
|
+
/** Manifest format version. */
|
|
14
|
+
readonly version: 1;
|
|
15
|
+
/** True only after the destination and report have been finalized successfully. */
|
|
16
|
+
readonly complete: boolean;
|
|
17
|
+
/** Resources durably written before interruption or completion. */
|
|
18
|
+
readonly resources: readonly TileResourceManifestEntry[];
|
|
19
|
+
/** Conversion summary saved after successful destination finalization. */
|
|
20
|
+
readonly report?: TileConversionReport;
|
|
21
|
+
}
|
|
22
|
+
/** Application-owned persistence for a conversion manifest. */
|
|
23
|
+
export interface TileResourceManifestStore {
|
|
24
|
+
/** Loads the previous manifest, or returns null when starting a new conversion. */
|
|
25
|
+
load(): Promise<TileResourceManifest | null>;
|
|
26
|
+
/** Atomically replaces the saved manifest with the supplied snapshot. */
|
|
27
|
+
save(manifest: TileResourceManifest): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/** Options for decorating a resource sink with restart-safe manifest tracking. */
|
|
30
|
+
export interface ManifestBackedTileConversionSinkOptions<TResource> {
|
|
31
|
+
/** Output destination with deterministic, idempotent resource writes. */
|
|
32
|
+
readonly sink: TileConversionSink<TResource>;
|
|
33
|
+
/** Persistence adapter for snapshots written after each resource. */
|
|
34
|
+
readonly manifestStore: TileResourceManifestStore;
|
|
35
|
+
/** Stable profile-specific path or resource key. */
|
|
36
|
+
readonly getResourceId: (resource: TResource) => string;
|
|
37
|
+
/** Byte length used to detect changed content under an existing resource ID. */
|
|
38
|
+
readonly measureResourceBytes: (resource: TResource) => number;
|
|
39
|
+
/** Stable fingerprint used to detect changed content under an existing resource ID. */
|
|
40
|
+
readonly fingerprintResource: (resource: TResource) => string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a sink that skips matching checkpointed resources when a process restarts.
|
|
44
|
+
*
|
|
45
|
+
* The destination must write resources idempotently by the ID returned from `getResourceId`.
|
|
46
|
+
* The manifest is persisted after every successful write; the store should replace snapshots
|
|
47
|
+
* atomically. Existing IDs must retain their byte length and fingerprint or the resumed job fails
|
|
48
|
+
* rather than silently mixing output from different conversion inputs. Writes are serialized even
|
|
49
|
+
* when callers issue them concurrently. Reports count resources processed by the current run,
|
|
50
|
+
* including writes skipped because the matching resource was already present. A graceful abort
|
|
51
|
+
* clears the manifest checkpoint before asking the destination to clean partial output, so the
|
|
52
|
+
* next run starts cleanly. A process interruption that does not call `abort` can resume from its
|
|
53
|
+
* last saved checkpoint.
|
|
54
|
+
*
|
|
55
|
+
* @param options - Destination, manifest store, stable IDs, byte measurement, and fingerprinting.
|
|
56
|
+
* @returns A `TileConversionSink` with resumable per-resource progress.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createManifestBackedTileConversionSink<TResource>(options: ManifestBackedTileConversionSinkOptions<TResource>): Promise<TileConversionSink<TResource>>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { CreateTilesetSpatialReferenceOptions, I3SSpatialBounds, I3STransformedPositions, Tiles3DSpatialBoundingVolume, TilesetSpatialOptions, TilesetSpatialReference } from '@loaders.gl/tiles';
|
|
2
|
+
/** Portable coordinate operations and output metadata for a 3D Tiles conversion. */
|
|
3
|
+
export interface Tiles3DConversionSpatialContext {
|
|
4
|
+
/** Source and selected target CRS, height reference, units, and transformation state. */
|
|
5
|
+
readonly spatialReference: TilesetSpatialReference;
|
|
6
|
+
/** Transform packed absolute xyz positions using double precision output. */
|
|
7
|
+
transformPositions(positions: ArrayLike<number>): Float64Array;
|
|
8
|
+
/** Transform packed normals using the corresponding source positions. */
|
|
9
|
+
transformNormals(normals: ArrayLike<number>, positions: ArrayLike<number>): Float32Array;
|
|
10
|
+
/** Rebuild a conservative bound in the selected target coordinate frame. */
|
|
11
|
+
transformBoundingVolume(volume: Tiles3DSpatialBoundingVolume, sourceTransform?: ArrayLike<number>): Tiles3DSpatialBoundingVolume;
|
|
12
|
+
}
|
|
13
|
+
/** Portable coordinate operations and output metadata for an I3S conversion. */
|
|
14
|
+
export interface I3SConversionSpatialContext {
|
|
15
|
+
/** Source and selected target CRS, height reference, units, and transformation state. */
|
|
16
|
+
readonly spatialReference: TilesetSpatialReference;
|
|
17
|
+
/** Transform absolute I3S positions after applying declared height units and placement. */
|
|
18
|
+
transformPositions(positions: ArrayLike<number>, sourceOrigin: ArrayLike<number>): I3STransformedPositions;
|
|
19
|
+
/** Transform absolute I3S positions when terrain or scene sampling is asynchronous. */
|
|
20
|
+
transformPositionsAsync(positions: ArrayLike<number>, sourceOrigin: ArrayLike<number>): Promise<I3STransformedPositions>;
|
|
21
|
+
/** Transform packed normals using the corresponding source positions. */
|
|
22
|
+
transformNormals(normals: ArrayLike<number>, positions: ArrayLike<number>, normalReferenceFrame?: string): Float32Array;
|
|
23
|
+
/** Rebuild a conservative I3S bound in the selected target frame. */
|
|
24
|
+
transformBoundingVolume(bounds: I3SSpatialBounds): I3SSpatialBounds | {
|
|
25
|
+
box?: number[];
|
|
26
|
+
region?: number[];
|
|
27
|
+
};
|
|
28
|
+
/** Rebuild a bound when terrain or scene sampling is asynchronous. */
|
|
29
|
+
transformBoundingVolumeAsync(bounds: I3SSpatialBounds): Promise<I3SSpatialBounds | {
|
|
30
|
+
box?: number[];
|
|
31
|
+
region?: number[];
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates the shared spatial operations used to write 3D Tiles in a selected CRS and height frame.
|
|
36
|
+
*
|
|
37
|
+
* Source discovery remains format-specific and should use `get3DTilesSpatialReference` or the
|
|
38
|
+
* initialized source's spatial metadata. Target choices on a normalized, transformable reference
|
|
39
|
+
* are retained unless overridden in `options`. Do not reuse a reference already marked
|
|
40
|
+
* `transformed`; that would apply the operation twice. The returned reference is the metadata to
|
|
41
|
+
* publish with transformed output; unresolved requests fail instead of guessing a CRS or height datum.
|
|
42
|
+
*
|
|
43
|
+
* @param discovered - Source CRS, units, coordinate epoch, and height metadata.
|
|
44
|
+
* @param options - Target CRS, height reference, and explicitly supplied geoid resources.
|
|
45
|
+
* @returns Shared position, normal, and bound operations with matching output metadata.
|
|
46
|
+
*/
|
|
47
|
+
export declare function createTiles3DConversionSpatialContext(discovered: CreateTilesetSpatialReferenceOptions | TilesetSpatialReference, options?: TilesetSpatialOptions): Tiles3DConversionSpatialContext;
|
|
48
|
+
/**
|
|
49
|
+
* Creates the shared spatial operations used to write I3S in a selected CRS and height frame.
|
|
50
|
+
*
|
|
51
|
+
* I3S height units, vertical datum, elevation placement, and bounds use the same transformer as
|
|
52
|
+
* the source-backed tile runtime. Terrain or scene elevation providers are explicit application
|
|
53
|
+
* inputs and may make position and bound operations asynchronous.
|
|
54
|
+
*
|
|
55
|
+
* @param discovered - Source CRS, vertical units, height reference, and elevation mode.
|
|
56
|
+
* @param options - Target CRS, height reference, geoid, or explicit elevation providers.
|
|
57
|
+
* @returns Shared position, normal, bound, and output-metadata operations.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createI3SConversionSpatialContext(discovered: CreateTilesetSpatialReferenceOptions | TilesetSpatialReference, options?: TilesetSpatialOptions): I3SConversionSpatialContext;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Tileset3D, TilesetContentTraversalItem, TilesetSourceMetadata, TraverseTilesetContentsOptions } from '@loaders.gl/tiles';
|
|
2
|
+
import type { TileConversionSource } from './conversion-api.js';
|
|
3
|
+
/** Decoded-content lifetime options for source-backed conversion. */
|
|
4
|
+
export type TilesetConversionSourceOptions = Pick<TraverseTilesetContentsOptions, 'unloadContent'>;
|
|
5
|
+
/**
|
|
6
|
+
* Adapts a source-backed tileset to the portable v5 conversion source contract.
|
|
7
|
+
*
|
|
8
|
+
* Inspection waits for initialization and returns the source's normalized metadata. Reading uses
|
|
9
|
+
* camera-independent shared traversal, retaining each placement and its ordered decoded contents.
|
|
10
|
+
* Source adapters own content, subtree, node-page, nested tileset, and archive resolution.
|
|
11
|
+
*
|
|
12
|
+
* Enable `unloadContent` on a dedicated runtime to release newly loaded payloads after the codec
|
|
13
|
+
* and awaited writes finish, or iteration closes on failure. Preloaded payloads remain attached.
|
|
14
|
+
* Applications own tileset destruction, format codecs, byte accounting, and output packaging.
|
|
15
|
+
* This adapter does not impose an aggregate input memory limit or transform coordinates.
|
|
16
|
+
*
|
|
17
|
+
* @param tileset - An initializing or initialized runtime backed by a 3D Tiles or I3S source.
|
|
18
|
+
* @param options - Optional cleanup of content loaded during conversion.
|
|
19
|
+
* @returns A source accepted by `inspectTileset` and `convertTileset`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createTilesetConversionSource(tileset: Tileset3D, options?: TilesetConversionSourceOptions): TileConversionSource<TilesetSourceMetadata, TilesetContentTraversalItem>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loaders.gl/tile-converter",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-alpha.10",
|
|
4
4
|
"description": "Converter",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,6 +24,26 @@
|
|
|
24
24
|
"types": "./dist/index.d.ts",
|
|
25
25
|
"import": "./dist/index.js",
|
|
26
26
|
"require": "./dist/index.cjs"
|
|
27
|
+
},
|
|
28
|
+
"./v5": {
|
|
29
|
+
"types": "./dist/v5/index.d.ts",
|
|
30
|
+
"import": "./dist/v5/index.js",
|
|
31
|
+
"require": "./dist/v5/index.cjs"
|
|
32
|
+
},
|
|
33
|
+
"./v5/browser": {
|
|
34
|
+
"types": "./dist/v5/browser.d.ts",
|
|
35
|
+
"import": "./dist/v5/browser.js",
|
|
36
|
+
"require": "./dist/v5/browser.cjs"
|
|
37
|
+
},
|
|
38
|
+
"./v5/core": {
|
|
39
|
+
"types": "./dist/v5/core.d.ts",
|
|
40
|
+
"import": "./dist/v5/core.js",
|
|
41
|
+
"require": "./dist/v5/core.cjs"
|
|
42
|
+
},
|
|
43
|
+
"./v5/adapters": {
|
|
44
|
+
"types": "./dist/v5/adapters.d.ts",
|
|
45
|
+
"import": "./dist/v5/adapters.js",
|
|
46
|
+
"require": "./dist/v5/adapters.cjs"
|
|
27
47
|
}
|
|
28
48
|
},
|
|
29
49
|
"sideEffects": false,
|
|
@@ -45,30 +65,36 @@
|
|
|
45
65
|
"process": false
|
|
46
66
|
},
|
|
47
67
|
"scripts": {
|
|
48
|
-
"pre-build": "npm run build-converter-bundle && npm run build-i3s-server-bundle && npm run copy-certificates",
|
|
49
|
-
"build-
|
|
50
|
-
"build-
|
|
51
|
-
"
|
|
68
|
+
"pre-build": "npm run build-package-entrypoints && npm run build-converter-bundle && npm run build-i3s-server-bundle && npm run copy-certificates",
|
|
69
|
+
"build-package-entrypoints": "esbuild src/index.ts --bundle --packages=external --platform=node --format=esm --outfile=dist/index.js && esbuild src/index.ts --bundle --packages=external --platform=node --format=cjs --outfile=dist/index.cjs && npm run build-v5-entrypoints && npm run build-v5-declarations",
|
|
70
|
+
"build-v5-declarations": "tsc --project tsconfig.v5.json",
|
|
71
|
+
"build-converter-bundle": "esbuild src/v4/converter-cli.ts --outfile=dist/converter.min.cjs --platform=node --target=esnext,node14 --external:join-images --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
|
|
72
|
+
"build-i3s-server-bundle": "esbuild src/v4/i3s-server/bin/www.ts --outfile=dist/i3s-server/bin/i3s-server.min.cjs --platform=node --target=esnext,node14 --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
|
|
73
|
+
"copy-certificates": "cp -R src/v4/i3s-server/certs dist/i3s-server",
|
|
74
|
+
"build-v5-entrypoints": "esbuild src/v5/core.ts src/v5/adapters.ts src/v5/index.ts src/v5/browser.ts --bundle --packages=external --external:@loaders.gl/* --platform=browser --outdir=dist/v5 --format=esm && esbuild src/v5/core.ts src/v5/adapters.ts src/v5/index.ts src/v5/browser.ts --bundle --packages=external --external:@loaders.gl/* --platform=browser --outdir=dist/v5 --format=cjs --out-extension:.js=.cjs"
|
|
52
75
|
},
|
|
53
76
|
"dependencies": {
|
|
54
|
-
"@loaders.gl/3d-tiles": "
|
|
55
|
-
"@loaders.gl/compression": "
|
|
56
|
-
"@loaders.gl/crypto": "
|
|
57
|
-
"@loaders.gl/draco": "
|
|
58
|
-
"@loaders.gl/gltf": "
|
|
59
|
-
"@loaders.gl/i3s": "
|
|
60
|
-
"@loaders.gl/images": "
|
|
61
|
-
"@loaders.gl/loader-utils": "
|
|
62
|
-
"@loaders.gl/
|
|
63
|
-
"@loaders.gl/
|
|
64
|
-
"@loaders.gl/
|
|
65
|
-
"@loaders.gl/
|
|
66
|
-
"@loaders.gl/
|
|
67
|
-
"@loaders.gl/
|
|
68
|
-
"@
|
|
69
|
-
"@math.gl/
|
|
70
|
-
"@math.gl/
|
|
71
|
-
"@math.gl/
|
|
77
|
+
"@loaders.gl/3d-tiles": "5.0.0-alpha.10",
|
|
78
|
+
"@loaders.gl/compression": "5.0.0-alpha.10",
|
|
79
|
+
"@loaders.gl/crypto": "5.0.0-alpha.10",
|
|
80
|
+
"@loaders.gl/draco": "5.0.0-alpha.10",
|
|
81
|
+
"@loaders.gl/gltf": "5.0.0-alpha.10",
|
|
82
|
+
"@loaders.gl/i3s": "5.0.0-alpha.10",
|
|
83
|
+
"@loaders.gl/images": "5.0.0-alpha.10",
|
|
84
|
+
"@loaders.gl/loader-utils": "5.0.0-alpha.10",
|
|
85
|
+
"@loaders.gl/polyfills": "5.0.0-alpha.10",
|
|
86
|
+
"@loaders.gl/schema": "5.0.0-alpha.10",
|
|
87
|
+
"@loaders.gl/schema-utils": "5.0.0-alpha.10",
|
|
88
|
+
"@loaders.gl/textures": "5.0.0-alpha.10",
|
|
89
|
+
"@loaders.gl/tiles": "5.0.0-alpha.10",
|
|
90
|
+
"@loaders.gl/worker-utils": "5.0.0-alpha.10",
|
|
91
|
+
"@loaders.gl/zip": "5.0.0-alpha.10",
|
|
92
|
+
"@math.gl/core": "5.0.0-alpha.13",
|
|
93
|
+
"@math.gl/crs": "5.0.0-alpha.13",
|
|
94
|
+
"@math.gl/culling": "5.0.0-alpha.13",
|
|
95
|
+
"@math.gl/geoid": "5.0.0-alpha.13",
|
|
96
|
+
"@math.gl/geometry-utils": "5.0.0-alpha.13",
|
|
97
|
+
"@math.gl/geospatial": "5.0.0-alpha.13",
|
|
72
98
|
"ajv": "^8.12.0",
|
|
73
99
|
"archiver": "^5.0.0",
|
|
74
100
|
"cors": "^2.8.5",
|
|
@@ -77,7 +103,6 @@
|
|
|
77
103
|
"express": "~4.19.2",
|
|
78
104
|
"inquirer": "^8.0.0",
|
|
79
105
|
"json-map-transform": "^1.2.6",
|
|
80
|
-
"jszip": "^3.5.0",
|
|
81
106
|
"md5": "^2.3.0",
|
|
82
107
|
"morgan": "~1.9.1",
|
|
83
108
|
"uuid": "^9.0.0"
|
|
@@ -88,10 +113,11 @@
|
|
|
88
113
|
},
|
|
89
114
|
"devDependencies": {
|
|
90
115
|
"@types/express": "^4.17.17",
|
|
91
|
-
"@types/inquirer": "^9.0.7"
|
|
116
|
+
"@types/inquirer": "^9.0.7",
|
|
117
|
+
"typescript": "^6.0.3"
|
|
92
118
|
},
|
|
93
119
|
"peerDependencies": {
|
|
94
|
-
"@loaders.gl/core": "~
|
|
120
|
+
"@loaders.gl/core": "~5.0.0-alpha.0"
|
|
95
121
|
},
|
|
96
|
-
"gitHead": "
|
|
122
|
+
"gitHead": "7cbfaef633e86356c946541dab4977b522745b6c"
|
|
97
123
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export {default as Tiles3DConverter} from './3d-tiles-converter/3d-tiles-converter';
|
|
1
|
+
export * from './v4/index.js';
|
|
@@ -14,6 +14,7 @@ import {load, isBrowser} from '@loaders.gl/core';
|
|
|
14
14
|
import {I3SLoader, I3SAttributeLoader, COORDINATE_SYSTEM} from '@loaders.gl/i3s';
|
|
15
15
|
import {Geoid} from '@math.gl/geoid';
|
|
16
16
|
|
|
17
|
+
import {validateI3SConversionSpatialReference} from './helpers/validate-i3s-spatial-reference';
|
|
17
18
|
import {PGMLoader} from '../pgm-loader';
|
|
18
19
|
import {i3sObbTo3dTilesObb} from './helpers/i3s-obb-to-3d-tiles-obb';
|
|
19
20
|
import {convertScreenThresholdToGeometricError} from '../lib/utils/lod-conversion-utils';
|
|
@@ -134,8 +135,6 @@ export default class Tiles3DConverter {
|
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
this.progress.startMonitoring();
|
|
138
|
-
|
|
139
138
|
this.sourceTileset = await loadFromArchive(
|
|
140
139
|
inputUrl,
|
|
141
140
|
I3SLoader,
|
|
@@ -151,6 +150,18 @@ export default class Tiles3DConverter {
|
|
|
151
150
|
return undefined;
|
|
152
151
|
}
|
|
153
152
|
|
|
153
|
+
try {
|
|
154
|
+
validateI3SConversionSpatialReference(this.sourceTileset);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
try {
|
|
157
|
+
await this.slpkFilesystem?.destroy();
|
|
158
|
+
} finally {
|
|
159
|
+
this.slpkFilesystem = null;
|
|
160
|
+
}
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
this.progress.startMonitoring();
|
|
164
|
+
|
|
154
165
|
const rootNode = this.sourceTileset?.root;
|
|
155
166
|
if (!rootNode.obb) {
|
|
156
167
|
rootNode.obb = createObbFromMbs(rootNode.mbs);
|
|
@@ -177,7 +188,7 @@ export default class Tiles3DConverter {
|
|
|
177
188
|
if (!this.conversionDump.restored) {
|
|
178
189
|
try {
|
|
179
190
|
await removeDir(this.tilesetPath);
|
|
180
|
-
} catch (
|
|
191
|
+
} catch (_e) {
|
|
181
192
|
// do nothing
|
|
182
193
|
}
|
|
183
194
|
}
|
package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/3d-tiles-content-converter.ts
RENAMED
|
@@ -209,7 +209,7 @@ export class Tiles3DContentConverter {
|
|
|
209
209
|
featureAttributes: I3STileAttributes
|
|
210
210
|
): PropertyAttribute | null {
|
|
211
211
|
const attributeValues = featureAttributes[attributeName];
|
|
212
|
-
const info = attributeStorageInfo.find(
|
|
212
|
+
const info = attributeStorageInfo.find(e => e.name === attributeName);
|
|
213
213
|
if (!info) {
|
|
214
214
|
return null;
|
|
215
215
|
}
|
|
@@ -477,6 +477,6 @@ export class Tiles3DContentConverter {
|
|
|
477
477
|
*/
|
|
478
478
|
_checkNormals(normals) {
|
|
479
479
|
// If all normals === 0, the resulting tileset is all in black colors on Cesium
|
|
480
|
-
return normals.find(
|
|
480
|
+
return normals.find(value => value);
|
|
481
481
|
}
|
|
482
482
|
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {parseWKTCRS, type WKTCRSNode} from '@math.gl/crs';
|
|
6
|
+
import {getSpatialCoordinateFrame} from '@loaders.gl/tiles';
|
|
7
|
+
|
|
8
|
+
/** Horizontal CRS declarations consumed by the legacy I3S converter. */
|
|
9
|
+
export type I3SConversionSpatialReference = {
|
|
10
|
+
/** Layer-level horizontal coordinate reference system. */
|
|
11
|
+
spatialReference?: {
|
|
12
|
+
/** Original spatial reference identifier. */
|
|
13
|
+
wkid?: number;
|
|
14
|
+
/** Current spatial reference identifier. */
|
|
15
|
+
latestWkid?: number;
|
|
16
|
+
/** Custom spatial reference definition. */
|
|
17
|
+
wkt?: string;
|
|
18
|
+
};
|
|
19
|
+
/** Fallback CRS declaration on the layer extent. */
|
|
20
|
+
fullExtent?: {
|
|
21
|
+
/** Coordinate system shared by the extent and layer. */
|
|
22
|
+
spatialReference?: I3SConversionSpatialReference['spatialReference'];
|
|
23
|
+
};
|
|
24
|
+
/** Coordinate systems declared for node bounds and geometry. */
|
|
25
|
+
store?: {
|
|
26
|
+
/** Coordinate system used by node bounds. */
|
|
27
|
+
indexCRS?: string;
|
|
28
|
+
/** Coordinate system used by geometry positions. */
|
|
29
|
+
vertexCRS?: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Reject explicit horizontal CRS declarations that the legacy converter cannot transform.
|
|
35
|
+
* Undeclared CRS metadata retains the historical WGS-84 assumption.
|
|
36
|
+
* @param layer - Source layer metadata, before interpreting any coordinates as longitude/latitude.
|
|
37
|
+
*/
|
|
38
|
+
export function validateI3SConversionSpatialReference(layer: I3SConversionSpatialReference): void {
|
|
39
|
+
const spatialReferences = [layer.spatialReference, layer.fullExtent?.spatialReference];
|
|
40
|
+
const unsupportedSpatialReference = spatialReferences.find(spatialReference => {
|
|
41
|
+
if (!spatialReference) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const identifier = spatialReference.latestWkid ?? spatialReference.wkid;
|
|
45
|
+
return (
|
|
46
|
+
(identifier !== undefined && identifier !== 4326 && identifier !== 4979) ||
|
|
47
|
+
(spatialReference.wkt !== undefined && !isWgs84GeographicWkt(spatialReference.wkt))
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
const declarations = [layer.store?.indexCRS, layer.store?.vertexCRS].filter(
|
|
51
|
+
(declaration): declaration is string => Boolean(declaration)
|
|
52
|
+
);
|
|
53
|
+
const unsupportedDeclaration = declarations.find(
|
|
54
|
+
declaration =>
|
|
55
|
+
!/^(?:EPSG:(?:4326|4979)|urn:ogc:def:crs:EPSG::(?:4326|4979)|https?:\/\/www\.opengis\.net\/def\/crs\/EPSG\/0\/(?:4326|4979)\/?)$/i.test(
|
|
56
|
+
declaration
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
if (unsupportedSpatialReference || unsupportedDeclaration) {
|
|
60
|
+
const identifier = unsupportedSpatialReference?.latestWkid ?? unsupportedSpatialReference?.wkid;
|
|
61
|
+
const description =
|
|
62
|
+
unsupportedDeclaration || (identifier !== undefined ? `EPSG:${identifier}` : 'custom WKT');
|
|
63
|
+
throw new Error(
|
|
64
|
+
`The legacy I3S-to-3D Tiles converter requires WGS-84 (EPSG:4326) input; received ${description}. Reproject the source I3S dataset to EPSG:4326 before conversion.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Recognize geographic WGS-84 WKT with degree units and the Greenwich prime meridian. */
|
|
70
|
+
function isWgs84GeographicWkt(wellKnownText: string): boolean {
|
|
71
|
+
try {
|
|
72
|
+
if (getSpatialCoordinateFrame(wellKnownText) !== 'geographic') {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const {root} = parseWKTCRS(wellKnownText);
|
|
76
|
+
const nodes = collectWktNodes(root);
|
|
77
|
+
const datum = root.values.find(
|
|
78
|
+
value =>
|
|
79
|
+
value.type === 'node' &&
|
|
80
|
+
['DATUM', 'ENSEMBLE', 'GEODETICDATUM'].includes(value.keyword.toUpperCase())
|
|
81
|
+
);
|
|
82
|
+
if (datum?.type !== 'node' || datum.values[0]?.type !== 'string') {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const datumName = datum.values[0].value.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
86
|
+
if (
|
|
87
|
+
![
|
|
88
|
+
'wgs84',
|
|
89
|
+
'wgs1984',
|
|
90
|
+
'dwgs1984',
|
|
91
|
+
'worldgeodeticsystem1984',
|
|
92
|
+
'worldgeodeticsystem1984ensemble'
|
|
93
|
+
].includes(datumName)
|
|
94
|
+
) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const angularUnits = nodes.filter(
|
|
98
|
+
node =>
|
|
99
|
+
['UNIT', 'ANGLEUNIT'].includes(node.keyword.toUpperCase()) &&
|
|
100
|
+
(node === root || root.values.includes(node) || node.keyword.toUpperCase() === 'ANGLEUNIT')
|
|
101
|
+
);
|
|
102
|
+
const primeMeridian = nodes.find(node => node.keyword.toUpperCase() === 'PRIMEM');
|
|
103
|
+
return (
|
|
104
|
+
angularUnits.length > 0 &&
|
|
105
|
+
angularUnits.every(
|
|
106
|
+
node =>
|
|
107
|
+
node.values[1]?.type === 'number' &&
|
|
108
|
+
Math.abs(node.values[1].value - Math.PI / 180) < 1e-12
|
|
109
|
+
) &&
|
|
110
|
+
(!primeMeridian ||
|
|
111
|
+
(primeMeridian.values[1]?.type === 'number' && primeMeridian.values[1].value === 0))
|
|
112
|
+
);
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Collect WKT nodes for semantic checks without inspecting quoted text as syntax. */
|
|
119
|
+
function collectWktNodes(node: WKTCRSNode): WKTCRSNode[] {
|
|
120
|
+
return [
|
|
121
|
+
node,
|
|
122
|
+
...node.values.flatMap(value => (value.type === 'node' ? collectWktNodes(value) : []))
|
|
123
|
+
];
|
|
124
|
+
}
|
|
@@ -22,21 +22,21 @@ const TILE = () => ({
|
|
|
22
22
|
},
|
|
23
23
|
children: {
|
|
24
24
|
path: 'children',
|
|
25
|
-
transform:
|
|
25
|
+
transform: val => val.map(tile => transform(tile, TILE()))
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
export const TILESET = () => ({
|
|
30
30
|
asset: {
|
|
31
31
|
path: 'asset',
|
|
32
|
-
transform:
|
|
32
|
+
transform: val => transform(val, ASSET())
|
|
33
33
|
},
|
|
34
34
|
geometricError: {
|
|
35
35
|
path: 'root',
|
|
36
|
-
transform:
|
|
36
|
+
transform: val => val.geometricError
|
|
37
37
|
},
|
|
38
38
|
root: {
|
|
39
39
|
path: 'root',
|
|
40
|
-
transform:
|
|
40
|
+
transform: val => transform(val, TILE())
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -152,7 +152,7 @@ async function main() {
|
|
|
152
152
|
await convert(validatedOptions);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
main().catch(
|
|
155
|
+
main().catch(error => {
|
|
156
156
|
console.log(error);
|
|
157
157
|
process.exit(1); // eslint-disable-line no-process-exit
|
|
158
158
|
});
|
|
@@ -280,13 +280,13 @@ function validateOptions(
|
|
|
280
280
|
inputType: {
|
|
281
281
|
getMessage: () =>
|
|
282
282
|
console.log('Missed/Incorrect: --input-type [tileset input type: I3S or 3DTILES]'),
|
|
283
|
-
condition:
|
|
283
|
+
condition: value =>
|
|
284
284
|
addHash || (Boolean(value) && Object.values(TILESET_TYPE).includes(value.toUpperCase()))
|
|
285
285
|
},
|
|
286
286
|
outputVersion: {
|
|
287
287
|
getMessage: () =>
|
|
288
288
|
console.log('Incorrect: --output-version [1.0 or 1.1] is for --input-type "I3S" only'),
|
|
289
|
-
condition:
|
|
289
|
+
condition: value =>
|
|
290
290
|
addHash ||
|
|
291
291
|
(Boolean(value) &&
|
|
292
292
|
Object.values(['1.0', '1.1']).includes(value) &&
|
|
@@ -307,7 +307,7 @@ function validateOptions(
|
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
if (exceptions.length) {
|
|
310
|
-
exceptions.forEach(
|
|
310
|
+
exceptions.forEach(exeption => exeption());
|
|
311
311
|
process.exit(1); // eslint-disable-line no-process-exit
|
|
312
312
|
}
|
|
313
313
|
return <ValidatedTileConversionOptions>options;
|
|
@@ -48,13 +48,13 @@ export class DepsInstaller {
|
|
|
48
48
|
await this.installFromNpm('draco', 'draco-worker-node.js');
|
|
49
49
|
|
|
50
50
|
console.log('Installing "Draco Writer" worker'); // eslint-disable-line no-console
|
|
51
|
-
await this.installFromNpm('draco', 'draco-writer-worker-node.
|
|
51
|
+
await this.installFromNpm('draco', 'draco-writer-worker-node.cjs');
|
|
52
52
|
|
|
53
53
|
console.log('Installing "Basis Loader" worker'); // eslint-disable-line no-console
|
|
54
|
-
await this.installFromNpm('textures', 'basis-worker-node.
|
|
54
|
+
await this.installFromNpm('textures', 'basis-worker-node.cjs');
|
|
55
55
|
|
|
56
56
|
console.log('Installing "KTX2 Basis Writer" worker'); // eslint-disable-line no-console
|
|
57
|
-
await this.installFromNpm('textures', 'ktx2-basis-writer-worker-node.
|
|
57
|
+
await this.installFromNpm('textures', 'ktx2-basis-writer-worker-node.cjs');
|
|
58
58
|
|
|
59
59
|
console.log('Installing "Draco decoder" library'); // eslint-disable-line no-console
|
|
60
60
|
await this.installFromUrl(
|
|
@@ -101,13 +101,16 @@ export class DepsInstaller {
|
|
|
101
101
|
console.log('All dependencies were installed succesfully.'); // eslint-disable-line no-console
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/** Download a published worker or library into the converter's local resource directory. */
|
|
104
105
|
private async installFromNpm(module: string, name: string, extraPath: string = '') {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
);
|
|
106
|
+
const resourcePath = ['dist', extraPath, name].filter(Boolean).join('/');
|
|
107
|
+
const resourceUrl = `https://unpkg.com/@loaders.gl/${module}@${VERSION}/${resourcePath}`;
|
|
108
|
+
const fileResponse = await fetchFile(resourceUrl);
|
|
108
109
|
|
|
109
110
|
if (fileResponse.status < 200 || fileResponse.status >= 300) {
|
|
110
|
-
throw new Error(
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Failed to load resource ${name} from ${resourceUrl}: HTTP ${fileResponse.status}`
|
|
113
|
+
);
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
const fileData = await fileResponse.arrayBuffer();
|
|
@@ -74,7 +74,7 @@ export class AttributeMetadataInfo {
|
|
|
74
74
|
/*
|
|
75
75
|
We will append a new attribute only in case it has not been added to the attribute storage info yet.
|
|
76
76
|
*/
|
|
77
|
-
const elementFound = this._attributeStorageInfo.find(
|
|
77
|
+
const elementFound = this._attributeStorageInfo.find(element => element.name === key);
|
|
78
78
|
if (!elementFound) {
|
|
79
79
|
const attributeType = attributeTypes[key];
|
|
80
80
|
|
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
} from '@loaders.gl/gltf';
|
|
11
11
|
import {EXT_MESH_FEATURES, EXT_FEATURE_METADATA} from '@loaders.gl/gltf';
|
|
12
12
|
import {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
13
|
-
import {emod} from '@
|
|
13
|
+
import {emod} from '@math.gl/geometry-utils';
|
|
14
14
|
import {TypedArray} from '@math.gl/core';
|
|
15
15
|
import {TextureImageProperties} from '../types';
|
|
16
16
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encodes I3S string attributes as little-endian counts followed by UTF-8 strings.
|
|
3
|
+
* Each string's byte count includes its trailing null byte. Values retain the
|
|
4
|
+
* converter's existing JavaScript string coercion, including null and undefined.
|
|
5
|
+
*/
|
|
6
|
+
export function encodeStringAttribute(values: readonly unknown[]): ArrayBuffer {
|
|
7
|
+
const textEncoder = new TextEncoder();
|
|
8
|
+
const encodedValues = Array.from(values, value => textEncoder.encode(`${String(value)}\0`));
|
|
9
|
+
const stringByteLength = encodedValues.reduce((total, value) => total + value.byteLength, 0);
|
|
10
|
+
const headerByteLength = (2 + values.length) * Uint32Array.BYTES_PER_ELEMENT;
|
|
11
|
+
const output = new Uint8Array(headerByteLength + stringByteLength);
|
|
12
|
+
const header = new DataView(output.buffer);
|
|
13
|
+
header.setUint32(0, values.length, true);
|
|
14
|
+
header.setUint32(4, stringByteLength, true);
|
|
15
|
+
|
|
16
|
+
let byteOffset = headerByteLength;
|
|
17
|
+
for (const [index, encodedValue] of encodedValues.entries()) {
|
|
18
|
+
header.setUint32(8 + index * Uint32Array.BYTES_PER_ELEMENT, encodedValue.byteLength, true);
|
|
19
|
+
output.set(encodedValue, byteOffset);
|
|
20
|
+
byteOffset += encodedValue.byteLength;
|
|
21
|
+
}
|
|
22
|
+
return output.buffer;
|
|
23
|
+
}
|
|
@@ -211,7 +211,7 @@ function unifyObjectsByFeatureId(
|
|
|
211
211
|
attributes: GroupedByFeatureIdAttributes[];
|
|
212
212
|
}[] = [];
|
|
213
213
|
for (const data of sortedData) {
|
|
214
|
-
const existingObject = groupedMetadata.find(
|
|
214
|
+
const existingObject = groupedMetadata.find(obj => obj.featureId === data.featureId);
|
|
215
215
|
if (existingObject) {
|
|
216
216
|
existingObject.attributes.push(data);
|
|
217
217
|
} else {
|