diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md index 0171c3aa..caf4601a 100644 --- a/IMPLEMENTATION.md +++ b/IMPLEMENTATION.md @@ -9,29 +9,51 @@ Parts of the current implementation may still change. This page is only a short - `./src/base`: Generic, low-level utility functions. Most of the functions here are grouped into classes. - `Buffers`: Padding, detecting GZIPpedness, obtaining "magic" bytes... + - `DataError`: An error indicating that input data was invalid on a low level (e.g. invalid binary data, or unparseable JSON) - `DeveloperError`: An error that was caused by the _developer_ (i.e. someone used the API in a wrong way) - `Iterables`: Iterating over files, filtering, mapping... - `Paths`: Resolving, checking/changing file extensions, ... - `Uris`: Detect data URIs or absolute URIs - Special cases: `defined` and `defaultValue`. These have some documentation explaining why they should rarely be used in TypeScript. -- `./src/contentOperations`: Operations that are applied to tile content - - `ContentOps`: Functions like ZIP/unZIP, conversions like `glbToB3dm`, _always_ operating on buffers: "Buffer in - Buffer out" +- `./src/contentProcessing`: Operations that are applied to tile content + - `ContentOps`: Functions like `glbToB3dm`, _always_ operating on buffers: "Buffer in - Buffer out" - `GltfUtilites`/`GltfPipelineLegacy`: Wrappers around `gltf-pipeline` (e.g. for optimizing/upgrading the GLB in a B3DM) - `./src/contentTypes`: Classes for determining the type of content data - `ContentData` as the main interface, implemented as `BufferedContentData` (to be created from a buffer that already exists in memory), or `LazyContentData` (that resolves "as little data as possible" to determine the content type) - - `ContentDataTypeRegistry`: Receives a `ContentData` object and returns a string that indicates the type, like `CONTENT_TYPE_B3DM` or `CONTENT_TYPE_TILESET`. + - `ContentDataTypes`: A set of strings representing different content data types, like `CONTENT_TYPE_B3DM` or `CONTENT_TYPE_TILESET`. + - `ContentDataTypeRegistry`: Receives a `ContentData` object and returns one of the `ContentDataTypes` strings - `ContentDataTypeChecks`: Offers methods to create predicates that check for certain `included/excluded` content types +- `./src/implicitTiling/`: Classes that represent the structure and information of implicit tilesets + - `AvailabilityInfo`: A simple interface for representing information about the availability of tiles, content, or child subtrees in implicit tiling. This is accessed with an _index_. Instances of classes implementing this interface can be created with the `AvailabilityInfos` class. + - `SubtreeInfo`: A structure that combines the `AvailabilityInfo` for tiles, content, and child subtrees (as it is defined in the input data). Instances of this structure can be created from a subtree JSON file or from binary subtree data, using the `SubtreeInfos` class. + - `BinarySubtreeData`: A simple structure from which the `SubtreeInfo` is created. It combines the data that represents a 'subtree' in implicit tiling, in its 'raw' form: It contains the `Subtree` JSON object, as well as a `BinaryBufferStructure`/`BinaryBufferData` that was created from the `buffers/bufferViews` and the resolved binary data + - `BinarySubtreeDataResolver`: A class that receives a `Subtree` JSON object, and returns the `BinarySubtreeData`, resolving all external `buffer.uri` references + - `ImplicitTilingError`: An error indicating that implicit tiling data was structurally invalid + - `ImplicitTilings`: Methods that try to hide the difference between `QUADTREE` and `OCTREE` tilings. They usually receive a `TileImplicitTiling` JSON object, and perform operations that _depend_ on the `subdivisionScheme`, but can be applied _agnostically_ of the subvision scheme. (Note: Some of this could be done in a cleaner and more generic way, involving ... generics (sic). This _does_ already exist (in a different language), but carrying type parameters along, as in `Availability>` can look obscure and "overengineered" at the first glance. I only hope that the current solution here does not turn out to be _underengineered_ ...) + - `TemplateUris`: Internal method to substitute quadtree- or octree coordinates into template URIs + - `./src/io`: Classes for "loading data" in a very generic way, from different sources - `ResourceResolver` is the main interface, with the core functionality of receiving a URI and returning the data for that URI, with implementations to obtain that data e.g. from a file system or from a 3D Tiles Package. +- `./src/metadata/`: Classes for an implementation of the 3D Metadata Specification + - Utilities for dealing with the JSON representations of metadata objects `ClassProperties`/`MetadataTypes`/`MetadataComponentTypes`... + - Internal utilities for processing metadata values (e.g. normalization, `offset` and `scale` etc.), in `MetadataValues` and `ArrayValues`. + - The `PropertyTableModel`, `MetadataEntityModel` and `PropertyModel` interfaces offer a very thin and simple abstraction layer for 3D Metadata. The structure of these classes is shown here: + ![PropertyTable](figures/PropertyTable.png) + - Implementations of these interfaces exist: + - For the JSON-based representation of metadata entities, metadata entity model instances can be created with `MetadataEntityModels` + - `./src/metadata/binary` contains implementations of the metadata interfaces for _binary_ data, with `BinaryPropertyTableModel` being the top-level class, implementing the `PropertyTableModel` interface. + - `./src/packages`: Classes for reading or creating 3D Tiles Package files - These are implementations of the `TilesetSource` and `TilesetTarget` interface (see `./src/tilesetData`), based on 3TZ or 3DTILES - `./src/pipelines`: **Preliminary** classes for modeling "processing pipelines" for tilesets +- `./src/spatial`: Basic classes for dealing with tree structures, specifically with quadtrees and octrees + - `./src/structure`: Plain old data objects for the elements of a Tileset JSON - E.g. `Tileset`, `Tile`, `Content`, ... - The goal is to have a _typed_ representation of a tileset JSON (assuming that the input JSON was indeed structurally valid - there are no validations or actual type checks during deserialization) @@ -56,6 +78,11 @@ Parts of the current implementation may still change. This page is only a short - `Tiles` for traversing (explicit!) tile hierarchies - `Tilesets` offering convenience functions for `merge/combine/upgrade` +- `./src/traversal`: Classes for traversing tilesets + - NOTE: The `SubtreeModel`/`SubtreeMetadataModel` interfaces _might_ at some point be moved into `implicitTiling`, but are currently tailored for the use in the traversal classes, and should be considered to be an "implementation detail" here. + - The `TilesetTraverser` class is the entry point for the traversal. It allows traversing a tileset, and offer each traversed tile as a `TraversedTile` instance. The `TraversedTile` describes a tile during traversal (e.g. with a parent, and semantic-based overrides) + + ## Demos The `./demos/` folder contains demos that show how to use various parts of the API @@ -71,6 +98,8 @@ The `./demos/` folder contains demos that show how to use various parts of the A - `TileFormatsDemoConversions`: Demos showing how to use the `TileFormats` class for conversions (like extracting GLB from B3DM etc.) - `TilesetProcessingDemos`: Demos for the `combine/merge/upgrade` functions - `TilesetUpgraderDemos`: More fine-grained demos for the upgrade functionality +- `TraversalDemo`: A basic example showing how to traverse a tileset +- `TraversalStatsDemo`: A basic example showing how to traverse a tileset and collect statistical information in the process. The `./demos/benchmarks` folder contains very basic benchmarks for creating/reading different 3D Tiles package formats. diff --git a/ThirdParty.json b/ThirdParty.json index 0fced04c..6d691cd4 100644 --- a/ThirdParty.json +++ b/ThirdParty.json @@ -28,7 +28,7 @@ "license": [ "Apache-2.0" ], - "version": "1.102.0", + "version": "1.103.0", "url": "https://www.npmjs.com/package/cesium" }, { diff --git a/demos/TileFormatsDemoConversions.ts b/demos/TileFormatsDemoConversions.ts index 22983f10..80110419 100644 --- a/demos/TileFormatsDemoConversions.ts +++ b/demos/TileFormatsDemoConversions.ts @@ -2,7 +2,7 @@ import fs from "fs"; import { Paths } from "../src/base/Paths"; -import { GltfUtilities } from "../src/contentOperations/GtlfUtilities"; +import { GltfUtilities } from "../src/contentProcessing/GtlfUtilities"; import { TileFormats } from "../src/tileFormats/TileFormats"; function glbToB3dm(inputFileName: string, outputFileName: string) { diff --git a/demos/TraversalDemo.ts b/demos/TraversalDemo.ts new file mode 100644 index 00000000..d64624bd --- /dev/null +++ b/demos/TraversalDemo.ts @@ -0,0 +1,43 @@ +import path from "path"; + +import { readJsonUnchecked } from "./readJsonUnchecked"; + +import { ResourceResolvers } from "../src/io/ResourceResolvers"; +import { TilesetTraverser } from "../src/traversal/TilesetTraverser"; + +async function tilesetTraversalDemo(filePath: string) { + const directory = path.dirname(filePath); + const resourceResolver = + ResourceResolvers.createFileResourceResolver(directory); + const tileset = await readJsonUnchecked(filePath); + // Note: External schemas are not considered here + const schema = tileset.schema; + const depthFirst = false; + console.log("Traversing tileset"); + await TilesetTraverser.traverse( + tileset, + schema, + resourceResolver, + async (traversedTile) => { + const contentUris = traversedTile.getFinalContents().map((c) => c.uri); + const geometricError = traversedTile.asFinalTile().geometricError; + console.log( + ` Traversed tile: ${traversedTile}, ` + + `path: ${traversedTile.path}, ` + + `contents [${contentUris}], ` + + `geometricError ${geometricError}` + ); + return true; + }, + depthFirst + ); + console.log("Traversing tileset DONE"); +} + +async function runDemo() { + const tilesetFileName = + "../3d-tiles-samples/1.1/SparseImplicitQuadtree/tileset.json"; + await tilesetTraversalDemo(tilesetFileName); +} + +runDemo(); diff --git a/demos/TraversalStatsDemo.ts b/demos/TraversalStatsDemo.ts new file mode 100644 index 00000000..fad50e03 --- /dev/null +++ b/demos/TraversalStatsDemo.ts @@ -0,0 +1,217 @@ +import fs from "fs"; +import path from "path"; + +import { readJsonUnchecked } from "./readJsonUnchecked"; + +import { ResourceResolvers } from "../src/io/ResourceResolvers"; + +import { TilesetTraverser } from "../src/traversal/TilesetTraverser"; +import { TraversedTile } from "../src/traversal/TraversedTile"; + +// A small demo that traverses a tileset, passes all +// traversed tiles to a "StatsCollector" (defined below), +// and creates a short JSON summary of some statistics. + +async function tilesetTraversalDemo(filePath: string) { + // Read the tileset from the input path + const directory = path.dirname(filePath); + const resourceResolver = + ResourceResolvers.createFileResourceResolver(directory); + const tileset = await readJsonUnchecked(filePath); + // Note: External schemas are not considered here + const schema = tileset.schema; + + // Traverse the tileset, and pass each tile to + // the StatsCollector + console.log("Traversing tileset"); + const tilesetStatsCollector = new TilesetStatsCollector(); + const depthFirst = false; + await TilesetTraverser.traverse( + tileset, + schema, + resourceResolver, + async (traversedTile) => { + tilesetStatsCollector.accept(traversedTile); + return true; + }, + depthFirst + ); + console.log("Traversing tileset DONE"); + + // Print the statistics summary to the console + console.log("Stats:"); + const json = tilesetStatsCollector.createJson(); + const jsonString = JSON.stringify(json, null, 2); + console.log(jsonString); +} + +// A simple class to collect statistical information +class StatsCollector { + // A mapping from value names to counters + private readonly counters: { + [key: string]: Counter; + } = {}; + + // A mapping from value names to statistical summaries + private readonly summaries: { + [key: string]: Summary; + } = {}; + + // Add one entry to a summary, creating it when necessary + acceptEntry(name: string, value: number) { + let summary = this.summaries[name]; + if (!summary) { + summary = new Summary(); + this.summaries[name] = summary; + } + summary.accept(value); + } + + // Increment a counter, creating it when necessary + increment(name: string) { + let counter = this.counters[name]; + if (!counter) { + counter = new Counter(); + this.counters[name] = counter; + } + counter.increment(); + } + + // Create a short JSON representation of the collected data + createJson(): any { + const json: any = {}; + for (const key of Object.keys(this.counters)) { + const counter = this.counters[key]; + json[key] = counter.getCount(); + } + for (const key of Object.keys(this.summaries)) { + const summary = this.summaries[key]; + json[key] = { + count: summary.getCount(), + sum: summary.getSum(), + min: summary.getMinimum(), + max: summary.getMaximum(), + avg: summary.getMean(), + stdDev: summary.getStandardDeviation(), + }; + } + return json; + } +} + +/** + * A class that serves as a counter in the `StatsCollector` + */ +class Counter { + private count: number; + + public constructor() { + this.count = 0; + } + + increment() { + this.count++; + } + + getCount() { + return this.count; + } +} + +/** + * A class that can accept numbers, and collects statistical + * information for these numbers. + */ +class Summary { + private count: number; + private sum: number; + private min: number; + private max: number; + private varianceTracker: number; + + public constructor() { + this.count = 0; + this.sum = 0.0; + this.min = Number.POSITIVE_INFINITY; + this.max = Number.NEGATIVE_INFINITY; + this.varianceTracker = 0.0; + } + + accept(value: number) { + const deviation = value - this.getMean(); + this.sum += value; + this.min = Math.min(this.min, value); + this.max = Math.max(this.max, value); + this.count++; + if (this.count > 1) { + this.varianceTracker += + (deviation * deviation * (this.count - 1)) / this.count; + } + } + + getCount() { + return this.count; + } + + getSum() { + return this.sum; + } + + getMinimum() { + return this.min; + } + + getMaximum() { + return this.max; + } + + getMean() { + return this.sum / this.count; + } + + getStandardDeviation() { + return Math.sqrt(this.varianceTracker / this.count); + } +} + +// A specialization of the `StatsColleror` that collects +// information about the tiles that are traversed with +// a TilesetTraverser +class TilesetStatsCollector extends StatsCollector { + // Accept the given tile during traversal, and collect + // statistical information + accept(traversedTile: TraversedTile) { + this.increment("totalNumberOfTiles"); + + // NOTE: This is a means of checking whether a tile + // is the root of an implicit tileset. This may be + // refactored at some point. + if (traversedTile.getImplicitTiling()) { + this.increment("totalNumberOfSubtres"); + } else { + // Obtain all content URIs, resolve them, and obtain + // the sizes of the corresponding files, storing them + // in the "tileFileSize" summary + const contentUris = traversedTile.getFinalContents().map((c) => c.uri); + for (const contentUri of contentUris) { + const resolvedContentUri = traversedTile.resolveUri(contentUri); + const stats = fs.statSync(resolvedContentUri); + const tileFileSizeInBytes = stats.size; + this.acceptEntry("tileFileSize", tileFileSizeInBytes); + } + } + + // Store the geometric error in the "geometricError" summary + const finalTile = traversedTile.asFinalTile(); + const geometricError = finalTile.geometricError; + this.acceptEntry("geometricError", geometricError); + } +} + +async function runDemo() { + const tilesetFileName = + "../3d-tiles-samples/1.1/SparseImplicitQuadtree/tileset.json"; + await tilesetTraversalDemo(tilesetFileName); +} + +runDemo(); diff --git a/demos/readJsonUnchecked.ts b/demos/readJsonUnchecked.ts new file mode 100644 index 00000000..6596ea65 --- /dev/null +++ b/demos/readJsonUnchecked.ts @@ -0,0 +1,27 @@ +import fs from "fs"; + +/** + * Only for internal use and basic tests: + * + * Reads a JSON file, parses it, and returns the result. + * If the file cannot be read or parsed, then an error + * message will be printed and `undefined` is returned. + * + * @param filePath - The path to the file + * @returns A promise that resolves with the result or `undefined` + */ +export async function readJsonUnchecked(filePath: string): Promise { + try { + const data = fs.readFileSync(filePath); + if (!data) { + console.error("Could not read " + filePath); + return undefined; + } + const jsonString = data.toString(); + const result = JSON.parse(jsonString); + return result; + } catch (error) { + console.error("Could not parse JSON", error); + return undefined; + } +} diff --git a/etc/3d-tiles-tools.api.md b/etc/3d-tiles-tools.api.md index c28a04d8..b0acc469 100644 --- a/etc/3d-tiles-tools.api.md +++ b/etc/3d-tiles-tools.api.md @@ -28,6 +28,20 @@ export class ArchiveFunctions3tz { static zipIndexFind(zipIndex: IndexEntry[], searchHash: Buffer): number; } +// Warning: (ae-internal-missing-underscore) The name "ArrayValues" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class ArrayValues { + static anyDeepGreaterThan(a: any, b: any): boolean; + static anyDeepLessThan(a: any, b: any): boolean; + static deepAdd(value: any, addend: any): any; + static deepClone(value: any): any; + static deepEquals(a: any, b: any): boolean; + static deepMax(a: any, b: any): any; + static deepMin(a: any, b: any): any; + static deepMultiply(value: any, factor: any): any; +} + // Warning: (ae-internal-missing-underscore) The name "Asset" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -50,6 +64,113 @@ export interface Availability extends RootProperty { constant?: number; } +// Warning: (ae-internal-missing-underscore) The name "AvailabilityInfo" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface AvailabilityInfo { + isAvailable(index: number): boolean; + get length(): number; +} + +// Warning: (ae-internal-missing-underscore) The name "AvailabilityInfos" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class AvailabilityInfos { + static createChildSubtree(availability: Availability, bufferViewDatas: Buffer[], implicitTiling: TileImplicitTiling): AvailabilityInfo; + static createTileOrContent(availability: Availability, bufferViewDatas: Buffer[], implicitTiling: TileImplicitTiling): AvailabilityInfo; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryBufferData" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface BinaryBufferData { + buffersData: Buffer[]; + bufferViewsData: Buffer[]; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryBufferDataResolver" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class BinaryBufferDataResolver { + static resolve(binaryBufferStructure: BinaryBufferStructure, binaryBuffer: Buffer | undefined, resourceResolver: ResourceResolver): Promise; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryBuffers" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class BinaryBuffers { + static createBinaryBufferStructure(binaryBufferData: BinaryBufferData, newBufferViewsData: Buffer[]): BinaryBufferStructure; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryBufferStructure" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface BinaryBufferStructure { + // (undocumented) + buffers: BufferObject[]; + // (undocumented) + bufferViews: BufferView[]; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryDataError" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class BinaryDataError extends Error { + constructor(message: string); + // (undocumented) + toString: () => string; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryPropertyTable" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface BinaryPropertyTable { + binaryBufferData: BinaryBufferData; + binaryBufferStructure: BinaryBufferStructure; + // Warning: (ae-forgotten-export) The symbol "BinaryEnumInfo" needs to be exported by the entry point index.d.ts + binaryEnumInfo: BinaryEnumInfo; + metadataClass: MetadataClass; + propertyTable: PropertyTable; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryPropertyTableModel" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class BinaryPropertyTableModel implements PropertyTableModel { + constructor(binaryPropertyTable: BinaryPropertyTable); + getClassProperty(propertyId: string): ClassProperty | undefined; + getMetadataEntityModel(index: number): MetadataEntityModel; + getPropertyModel(propertyId: string): PropertyModel | undefined; + getPropertyTableProperty(propertyId: string): PropertyTableProperty | undefined; +} + +// Warning: (ae-internal-missing-underscore) The name "BinaryPropertyTables" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class BinaryPropertyTables { + static createBinaryPropertyTable(schema: Schema, className: string, propertyName: string, values: any, arrayOffsetType: string | undefined, stringOffsetType: string | undefined): BinaryPropertyTable; + static createBinaryPropertyTableFromProperty(propertyName: string, classProperty: ClassProperty, values: any, arrayOffsetType: string | undefined, stringOffsetType: string | undefined, metadataEnum: MetadataEnum | undefined): BinaryPropertyTable; + static createSchemaFromClassProperty(propertyName: string, classProperty: ClassProperty, metadataEnum: MetadataEnum | undefined): Schema; +} + +// Warning: (ae-internal-missing-underscore) The name "BinarySubtreeData" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface BinarySubtreeData { + binaryBufferData: BinaryBufferData; + binaryBufferStructure: BinaryBufferStructure; + subtree: Subtree; +} + +// Warning: (ae-internal-missing-underscore) The name "BinarySubtreeDataResolver" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class BinarySubtreeDataResolver { + static resolveFromBuffer(input: Buffer, resourceResolver: ResourceResolver): Promise; + static resolveFromJson(subtree: Subtree, resourceResolver: ResourceResolver): Promise; + static resolveInternal(subtree: Subtree, binaryBuffer: Buffer | undefined, resourceResolver: ResourceResolver): Promise; +} + // Warning: (ae-internal-missing-underscore) The name "BoundingVolume" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -78,11 +199,14 @@ export interface BufferObject extends RootProperty { // // @internal export class Buffers { + static createBinaryString(buffer: Buffer): string; static getBufferPadded(buffer: Buffer, byteOffset?: number): Buffer; static getJson(buffer: Buffer): any; static getJsonBufferPadded(json: any, byteOffset?: number): Buffer; static getMagic(buffer: Buffer, byteOffset?: number): string; static getUnicodeBOMDescription(buffer: Buffer): string | undefined; + static gunzip(inputBuffer: Buffer): Buffer; + static gzip(inputBuffer: Buffer): Buffer; static isGzipped(buffer: Buffer): boolean; static isProbablyJson(buffer: Buffer): boolean; } @@ -101,6 +225,14 @@ export interface BufferView extends RootProperty { name?: string; } +// Warning: (ae-internal-missing-underscore) The name "ClassProperties" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class ClassProperties { + static hasEffectivelyFloatingPointType(property: ClassProperty): boolean; + static hasNumericType(property: ClassProperty): boolean; +} + // Warning: (ae-internal-missing-underscore) The name "ClassProperty" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -172,6 +304,17 @@ export class ContentDataTypeRegistry { static findContentDataType(contentData: ContentData): Promise; } +// Warning: (ae-internal-missing-underscore) The name "DefaultMetadataEntityModel" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class DefaultMetadataEntityModel implements MetadataEntityModel { + constructor(metadataClass: MetadataClass, semanticToPropertyId: { + [key: string]: string; + }, json: any); + getPropertyValue(propertyId: string): any; + getPropertyValueBySemantic(semantic: string): any; +} + // Warning: (ae-internal-missing-underscore) The name "defaultValue" should be prefixed with an underscore because the declaration is marked as @internal // // @internal @@ -180,7 +323,7 @@ export function defaultValue(a: T | undefined, b: T): T; // Warning: (ae-internal-missing-underscore) The name "defined" should be prefixed with an underscore because the declaration is marked as @internal // // @internal -export function defined(value: any): value is NonNullable; +export function defined(value: T): value is NonNullable; // Warning: (ae-internal-missing-underscore) The name "DeveloperError" should be prefixed with an underscore because the declaration is marked as @internal // @@ -203,18 +346,47 @@ export interface EnumValue extends RootProperty { value: number; } +// Warning: (ae-internal-missing-underscore) The name "ExplicitTraversedTile" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class ExplicitTraversedTile implements TraversedTile { + constructor(tile: Tile, path: string, level: number, parent: TraversedTile | undefined, schema: Schema | undefined, resourceResolver: ResourceResolver); + asFinalTile(): Tile; + asRawTile(): Tile; + getChildren(): Promise; + // (undocumented) + getFinalContents(): Content[]; + // (undocumented) + getImplicitTiling(): TileImplicitTiling | undefined; + // (undocumented) + getMetadata(): MetadataEntity | undefined; + getParent(): TraversedTile | undefined; + getRawContents(): Content[]; + // (undocumented) + getSubtreeUri(): string | undefined; + get level(): number; + get path(): string; + // (undocumented) + resolveUri(uri: string): string; + // (undocumented) + toString: () => string; +} + +// Warning: (ae-internal-missing-underscore) The name "ExplicitTraversedTiles" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class ExplicitTraversedTiles { + static createTraversedChildren(implicitTiling: TileImplicitTiling, schema: Schema | undefined, parent: ExplicitTraversedTile, resourceResolver: ResourceResolver): Promise; +} + // Warning: (ae-internal-missing-underscore) The name "FileResourceResolver" should be prefixed with an underscore because the declaration is marked as @internal // // @internal export class FileResourceResolver implements ResourceResolver { constructor(basePath: string); - // (undocumented) derive(uri: string): ResourceResolver; - // (undocumented) resolveData(uri: string): Promise; - // (undocumented) resolveDataPartial(uri: string, maxBytes: number): Promise; - // (undocumented) resolveUri(uri: string): string; } @@ -224,6 +396,56 @@ export class FileResourceResolver implements ResourceResolver { export interface Group extends MetadataEntity { } +// Warning: (ae-internal-missing-underscore) The name "ImplicitTilingError" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class ImplicitTilingError extends Error { + constructor(message: string); + // (undocumented) + toString: () => string; +} + +// Warning: (ae-internal-missing-underscore) The name "ImplicitTilings" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class ImplicitTilings { + static computeNumberOfNodesInLevel(implicitTiling: TileImplicitTiling, level: number): number; + static computeNumberOfNodesPerSubtree(implicitTiling: TileImplicitTiling): number; + static createRootCoordinates(implicitTiling: TileImplicitTiling): TreeCoordinates; + static createString(coordinates: TreeCoordinates): string; + static createSubtreeCoordinatesIterator(implicitTiling: TileImplicitTiling): IterableIterator; + static globalizeCoordinates(implicitTiling: TileImplicitTiling, rootCoordinates: TreeCoordinates, coordinates: TreeCoordinates): TreeCoordinates; + static substituteTemplateUri(subdivisionScheme: string, templateUri: string, coordinates: TreeCoordinates): string; +} + +// Warning: (ae-internal-missing-underscore) The name "ImplicitTraversedTile" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class ImplicitTraversedTile implements TraversedTile { + constructor(implicitTiling: TileImplicitTiling, resourceResolver: ResourceResolver, root: TraversedTile, path: string, subtreeModel: SubtreeModel, globalLevel: number, globalCoordinate: TreeCoordinates, rootCoordinate: TreeCoordinates, localCoordinate: TreeCoordinates, parent: TraversedTile); + asFinalTile(): Tile; + asRawTile(): Tile; + getChildren(): Promise; + // (undocumented) + getFinalContents(): Content[]; + getGlobalCoordinate(): TreeCoordinates; + // (undocumented) + getImplicitTiling(): TileImplicitTiling | undefined; + getLocalCoordinate(): TreeCoordinates; + // (undocumented) + getMetadata(): MetadataEntity | undefined; + getParent(): TraversedTile | undefined; + getRawContents(): Content[]; + // (undocumented) + getSubtreeUri(): string | undefined; + get level(): number; + get path(): string; + // (undocumented) + resolveUri(uri: string): string; + // (undocumented) + toString: () => string; +} + // Warning: (ae-internal-missing-underscore) The name "IndexBuilder" should be prefixed with an underscore because the declaration is marked as @internal // // @internal @@ -261,6 +483,19 @@ export class Iterables { static overFiles(directory: string | PathLike, recurse?: boolean): IterableIterator; } +// Warning: (ae-internal-missing-underscore) The name "LazyContentData" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class LazyContentData implements ContentData { + constructor(uri: string, resourceResolver: ResourceResolver); + exists(): Promise; + get extension(): string; + getData(): Promise; + getMagic(): Promise; + getParsedObject(): Promise; + get uri(): string; +} + // Warning: (ae-internal-missing-underscore) The name "MetadataClass" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -275,6 +510,20 @@ export interface MetadataClass extends RootProperty { }; } +// Warning: (ae-internal-missing-underscore) The name "MetadataComponentTypes" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class MetadataComponentTypes { + static allComponentTypes: string[]; + static byteSizeForComponentType(componentType: string): number; + static integerComponentTypes: string[]; + static isIntegerComponentType(componentType: string | undefined): boolean; + static isUnsignedComponentType(componentType: string | undefined): boolean; + // (undocumented) + static normalize(value: number, componentType: string | undefined): number; + static unsignedComponentTypes: string[]; +} + // Warning: (ae-internal-missing-underscore) The name "MetadataEntity" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -287,6 +536,27 @@ export interface MetadataEntity extends RootProperty { }; } +// Warning: (ae-internal-missing-underscore) The name "MetadataEntityModel" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface MetadataEntityModel { + getPropertyValue(propertyId: string): any; + getPropertyValueBySemantic(semantic: string): any; +} + +// Warning: (ae-internal-missing-underscore) The name "MetadataEntityModels" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class MetadataEntityModels { + static computeSemanticToPropertyIdMapping(metadataClass: MetadataClass): { + [key: string]: string; + }; + static create(schema: Schema, entity: MetadataEntity): MetadataEntityModel; + static createFromClass(metadataClass: MetadataClass, entityProperties: { + [key: string]: any; + }): DefaultMetadataEntityModel; +} + // Warning: (ae-internal-missing-underscore) The name "MetadataEnum" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -301,6 +571,80 @@ export interface MetadataEnum extends RootProperty { valueType?: string; } +// Warning: (ae-internal-missing-underscore) The name "MetadataError" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class MetadataError extends Error { + constructor(message: string); + // (undocumented) + toString: () => string; +} + +// Warning: (ae-internal-missing-underscore) The name "MetadataTypes" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class MetadataTypes { + static allTypes: string[]; + static componentCountForType(type: string): number; + static isNumericType(type: string): boolean; + static numericTypes: string[]; +} + +// Warning: (ae-internal-missing-underscore) The name "MetadataUtilities" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class MetadataUtilities { + static computeBinaryEnumInfo(schema: Schema): BinaryEnumInfo; + static obtainEnumValueNames(classProperty: ClassProperty, schema: Schema): string[]; +} + +// Warning: (ae-internal-missing-underscore) The name "MetadataValues" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class MetadataValues { + static processValue(classProperty: ClassProperty, offsetOverride: any, scaleOverride: any, value: any): any; +} + +// Warning: (ae-internal-missing-underscore) The name "NumericBuffers" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class NumericBuffers { + static getNumericArrayFromBuffer(buffer: Buffer, index: number, arrayLength: number, componentType: string): any; + static getNumericBufferAsArray(buffer: Buffer, componentType: string): any; + static getNumericFromBuffer(buffer: Buffer, index: number, componentType: string): any; +} + +// Warning: (ae-internal-missing-underscore) The name "OctreeCoordinates" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class OctreeCoordinates implements TreeCoordinates { + constructor(level: number, x: number, y: number, z: number); + children(): IterableIterator; + descendants(maxLevelInclusive: number, depthFirst: boolean): IterableIterator; + get level(): number; + parent(): OctreeCoordinates | null; + toArray(): number[]; + toIndex(): number; + toIndexInLevel(): number; + // (undocumented) + toString: () => string; + // (undocumented) + get x(): number; + // (undocumented) + get y(): number; + // (undocumented) + get z(): number; +} + +// Warning: (ae-internal-missing-underscore) The name "Octrees" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class Octrees { + static computeNumberOfNodesForLevels(levels: number): number; + static coordinatesForLevel(level: number): Generator; + static isValid(c: OctreeCoordinates): boolean; +} + // Warning: (ae-internal-missing-underscore) The name "Paths" should be prefixed with an underscore because the declaration is marked as @internal // // @internal @@ -324,6 +668,13 @@ export interface Properties extends RootProperty { minimum: number; } +// Warning: (ae-internal-missing-underscore) The name "PropertyModel" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface PropertyModel { + getPropertyValue(index: number): any; +} + // Warning: (ae-internal-missing-underscore) The name "PropertyTable" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -340,6 +691,16 @@ export interface PropertyTable extends RootProperty { }; } +// Warning: (ae-internal-missing-underscore) The name "PropertyTableModel" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface PropertyTableModel { + getClassProperty(propertyId: string): ClassProperty | undefined; + getMetadataEntityModel(index: number): MetadataEntityModel; + getPropertyModel(propertyId: string): PropertyModel | undefined; + getPropertyTableProperty(propertyId: string): PropertyTableProperty | undefined; +} + // Warning: (ae-internal-missing-underscore) The name "PropertyTableProperty" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -364,6 +725,35 @@ export interface PropertyTableProperty extends RootProperty { values: number; } +// Warning: (ae-internal-missing-underscore) The name "QuadtreeCoordinates" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class QuadtreeCoordinates implements TreeCoordinates { + constructor(level: number, x: number, y: number); + children(): IterableIterator; + descendants(maxLevelInclusive: number, depthFirst: boolean): IterableIterator; + get level(): number; + parent(): QuadtreeCoordinates | null; + toArray(): number[]; + toIndex(): number; + toIndexInLevel(): number; + // (undocumented) + toString: () => string; + // (undocumented) + get x(): number; + // (undocumented) + get y(): number; +} + +// Warning: (ae-internal-missing-underscore) The name "Quadtrees" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class Quadtrees { + static computeNumberOfNodesForLevels(levels: number): number; + static coordinatesForLevel(level: number): Generator; + static isValid(c: QuadtreeCoordinates): boolean; +} + // Warning: (ae-internal-missing-underscore) The name "ResourceResolver" should be prefixed with an underscore because the declaration is marked as @internal // // @internal @@ -489,6 +879,57 @@ export interface Subtree extends RootProperty { tileMetadata?: number; } +// Warning: (ae-internal-missing-underscore) The name "SubtreeInfo" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface SubtreeInfo { + childSubtreeAvailabilityInfo: AvailabilityInfo; + contentAvailabilityInfos: AvailabilityInfo[]; + tileAvailabilityInfo: AvailabilityInfo; +} + +// Warning: (ae-internal-missing-underscore) The name "SubtreeInfos" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class SubtreeInfos { + static create(binarySubtreeData: BinarySubtreeData, implicitTiling: TileImplicitTiling): SubtreeInfo; + static createFromBuffer(input: Buffer, implicitTiling: TileImplicitTiling, resourceResolver: ResourceResolver): Promise; + static createFromJson(subtree: Subtree, implicitTiling: TileImplicitTiling, resourceResolver: ResourceResolver): Promise; +} + +// Warning: (ae-internal-missing-underscore) The name "SubtreeMetadataModel" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface SubtreeMetadataModel { + contentIndexMappings: number[][]; + contentMetadataModels: PropertyTableModel[]; + schema: Schema; + tileIndexMapping: number[] | undefined; + tileMetadataModel: PropertyTableModel | undefined; +} + +// Warning: (ae-internal-missing-underscore) The name "SubtreeMetadataModels" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class SubtreeMetadataModels { + static create(binarySubtreeData: BinarySubtreeData, subtreeInfo: SubtreeInfo, schema: Schema): SubtreeMetadataModel; +} + +// Warning: (ae-internal-missing-underscore) The name "SubtreeModel" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface SubtreeModel { + subtreeInfo: SubtreeInfo; + subtreeMetadataModel: SubtreeMetadataModel | undefined; +} + +// Warning: (ae-internal-missing-underscore) The name "SubtreeModels" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class SubtreeModels { + static resolve(implicitTiling: TileImplicitTiling, schema: Schema | undefined, resourceResolver: ResourceResolver, coordinates: TreeCoordinates): Promise; +} + // Warning: (ae-internal-missing-underscore) The name "Subtrees" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -497,6 +938,16 @@ export interface Subtrees extends RootProperty { uri: string; } +// Warning: (ae-internal-missing-underscore) The name "TemplateUris" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class TemplateUris { + static substituteOctree(templateUri: string, coordinates: OctreeCoordinates): string; + static substituteOctreeInternal(templateUri: string, level: number, x: number, y: number, z: number): string; + static substituteQuadtree(templateUri: string, coordinates: QuadtreeCoordinates): string; + static substituteQuadtreeInternal(templateUri: string, level: number, x: number, y: number): string; +} + // Warning: (ae-internal-missing-underscore) The name "Tile" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) @@ -597,13 +1048,9 @@ export interface TilesetSource { // @internal export class TilesetSource3dtiles implements TilesetSource { constructor(); - // (undocumented) close(): void; - // (undocumented) getKeys(): IterableIterator; - // (undocumented) getValue(key: string): Buffer | undefined; - // (undocumented) open(fullInputName: string): void; } @@ -612,15 +1059,11 @@ export class TilesetSource3dtiles implements TilesetSource { // @internal export class TilesetSource3tz implements TilesetSource { constructor(); - // (undocumented) close(): void; - // (undocumented) getKeys(): IterableIterator; - // (undocumented) getValue(key: string): Buffer | undefined; // (undocumented) getZipIndex(): IndexEntry[] | undefined; - // (undocumented) open(fullInputName: string): void; } @@ -629,13 +1072,9 @@ export class TilesetSource3tz implements TilesetSource { // @internal export class TilesetSourceFs implements TilesetSource { constructor(); - // (undocumented) close(): void; - // (undocumented) getKeys(): IterableIterator; - // (undocumented) getValue(key: string): Buffer | undefined; - // (undocumented) open(fullInputName: string): void; } @@ -644,13 +1083,9 @@ export class TilesetSourceFs implements TilesetSource { // @internal export class TilesetSourceResourceResolver implements ResourceResolver { constructor(basePath: string, tilesetSourceFileName: string, tilesetSource: TilesetSource); - // (undocumented) derive(uri: string): ResourceResolver; - // (undocumented) resolveData(uri: string): Promise; - // (undocumented) resolveDataPartial(uri: string, maxBytes: number): Promise; - // (undocumented) resolveUri(uri: string): string; } @@ -677,11 +1112,8 @@ export interface TilesetTarget { // @internal export class TilesetTarget3dtiles implements TilesetTarget { constructor(); - // (undocumented) addEntry(key: string, content: Buffer): void; - // (undocumented) begin(fullOutputName: string, overwrite: boolean): void; - // (undocumented) end(): Promise; } @@ -690,11 +1122,8 @@ export class TilesetTarget3dtiles implements TilesetTarget { // @internal export class TilesetTarget3tz implements TilesetTarget { constructor(); - // (undocumented) addEntry(key: string, content: Buffer): void; - // (undocumented) begin(fullOutputName: string, overwrite: boolean): void; - // (undocumented) end(): Promise; } @@ -703,11 +1132,8 @@ export class TilesetTarget3tz implements TilesetTarget { // @internal export class TilesetTargetFs implements TilesetTarget { constructor(); - // (undocumented) addEntry(key: string, content: Buffer): void; - // (undocumented) begin(fullOutputName: string, overwrite: boolean): void; - // (undocumented) end(): Promise; } @@ -720,18 +1146,64 @@ export class TilesetTargets { static putEntries(tilesetTarget: TilesetTarget, entries: IterableIterator): void; } +// Warning: (ae-internal-missing-underscore) The name "TilesetTraverser" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export class TilesetTraverser { + static traverse(tileset: Tileset, schema: Schema | undefined, resourceResolver: ResourceResolver, traversalCallback: TraversalCallback, depthFirst: boolean): Promise; +} + +// Warning: (ae-internal-missing-underscore) The name "TraversalCallback" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface TraversalCallback { + (traversedTile: TraversedTile): Promise; +} + +// Warning: (ae-internal-missing-underscore) The name "TraversedTile" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface TraversedTile { + asFinalTile(): Tile; + asRawTile(): Tile; + getChildren(): Promise; + // (undocumented) + getFinalContents(): Content[]; + // (undocumented) + getImplicitTiling(): TileImplicitTiling | undefined; + // (undocumented) + getMetadata(): MetadataEntity | undefined; + getParent(): TraversedTile | undefined; + getRawContents(): Content[]; + // (undocumented) + getSubtreeUri(): string | undefined; + get level(): number; + get path(): string; + // (undocumented) + resolveUri(uri: string): string; +} + +// Warning: (ae-internal-missing-underscore) The name "TreeCoordinates" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface TreeCoordinates { + children(): IterableIterator; + descendants(maxLevelInclusive: number, depthFirst: boolean): IterableIterator; + get level(): number; + parent(): TreeCoordinates | null; + toArray(): number[]; + toIndex(): number; + toIndexInLevel(): number; +} + // Warning: (ae-internal-missing-underscore) The name "UnzippingResourceResolver" should be prefixed with an underscore because the declaration is marked as @internal // // @internal export class UnzippingResourceResolver implements ResourceResolver { constructor(delegate: ResourceResolver); - // (undocumented) derive(uri: string): ResourceResolver; - // (undocumented) resolveData(uri: string): Promise; - // (undocumented) resolveDataPartial(uri: string, maxBytes: number): Promise; - // (undocumented) resolveUri(uri: string): string; } diff --git a/figures/PropertyTable.png b/figures/PropertyTable.png new file mode 100644 index 00000000..a9db2917 Binary files /dev/null and b/figures/PropertyTable.png differ diff --git a/figures/PropertyTable.svg b/figures/PropertyTable.svg new file mode 100644 index 00000000..3edbe82c --- /dev/null +++ b/figures/PropertyTable.svg @@ -0,0 +1,591 @@ + + + + + + + + + + + + + + index + 0 + "red" + "green" + "blue" + "yellow" + 1 + 2 + 2 + 1994 + 2003 + 1987 + 2012 + 3 + 1 + 2 + 3 + color + year + stories + + + + + + + + + + + PropertyTableModel + MetadataEntityModel + PropertyModel + + + + + + getPropertyModel(propertyId: string) + getMetadataEntityModel(index: number) + getPropertyValue(index: number) + Represents one property - that is, one column of the table. The values in thiscolumn can be accessed with an index. + Each column is a PropertyModel, that can be accessed with the property ID (column name). + Represents a property table with rows and columns. + Each row is a MetadataEntityModel, that canbe accessed with the row index. + Represents one metadata entity - that is,one row of the table. The values in thisentity can be accessed with a property ID. + Example: + getPropertyValue(propertyId: string) + m.getPropertyValue("color") === "green" + Example: + m.getPropertyValue(1) === 2003 + + diff --git a/package.json b/package.json index 92ddb89f..dd7f3799 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@types/better-sqlite3": "^7.6.2", "archiver": "^5.3.1", "better-sqlite3": "^7.5.3", - "cesium": "^1.102.0", + "cesium": "^1.103.0", "gltf-pipeline": "^4.0.1", "minimist": "^1.2.7", "node-stream-zip": "^1.15.0", diff --git a/specs/data/TilesetWithFullMetadata/tileset.json b/specs/data/TilesetWithFullMetadata/tileset.json new file mode 100644 index 00000000..45e1dcd1 --- /dev/null +++ b/specs/data/TilesetWithFullMetadata/tileset.json @@ -0,0 +1,3639 @@ +{ + "asset" : { + "version" : "1.1" + }, + "schema" : { + "id": "TilesetWithFullMetadataSchema", + "classes" : { + "exampleClass" : { + "name" : "Full example metadata class", + "description" : "An example metadata class with all property types", + "properties" : { + "example_STRING" : { + "name" : "Example STRING property", + "description" : "An example property, with type STRING", + "type" : "STRING", + "array" : false + }, + "example_variable_length_STRING_array" : { + "name" : "Example variable-length STRING array property", + "description" : "An example variable length array property, with type STRING", + "type" : "STRING", + "array" : true + }, + "example_fixed_length_STRING_array" : { + "name" : "Example fixed-length STRING array property", + "description" : "An example fixed length array property, with type STRING", + "type" : "STRING", + "array" : true, + "count" : 5 + }, + "example_BOOLEAN" : { + "name" : "Example BOOLEAN property", + "description" : "An example property, with type BOOLEAN", + "type" : "BOOLEAN", + "array" : false + }, + "example_variable_length_BOOLEAN_array" : { + "name" : "Example variable-length BOOLEAN array property", + "description" : "An example variable length array property, with type BOOLEAN", + "type" : "BOOLEAN", + "array" : true + }, + "example_fixed_length_BOOLEAN_array" : { + "name" : "Example fixed-length BOOLEAN array property", + "description" : "An example fixed length array property, with type BOOLEAN", + "type" : "BOOLEAN", + "array" : true, + "count" : 5 + }, + "example_ENUM" : { + "name" : "Example ENUM property", + "description" : "An example property, with type ENUM, enum type exampleEnumType", + "type" : "ENUM", + "enumType" : "exampleEnumType", + "array" : false + }, + "example_variable_length_ENUM_array" : { + "name" : "Example variable-length ENUM array property", + "description" : "An example variable length array property, with type ENUM, enum type exampleEnumType", + "type" : "ENUM", + "enumType" : "exampleEnumType", + "array" : true + }, + "example_fixed_length_ENUM_array" : { + "name" : "Example fixed-length ENUM array property", + "description" : "An example fixed length array property, with type ENUM, enum type exampleEnumType", + "type" : "ENUM", + "enumType" : "exampleEnumType", + "array" : true, + "count" : 5 + }, + "example_INT8_SCALAR" : { + "name" : "Example SCALAR property with INT8 components", + "description" : "An example property, with type SCALAR, with component type INT8", + "type" : "SCALAR", + "componentType" : "INT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT8_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with INT8 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT8", + "type" : "SCALAR", + "componentType" : "INT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT8_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with INT8 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT8", + "type" : "SCALAR", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT8_SCALAR" : { + "name" : "Example SCALAR property with normalized INT8 components", + "description" : "An example property, with type SCALAR, with component type INT8, normalized", + "type" : "SCALAR", + "componentType" : "INT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT8_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized INT8 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT8, normalized", + "type" : "SCALAR", + "componentType" : "INT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT8_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized INT8 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT8, normalized", + "type" : "SCALAR", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT8_SCALAR" : { + "name" : "Example SCALAR property with UINT8 components", + "description" : "An example property, with type SCALAR, with component type UINT8", + "type" : "SCALAR", + "componentType" : "UINT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT8_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with UINT8 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT8", + "type" : "SCALAR", + "componentType" : "UINT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT8_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with UINT8 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT8", + "type" : "SCALAR", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT8_SCALAR" : { + "name" : "Example SCALAR property with normalized UINT8 components", + "description" : "An example property, with type SCALAR, with component type UINT8, normalized", + "type" : "SCALAR", + "componentType" : "UINT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT8_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized UINT8 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT8, normalized", + "type" : "SCALAR", + "componentType" : "UINT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT8_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized UINT8 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT8, normalized", + "type" : "SCALAR", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT16_SCALAR" : { + "name" : "Example SCALAR property with INT16 components", + "description" : "An example property, with type SCALAR, with component type INT16", + "type" : "SCALAR", + "componentType" : "INT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT16_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with INT16 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT16", + "type" : "SCALAR", + "componentType" : "INT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT16_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with INT16 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT16", + "type" : "SCALAR", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT16_SCALAR" : { + "name" : "Example SCALAR property with normalized INT16 components", + "description" : "An example property, with type SCALAR, with component type INT16, normalized", + "type" : "SCALAR", + "componentType" : "INT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT16_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized INT16 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT16, normalized", + "type" : "SCALAR", + "componentType" : "INT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT16_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized INT16 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT16, normalized", + "type" : "SCALAR", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT16_SCALAR" : { + "name" : "Example SCALAR property with UINT16 components", + "description" : "An example property, with type SCALAR, with component type UINT16", + "type" : "SCALAR", + "componentType" : "UINT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT16_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with UINT16 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT16", + "type" : "SCALAR", + "componentType" : "UINT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT16_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with UINT16 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT16", + "type" : "SCALAR", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT16_SCALAR" : { + "name" : "Example SCALAR property with normalized UINT16 components", + "description" : "An example property, with type SCALAR, with component type UINT16, normalized", + "type" : "SCALAR", + "componentType" : "UINT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT16_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized UINT16 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT16, normalized", + "type" : "SCALAR", + "componentType" : "UINT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT16_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized UINT16 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT16, normalized", + "type" : "SCALAR", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT32_SCALAR" : { + "name" : "Example SCALAR property with INT32 components", + "description" : "An example property, with type SCALAR, with component type INT32", + "type" : "SCALAR", + "componentType" : "INT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT32_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with INT32 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT32", + "type" : "SCALAR", + "componentType" : "INT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT32_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with INT32 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT32", + "type" : "SCALAR", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT32_SCALAR" : { + "name" : "Example SCALAR property with normalized INT32 components", + "description" : "An example property, with type SCALAR, with component type INT32, normalized", + "type" : "SCALAR", + "componentType" : "INT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT32_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized INT32 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT32, normalized", + "type" : "SCALAR", + "componentType" : "INT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT32_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized INT32 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT32, normalized", + "type" : "SCALAR", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT32_SCALAR" : { + "name" : "Example SCALAR property with UINT32 components", + "description" : "An example property, with type SCALAR, with component type UINT32", + "type" : "SCALAR", + "componentType" : "UINT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT32_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with UINT32 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT32", + "type" : "SCALAR", + "componentType" : "UINT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT32_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with UINT32 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT32", + "type" : "SCALAR", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT32_SCALAR" : { + "name" : "Example SCALAR property with normalized UINT32 components", + "description" : "An example property, with type SCALAR, with component type UINT32, normalized", + "type" : "SCALAR", + "componentType" : "UINT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT32_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized UINT32 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT32, normalized", + "type" : "SCALAR", + "componentType" : "UINT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT32_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized UINT32 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT32, normalized", + "type" : "SCALAR", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT64_SCALAR" : { + "name" : "Example SCALAR property with INT64 components", + "description" : "An example property, with type SCALAR, with component type INT64", + "type" : "SCALAR", + "componentType" : "INT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT64_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with INT64 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT64", + "type" : "SCALAR", + "componentType" : "INT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT64_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with INT64 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT64", + "type" : "SCALAR", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT64_SCALAR" : { + "name" : "Example SCALAR property with normalized INT64 components", + "description" : "An example property, with type SCALAR, with component type INT64, normalized", + "type" : "SCALAR", + "componentType" : "INT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT64_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized INT64 components", + "description" : "An example variable length array property, with type SCALAR, with component type INT64, normalized", + "type" : "SCALAR", + "componentType" : "INT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT64_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized INT64 components", + "description" : "An example fixed length array property, with type SCALAR, with component type INT64, normalized", + "type" : "SCALAR", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT64_SCALAR" : { + "name" : "Example SCALAR property with UINT64 components", + "description" : "An example property, with type SCALAR, with component type UINT64", + "type" : "SCALAR", + "componentType" : "UINT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT64_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with UINT64 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT64", + "type" : "SCALAR", + "componentType" : "UINT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT64_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with UINT64 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT64", + "type" : "SCALAR", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT64_SCALAR" : { + "name" : "Example SCALAR property with normalized UINT64 components", + "description" : "An example property, with type SCALAR, with component type UINT64, normalized", + "type" : "SCALAR", + "componentType" : "UINT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT64_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with normalized UINT64 components", + "description" : "An example variable length array property, with type SCALAR, with component type UINT64, normalized", + "type" : "SCALAR", + "componentType" : "UINT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT64_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with normalized UINT64 components", + "description" : "An example fixed length array property, with type SCALAR, with component type UINT64, normalized", + "type" : "SCALAR", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_FLOAT32_SCALAR" : { + "name" : "Example SCALAR property with FLOAT32 components", + "description" : "An example property, with type SCALAR, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT32_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with FLOAT32 components", + "description" : "An example variable length array property, with type SCALAR, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT32_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with FLOAT32 components", + "description" : "An example fixed length array property, with type SCALAR, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_FLOAT64_SCALAR" : { + "name" : "Example SCALAR property with FLOAT64 components", + "description" : "An example property, with type SCALAR, with component type FLOAT64", + "type" : "SCALAR", + "componentType" : "FLOAT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT64_SCALAR_array" : { + "name" : "Example variable-length SCALAR array property with FLOAT64 components", + "description" : "An example variable length array property, with type SCALAR, with component type FLOAT64", + "type" : "SCALAR", + "componentType" : "FLOAT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT64_SCALAR_array" : { + "name" : "Example fixed-length SCALAR array property with FLOAT64 components", + "description" : "An example fixed length array property, with type SCALAR, with component type FLOAT64", + "type" : "SCALAR", + "componentType" : "FLOAT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_INT8_VEC2" : { + "name" : "Example VEC2 property with INT8 components", + "description" : "An example property, with type VEC2, with component type INT8", + "type" : "VEC2", + "componentType" : "INT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT8_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with INT8 components", + "description" : "An example variable length array property, with type VEC2, with component type INT8", + "type" : "VEC2", + "componentType" : "INT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT8_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with INT8 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT8", + "type" : "VEC2", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT8_VEC2" : { + "name" : "Example VEC2 property with normalized INT8 components", + "description" : "An example property, with type VEC2, with component type INT8, normalized", + "type" : "VEC2", + "componentType" : "INT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT8_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized INT8 components", + "description" : "An example variable length array property, with type VEC2, with component type INT8, normalized", + "type" : "VEC2", + "componentType" : "INT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT8_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized INT8 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT8, normalized", + "type" : "VEC2", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT8_VEC2" : { + "name" : "Example VEC2 property with UINT8 components", + "description" : "An example property, with type VEC2, with component type UINT8", + "type" : "VEC2", + "componentType" : "UINT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT8_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with UINT8 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT8", + "type" : "VEC2", + "componentType" : "UINT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT8_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with UINT8 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT8", + "type" : "VEC2", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT8_VEC2" : { + "name" : "Example VEC2 property with normalized UINT8 components", + "description" : "An example property, with type VEC2, with component type UINT8, normalized", + "type" : "VEC2", + "componentType" : "UINT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT8_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized UINT8 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT8, normalized", + "type" : "VEC2", + "componentType" : "UINT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT8_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized UINT8 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT8, normalized", + "type" : "VEC2", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT16_VEC2" : { + "name" : "Example VEC2 property with INT16 components", + "description" : "An example property, with type VEC2, with component type INT16", + "type" : "VEC2", + "componentType" : "INT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT16_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with INT16 components", + "description" : "An example variable length array property, with type VEC2, with component type INT16", + "type" : "VEC2", + "componentType" : "INT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT16_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with INT16 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT16", + "type" : "VEC2", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT16_VEC2" : { + "name" : "Example VEC2 property with normalized INT16 components", + "description" : "An example property, with type VEC2, with component type INT16, normalized", + "type" : "VEC2", + "componentType" : "INT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT16_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized INT16 components", + "description" : "An example variable length array property, with type VEC2, with component type INT16, normalized", + "type" : "VEC2", + "componentType" : "INT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT16_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized INT16 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT16, normalized", + "type" : "VEC2", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT16_VEC2" : { + "name" : "Example VEC2 property with UINT16 components", + "description" : "An example property, with type VEC2, with component type UINT16", + "type" : "VEC2", + "componentType" : "UINT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT16_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with UINT16 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT16", + "type" : "VEC2", + "componentType" : "UINT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT16_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with UINT16 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT16", + "type" : "VEC2", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT16_VEC2" : { + "name" : "Example VEC2 property with normalized UINT16 components", + "description" : "An example property, with type VEC2, with component type UINT16, normalized", + "type" : "VEC2", + "componentType" : "UINT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT16_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized UINT16 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT16, normalized", + "type" : "VEC2", + "componentType" : "UINT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT16_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized UINT16 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT16, normalized", + "type" : "VEC2", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT32_VEC2" : { + "name" : "Example VEC2 property with INT32 components", + "description" : "An example property, with type VEC2, with component type INT32", + "type" : "VEC2", + "componentType" : "INT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT32_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with INT32 components", + "description" : "An example variable length array property, with type VEC2, with component type INT32", + "type" : "VEC2", + "componentType" : "INT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT32_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with INT32 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT32", + "type" : "VEC2", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT32_VEC2" : { + "name" : "Example VEC2 property with normalized INT32 components", + "description" : "An example property, with type VEC2, with component type INT32, normalized", + "type" : "VEC2", + "componentType" : "INT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT32_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized INT32 components", + "description" : "An example variable length array property, with type VEC2, with component type INT32, normalized", + "type" : "VEC2", + "componentType" : "INT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT32_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized INT32 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT32, normalized", + "type" : "VEC2", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT32_VEC2" : { + "name" : "Example VEC2 property with UINT32 components", + "description" : "An example property, with type VEC2, with component type UINT32", + "type" : "VEC2", + "componentType" : "UINT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT32_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with UINT32 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT32", + "type" : "VEC2", + "componentType" : "UINT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT32_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with UINT32 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT32", + "type" : "VEC2", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT32_VEC2" : { + "name" : "Example VEC2 property with normalized UINT32 components", + "description" : "An example property, with type VEC2, with component type UINT32, normalized", + "type" : "VEC2", + "componentType" : "UINT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT32_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized UINT32 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT32, normalized", + "type" : "VEC2", + "componentType" : "UINT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT32_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized UINT32 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT32, normalized", + "type" : "VEC2", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT64_VEC2" : { + "name" : "Example VEC2 property with INT64 components", + "description" : "An example property, with type VEC2, with component type INT64", + "type" : "VEC2", + "componentType" : "INT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT64_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with INT64 components", + "description" : "An example variable length array property, with type VEC2, with component type INT64", + "type" : "VEC2", + "componentType" : "INT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT64_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with INT64 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT64", + "type" : "VEC2", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT64_VEC2" : { + "name" : "Example VEC2 property with normalized INT64 components", + "description" : "An example property, with type VEC2, with component type INT64, normalized", + "type" : "VEC2", + "componentType" : "INT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT64_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized INT64 components", + "description" : "An example variable length array property, with type VEC2, with component type INT64, normalized", + "type" : "VEC2", + "componentType" : "INT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT64_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized INT64 components", + "description" : "An example fixed length array property, with type VEC2, with component type INT64, normalized", + "type" : "VEC2", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT64_VEC2" : { + "name" : "Example VEC2 property with UINT64 components", + "description" : "An example property, with type VEC2, with component type UINT64", + "type" : "VEC2", + "componentType" : "UINT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT64_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with UINT64 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT64", + "type" : "VEC2", + "componentType" : "UINT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT64_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with UINT64 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT64", + "type" : "VEC2", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT64_VEC2" : { + "name" : "Example VEC2 property with normalized UINT64 components", + "description" : "An example property, with type VEC2, with component type UINT64, normalized", + "type" : "VEC2", + "componentType" : "UINT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT64_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with normalized UINT64 components", + "description" : "An example variable length array property, with type VEC2, with component type UINT64, normalized", + "type" : "VEC2", + "componentType" : "UINT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT64_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with normalized UINT64 components", + "description" : "An example fixed length array property, with type VEC2, with component type UINT64, normalized", + "type" : "VEC2", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_FLOAT32_VEC2" : { + "name" : "Example VEC2 property with FLOAT32 components", + "description" : "An example property, with type VEC2, with component type FLOAT32", + "type" : "VEC2", + "componentType" : "FLOAT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT32_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with FLOAT32 components", + "description" : "An example variable length array property, with type VEC2, with component type FLOAT32", + "type" : "VEC2", + "componentType" : "FLOAT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT32_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with FLOAT32 components", + "description" : "An example fixed length array property, with type VEC2, with component type FLOAT32", + "type" : "VEC2", + "componentType" : "FLOAT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_FLOAT64_VEC2" : { + "name" : "Example VEC2 property with FLOAT64 components", + "description" : "An example property, with type VEC2, with component type FLOAT64", + "type" : "VEC2", + "componentType" : "FLOAT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT64_VEC2_array" : { + "name" : "Example variable-length VEC2 array property with FLOAT64 components", + "description" : "An example variable length array property, with type VEC2, with component type FLOAT64", + "type" : "VEC2", + "componentType" : "FLOAT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT64_VEC2_array" : { + "name" : "Example fixed-length VEC2 array property with FLOAT64 components", + "description" : "An example fixed length array property, with type VEC2, with component type FLOAT64", + "type" : "VEC2", + "componentType" : "FLOAT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_INT8_VEC3" : { + "name" : "Example VEC3 property with INT8 components", + "description" : "An example property, with type VEC3, with component type INT8", + "type" : "VEC3", + "componentType" : "INT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT8_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with INT8 components", + "description" : "An example variable length array property, with type VEC3, with component type INT8", + "type" : "VEC3", + "componentType" : "INT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT8_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with INT8 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT8", + "type" : "VEC3", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT8_VEC3" : { + "name" : "Example VEC3 property with normalized INT8 components", + "description" : "An example property, with type VEC3, with component type INT8, normalized", + "type" : "VEC3", + "componentType" : "INT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT8_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized INT8 components", + "description" : "An example variable length array property, with type VEC3, with component type INT8, normalized", + "type" : "VEC3", + "componentType" : "INT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT8_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized INT8 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT8, normalized", + "type" : "VEC3", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT8_VEC3" : { + "name" : "Example VEC3 property with UINT8 components", + "description" : "An example property, with type VEC3, with component type UINT8", + "type" : "VEC3", + "componentType" : "UINT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT8_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with UINT8 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT8", + "type" : "VEC3", + "componentType" : "UINT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT8_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with UINT8 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT8", + "type" : "VEC3", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT8_VEC3" : { + "name" : "Example VEC3 property with normalized UINT8 components", + "description" : "An example property, with type VEC3, with component type UINT8, normalized", + "type" : "VEC3", + "componentType" : "UINT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT8_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized UINT8 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT8, normalized", + "type" : "VEC3", + "componentType" : "UINT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT8_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized UINT8 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT8, normalized", + "type" : "VEC3", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT16_VEC3" : { + "name" : "Example VEC3 property with INT16 components", + "description" : "An example property, with type VEC3, with component type INT16", + "type" : "VEC3", + "componentType" : "INT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT16_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with INT16 components", + "description" : "An example variable length array property, with type VEC3, with component type INT16", + "type" : "VEC3", + "componentType" : "INT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT16_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with INT16 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT16", + "type" : "VEC3", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT16_VEC3" : { + "name" : "Example VEC3 property with normalized INT16 components", + "description" : "An example property, with type VEC3, with component type INT16, normalized", + "type" : "VEC3", + "componentType" : "INT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT16_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized INT16 components", + "description" : "An example variable length array property, with type VEC3, with component type INT16, normalized", + "type" : "VEC3", + "componentType" : "INT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT16_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized INT16 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT16, normalized", + "type" : "VEC3", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT16_VEC3" : { + "name" : "Example VEC3 property with UINT16 components", + "description" : "An example property, with type VEC3, with component type UINT16", + "type" : "VEC3", + "componentType" : "UINT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT16_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with UINT16 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT16", + "type" : "VEC3", + "componentType" : "UINT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT16_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with UINT16 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT16", + "type" : "VEC3", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT16_VEC3" : { + "name" : "Example VEC3 property with normalized UINT16 components", + "description" : "An example property, with type VEC3, with component type UINT16, normalized", + "type" : "VEC3", + "componentType" : "UINT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT16_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized UINT16 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT16, normalized", + "type" : "VEC3", + "componentType" : "UINT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT16_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized UINT16 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT16, normalized", + "type" : "VEC3", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT32_VEC3" : { + "name" : "Example VEC3 property with INT32 components", + "description" : "An example property, with type VEC3, with component type INT32", + "type" : "VEC3", + "componentType" : "INT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT32_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with INT32 components", + "description" : "An example variable length array property, with type VEC3, with component type INT32", + "type" : "VEC3", + "componentType" : "INT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT32_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with INT32 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT32", + "type" : "VEC3", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT32_VEC3" : { + "name" : "Example VEC3 property with normalized INT32 components", + "description" : "An example property, with type VEC3, with component type INT32, normalized", + "type" : "VEC3", + "componentType" : "INT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT32_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized INT32 components", + "description" : "An example variable length array property, with type VEC3, with component type INT32, normalized", + "type" : "VEC3", + "componentType" : "INT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT32_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized INT32 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT32, normalized", + "type" : "VEC3", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT32_VEC3" : { + "name" : "Example VEC3 property with UINT32 components", + "description" : "An example property, with type VEC3, with component type UINT32", + "type" : "VEC3", + "componentType" : "UINT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT32_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with UINT32 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT32", + "type" : "VEC3", + "componentType" : "UINT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT32_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with UINT32 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT32", + "type" : "VEC3", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT32_VEC3" : { + "name" : "Example VEC3 property with normalized UINT32 components", + "description" : "An example property, with type VEC3, with component type UINT32, normalized", + "type" : "VEC3", + "componentType" : "UINT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT32_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized UINT32 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT32, normalized", + "type" : "VEC3", + "componentType" : "UINT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT32_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized UINT32 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT32, normalized", + "type" : "VEC3", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT64_VEC3" : { + "name" : "Example VEC3 property with INT64 components", + "description" : "An example property, with type VEC3, with component type INT64", + "type" : "VEC3", + "componentType" : "INT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT64_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with INT64 components", + "description" : "An example variable length array property, with type VEC3, with component type INT64", + "type" : "VEC3", + "componentType" : "INT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT64_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with INT64 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT64", + "type" : "VEC3", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT64_VEC3" : { + "name" : "Example VEC3 property with normalized INT64 components", + "description" : "An example property, with type VEC3, with component type INT64, normalized", + "type" : "VEC3", + "componentType" : "INT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT64_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized INT64 components", + "description" : "An example variable length array property, with type VEC3, with component type INT64, normalized", + "type" : "VEC3", + "componentType" : "INT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT64_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized INT64 components", + "description" : "An example fixed length array property, with type VEC3, with component type INT64, normalized", + "type" : "VEC3", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT64_VEC3" : { + "name" : "Example VEC3 property with UINT64 components", + "description" : "An example property, with type VEC3, with component type UINT64", + "type" : "VEC3", + "componentType" : "UINT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT64_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with UINT64 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT64", + "type" : "VEC3", + "componentType" : "UINT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT64_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with UINT64 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT64", + "type" : "VEC3", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT64_VEC3" : { + "name" : "Example VEC3 property with normalized UINT64 components", + "description" : "An example property, with type VEC3, with component type UINT64, normalized", + "type" : "VEC3", + "componentType" : "UINT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT64_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with normalized UINT64 components", + "description" : "An example variable length array property, with type VEC3, with component type UINT64, normalized", + "type" : "VEC3", + "componentType" : "UINT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT64_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with normalized UINT64 components", + "description" : "An example fixed length array property, with type VEC3, with component type UINT64, normalized", + "type" : "VEC3", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_FLOAT32_VEC3" : { + "name" : "Example VEC3 property with FLOAT32 components", + "description" : "An example property, with type VEC3, with component type FLOAT32", + "type" : "VEC3", + "componentType" : "FLOAT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT32_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with FLOAT32 components", + "description" : "An example variable length array property, with type VEC3, with component type FLOAT32", + "type" : "VEC3", + "componentType" : "FLOAT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT32_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with FLOAT32 components", + "description" : "An example fixed length array property, with type VEC3, with component type FLOAT32", + "type" : "VEC3", + "componentType" : "FLOAT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_FLOAT64_VEC3" : { + "name" : "Example VEC3 property with FLOAT64 components", + "description" : "An example property, with type VEC3, with component type FLOAT64", + "type" : "VEC3", + "componentType" : "FLOAT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT64_VEC3_array" : { + "name" : "Example variable-length VEC3 array property with FLOAT64 components", + "description" : "An example variable length array property, with type VEC3, with component type FLOAT64", + "type" : "VEC3", + "componentType" : "FLOAT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT64_VEC3_array" : { + "name" : "Example fixed-length VEC3 array property with FLOAT64 components", + "description" : "An example fixed length array property, with type VEC3, with component type FLOAT64", + "type" : "VEC3", + "componentType" : "FLOAT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_INT8_VEC4" : { + "name" : "Example VEC4 property with INT8 components", + "description" : "An example property, with type VEC4, with component type INT8", + "type" : "VEC4", + "componentType" : "INT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT8_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with INT8 components", + "description" : "An example variable length array property, with type VEC4, with component type INT8", + "type" : "VEC4", + "componentType" : "INT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT8_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with INT8 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT8", + "type" : "VEC4", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT8_VEC4" : { + "name" : "Example VEC4 property with normalized INT8 components", + "description" : "An example property, with type VEC4, with component type INT8, normalized", + "type" : "VEC4", + "componentType" : "INT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT8_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized INT8 components", + "description" : "An example variable length array property, with type VEC4, with component type INT8, normalized", + "type" : "VEC4", + "componentType" : "INT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT8_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized INT8 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT8, normalized", + "type" : "VEC4", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT8_VEC4" : { + "name" : "Example VEC4 property with UINT8 components", + "description" : "An example property, with type VEC4, with component type UINT8", + "type" : "VEC4", + "componentType" : "UINT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT8_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with UINT8 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT8", + "type" : "VEC4", + "componentType" : "UINT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT8_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with UINT8 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT8", + "type" : "VEC4", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT8_VEC4" : { + "name" : "Example VEC4 property with normalized UINT8 components", + "description" : "An example property, with type VEC4, with component type UINT8, normalized", + "type" : "VEC4", + "componentType" : "UINT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT8_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized UINT8 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT8, normalized", + "type" : "VEC4", + "componentType" : "UINT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT8_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized UINT8 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT8, normalized", + "type" : "VEC4", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT16_VEC4" : { + "name" : "Example VEC4 property with INT16 components", + "description" : "An example property, with type VEC4, with component type INT16", + "type" : "VEC4", + "componentType" : "INT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT16_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with INT16 components", + "description" : "An example variable length array property, with type VEC4, with component type INT16", + "type" : "VEC4", + "componentType" : "INT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT16_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with INT16 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT16", + "type" : "VEC4", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT16_VEC4" : { + "name" : "Example VEC4 property with normalized INT16 components", + "description" : "An example property, with type VEC4, with component type INT16, normalized", + "type" : "VEC4", + "componentType" : "INT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT16_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized INT16 components", + "description" : "An example variable length array property, with type VEC4, with component type INT16, normalized", + "type" : "VEC4", + "componentType" : "INT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT16_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized INT16 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT16, normalized", + "type" : "VEC4", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT16_VEC4" : { + "name" : "Example VEC4 property with UINT16 components", + "description" : "An example property, with type VEC4, with component type UINT16", + "type" : "VEC4", + "componentType" : "UINT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT16_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with UINT16 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT16", + "type" : "VEC4", + "componentType" : "UINT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT16_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with UINT16 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT16", + "type" : "VEC4", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT16_VEC4" : { + "name" : "Example VEC4 property with normalized UINT16 components", + "description" : "An example property, with type VEC4, with component type UINT16, normalized", + "type" : "VEC4", + "componentType" : "UINT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT16_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized UINT16 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT16, normalized", + "type" : "VEC4", + "componentType" : "UINT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT16_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized UINT16 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT16, normalized", + "type" : "VEC4", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT32_VEC4" : { + "name" : "Example VEC4 property with INT32 components", + "description" : "An example property, with type VEC4, with component type INT32", + "type" : "VEC4", + "componentType" : "INT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT32_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with INT32 components", + "description" : "An example variable length array property, with type VEC4, with component type INT32", + "type" : "VEC4", + "componentType" : "INT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT32_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with INT32 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT32", + "type" : "VEC4", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT32_VEC4" : { + "name" : "Example VEC4 property with normalized INT32 components", + "description" : "An example property, with type VEC4, with component type INT32, normalized", + "type" : "VEC4", + "componentType" : "INT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT32_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized INT32 components", + "description" : "An example variable length array property, with type VEC4, with component type INT32, normalized", + "type" : "VEC4", + "componentType" : "INT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT32_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized INT32 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT32, normalized", + "type" : "VEC4", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT32_VEC4" : { + "name" : "Example VEC4 property with UINT32 components", + "description" : "An example property, with type VEC4, with component type UINT32", + "type" : "VEC4", + "componentType" : "UINT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT32_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with UINT32 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT32", + "type" : "VEC4", + "componentType" : "UINT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT32_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with UINT32 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT32", + "type" : "VEC4", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT32_VEC4" : { + "name" : "Example VEC4 property with normalized UINT32 components", + "description" : "An example property, with type VEC4, with component type UINT32, normalized", + "type" : "VEC4", + "componentType" : "UINT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT32_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized UINT32 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT32, normalized", + "type" : "VEC4", + "componentType" : "UINT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT32_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized UINT32 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT32, normalized", + "type" : "VEC4", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT64_VEC4" : { + "name" : "Example VEC4 property with INT64 components", + "description" : "An example property, with type VEC4, with component type INT64", + "type" : "VEC4", + "componentType" : "INT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT64_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with INT64 components", + "description" : "An example variable length array property, with type VEC4, with component type INT64", + "type" : "VEC4", + "componentType" : "INT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT64_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with INT64 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT64", + "type" : "VEC4", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT64_VEC4" : { + "name" : "Example VEC4 property with normalized INT64 components", + "description" : "An example property, with type VEC4, with component type INT64, normalized", + "type" : "VEC4", + "componentType" : "INT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT64_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized INT64 components", + "description" : "An example variable length array property, with type VEC4, with component type INT64, normalized", + "type" : "VEC4", + "componentType" : "INT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT64_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized INT64 components", + "description" : "An example fixed length array property, with type VEC4, with component type INT64, normalized", + "type" : "VEC4", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT64_VEC4" : { + "name" : "Example VEC4 property with UINT64 components", + "description" : "An example property, with type VEC4, with component type UINT64", + "type" : "VEC4", + "componentType" : "UINT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT64_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with UINT64 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT64", + "type" : "VEC4", + "componentType" : "UINT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT64_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with UINT64 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT64", + "type" : "VEC4", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT64_VEC4" : { + "name" : "Example VEC4 property with normalized UINT64 components", + "description" : "An example property, with type VEC4, with component type UINT64, normalized", + "type" : "VEC4", + "componentType" : "UINT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT64_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with normalized UINT64 components", + "description" : "An example variable length array property, with type VEC4, with component type UINT64, normalized", + "type" : "VEC4", + "componentType" : "UINT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT64_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with normalized UINT64 components", + "description" : "An example fixed length array property, with type VEC4, with component type UINT64, normalized", + "type" : "VEC4", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_FLOAT32_VEC4" : { + "name" : "Example VEC4 property with FLOAT32 components", + "description" : "An example property, with type VEC4, with component type FLOAT32", + "type" : "VEC4", + "componentType" : "FLOAT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT32_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with FLOAT32 components", + "description" : "An example variable length array property, with type VEC4, with component type FLOAT32", + "type" : "VEC4", + "componentType" : "FLOAT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT32_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with FLOAT32 components", + "description" : "An example fixed length array property, with type VEC4, with component type FLOAT32", + "type" : "VEC4", + "componentType" : "FLOAT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_FLOAT64_VEC4" : { + "name" : "Example VEC4 property with FLOAT64 components", + "description" : "An example property, with type VEC4, with component type FLOAT64", + "type" : "VEC4", + "componentType" : "FLOAT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT64_VEC4_array" : { + "name" : "Example variable-length VEC4 array property with FLOAT64 components", + "description" : "An example variable length array property, with type VEC4, with component type FLOAT64", + "type" : "VEC4", + "componentType" : "FLOAT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT64_VEC4_array" : { + "name" : "Example fixed-length VEC4 array property with FLOAT64 components", + "description" : "An example fixed length array property, with type VEC4, with component type FLOAT64", + "type" : "VEC4", + "componentType" : "FLOAT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_INT8_MAT2" : { + "name" : "Example MAT2 property with INT8 components", + "description" : "An example property, with type MAT2, with component type INT8", + "type" : "MAT2", + "componentType" : "INT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT8_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with INT8 components", + "description" : "An example variable length array property, with type MAT2, with component type INT8", + "type" : "MAT2", + "componentType" : "INT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT8_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with INT8 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT8", + "type" : "MAT2", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT8_MAT2" : { + "name" : "Example MAT2 property with normalized INT8 components", + "description" : "An example property, with type MAT2, with component type INT8, normalized", + "type" : "MAT2", + "componentType" : "INT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT8_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized INT8 components", + "description" : "An example variable length array property, with type MAT2, with component type INT8, normalized", + "type" : "MAT2", + "componentType" : "INT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT8_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized INT8 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT8, normalized", + "type" : "MAT2", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT8_MAT2" : { + "name" : "Example MAT2 property with UINT8 components", + "description" : "An example property, with type MAT2, with component type UINT8", + "type" : "MAT2", + "componentType" : "UINT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT8_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with UINT8 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT8", + "type" : "MAT2", + "componentType" : "UINT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT8_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with UINT8 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT8", + "type" : "MAT2", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT8_MAT2" : { + "name" : "Example MAT2 property with normalized UINT8 components", + "description" : "An example property, with type MAT2, with component type UINT8, normalized", + "type" : "MAT2", + "componentType" : "UINT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT8_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized UINT8 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT8, normalized", + "type" : "MAT2", + "componentType" : "UINT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT8_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized UINT8 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT8, normalized", + "type" : "MAT2", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT16_MAT2" : { + "name" : "Example MAT2 property with INT16 components", + "description" : "An example property, with type MAT2, with component type INT16", + "type" : "MAT2", + "componentType" : "INT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT16_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with INT16 components", + "description" : "An example variable length array property, with type MAT2, with component type INT16", + "type" : "MAT2", + "componentType" : "INT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT16_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with INT16 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT16", + "type" : "MAT2", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT16_MAT2" : { + "name" : "Example MAT2 property with normalized INT16 components", + "description" : "An example property, with type MAT2, with component type INT16, normalized", + "type" : "MAT2", + "componentType" : "INT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT16_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized INT16 components", + "description" : "An example variable length array property, with type MAT2, with component type INT16, normalized", + "type" : "MAT2", + "componentType" : "INT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT16_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized INT16 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT16, normalized", + "type" : "MAT2", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT16_MAT2" : { + "name" : "Example MAT2 property with UINT16 components", + "description" : "An example property, with type MAT2, with component type UINT16", + "type" : "MAT2", + "componentType" : "UINT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT16_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with UINT16 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT16", + "type" : "MAT2", + "componentType" : "UINT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT16_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with UINT16 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT16", + "type" : "MAT2", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT16_MAT2" : { + "name" : "Example MAT2 property with normalized UINT16 components", + "description" : "An example property, with type MAT2, with component type UINT16, normalized", + "type" : "MAT2", + "componentType" : "UINT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT16_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized UINT16 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT16, normalized", + "type" : "MAT2", + "componentType" : "UINT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT16_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized UINT16 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT16, normalized", + "type" : "MAT2", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT32_MAT2" : { + "name" : "Example MAT2 property with INT32 components", + "description" : "An example property, with type MAT2, with component type INT32", + "type" : "MAT2", + "componentType" : "INT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT32_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with INT32 components", + "description" : "An example variable length array property, with type MAT2, with component type INT32", + "type" : "MAT2", + "componentType" : "INT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT32_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with INT32 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT32", + "type" : "MAT2", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT32_MAT2" : { + "name" : "Example MAT2 property with normalized INT32 components", + "description" : "An example property, with type MAT2, with component type INT32, normalized", + "type" : "MAT2", + "componentType" : "INT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT32_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized INT32 components", + "description" : "An example variable length array property, with type MAT2, with component type INT32, normalized", + "type" : "MAT2", + "componentType" : "INT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT32_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized INT32 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT32, normalized", + "type" : "MAT2", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT32_MAT2" : { + "name" : "Example MAT2 property with UINT32 components", + "description" : "An example property, with type MAT2, with component type UINT32", + "type" : "MAT2", + "componentType" : "UINT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT32_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with UINT32 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT32", + "type" : "MAT2", + "componentType" : "UINT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT32_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with UINT32 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT32", + "type" : "MAT2", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT32_MAT2" : { + "name" : "Example MAT2 property with normalized UINT32 components", + "description" : "An example property, with type MAT2, with component type UINT32, normalized", + "type" : "MAT2", + "componentType" : "UINT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT32_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized UINT32 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT32, normalized", + "type" : "MAT2", + "componentType" : "UINT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT32_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized UINT32 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT32, normalized", + "type" : "MAT2", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT64_MAT2" : { + "name" : "Example MAT2 property with INT64 components", + "description" : "An example property, with type MAT2, with component type INT64", + "type" : "MAT2", + "componentType" : "INT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT64_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with INT64 components", + "description" : "An example variable length array property, with type MAT2, with component type INT64", + "type" : "MAT2", + "componentType" : "INT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT64_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with INT64 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT64", + "type" : "MAT2", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT64_MAT2" : { + "name" : "Example MAT2 property with normalized INT64 components", + "description" : "An example property, with type MAT2, with component type INT64, normalized", + "type" : "MAT2", + "componentType" : "INT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT64_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized INT64 components", + "description" : "An example variable length array property, with type MAT2, with component type INT64, normalized", + "type" : "MAT2", + "componentType" : "INT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT64_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized INT64 components", + "description" : "An example fixed length array property, with type MAT2, with component type INT64, normalized", + "type" : "MAT2", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT64_MAT2" : { + "name" : "Example MAT2 property with UINT64 components", + "description" : "An example property, with type MAT2, with component type UINT64", + "type" : "MAT2", + "componentType" : "UINT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT64_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with UINT64 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT64", + "type" : "MAT2", + "componentType" : "UINT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT64_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with UINT64 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT64", + "type" : "MAT2", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT64_MAT2" : { + "name" : "Example MAT2 property with normalized UINT64 components", + "description" : "An example property, with type MAT2, with component type UINT64, normalized", + "type" : "MAT2", + "componentType" : "UINT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT64_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with normalized UINT64 components", + "description" : "An example variable length array property, with type MAT2, with component type UINT64, normalized", + "type" : "MAT2", + "componentType" : "UINT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT64_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with normalized UINT64 components", + "description" : "An example fixed length array property, with type MAT2, with component type UINT64, normalized", + "type" : "MAT2", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_FLOAT32_MAT2" : { + "name" : "Example MAT2 property with FLOAT32 components", + "description" : "An example property, with type MAT2, with component type FLOAT32", + "type" : "MAT2", + "componentType" : "FLOAT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT32_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with FLOAT32 components", + "description" : "An example variable length array property, with type MAT2, with component type FLOAT32", + "type" : "MAT2", + "componentType" : "FLOAT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT32_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with FLOAT32 components", + "description" : "An example fixed length array property, with type MAT2, with component type FLOAT32", + "type" : "MAT2", + "componentType" : "FLOAT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_FLOAT64_MAT2" : { + "name" : "Example MAT2 property with FLOAT64 components", + "description" : "An example property, with type MAT2, with component type FLOAT64", + "type" : "MAT2", + "componentType" : "FLOAT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT64_MAT2_array" : { + "name" : "Example variable-length MAT2 array property with FLOAT64 components", + "description" : "An example variable length array property, with type MAT2, with component type FLOAT64", + "type" : "MAT2", + "componentType" : "FLOAT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT64_MAT2_array" : { + "name" : "Example fixed-length MAT2 array property with FLOAT64 components", + "description" : "An example fixed length array property, with type MAT2, with component type FLOAT64", + "type" : "MAT2", + "componentType" : "FLOAT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_INT8_MAT3" : { + "name" : "Example MAT3 property with INT8 components", + "description" : "An example property, with type MAT3, with component type INT8", + "type" : "MAT3", + "componentType" : "INT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT8_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with INT8 components", + "description" : "An example variable length array property, with type MAT3, with component type INT8", + "type" : "MAT3", + "componentType" : "INT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT8_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with INT8 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT8", + "type" : "MAT3", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT8_MAT3" : { + "name" : "Example MAT3 property with normalized INT8 components", + "description" : "An example property, with type MAT3, with component type INT8, normalized", + "type" : "MAT3", + "componentType" : "INT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT8_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized INT8 components", + "description" : "An example variable length array property, with type MAT3, with component type INT8, normalized", + "type" : "MAT3", + "componentType" : "INT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT8_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized INT8 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT8, normalized", + "type" : "MAT3", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT8_MAT3" : { + "name" : "Example MAT3 property with UINT8 components", + "description" : "An example property, with type MAT3, with component type UINT8", + "type" : "MAT3", + "componentType" : "UINT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT8_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with UINT8 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT8", + "type" : "MAT3", + "componentType" : "UINT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT8_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with UINT8 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT8", + "type" : "MAT3", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT8_MAT3" : { + "name" : "Example MAT3 property with normalized UINT8 components", + "description" : "An example property, with type MAT3, with component type UINT8, normalized", + "type" : "MAT3", + "componentType" : "UINT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT8_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized UINT8 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT8, normalized", + "type" : "MAT3", + "componentType" : "UINT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT8_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized UINT8 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT8, normalized", + "type" : "MAT3", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT16_MAT3" : { + "name" : "Example MAT3 property with INT16 components", + "description" : "An example property, with type MAT3, with component type INT16", + "type" : "MAT3", + "componentType" : "INT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT16_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with INT16 components", + "description" : "An example variable length array property, with type MAT3, with component type INT16", + "type" : "MAT3", + "componentType" : "INT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT16_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with INT16 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT16", + "type" : "MAT3", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT16_MAT3" : { + "name" : "Example MAT3 property with normalized INT16 components", + "description" : "An example property, with type MAT3, with component type INT16, normalized", + "type" : "MAT3", + "componentType" : "INT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT16_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized INT16 components", + "description" : "An example variable length array property, with type MAT3, with component type INT16, normalized", + "type" : "MAT3", + "componentType" : "INT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT16_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized INT16 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT16, normalized", + "type" : "MAT3", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT16_MAT3" : { + "name" : "Example MAT3 property with UINT16 components", + "description" : "An example property, with type MAT3, with component type UINT16", + "type" : "MAT3", + "componentType" : "UINT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT16_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with UINT16 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT16", + "type" : "MAT3", + "componentType" : "UINT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT16_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with UINT16 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT16", + "type" : "MAT3", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT16_MAT3" : { + "name" : "Example MAT3 property with normalized UINT16 components", + "description" : "An example property, with type MAT3, with component type UINT16, normalized", + "type" : "MAT3", + "componentType" : "UINT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT16_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized UINT16 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT16, normalized", + "type" : "MAT3", + "componentType" : "UINT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT16_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized UINT16 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT16, normalized", + "type" : "MAT3", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT32_MAT3" : { + "name" : "Example MAT3 property with INT32 components", + "description" : "An example property, with type MAT3, with component type INT32", + "type" : "MAT3", + "componentType" : "INT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT32_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with INT32 components", + "description" : "An example variable length array property, with type MAT3, with component type INT32", + "type" : "MAT3", + "componentType" : "INT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT32_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with INT32 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT32", + "type" : "MAT3", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT32_MAT3" : { + "name" : "Example MAT3 property with normalized INT32 components", + "description" : "An example property, with type MAT3, with component type INT32, normalized", + "type" : "MAT3", + "componentType" : "INT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT32_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized INT32 components", + "description" : "An example variable length array property, with type MAT3, with component type INT32, normalized", + "type" : "MAT3", + "componentType" : "INT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT32_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized INT32 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT32, normalized", + "type" : "MAT3", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT32_MAT3" : { + "name" : "Example MAT3 property with UINT32 components", + "description" : "An example property, with type MAT3, with component type UINT32", + "type" : "MAT3", + "componentType" : "UINT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT32_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with UINT32 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT32", + "type" : "MAT3", + "componentType" : "UINT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT32_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with UINT32 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT32", + "type" : "MAT3", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT32_MAT3" : { + "name" : "Example MAT3 property with normalized UINT32 components", + "description" : "An example property, with type MAT3, with component type UINT32, normalized", + "type" : "MAT3", + "componentType" : "UINT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT32_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized UINT32 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT32, normalized", + "type" : "MAT3", + "componentType" : "UINT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT32_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized UINT32 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT32, normalized", + "type" : "MAT3", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT64_MAT3" : { + "name" : "Example MAT3 property with INT64 components", + "description" : "An example property, with type MAT3, with component type INT64", + "type" : "MAT3", + "componentType" : "INT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT64_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with INT64 components", + "description" : "An example variable length array property, with type MAT3, with component type INT64", + "type" : "MAT3", + "componentType" : "INT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT64_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with INT64 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT64", + "type" : "MAT3", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT64_MAT3" : { + "name" : "Example MAT3 property with normalized INT64 components", + "description" : "An example property, with type MAT3, with component type INT64, normalized", + "type" : "MAT3", + "componentType" : "INT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT64_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized INT64 components", + "description" : "An example variable length array property, with type MAT3, with component type INT64, normalized", + "type" : "MAT3", + "componentType" : "INT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT64_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized INT64 components", + "description" : "An example fixed length array property, with type MAT3, with component type INT64, normalized", + "type" : "MAT3", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT64_MAT3" : { + "name" : "Example MAT3 property with UINT64 components", + "description" : "An example property, with type MAT3, with component type UINT64", + "type" : "MAT3", + "componentType" : "UINT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT64_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with UINT64 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT64", + "type" : "MAT3", + "componentType" : "UINT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT64_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with UINT64 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT64", + "type" : "MAT3", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT64_MAT3" : { + "name" : "Example MAT3 property with normalized UINT64 components", + "description" : "An example property, with type MAT3, with component type UINT64, normalized", + "type" : "MAT3", + "componentType" : "UINT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT64_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with normalized UINT64 components", + "description" : "An example variable length array property, with type MAT3, with component type UINT64, normalized", + "type" : "MAT3", + "componentType" : "UINT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT64_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with normalized UINT64 components", + "description" : "An example fixed length array property, with type MAT3, with component type UINT64, normalized", + "type" : "MAT3", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_FLOAT32_MAT3" : { + "name" : "Example MAT3 property with FLOAT32 components", + "description" : "An example property, with type MAT3, with component type FLOAT32", + "type" : "MAT3", + "componentType" : "FLOAT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT32_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with FLOAT32 components", + "description" : "An example variable length array property, with type MAT3, with component type FLOAT32", + "type" : "MAT3", + "componentType" : "FLOAT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT32_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with FLOAT32 components", + "description" : "An example fixed length array property, with type MAT3, with component type FLOAT32", + "type" : "MAT3", + "componentType" : "FLOAT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_FLOAT64_MAT3" : { + "name" : "Example MAT3 property with FLOAT64 components", + "description" : "An example property, with type MAT3, with component type FLOAT64", + "type" : "MAT3", + "componentType" : "FLOAT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT64_MAT3_array" : { + "name" : "Example variable-length MAT3 array property with FLOAT64 components", + "description" : "An example variable length array property, with type MAT3, with component type FLOAT64", + "type" : "MAT3", + "componentType" : "FLOAT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT64_MAT3_array" : { + "name" : "Example fixed-length MAT3 array property with FLOAT64 components", + "description" : "An example fixed length array property, with type MAT3, with component type FLOAT64", + "type" : "MAT3", + "componentType" : "FLOAT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_INT8_MAT4" : { + "name" : "Example MAT4 property with INT8 components", + "description" : "An example property, with type MAT4, with component type INT8", + "type" : "MAT4", + "componentType" : "INT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT8_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with INT8 components", + "description" : "An example variable length array property, with type MAT4, with component type INT8", + "type" : "MAT4", + "componentType" : "INT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT8_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with INT8 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT8", + "type" : "MAT4", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT8_MAT4" : { + "name" : "Example MAT4 property with normalized INT8 components", + "description" : "An example property, with type MAT4, with component type INT8, normalized", + "type" : "MAT4", + "componentType" : "INT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT8_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized INT8 components", + "description" : "An example variable length array property, with type MAT4, with component type INT8, normalized", + "type" : "MAT4", + "componentType" : "INT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT8_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized INT8 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT8, normalized", + "type" : "MAT4", + "componentType" : "INT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT8_MAT4" : { + "name" : "Example MAT4 property with UINT8 components", + "description" : "An example property, with type MAT4, with component type UINT8", + "type" : "MAT4", + "componentType" : "UINT8", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT8_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with UINT8 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT8", + "type" : "MAT4", + "componentType" : "UINT8", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT8_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with UINT8 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT8", + "type" : "MAT4", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT8_MAT4" : { + "name" : "Example MAT4 property with normalized UINT8 components", + "description" : "An example property, with type MAT4, with component type UINT8, normalized", + "type" : "MAT4", + "componentType" : "UINT8", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT8_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized UINT8 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT8, normalized", + "type" : "MAT4", + "componentType" : "UINT8", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT8_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized UINT8 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT8, normalized", + "type" : "MAT4", + "componentType" : "UINT8", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT16_MAT4" : { + "name" : "Example MAT4 property with INT16 components", + "description" : "An example property, with type MAT4, with component type INT16", + "type" : "MAT4", + "componentType" : "INT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT16_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with INT16 components", + "description" : "An example variable length array property, with type MAT4, with component type INT16", + "type" : "MAT4", + "componentType" : "INT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT16_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with INT16 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT16", + "type" : "MAT4", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT16_MAT4" : { + "name" : "Example MAT4 property with normalized INT16 components", + "description" : "An example property, with type MAT4, with component type INT16, normalized", + "type" : "MAT4", + "componentType" : "INT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT16_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized INT16 components", + "description" : "An example variable length array property, with type MAT4, with component type INT16, normalized", + "type" : "MAT4", + "componentType" : "INT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT16_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized INT16 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT16, normalized", + "type" : "MAT4", + "componentType" : "INT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT16_MAT4" : { + "name" : "Example MAT4 property with UINT16 components", + "description" : "An example property, with type MAT4, with component type UINT16", + "type" : "MAT4", + "componentType" : "UINT16", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT16_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with UINT16 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT16", + "type" : "MAT4", + "componentType" : "UINT16", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT16_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with UINT16 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT16", + "type" : "MAT4", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT16_MAT4" : { + "name" : "Example MAT4 property with normalized UINT16 components", + "description" : "An example property, with type MAT4, with component type UINT16, normalized", + "type" : "MAT4", + "componentType" : "UINT16", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT16_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized UINT16 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT16, normalized", + "type" : "MAT4", + "componentType" : "UINT16", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT16_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized UINT16 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT16, normalized", + "type" : "MAT4", + "componentType" : "UINT16", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT32_MAT4" : { + "name" : "Example MAT4 property with INT32 components", + "description" : "An example property, with type MAT4, with component type INT32", + "type" : "MAT4", + "componentType" : "INT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT32_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with INT32 components", + "description" : "An example variable length array property, with type MAT4, with component type INT32", + "type" : "MAT4", + "componentType" : "INT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT32_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with INT32 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT32", + "type" : "MAT4", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT32_MAT4" : { + "name" : "Example MAT4 property with normalized INT32 components", + "description" : "An example property, with type MAT4, with component type INT32, normalized", + "type" : "MAT4", + "componentType" : "INT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT32_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized INT32 components", + "description" : "An example variable length array property, with type MAT4, with component type INT32, normalized", + "type" : "MAT4", + "componentType" : "INT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT32_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized INT32 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT32, normalized", + "type" : "MAT4", + "componentType" : "INT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT32_MAT4" : { + "name" : "Example MAT4 property with UINT32 components", + "description" : "An example property, with type MAT4, with component type UINT32", + "type" : "MAT4", + "componentType" : "UINT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT32_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with UINT32 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT32", + "type" : "MAT4", + "componentType" : "UINT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT32_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with UINT32 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT32", + "type" : "MAT4", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT32_MAT4" : { + "name" : "Example MAT4 property with normalized UINT32 components", + "description" : "An example property, with type MAT4, with component type UINT32, normalized", + "type" : "MAT4", + "componentType" : "UINT32", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT32_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized UINT32 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT32, normalized", + "type" : "MAT4", + "componentType" : "UINT32", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT32_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized UINT32 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT32, normalized", + "type" : "MAT4", + "componentType" : "UINT32", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_INT64_MAT4" : { + "name" : "Example MAT4 property with INT64 components", + "description" : "An example property, with type MAT4, with component type INT64", + "type" : "MAT4", + "componentType" : "INT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_INT64_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with INT64 components", + "description" : "An example variable length array property, with type MAT4, with component type INT64", + "type" : "MAT4", + "componentType" : "INT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_INT64_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with INT64 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT64", + "type" : "MAT4", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_INT64_MAT4" : { + "name" : "Example MAT4 property with normalized INT64 components", + "description" : "An example property, with type MAT4, with component type INT64, normalized", + "type" : "MAT4", + "componentType" : "INT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_INT64_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized INT64 components", + "description" : "An example variable length array property, with type MAT4, with component type INT64, normalized", + "type" : "MAT4", + "componentType" : "INT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_INT64_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized INT64 components", + "description" : "An example fixed length array property, with type MAT4, with component type INT64, normalized", + "type" : "MAT4", + "componentType" : "INT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_UINT64_MAT4" : { + "name" : "Example MAT4 property with UINT64 components", + "description" : "An example property, with type MAT4, with component type UINT64", + "type" : "MAT4", + "componentType" : "UINT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_UINT64_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with UINT64 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT64", + "type" : "MAT4", + "componentType" : "UINT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_UINT64_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with UINT64 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT64", + "type" : "MAT4", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_normalized_UINT64_MAT4" : { + "name" : "Example MAT4 property with normalized UINT64 components", + "description" : "An example property, with type MAT4, with component type UINT64, normalized", + "type" : "MAT4", + "componentType" : "UINT64", + "array" : false, + "normalized" : true + }, + "example_variable_length_normalized_UINT64_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with normalized UINT64 components", + "description" : "An example variable length array property, with type MAT4, with component type UINT64, normalized", + "type" : "MAT4", + "componentType" : "UINT64", + "array" : true, + "normalized" : true + }, + "example_fixed_length_normalized_UINT64_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with normalized UINT64 components", + "description" : "An example fixed length array property, with type MAT4, with component type UINT64, normalized", + "type" : "MAT4", + "componentType" : "UINT64", + "array" : true, + "count" : 5, + "normalized" : true + }, + "example_FLOAT32_MAT4" : { + "name" : "Example MAT4 property with FLOAT32 components", + "description" : "An example property, with type MAT4, with component type FLOAT32", + "type" : "MAT4", + "componentType" : "FLOAT32", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT32_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with FLOAT32 components", + "description" : "An example variable length array property, with type MAT4, with component type FLOAT32", + "type" : "MAT4", + "componentType" : "FLOAT32", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT32_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with FLOAT32 components", + "description" : "An example fixed length array property, with type MAT4, with component type FLOAT32", + "type" : "MAT4", + "componentType" : "FLOAT32", + "array" : true, + "count" : 5, + "normalized" : false + }, + "example_FLOAT64_MAT4" : { + "name" : "Example MAT4 property with FLOAT64 components", + "description" : "An example property, with type MAT4, with component type FLOAT64", + "type" : "MAT4", + "componentType" : "FLOAT64", + "array" : false, + "normalized" : false + }, + "example_variable_length_FLOAT64_MAT4_array" : { + "name" : "Example variable-length MAT4 array property with FLOAT64 components", + "description" : "An example variable length array property, with type MAT4, with component type FLOAT64", + "type" : "MAT4", + "componentType" : "FLOAT64", + "array" : true, + "normalized" : false + }, + "example_fixed_length_FLOAT64_MAT4_array" : { + "name" : "Example fixed-length MAT4 array property with FLOAT64 components", + "description" : "An example fixed length array property, with type MAT4, with component type FLOAT64", + "type" : "MAT4", + "componentType" : "FLOAT64", + "array" : true, + "count" : 5, + "normalized" : false + } + } + } + }, + "enums" : { + "exampleEnumType" : { + "values" : [ { + "name" : "ExampleEnumValueA", + "value" : 0 + }, { + "name" : "ExampleEnumValueB", + "value" : 1 + }, { + "name" : "ExampleEnumValueC", + "value" : 2 + } ] + } + } + }, + "metadata" : { + "class" : "exampleClass", + "properties" : { + "example_STRING" : "An example string", + "example_variable_length_STRING_array" : [ "This", "is", "an", "example" ], + "example_fixed_length_STRING_array" : [ "This", "is", "an", "example", "string" ], + "example_BOOLEAN" : true, + "example_variable_length_BOOLEAN_array" : [ true, false, true, false ], + "example_fixed_length_BOOLEAN_array" : [ true, false, true, false, true ], + "example_ENUM" : "ExampleEnumValueB", + "example_variable_length_ENUM_array" : [ "ExampleEnumValueA", "ExampleEnumValueB", "ExampleEnumValueC", "ExampleEnumValueA" ], + "example_fixed_length_ENUM_array" : [ "ExampleEnumValueA", "ExampleEnumValueB", "ExampleEnumValueC", "ExampleEnumValueA", "ExampleEnumValueB" ], + "example_INT8_SCALAR" : -128, + "example_variable_length_INT8_SCALAR_array" : [ -128, -43, 42, 127 ], + "example_fixed_length_INT8_SCALAR_array" : [ -128, -64, 0, 63, 127 ], + "example_normalized_INT8_SCALAR" : -128, + "example_variable_length_normalized_INT8_SCALAR_array" : [ -128, -43, 42, 127 ], + "example_fixed_length_normalized_INT8_SCALAR_array" : [ -128, -64, 0, 63, 127 ], + "example_UINT8_SCALAR" : 255, + "example_variable_length_UINT8_SCALAR_array" : [ 0, 84, 170, 255 ], + "example_fixed_length_UINT8_SCALAR_array" : [ 0, 63, 127, 191, 255 ], + "example_normalized_UINT8_SCALAR" : 255, + "example_variable_length_normalized_UINT8_SCALAR_array" : [ 0, 84, 170, 255 ], + "example_fixed_length_normalized_UINT8_SCALAR_array" : [ 0, 63, 127, 191, 255 ], + "example_INT16_SCALAR" : -32768, + "example_variable_length_INT16_SCALAR_array" : [ -32768, -10923, 10922, 32767 ], + "example_fixed_length_INT16_SCALAR_array" : [ -32768, -16384, 0, 16383, 32767 ], + "example_normalized_INT16_SCALAR" : -32768, + "example_variable_length_normalized_INT16_SCALAR_array" : [ -32768, -10923, 10922, 32767 ], + "example_fixed_length_normalized_INT16_SCALAR_array" : [ -32768, -16384, 0, 16383, 32767 ], + "example_UINT16_SCALAR" : 65535, + "example_variable_length_UINT16_SCALAR_array" : [ 0, 21844, 43690, 65535 ], + "example_fixed_length_UINT16_SCALAR_array" : [ 0, 16383, 32767, 49151, 65535 ], + "example_normalized_UINT16_SCALAR" : 65535, + "example_variable_length_normalized_UINT16_SCALAR_array" : [ 0, 21844, 43690, 65535 ], + "example_fixed_length_normalized_UINT16_SCALAR_array" : [ 0, 16383, 32767, 49151, 65535 ], + "example_INT32_SCALAR" : -2147483648, + "example_variable_length_INT32_SCALAR_array" : [ -2147483648, -715827883, 715827882, 2147483647 ], + "example_fixed_length_INT32_SCALAR_array" : [ -2147483648, -1073741824, 0, 1073741823, 2147483647 ], + "example_normalized_INT32_SCALAR" : -2147483648, + "example_variable_length_normalized_INT32_SCALAR_array" : [ -2147483648, -715827883, 715827882, 2147483647 ], + "example_fixed_length_normalized_INT32_SCALAR_array" : [ -2147483648, -1073741824, 0, 1073741823, 2147483647 ], + "example_UINT32_SCALAR" : 4294967295, + "example_variable_length_UINT32_SCALAR_array" : [ 0, 1431655764, 2863311530, 4294967295 ], + "example_fixed_length_UINT32_SCALAR_array" : [ 0, 1073741823, 2147483647, 3221225471, 4294967295 ], + "example_normalized_UINT32_SCALAR" : 4294967295, + "example_variable_length_normalized_UINT32_SCALAR_array" : [ 0, 1431655764, 2863311530, 4294967295 ], + "example_fixed_length_normalized_UINT32_SCALAR_array" : [ 0, 1073741823, 2147483647, 3221225471, 4294967295 ], + "example_INT64_SCALAR" : -9223372036854775808, + "example_variable_length_INT64_SCALAR_array" : [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], + "example_fixed_length_INT64_SCALAR_array" : [ -9223372036854775808, -4611686018427387904, 0, 4611686018427387903, 9223372036854775807 ], + "example_normalized_INT64_SCALAR" : -9223372036854775808, + "example_variable_length_normalized_INT64_SCALAR_array" : [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], + "example_fixed_length_normalized_INT64_SCALAR_array" : [ -9223372036854775808, -4611686018427387904, 0, 4611686018427387903, 9223372036854775807 ], + "example_UINT64_SCALAR" : 18446744073709551615, + "example_variable_length_UINT64_SCALAR_array" : [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], + "example_fixed_length_UINT64_SCALAR_array" : [ 0, 4611686018427387903, 9223372036854775807, 13835058055282163711, 18446744073709551615 ], + "example_normalized_UINT64_SCALAR" : 18446744073709551615, + "example_variable_length_normalized_UINT64_SCALAR_array" : [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], + "example_fixed_length_normalized_UINT64_SCALAR_array" : [ 0, 4611686018427387903, 9223372036854775807, 13835058055282163711, 18446744073709551615 ], + "example_FLOAT32_SCALAR" : 1.2, + "example_variable_length_FLOAT32_SCALAR_array" : [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], + "example_fixed_length_FLOAT32_SCALAR_array" : [ -1.0, -0.5, 0.0, 0.5, 1.0 ], + "example_FLOAT64_SCALAR" : 12.34, + "example_variable_length_FLOAT64_SCALAR_array" : [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], + "example_fixed_length_FLOAT64_SCALAR_array" : [ -1.0, -0.5, 0.0, 0.5, 1.0 ], + "example_INT8_VEC2" : [ -128, 127 ], + "example_variable_length_INT8_VEC2_array" : [ [ -128, 127 ], [ -128, 127 ], [ -128, 127 ], [ -128, 127 ] ], + "example_fixed_length_INT8_VEC2_array" : [ [ -128, 127 ], [ -128, 127 ], [ -128, 127 ], [ -128, 127 ], [ -128, 127 ] ], + "example_normalized_INT8_VEC2" : [ -128, 127 ], + "example_variable_length_normalized_INT8_VEC2_array" : [ [ -128, 127 ], [ -128, 127 ], [ -128, 127 ], [ -128, 127 ] ], + "example_fixed_length_normalized_INT8_VEC2_array" : [ [ -128, 127 ], [ -128, 127 ], [ -128, 127 ], [ -128, 127 ], [ -128, 127 ] ], + "example_UINT8_VEC2" : [ 0, 255 ], + "example_variable_length_UINT8_VEC2_array" : [ [ 0, 255 ], [ 0, 255 ], [ 0, 255 ], [ 0, 255 ] ], + "example_fixed_length_UINT8_VEC2_array" : [ [ 0, 255 ], [ 0, 255 ], [ 0, 255 ], [ 0, 255 ], [ 0, 255 ] ], + "example_normalized_UINT8_VEC2" : [ 0, 255 ], + "example_variable_length_normalized_UINT8_VEC2_array" : [ [ 0, 255 ], [ 0, 255 ], [ 0, 255 ], [ 0, 255 ] ], + "example_fixed_length_normalized_UINT8_VEC2_array" : [ [ 0, 255 ], [ 0, 255 ], [ 0, 255 ], [ 0, 255 ], [ 0, 255 ] ], + "example_INT16_VEC2" : [ -32768, 32767 ], + "example_variable_length_INT16_VEC2_array" : [ [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ] ], + "example_fixed_length_INT16_VEC2_array" : [ [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ] ], + "example_normalized_INT16_VEC2" : [ -32768, 32767 ], + "example_variable_length_normalized_INT16_VEC2_array" : [ [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ] ], + "example_fixed_length_normalized_INT16_VEC2_array" : [ [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ], [ -32768, 32767 ] ], + "example_UINT16_VEC2" : [ 0, 65535 ], + "example_variable_length_UINT16_VEC2_array" : [ [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ] ], + "example_fixed_length_UINT16_VEC2_array" : [ [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ] ], + "example_normalized_UINT16_VEC2" : [ 0, 65535 ], + "example_variable_length_normalized_UINT16_VEC2_array" : [ [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ] ], + "example_fixed_length_normalized_UINT16_VEC2_array" : [ [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ], [ 0, 65535 ] ], + "example_INT32_VEC2" : [ -2147483648, 2147483647 ], + "example_variable_length_INT32_VEC2_array" : [ [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ] ], + "example_fixed_length_INT32_VEC2_array" : [ [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ] ], + "example_normalized_INT32_VEC2" : [ -2147483648, 2147483647 ], + "example_variable_length_normalized_INT32_VEC2_array" : [ [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ] ], + "example_fixed_length_normalized_INT32_VEC2_array" : [ [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ], [ -2147483648, 2147483647 ] ], + "example_UINT32_VEC2" : [ 0, 4294967295 ], + "example_variable_length_UINT32_VEC2_array" : [ [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ] ], + "example_fixed_length_UINT32_VEC2_array" : [ [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ] ], + "example_normalized_UINT32_VEC2" : [ 0, 4294967295 ], + "example_variable_length_normalized_UINT32_VEC2_array" : [ [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ] ], + "example_fixed_length_normalized_UINT32_VEC2_array" : [ [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ], [ 0, 4294967295 ] ], + "example_INT64_VEC2" : [ -9223372036854775808, 9223372036854775807 ], + "example_variable_length_INT64_VEC2_array" : [ [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ] ], + "example_fixed_length_INT64_VEC2_array" : [ [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ] ], + "example_normalized_INT64_VEC2" : [ -9223372036854775808, 9223372036854775807 ], + "example_variable_length_normalized_INT64_VEC2_array" : [ [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ] ], + "example_fixed_length_normalized_INT64_VEC2_array" : [ [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ], [ -9223372036854775808, 9223372036854775807 ] ], + "example_UINT64_VEC2" : [ 0, 18446744073709551615 ], + "example_variable_length_UINT64_VEC2_array" : [ [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ] ], + "example_fixed_length_UINT64_VEC2_array" : [ [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ] ], + "example_normalized_UINT64_VEC2" : [ 0, 18446744073709551615 ], + "example_variable_length_normalized_UINT64_VEC2_array" : [ [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ] ], + "example_fixed_length_normalized_UINT64_VEC2_array" : [ [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ], [ 0, 18446744073709551615 ] ], + "example_FLOAT32_VEC2" : [ -1.0, 1.0 ], + "example_variable_length_FLOAT32_VEC2_array" : [ [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ] ], + "example_fixed_length_FLOAT32_VEC2_array" : [ [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ] ], + "example_FLOAT64_VEC2" : [ -1.0, 1.0 ], + "example_variable_length_FLOAT64_VEC2_array" : [ [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ] ], + "example_fixed_length_FLOAT64_VEC2_array" : [ [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ], [ -1.0, 1.0 ] ], + "example_INT8_VEC3" : [ -128, 0, 127 ], + "example_variable_length_INT8_VEC3_array" : [ [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ] ], + "example_fixed_length_INT8_VEC3_array" : [ [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ] ], + "example_normalized_INT8_VEC3" : [ -128, 0, 127 ], + "example_variable_length_normalized_INT8_VEC3_array" : [ [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ] ], + "example_fixed_length_normalized_INT8_VEC3_array" : [ [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ], [ -128, 0, 127 ] ], + "example_UINT8_VEC3" : [ 0, 127, 255 ], + "example_variable_length_UINT8_VEC3_array" : [ [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ] ], + "example_fixed_length_UINT8_VEC3_array" : [ [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ] ], + "example_normalized_UINT8_VEC3" : [ 0, 127, 255 ], + "example_variable_length_normalized_UINT8_VEC3_array" : [ [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ] ], + "example_fixed_length_normalized_UINT8_VEC3_array" : [ [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ], [ 0, 127, 255 ] ], + "example_INT16_VEC3" : [ -32768, 0, 32767 ], + "example_variable_length_INT16_VEC3_array" : [ [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ] ], + "example_fixed_length_INT16_VEC3_array" : [ [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ] ], + "example_normalized_INT16_VEC3" : [ -32768, 0, 32767 ], + "example_variable_length_normalized_INT16_VEC3_array" : [ [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ] ], + "example_fixed_length_normalized_INT16_VEC3_array" : [ [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ], [ -32768, 0, 32767 ] ], + "example_UINT16_VEC3" : [ 0, 32767, 65535 ], + "example_variable_length_UINT16_VEC3_array" : [ [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ] ], + "example_fixed_length_UINT16_VEC3_array" : [ [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ] ], + "example_normalized_UINT16_VEC3" : [ 0, 32767, 65535 ], + "example_variable_length_normalized_UINT16_VEC3_array" : [ [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ] ], + "example_fixed_length_normalized_UINT16_VEC3_array" : [ [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ], [ 0, 32767, 65535 ] ], + "example_INT32_VEC3" : [ -2147483648, 0, 2147483647 ], + "example_variable_length_INT32_VEC3_array" : [ [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ] ], + "example_fixed_length_INT32_VEC3_array" : [ [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ] ], + "example_normalized_INT32_VEC3" : [ -2147483648, 0, 2147483647 ], + "example_variable_length_normalized_INT32_VEC3_array" : [ [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ] ], + "example_fixed_length_normalized_INT32_VEC3_array" : [ [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ], [ -2147483648, 0, 2147483647 ] ], + "example_UINT32_VEC3" : [ 0, 2147483647, 4294967295 ], + "example_variable_length_UINT32_VEC3_array" : [ [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ] ], + "example_fixed_length_UINT32_VEC3_array" : [ [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ] ], + "example_normalized_UINT32_VEC3" : [ 0, 2147483647, 4294967295 ], + "example_variable_length_normalized_UINT32_VEC3_array" : [ [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ] ], + "example_fixed_length_normalized_UINT32_VEC3_array" : [ [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ], [ 0, 2147483647, 4294967295 ] ], + "example_INT64_VEC3" : [ -9223372036854775808, 0, 9223372036854775807 ], + "example_variable_length_INT64_VEC3_array" : [ [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ] ], + "example_fixed_length_INT64_VEC3_array" : [ [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ] ], + "example_normalized_INT64_VEC3" : [ -9223372036854775808, 0, 9223372036854775807 ], + "example_variable_length_normalized_INT64_VEC3_array" : [ [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ] ], + "example_fixed_length_normalized_INT64_VEC3_array" : [ [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ], [ -9223372036854775808, 0, 9223372036854775807 ] ], + "example_UINT64_VEC3" : [ 0, 9223372036854775807, 18446744073709551615 ], + "example_variable_length_UINT64_VEC3_array" : [ [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ] ], + "example_fixed_length_UINT64_VEC3_array" : [ [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ] ], + "example_normalized_UINT64_VEC3" : [ 0, 9223372036854775807, 18446744073709551615 ], + "example_variable_length_normalized_UINT64_VEC3_array" : [ [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ] ], + "example_fixed_length_normalized_UINT64_VEC3_array" : [ [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ], [ 0, 9223372036854775807, 18446744073709551615 ] ], + "example_FLOAT32_VEC3" : [ -1.0, 0.0, 1.0 ], + "example_variable_length_FLOAT32_VEC3_array" : [ [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ] ], + "example_fixed_length_FLOAT32_VEC3_array" : [ [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ] ], + "example_FLOAT64_VEC3" : [ -1.0, 0.0, 1.0 ], + "example_variable_length_FLOAT64_VEC3_array" : [ [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ] ], + "example_fixed_length_FLOAT64_VEC3_array" : [ [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ], [ -1.0, 0.0, 1.0 ] ], + "example_INT8_VEC4" : [ -128, -43, 42, 127 ], + "example_variable_length_INT8_VEC4_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_fixed_length_INT8_VEC4_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_normalized_INT8_VEC4" : [ -128, -43, 42, 127 ], + "example_variable_length_normalized_INT8_VEC4_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_fixed_length_normalized_INT8_VEC4_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_UINT8_VEC4" : [ 0, 84, 170, 255 ], + "example_variable_length_UINT8_VEC4_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_fixed_length_UINT8_VEC4_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_normalized_UINT8_VEC4" : [ 0, 84, 170, 255 ], + "example_variable_length_normalized_UINT8_VEC4_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_fixed_length_normalized_UINT8_VEC4_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_INT16_VEC4" : [ -32768, -10923, 10922, 32767 ], + "example_variable_length_INT16_VEC4_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_fixed_length_INT16_VEC4_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_normalized_INT16_VEC4" : [ -32768, -10923, 10922, 32767 ], + "example_variable_length_normalized_INT16_VEC4_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_fixed_length_normalized_INT16_VEC4_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_UINT16_VEC4" : [ 0, 21844, 43690, 65535 ], + "example_variable_length_UINT16_VEC4_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_fixed_length_UINT16_VEC4_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_normalized_UINT16_VEC4" : [ 0, 21844, 43690, 65535 ], + "example_variable_length_normalized_UINT16_VEC4_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_fixed_length_normalized_UINT16_VEC4_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_INT32_VEC4" : [ -2147483648, -715827883, 715827882, 2147483647 ], + "example_variable_length_INT32_VEC4_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_fixed_length_INT32_VEC4_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_normalized_INT32_VEC4" : [ -2147483648, -715827883, 715827882, 2147483647 ], + "example_variable_length_normalized_INT32_VEC4_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_fixed_length_normalized_INT32_VEC4_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_UINT32_VEC4" : [ 0, 1431655764, 2863311530, 4294967295 ], + "example_variable_length_UINT32_VEC4_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_fixed_length_UINT32_VEC4_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_normalized_UINT32_VEC4" : [ 0, 1431655764, 2863311530, 4294967295 ], + "example_variable_length_normalized_UINT32_VEC4_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_fixed_length_normalized_UINT32_VEC4_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_INT64_VEC4" : [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], + "example_variable_length_INT64_VEC4_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_fixed_length_INT64_VEC4_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_normalized_INT64_VEC4" : [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], + "example_variable_length_normalized_INT64_VEC4_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_fixed_length_normalized_INT64_VEC4_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_UINT64_VEC4" : [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], + "example_variable_length_UINT64_VEC4_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_fixed_length_UINT64_VEC4_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_normalized_UINT64_VEC4" : [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], + "example_variable_length_normalized_UINT64_VEC4_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_fixed_length_normalized_UINT64_VEC4_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_FLOAT32_VEC4" : [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], + "example_variable_length_FLOAT32_VEC4_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_fixed_length_FLOAT32_VEC4_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_FLOAT64_VEC4" : [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], + "example_variable_length_FLOAT64_VEC4_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_fixed_length_FLOAT64_VEC4_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_INT8_MAT2" : [ -128, -43, 42, 127 ], + "example_variable_length_INT8_MAT2_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_fixed_length_INT8_MAT2_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_normalized_INT8_MAT2" : [ -128, -43, 42, 127 ], + "example_variable_length_normalized_INT8_MAT2_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_fixed_length_normalized_INT8_MAT2_array" : [ [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ], [ -128, -43, 42, 127 ] ], + "example_UINT8_MAT2" : [ 0, 84, 170, 255 ], + "example_variable_length_UINT8_MAT2_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_fixed_length_UINT8_MAT2_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_normalized_UINT8_MAT2" : [ 0, 84, 170, 255 ], + "example_variable_length_normalized_UINT8_MAT2_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_fixed_length_normalized_UINT8_MAT2_array" : [ [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ], [ 0, 84, 170, 255 ] ], + "example_INT16_MAT2" : [ -32768, -10923, 10922, 32767 ], + "example_variable_length_INT16_MAT2_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_fixed_length_INT16_MAT2_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_normalized_INT16_MAT2" : [ -32768, -10923, 10922, 32767 ], + "example_variable_length_normalized_INT16_MAT2_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_fixed_length_normalized_INT16_MAT2_array" : [ [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ], [ -32768, -10923, 10922, 32767 ] ], + "example_UINT16_MAT2" : [ 0, 21844, 43690, 65535 ], + "example_variable_length_UINT16_MAT2_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_fixed_length_UINT16_MAT2_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_normalized_UINT16_MAT2" : [ 0, 21844, 43690, 65535 ], + "example_variable_length_normalized_UINT16_MAT2_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_fixed_length_normalized_UINT16_MAT2_array" : [ [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ], [ 0, 21844, 43690, 65535 ] ], + "example_INT32_MAT2" : [ -2147483648, -715827883, 715827882, 2147483647 ], + "example_variable_length_INT32_MAT2_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_fixed_length_INT32_MAT2_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_normalized_INT32_MAT2" : [ -2147483648, -715827883, 715827882, 2147483647 ], + "example_variable_length_normalized_INT32_MAT2_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_fixed_length_normalized_INT32_MAT2_array" : [ [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ], [ -2147483648, -715827883, 715827882, 2147483647 ] ], + "example_UINT32_MAT2" : [ 0, 1431655764, 2863311530, 4294967295 ], + "example_variable_length_UINT32_MAT2_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_fixed_length_UINT32_MAT2_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_normalized_UINT32_MAT2" : [ 0, 1431655764, 2863311530, 4294967295 ], + "example_variable_length_normalized_UINT32_MAT2_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_fixed_length_normalized_UINT32_MAT2_array" : [ [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ], [ 0, 1431655764, 2863311530, 4294967295 ] ], + "example_INT64_MAT2" : [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], + "example_variable_length_INT64_MAT2_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_fixed_length_INT64_MAT2_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_normalized_INT64_MAT2" : [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], + "example_variable_length_normalized_INT64_MAT2_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_fixed_length_normalized_INT64_MAT2_array" : [ [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ], [ -9223372036854775808, -3074457346233150072, 3074457346233150071, 9223372036854775807 ] ], + "example_UINT64_MAT2" : [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], + "example_variable_length_UINT64_MAT2_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_fixed_length_UINT64_MAT2_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_normalized_UINT64_MAT2" : [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], + "example_variable_length_normalized_UINT64_MAT2_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_fixed_length_normalized_UINT64_MAT2_array" : [ [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ], [ 0, 6148914690621625735, 12297829383087925879, 18446744073709551615 ] ], + "example_FLOAT32_MAT2" : [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], + "example_variable_length_FLOAT32_MAT2_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_fixed_length_FLOAT32_MAT2_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_FLOAT64_MAT2" : [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], + "example_variable_length_FLOAT64_MAT2_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_fixed_length_FLOAT64_MAT2_array" : [ [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ], [ -1.0, -0.3333333334, 0.3333333334, 1.0 ] ], + "example_INT8_MAT3" : [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], + "example_variable_length_INT8_MAT3_array" : [ [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ] ], + "example_fixed_length_INT8_MAT3_array" : [ [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ] ], + "example_normalized_INT8_MAT3" : [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], + "example_variable_length_normalized_INT8_MAT3_array" : [ [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ] ], + "example_fixed_length_normalized_INT8_MAT3_array" : [ [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ], [ -128, -96, -64, -32, 0, 31, 63, 95, 127 ] ], + "example_UINT8_MAT3" : [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], + "example_variable_length_UINT8_MAT3_array" : [ [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ] ], + "example_fixed_length_UINT8_MAT3_array" : [ [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ] ], + "example_normalized_UINT8_MAT3" : [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], + "example_variable_length_normalized_UINT8_MAT3_array" : [ [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ] ], + "example_fixed_length_normalized_UINT8_MAT3_array" : [ [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ], [ 0, 31, 63, 95, 127, 159, 191, 223, 255 ] ], + "example_INT16_MAT3" : [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], + "example_variable_length_INT16_MAT3_array" : [ [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ] ], + "example_fixed_length_INT16_MAT3_array" : [ [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ] ], + "example_normalized_INT16_MAT3" : [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], + "example_variable_length_normalized_INT16_MAT3_array" : [ [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ] ], + "example_fixed_length_normalized_INT16_MAT3_array" : [ [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ], [ -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767 ] ], + "example_UINT16_MAT3" : [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], + "example_variable_length_UINT16_MAT3_array" : [ [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ] ], + "example_fixed_length_UINT16_MAT3_array" : [ [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ] ], + "example_normalized_UINT16_MAT3" : [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], + "example_variable_length_normalized_UINT16_MAT3_array" : [ [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ] ], + "example_fixed_length_normalized_UINT16_MAT3_array" : [ [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ], [ 0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535 ] ], + "example_INT32_MAT3" : [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], + "example_variable_length_INT32_MAT3_array" : [ [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ] ], + "example_fixed_length_INT32_MAT3_array" : [ [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ] ], + "example_normalized_INT32_MAT3" : [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], + "example_variable_length_normalized_INT32_MAT3_array" : [ [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ] ], + "example_fixed_length_normalized_INT32_MAT3_array" : [ [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ], [ -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, 1073741823, 1610612735, 2147483647 ] ], + "example_UINT32_MAT3" : [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], + "example_variable_length_UINT32_MAT3_array" : [ [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ] ], + "example_fixed_length_UINT32_MAT3_array" : [ [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ] ], + "example_normalized_UINT32_MAT3" : [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], + "example_variable_length_normalized_UINT32_MAT3_array" : [ [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ] ], + "example_fixed_length_normalized_UINT32_MAT3_array" : [ [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ], [ 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, 3758096383, 4294967295 ] ], + "example_INT64_MAT3" : [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], + "example_variable_length_INT64_MAT3_array" : [ [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ] ], + "example_fixed_length_INT64_MAT3_array" : [ [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ] ], + "example_normalized_INT64_MAT3" : [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], + "example_variable_length_normalized_INT64_MAT3_array" : [ [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ] ], + "example_fixed_length_normalized_INT64_MAT3_array" : [ [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ], [ -9223372036854775808, -6917529027641081856, -4611686018427387904, -2305843009213693952, 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807 ] ], + "example_UINT64_MAT3" : [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], + "example_variable_length_UINT64_MAT3_array" : [ [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ] ], + "example_fixed_length_UINT64_MAT3_array" : [ [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ] ], + "example_normalized_UINT64_MAT3" : [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], + "example_variable_length_normalized_UINT64_MAT3_array" : [ [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ] ], + "example_fixed_length_normalized_UINT64_MAT3_array" : [ [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ], [ 0, 2305843009213693951, 4611686018427387903, 6917529027641081855, 9223372036854775807, 11529215046068469759, 13835058055282163711, 16140901064495857663, 18446744073709551615 ] ], + "example_FLOAT32_MAT3" : [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], + "example_variable_length_FLOAT32_MAT3_array" : [ [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ] ], + "example_fixed_length_FLOAT32_MAT3_array" : [ [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ] ], + "example_FLOAT64_MAT3" : [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], + "example_variable_length_FLOAT64_MAT3_array" : [ [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ] ], + "example_fixed_length_FLOAT64_MAT3_array" : [ [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ], [ -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0 ] ], + "example_INT8_MAT4" : [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], + "example_variable_length_INT8_MAT4_array" : [ [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ] ], + "example_fixed_length_INT8_MAT4_array" : [ [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ] ], + "example_normalized_INT8_MAT4" : [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], + "example_variable_length_normalized_INT8_MAT4_array" : [ [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ] ], + "example_fixed_length_normalized_INT8_MAT4_array" : [ [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ], [ -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127 ] ], + "example_UINT8_MAT4" : [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], + "example_variable_length_UINT8_MAT4_array" : [ [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ] ], + "example_fixed_length_UINT8_MAT4_array" : [ [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ] ], + "example_normalized_UINT8_MAT4" : [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], + "example_variable_length_normalized_UINT8_MAT4_array" : [ [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ] ], + "example_fixed_length_normalized_UINT8_MAT4_array" : [ [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ], [ 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255 ] ], + "example_INT16_MAT4" : [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], + "example_variable_length_INT16_MAT4_array" : [ [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ] ], + "example_fixed_length_INT16_MAT4_array" : [ [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ] ], + "example_normalized_INT16_MAT4" : [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], + "example_variable_length_normalized_INT16_MAT4_array" : [ [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ] ], + "example_fixed_length_normalized_INT16_MAT4_array" : [ [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ], [ -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, 10922, 15290, 19660, 24029, 28397, 32767 ] ], + "example_UINT16_MAT4" : [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], + "example_variable_length_UINT16_MAT4_array" : [ [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ] ], + "example_fixed_length_UINT16_MAT4_array" : [ [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ] ], + "example_normalized_UINT16_MAT4" : [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], + "example_variable_length_normalized_UINT16_MAT4_array" : [ [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ] ], + "example_fixed_length_normalized_UINT16_MAT4_array" : [ [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ], [ 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, 48058, 52428, 56797, 61165, 65535 ] ], + "example_INT32_MAT4" : [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], + "example_variable_length_INT32_MAT4_array" : [ [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ] ], + "example_fixed_length_INT32_MAT4_array" : [ [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ] ], + "example_normalized_INT32_MAT4" : [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], + "example_variable_length_normalized_INT32_MAT4_array" : [ [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ] ], + "example_fixed_length_normalized_INT32_MAT4_array" : [ [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ], [ -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, 1002159034, 1288490188, 1574821341, 1861152493, 2147483647 ] ], + "example_UINT32_MAT4" : [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], + "example_variable_length_UINT32_MAT4_array" : [ [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ] ], + "example_fixed_length_UINT32_MAT4_array" : [ [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ] ], + "example_normalized_UINT32_MAT4" : [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], + "example_variable_length_normalized_UINT32_MAT4_array" : [ [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ] ], + "example_fixed_length_normalized_UINT32_MAT4_array" : [ [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ], [ 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, 3722304989, 4008636141, 4294967295 ] ], + "example_INT64_MAT4" : [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], + "example_variable_length_INT64_MAT4_array" : [ [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ] ], + "example_fixed_length_INT64_MAT4_array" : [ [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ] ], + "example_normalized_INT64_MAT4" : [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], + "example_variable_length_normalized_INT64_MAT4_array" : [ [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ] ], + "example_fixed_length_normalized_INT64_MAT4_array" : [ [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ], [ -9223372036854775808, -7993589097992580897, -6763806160975060395, -5534023222112865485, -4304240283250670574, -3074457346233150072, -1844674407370955162, -614891468508760251, 614891468508760250, 1844674407370955161, 3074457346233150071, 4304240283250670573, 5534023222112865484, 6763806160975060394, 7993589097992580896, 9223372036854775807 ] ], + "example_UINT64_MAT4" : [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], + "example_variable_length_UINT64_MAT4_array" : [ [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ] ], + "example_fixed_length_UINT64_MAT4_array" : [ [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ] ], + "example_normalized_UINT64_MAT4" : [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], + "example_variable_length_normalized_UINT64_MAT4_array" : [ [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ] ], + "example_fixed_length_normalized_UINT64_MAT4_array" : [ [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ], [ 0, 1229782938862194910, 2459565875879715412, 3689348814741910323, 4919131753604105233, 6148914690621625735, 7378697629483820646, 8608480568346015556, 9838263505363536058, 11068046444225730969, 12297829383087925879, 13527612320105446381, 14757395258967641292, 15987178197829836202, 17216961134847356704, 18446744073709551615 ] ], + "example_FLOAT32_MAT4" : [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], + "example_variable_length_FLOAT32_MAT4_array" : [ [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ] ], + "example_fixed_length_FLOAT32_MAT4_array" : [ [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ] ], + "example_FLOAT64_MAT4" : [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], + "example_variable_length_FLOAT64_MAT4_array" : [ [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ] ], + "example_fixed_length_FLOAT64_MAT4_array" : [ [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ], [ -1.0, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, 0.7333333334, 0.8666666666, 1.0 ] ] + } + }, + "geometricError" : 2.0, + "root" : { + "boundingVolume" : { + "box" : [ 0.5, 0.5, 0.5, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5 ] + }, + "geometricError" : 1.0 + } +} \ No newline at end of file diff --git a/specs/metadata/ArrayValuesSpec.ts b/specs/metadata/ArrayValuesSpec.ts new file mode 100644 index 00000000..b26ed432 --- /dev/null +++ b/specs/metadata/ArrayValuesSpec.ts @@ -0,0 +1,635 @@ +import { ArrayValues } from "../../src/metadata/ArrayValues"; + +describe("metadata/ArrayValues", function () { + //========================================================================== + // deepMultiply + + it("performs deepMultiply for number,number", function () { + const value = 2; + const factor = 3; + const expected = 2 * 3; + const actual = ArrayValues.deepMultiply(value, factor); + expect(actual).toEqual(expected); + }); + + it("performs deepMultiply for number[],number[]", function () { + const value = [2, 3]; + const factor = [3, 4]; + const expected = [2 * 3, 3 * 4]; + const actual = ArrayValues.deepMultiply(value, factor); + expect(actual).toEqual(expected); + }); + + it("performs deepMultiply for number[][],number[][]", function () { + const value = [ + [2, 3], + [4, 5], + ]; + const factor = [ + [3, 4], + [5, 6], + ]; + const expected = [ + [2 * 3, 3 * 4], + [4 * 5, 5 * 6], + ]; + const actual = ArrayValues.deepMultiply(value, factor); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepAdd + + it("performs deepAdd for number,number", function () { + const value = 2; + const factor = 3; + const expected = 2 + 3; + const actual = ArrayValues.deepAdd(value, factor); + expect(actual).toEqual(expected); + }); + + it("performs deepAdd for number[],number[]", function () { + const value = [2, 3]; + const factor = [3, 4]; + const expected = [2 + 3, 3 + 4]; + const actual = ArrayValues.deepAdd(value, factor); + expect(actual).toEqual(expected); + }); + + it("performs deepAdd for number[][],number[][]", function () { + const value = [ + [2, 3], + [4, 5], + ]; + const factor = [ + [3, 4], + [5, 6], + ]; + const expected = [ + [2 + 3, 3 + 4], + [4 + 5, 5 + 6], + ]; + const actual = ArrayValues.deepAdd(value, factor); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMin number,number + + it("performs deepMin for number,number", function () { + const a = 2; + const b = 3; + const expected = 2; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for number[],number[]", function () { + const a = [5, 2]; + const b = [3, 4]; + const expected = [3, 2]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for number[][],number[][]", function () { + const a = [ + [5, 2], + [1, 7], + ]; + const b = [ + [3, 4], + [5, 6], + ]; + const expected = [ + [3, 2], + [1, 6], + ]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMin number,bigint + + it("performs deepMin for number,bigint", function () { + const a = 2; + const b = BigInt(3); + const expected = 2; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for number[],bigint[]", function () { + const a = [5, 2]; + const b = [BigInt(3), BigInt(4)]; + const expected = [BigInt(3), 2]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for number[][],bigint[][]", function () { + const a = [ + [5, 2], + [1, 7], + ]; + const b = [ + [BigInt(3), BigInt(4)], + [BigInt(5), BigInt(6)], + ]; + const expected = [ + [BigInt(3), 2], + [1, BigInt(6)], + ]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMin bigint,number + + it("performs deepMin for bigint,number", function () { + const a = BigInt(2); + const b = 3; + const expected = BigInt(2); + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for bigint[],number[]", function () { + const a = [BigInt(2), BigInt(3)]; + const b = [3, 4]; + const expected = [BigInt(2), BigInt(3)]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for bigint[][],number[][]", function () { + const a = [ + [BigInt(5), BigInt(2)], + [BigInt(1), BigInt(7)], + ]; + const b = [ + [3, 4], + [5, 6], + ]; + const expected = [ + [3, BigInt(2)], + [BigInt(1), 6], + ]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMin bigint,bigint + + it("performs deepMin for bigint,bigint", function () { + const a = BigInt(2); + const b = BigInt(3); + const expected = BigInt(2); + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for bigint[],bigint[]", function () { + const a = [BigInt(5), BigInt(2)]; + const b = [BigInt(3), BigInt(4)]; + const expected = [BigInt(3), BigInt(2)]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMin for bigint[][],bigint[][]", function () { + const a = [ + [BigInt(5), BigInt(2)], + [BigInt(1), BigInt(7)], + ]; + const b = [ + [BigInt(3), BigInt(4)], + [BigInt(5), BigInt(6)], + ]; + const expected = [ + [BigInt(3), BigInt(2)], + [BigInt(1), BigInt(6)], + ]; + const actual = ArrayValues.deepMin(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMax number,number + + it("performs deepMax for number,number", function () { + const a = 2; + const b = 3; + const expected = 3; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for number[],number[]", function () { + const a = [5, 2]; + const b = [3, 4]; + const expected = [5, 4]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for number[][],number[][]", function () { + const a = [ + [5, 2], + [1, 7], + ]; + const b = [ + [3, 4], + [5, 6], + ]; + const expected = [ + [5, 4], + [5, 7], + ]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMax number,bigint + + it("performs deepMax for number,bigint", function () { + const a = 2; + const b = BigInt(3); + const expected = BigInt(3); + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for number[],bigint[]", function () { + const a = [5, 2]; + const b = [BigInt(3), BigInt(4)]; + const expected = [5, BigInt(4)]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for number[][],bigint[][]", function () { + const a = [ + [5, 2], + [1, 7], + ]; + const b = [ + [BigInt(3), BigInt(4)], + [BigInt(5), BigInt(6)], + ]; + const expected = [ + [5, BigInt(4)], + [BigInt(5), 7], + ]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMax bigint,number + + it("performs deepMax for bigint,number", function () { + const a = BigInt(2); + const b = 3; + const expected = 3; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for bigint[],number[]", function () { + const a = [BigInt(5), BigInt(2)]; + const b = [3, 4]; + const expected = [BigInt(5), 4]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for bigint[][],number[][]", function () { + const a = [ + [BigInt(5), BigInt(2)], + [BigInt(1), BigInt(7)], + ]; + const b = [ + [3, 4], + [5, 6], + ]; + const expected = [ + [BigInt(5), 4], + [5, BigInt(7)], + ]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // deepMax bigint,bigint + + it("performs deepMax for bigint,bigint", function () { + const a = BigInt(2); + const b = BigInt(3); + const expected = BigInt(3); + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for bigint[],bigint[]", function () { + const a = [BigInt(5), BigInt(2)]; + const b = [BigInt(3), BigInt(4)]; + const expected = [BigInt(5), BigInt(4)]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + it("performs deepMax for bigint[][],bigint[][]", function () { + const a = [ + [BigInt(5), BigInt(2)], + [BigInt(1), BigInt(7)], + ]; + const b = [ + [BigInt(3), BigInt(4)], + [BigInt(5), BigInt(6)], + ]; + const expected = [ + [BigInt(5), BigInt(4)], + [BigInt(5), BigInt(7)], + ]; + const actual = ArrayValues.deepMax(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepLessThan number, number + + it("performs anyDeepLessThan for number,number", function () { + const a = 4; + const b = 5; + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for number,number", function () { + const a = 6; + const b = 5; + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for number[],number[]", function () { + const a = [4, 5]; + const b = [5, 5]; + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepLessThan for number[],number[]", function () { + const a = [6, 5]; + const b = [5, 5]; + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepLessThan bigint, number + + it("performs anyDeepLessThan for bigint,number", function () { + const a = BigInt(4); + const b = 5; + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for bigint,number", function () { + const a = BigInt(6); + const b = 5; + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for bigint[],number[]", function () { + const a = [BigInt(4), BigInt(5)]; + const b = [5, 5]; + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepLessThan for bigint[],number[]", function () { + const a = [BigInt(6), BigInt(5)]; + const b = [5, 5]; + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepLessThan number, bigint + + it("performs anyDeepLessThan for number,bigint", function () { + const a = 4; + const b = BigInt(5); + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for number,bigint", function () { + const a = 6; + const b = BigInt(5); + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for number[],bigint[]", function () { + const a = [4, 5]; + const b = [BigInt(5), BigInt(5)]; + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepLessThan for number[],bigint[]", function () { + const a = [6, 5]; + const b = [BigInt(5), BigInt(5)]; + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepLessThan bigint,bigint + + it("performs anyDeepLessThan for bigint,bigint", function () { + const a = BigInt(4); + const b = BigInt(5); + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for bigint,bigint", function () { + const a = BigInt(6); + const b = BigInt(5); + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepLessThan for bigint[],bigint[]", function () { + const a = [BigInt(4), BigInt(5)]; + const b = [BigInt(5), BigInt(5)]; + const expected = true; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepLessThan for bigint[],bigint[]", function () { + const a = [BigInt(6), BigInt(5)]; + const b = [BigInt(5), BigInt(5)]; + const expected = false; + const actual = ArrayValues.anyDeepLessThan(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepGreaterThan number, number + + it("performs anyDeepGreaterThan for number,number", function () { + const a = 4; + const b = 5; + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for number,number", function () { + const a = 6; + const b = 5; + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for number[],number[]", function () { + const a = [4, 5]; + const b = [5, 5]; + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepGreaterThan for number[],number[]", function () { + const a = [6, 5]; + const b = [5, 5]; + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepGreaterThan bigint, number + + it("performs anyDeepGreaterThan for bigint,number", function () { + const a = BigInt(4); + const b = 5; + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for bigint,number", function () { + const a = BigInt(6); + const b = 5; + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for bigint[],number[]", function () { + const a = [BigInt(4), BigInt(5)]; + const b = [5, 5]; + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepGreaterThan for bigint[],number[]", function () { + const a = [BigInt(6), BigInt(5)]; + const b = [5, 5]; + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepGreaterThan number, bigint + + it("performs anyDeepGreaterThan for number,bigint", function () { + const a = 4; + const b = BigInt(5); + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for number,bigint", function () { + const a = 6; + const b = BigInt(5); + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for number[],bigint[]", function () { + const a = [4, 5]; + const b = [BigInt(5), BigInt(5)]; + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepGreaterThan for number[],bigint[]", function () { + const a = [6, 5]; + const b = [BigInt(5), BigInt(5)]; + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + //========================================================================== + // anyDeepGreaterThan bigint,bigint + + it("performs anyDeepGreaterThan for bigint,bigint", function () { + const a = BigInt(4); + const b = BigInt(5); + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for bigint,bigint", function () { + const a = BigInt(6); + const b = BigInt(5); + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + + it("performs anyDeepGreaterThan for bigint[],bigint[]", function () { + const a = [BigInt(4), BigInt(5)]; + const b = [BigInt(5), BigInt(5)]; + const expected = false; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); + it("performs anyDeepGreaterThan for bigint[],bigint[]", function () { + const a = [BigInt(6), BigInt(5)]; + const b = [BigInt(5), BigInt(5)]; + const expected = true; + const actual = ArrayValues.anyDeepGreaterThan(a, b); + expect(actual).toEqual(expected); + }); +}); diff --git a/specs/metadata/MetadataEntityModelBasicSpec.ts b/specs/metadata/MetadataEntityModelBasicSpec.ts new file mode 100644 index 00000000..c824f41e --- /dev/null +++ b/specs/metadata/MetadataEntityModelBasicSpec.ts @@ -0,0 +1,5546 @@ +import { genericEquals } from "./genericEquals"; +import { readJsonUnchecked } from "./readJsonUnchecked"; + +import { MetadataEntityModel } from "../../src/metadata/MetadataEntityModel"; +import { MetadataEntityModels } from "../../src/metadata/MetadataEntityModels"; + +describe("metadata/MetadataEntityModelBasic", function () { + const epsilon = 0.000001; + let metadataEntityModel: MetadataEntityModel; + + beforeEach(async function () { + const tileset = await readJsonUnchecked( + "specs/data/TilesetWithFullMetadata/tileset.json" + ); + metadataEntityModel = MetadataEntityModels.create( + tileset.schema, + tileset.metadata + ); + }); + + it("obtains the right value for example_STRING", function () { + const propertyName = "example_STRING"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = "An example string"; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_STRING_array", function () { + const propertyName = "example_variable_length_STRING_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = ["This", "is", "an", "example"]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_STRING_array", function () { + const propertyName = "example_fixed_length_STRING_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = ["This", "is", "an", "example", "string"]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_BOOLEAN", function () { + const propertyName = "example_BOOLEAN"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = true; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_BOOLEAN_array", function () { + const propertyName = "example_variable_length_BOOLEAN_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [true, false, true, false]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_BOOLEAN_array", function () { + const propertyName = "example_fixed_length_BOOLEAN_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [true, false, true, false, true]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_ENUM", function () { + const propertyName = "example_ENUM"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = "ExampleEnumValueB"; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_ENUM_array", function () { + const propertyName = "example_variable_length_ENUM_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + "ExampleEnumValueA", + "ExampleEnumValueB", + "ExampleEnumValueC", + "ExampleEnumValueA", + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_ENUM_array", function () { + const propertyName = "example_fixed_length_ENUM_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + "ExampleEnumValueA", + "ExampleEnumValueB", + "ExampleEnumValueC", + "ExampleEnumValueA", + "ExampleEnumValueB", + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT8_SCALAR", function () { + const propertyName = "example_INT8_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -128; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT8_SCALAR_array", function () { + const propertyName = "example_variable_length_INT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-128, -43, 42, 127]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT8_SCALAR_array", function () { + const propertyName = "example_fixed_length_INT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-128, -64, 0, 63, 127]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT8_SCALAR", function () { + const propertyName = "example_normalized_INT8_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT8_SCALAR_array", function () { + const propertyName = "example_variable_length_normalized_INT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.33858267716535434, 0.33070866141732286, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT8_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_INT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.5039370078740157, 0, 0.49606299212598426, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT8_SCALAR", function () { + const propertyName = "example_UINT8_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 255; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT8_SCALAR_array", function () { + const propertyName = "example_variable_length_UINT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 84, 170, 255]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT8_SCALAR_array", function () { + const propertyName = "example_fixed_length_UINT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 63, 127, 191, 255]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT8_SCALAR", function () { + const propertyName = "example_normalized_UINT8_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT8_SCALAR_array", function () { + const propertyName = + "example_variable_length_normalized_UINT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.32941176470588235, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT8_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_UINT8_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.24705882352941178, 0.4980392156862745, 0.7490196078431373, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT16_SCALAR", function () { + const propertyName = "example_INT16_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -32768; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT16_SCALAR_array", function () { + const propertyName = "example_variable_length_INT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-32768, -10923, 10922, 32767]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT16_SCALAR_array", function () { + const propertyName = "example_fixed_length_INT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-32768, -16384, 0, 16383, 32767]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT16_SCALAR", function () { + const propertyName = "example_normalized_INT16_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT16_SCALAR_array", function () { + const propertyName = + "example_variable_length_normalized_INT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.33335367900631735, 0.33332316049684135, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT16_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_INT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.500015259254738, 0, 0.499984740745262, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT16_SCALAR", function () { + const propertyName = "example_UINT16_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 65535; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT16_SCALAR_array", function () { + const propertyName = "example_variable_length_UINT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 21844, 43690, 65535]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT16_SCALAR_array", function () { + const propertyName = "example_fixed_length_UINT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 16383, 32767, 49151, 65535]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT16_SCALAR", function () { + const propertyName = "example_normalized_UINT16_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT16_SCALAR_array", function () { + const propertyName = + "example_variable_length_normalized_UINT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.3333180743114366, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT16_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_UINT16_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.24998855573357748, 0.49999237048905165, 0.7499961852445258, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT32_SCALAR", function () { + const propertyName = "example_INT32_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -2147483648; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT32_SCALAR_array", function () { + const propertyName = "example_variable_length_INT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-2147483648, -715827883, 715827882, 2147483647]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT32_SCALAR_array", function () { + const propertyName = "example_fixed_length_INT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-2147483648, -1073741824, 0, 1073741823, 2147483647]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT32_SCALAR", function () { + const propertyName = "example_normalized_INT32_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT32_SCALAR_array", function () { + const propertyName = + "example_variable_length_normalized_INT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333336437742, 0.3333333331781129, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT32_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_INT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.5000000002328306, 0, 0.49999999976716936, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT32_SCALAR", function () { + const propertyName = "example_UINT32_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 4294967295; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT32_SCALAR_array", function () { + const propertyName = "example_variable_length_UINT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1431655764, 2863311530, 4294967295]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT32_SCALAR_array", function () { + const propertyName = "example_fixed_length_UINT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1073741823, 2147483647, 3221225471, 4294967295]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT32_SCALAR", function () { + const propertyName = "example_normalized_UINT32_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT32_SCALAR_array", function () { + const propertyName = + "example_variable_length_normalized_UINT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.33333333310050267, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT32_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_UINT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.24999999982537702, 0.4999999998835847, 0.7499999999417923, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT64_SCALAR", function () { + const propertyName = "example_INT64_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -9223372036854776000n; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT64_SCALAR_array", function () { + const propertyName = "example_variable_length_INT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT64_SCALAR_array", function () { + const propertyName = "example_fixed_length_INT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -9223372036854776000n, + -4611686018427388000n, + 0, + 4611686018427388000n, + 9223372036854776000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT64_SCALAR", function () { + const propertyName = "example_normalized_INT64_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = -1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT64_SCALAR_array", function () { + const propertyName = + "example_variable_length_normalized_INT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT64_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_INT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.5, 0, 0.5, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT64_SCALAR", function () { + const propertyName = "example_UINT64_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 18446744073709552000n; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT64_SCALAR_array", function () { + const propertyName = "example_variable_length_UINT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, + 6148914690621625000n, + 12297829383087925000n, + 18446744073709552000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT64_SCALAR_array", function () { + const propertyName = "example_fixed_length_UINT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, + 4611686018427388000n, + 9223372036854776000n, + 13835058055282164000n, + 18446744073709552000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT64_SCALAR", function () { + const propertyName = "example_normalized_UINT64_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 1; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT64_SCALAR_array", function () { + const propertyName = + "example_variable_length_normalized_UINT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.3333333333, 0.6666666667, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT64_SCALAR_array", function () { + const propertyName = "example_fixed_length_normalized_UINT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.25, 0.5, 0.75, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT32_SCALAR", function () { + const propertyName = "example_FLOAT32_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 1.2; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT32_SCALAR_array", function () { + const propertyName = "example_variable_length_FLOAT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT32_SCALAR_array", function () { + const propertyName = "example_fixed_length_FLOAT32_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.5, 0, 0.5, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT64_SCALAR", function () { + const propertyName = "example_FLOAT64_SCALAR"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = 12.34; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT64_SCALAR_array", function () { + const propertyName = "example_variable_length_FLOAT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT64_SCALAR_array", function () { + const propertyName = "example_fixed_length_FLOAT64_SCALAR_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.5, 0, 0.5, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT8_VEC2", function () { + const propertyName = "example_INT8_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-128, 127]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT8_VEC2_array", function () { + const propertyName = "example_variable_length_INT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, 127], + [-128, 127], + [-128, 127], + [-128, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT8_VEC2_array", function () { + const propertyName = "example_fixed_length_INT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, 127], + [-128, 127], + [-128, 127], + [-128, 127], + [-128, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT8_VEC2", function () { + const propertyName = "example_normalized_INT8_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT8_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_INT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT8_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_INT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT8_VEC2", function () { + const propertyName = "example_UINT8_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 255]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT8_VEC2_array", function () { + const propertyName = "example_variable_length_UINT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 255], + [0, 255], + [0, 255], + [0, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT8_VEC2_array", function () { + const propertyName = "example_fixed_length_UINT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 255], + [0, 255], + [0, 255], + [0, 255], + [0, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT8_VEC2", function () { + const propertyName = "example_normalized_UINT8_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT8_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_UINT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT8_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT8_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT16_VEC2", function () { + const propertyName = "example_INT16_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-32768, 32767]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT16_VEC2_array", function () { + const propertyName = "example_variable_length_INT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, 32767], + [-32768, 32767], + [-32768, 32767], + [-32768, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT16_VEC2_array", function () { + const propertyName = "example_fixed_length_INT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, 32767], + [-32768, 32767], + [-32768, 32767], + [-32768, 32767], + [-32768, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT16_VEC2", function () { + const propertyName = "example_normalized_INT16_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT16_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_INT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT16_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_INT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT16_VEC2", function () { + const propertyName = "example_UINT16_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 65535]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT16_VEC2_array", function () { + const propertyName = "example_variable_length_UINT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 65535], + [0, 65535], + [0, 65535], + [0, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT16_VEC2_array", function () { + const propertyName = "example_fixed_length_UINT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 65535], + [0, 65535], + [0, 65535], + [0, 65535], + [0, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT16_VEC2", function () { + const propertyName = "example_normalized_UINT16_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT16_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_UINT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT16_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT16_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT32_VEC2", function () { + const propertyName = "example_INT32_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-2147483648, 2147483647]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT32_VEC2_array", function () { + const propertyName = "example_variable_length_INT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, 2147483647], + [-2147483648, 2147483647], + [-2147483648, 2147483647], + [-2147483648, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT32_VEC2_array", function () { + const propertyName = "example_fixed_length_INT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, 2147483647], + [-2147483648, 2147483647], + [-2147483648, 2147483647], + [-2147483648, 2147483647], + [-2147483648, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT32_VEC2", function () { + const propertyName = "example_normalized_INT32_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT32_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_INT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT32_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_INT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT32_VEC2", function () { + const propertyName = "example_UINT32_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 4294967295]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT32_VEC2_array", function () { + const propertyName = "example_variable_length_UINT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 4294967295], + [0, 4294967295], + [0, 4294967295], + [0, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT32_VEC2_array", function () { + const propertyName = "example_fixed_length_UINT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 4294967295], + [0, 4294967295], + [0, 4294967295], + [0, 4294967295], + [0, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT32_VEC2", function () { + const propertyName = "example_normalized_UINT32_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT32_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_UINT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT32_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT64_VEC2", function () { + const propertyName = "example_INT64_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-9223372036854776000n, 9223372036854776000n]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT64_VEC2_array", function () { + const propertyName = "example_variable_length_INT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-9223372036854776000n, 9223372036854776000n], + [-9223372036854776000n, 9223372036854776000n], + [-9223372036854776000n, 9223372036854776000n], + [-9223372036854776000n, 9223372036854776000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT64_VEC2_array", function () { + const propertyName = "example_fixed_length_INT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-9223372036854776000n, 9223372036854776000n], + [-9223372036854776000n, 9223372036854776000n], + [-9223372036854776000n, 9223372036854776000n], + [-9223372036854776000n, 9223372036854776000n], + [-9223372036854776000n, 9223372036854776000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT64_VEC2", function () { + const propertyName = "example_normalized_INT64_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT64_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_INT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT64_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_INT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT64_VEC2", function () { + const propertyName = "example_UINT64_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 18446744073709552000n]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT64_VEC2_array", function () { + const propertyName = "example_variable_length_UINT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 18446744073709552000n], + [0, 18446744073709552000n], + [0, 18446744073709552000n], + [0, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT64_VEC2_array", function () { + const propertyName = "example_fixed_length_UINT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 18446744073709552000n], + [0, 18446744073709552000n], + [0, 18446744073709552000n], + [0, 18446744073709552000n], + [0, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT64_VEC2", function () { + const propertyName = "example_normalized_UINT64_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT64_VEC2_array", function () { + const propertyName = "example_variable_length_normalized_UINT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT64_VEC2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT32_VEC2", function () { + const propertyName = "example_FLOAT32_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT32_VEC2_array", function () { + const propertyName = "example_variable_length_FLOAT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT32_VEC2_array", function () { + const propertyName = "example_fixed_length_FLOAT32_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT64_VEC2", function () { + const propertyName = "example_FLOAT64_VEC2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT64_VEC2_array", function () { + const propertyName = "example_variable_length_FLOAT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT64_VEC2_array", function () { + const propertyName = "example_fixed_length_FLOAT64_VEC2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + [-1, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT8_VEC3", function () { + const propertyName = "example_INT8_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-128, 0, 127]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT8_VEC3_array", function () { + const propertyName = "example_variable_length_INT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, 0, 127], + [-128, 0, 127], + [-128, 0, 127], + [-128, 0, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT8_VEC3_array", function () { + const propertyName = "example_fixed_length_INT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, 0, 127], + [-128, 0, 127], + [-128, 0, 127], + [-128, 0, 127], + [-128, 0, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT8_VEC3", function () { + const propertyName = "example_normalized_INT8_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT8_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_INT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT8_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_INT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT8_VEC3", function () { + const propertyName = "example_UINT8_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 127, 255]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT8_VEC3_array", function () { + const propertyName = "example_variable_length_UINT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 127, 255], + [0, 127, 255], + [0, 127, 255], + [0, 127, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT8_VEC3_array", function () { + const propertyName = "example_fixed_length_UINT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 127, 255], + [0, 127, 255], + [0, 127, 255], + [0, 127, 255], + [0, 127, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT8_VEC3", function () { + const propertyName = "example_normalized_UINT8_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.4980392156862745, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT8_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_UINT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.4980392156862745, 1], + [0, 0.4980392156862745, 1], + [0, 0.4980392156862745, 1], + [0, 0.4980392156862745, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT8_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT8_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.4980392156862745, 1], + [0, 0.4980392156862745, 1], + [0, 0.4980392156862745, 1], + [0, 0.4980392156862745, 1], + [0, 0.4980392156862745, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT16_VEC3", function () { + const propertyName = "example_INT16_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-32768, 0, 32767]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT16_VEC3_array", function () { + const propertyName = "example_variable_length_INT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, 0, 32767], + [-32768, 0, 32767], + [-32768, 0, 32767], + [-32768, 0, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT16_VEC3_array", function () { + const propertyName = "example_fixed_length_INT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, 0, 32767], + [-32768, 0, 32767], + [-32768, 0, 32767], + [-32768, 0, 32767], + [-32768, 0, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT16_VEC3", function () { + const propertyName = "example_normalized_INT16_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT16_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_INT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT16_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_INT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT16_VEC3", function () { + const propertyName = "example_UINT16_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 32767, 65535]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT16_VEC3_array", function () { + const propertyName = "example_variable_length_UINT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 32767, 65535], + [0, 32767, 65535], + [0, 32767, 65535], + [0, 32767, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT16_VEC3_array", function () { + const propertyName = "example_fixed_length_UINT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 32767, 65535], + [0, 32767, 65535], + [0, 32767, 65535], + [0, 32767, 65535], + [0, 32767, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT16_VEC3", function () { + const propertyName = "example_normalized_UINT16_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.49999237048905165, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT16_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_UINT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.49999237048905165, 1], + [0, 0.49999237048905165, 1], + [0, 0.49999237048905165, 1], + [0, 0.49999237048905165, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT16_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT16_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.49999237048905165, 1], + [0, 0.49999237048905165, 1], + [0, 0.49999237048905165, 1], + [0, 0.49999237048905165, 1], + [0, 0.49999237048905165, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT32_VEC3", function () { + const propertyName = "example_INT32_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-2147483648, 0, 2147483647]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT32_VEC3_array", function () { + const propertyName = "example_variable_length_INT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, 0, 2147483647], + [-2147483648, 0, 2147483647], + [-2147483648, 0, 2147483647], + [-2147483648, 0, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT32_VEC3_array", function () { + const propertyName = "example_fixed_length_INT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, 0, 2147483647], + [-2147483648, 0, 2147483647], + [-2147483648, 0, 2147483647], + [-2147483648, 0, 2147483647], + [-2147483648, 0, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT32_VEC3", function () { + const propertyName = "example_normalized_INT32_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT32_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_INT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT32_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_INT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT32_VEC3", function () { + const propertyName = "example_UINT32_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 2147483647, 4294967295]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT32_VEC3_array", function () { + const propertyName = "example_variable_length_UINT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 2147483647, 4294967295], + [0, 2147483647, 4294967295], + [0, 2147483647, 4294967295], + [0, 2147483647, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT32_VEC3_array", function () { + const propertyName = "example_fixed_length_UINT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 2147483647, 4294967295], + [0, 2147483647, 4294967295], + [0, 2147483647, 4294967295], + [0, 2147483647, 4294967295], + [0, 2147483647, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT32_VEC3", function () { + const propertyName = "example_normalized_UINT32_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.4999999998835847, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT32_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_UINT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.4999999998835847, 1], + [0, 0.4999999998835847, 1], + [0, 0.4999999998835847, 1], + [0, 0.4999999998835847, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT32_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.4999999998835847, 1], + [0, 0.4999999998835847, 1], + [0, 0.4999999998835847, 1], + [0, 0.4999999998835847, 1], + [0, 0.4999999998835847, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT64_VEC3", function () { + const propertyName = "example_INT64_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-9223372036854776000n, 0, 9223372036854776000n]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT64_VEC3_array", function () { + const propertyName = "example_variable_length_INT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-9223372036854776000n, 0, 9223372036854776000n], + [-9223372036854776000n, 0, 9223372036854776000n], + [-9223372036854776000n, 0, 9223372036854776000n], + [-9223372036854776000n, 0, 9223372036854776000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT64_VEC3_array", function () { + const propertyName = "example_fixed_length_INT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-9223372036854776000n, 0, 9223372036854776000n], + [-9223372036854776000n, 0, 9223372036854776000n], + [-9223372036854776000n, 0, 9223372036854776000n], + [-9223372036854776000n, 0, 9223372036854776000n], + [-9223372036854776000n, 0, 9223372036854776000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT64_VEC3", function () { + const propertyName = "example_normalized_INT64_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT64_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_INT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT64_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_INT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT64_VEC3", function () { + const propertyName = "example_UINT64_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 9223372036854776000n, 18446744073709552000n]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT64_VEC3_array", function () { + const propertyName = "example_variable_length_UINT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 9223372036854776000n, 18446744073709552000n], + [0, 9223372036854776000n, 18446744073709552000n], + [0, 9223372036854776000n, 18446744073709552000n], + [0, 9223372036854776000n, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT64_VEC3_array", function () { + const propertyName = "example_fixed_length_UINT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 9223372036854776000n, 18446744073709552000n], + [0, 9223372036854776000n, 18446744073709552000n], + [0, 9223372036854776000n, 18446744073709552000n], + [0, 9223372036854776000n, 18446744073709552000n], + [0, 9223372036854776000n, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT64_VEC3", function () { + const propertyName = "example_normalized_UINT64_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.5, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT64_VEC3_array", function () { + const propertyName = "example_variable_length_normalized_UINT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.5, 1], + [0, 0.5, 1], + [0, 0.5, 1], + [0, 0.5, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT64_VEC3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.5, 1], + [0, 0.5, 1], + [0, 0.5, 1], + [0, 0.5, 1], + [0, 0.5, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT32_VEC3", function () { + const propertyName = "example_FLOAT32_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT32_VEC3_array", function () { + const propertyName = "example_variable_length_FLOAT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT32_VEC3_array", function () { + const propertyName = "example_fixed_length_FLOAT32_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT64_VEC3", function () { + const propertyName = "example_FLOAT64_VEC3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, 0, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT64_VEC3_array", function () { + const propertyName = "example_variable_length_FLOAT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT64_VEC3_array", function () { + const propertyName = "example_fixed_length_FLOAT64_VEC3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + [-1, 0, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT8_VEC4", function () { + const propertyName = "example_INT8_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-128, -43, 42, 127]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT8_VEC4_array", function () { + const propertyName = "example_variable_length_INT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT8_VEC4_array", function () { + const propertyName = "example_fixed_length_INT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT8_VEC4", function () { + const propertyName = "example_normalized_INT8_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.33858267716535434, 0.33070866141732286, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT8_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_INT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT8_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_INT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT8_VEC4", function () { + const propertyName = "example_UINT8_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 84, 170, 255]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT8_VEC4_array", function () { + const propertyName = "example_variable_length_UINT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT8_VEC4_array", function () { + const propertyName = "example_fixed_length_UINT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT8_VEC4", function () { + const propertyName = "example_normalized_UINT8_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.32941176470588235, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT8_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_UINT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT8_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT8_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT16_VEC4", function () { + const propertyName = "example_INT16_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-32768, -10923, 10922, 32767]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT16_VEC4_array", function () { + const propertyName = "example_variable_length_INT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT16_VEC4_array", function () { + const propertyName = "example_fixed_length_INT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT16_VEC4", function () { + const propertyName = "example_normalized_INT16_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.33335367900631735, 0.33332316049684135, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT16_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_INT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT16_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_INT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT16_VEC4", function () { + const propertyName = "example_UINT16_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 21844, 43690, 65535]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT16_VEC4_array", function () { + const propertyName = "example_variable_length_UINT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT16_VEC4_array", function () { + const propertyName = "example_fixed_length_UINT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT16_VEC4", function () { + const propertyName = "example_normalized_UINT16_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.3333180743114366, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT16_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_UINT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT16_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT16_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT32_VEC4", function () { + const propertyName = "example_INT32_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-2147483648, -715827883, 715827882, 2147483647]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT32_VEC4_array", function () { + const propertyName = "example_variable_length_INT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT32_VEC4_array", function () { + const propertyName = "example_fixed_length_INT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT32_VEC4", function () { + const propertyName = "example_normalized_INT32_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333336437742, 0.3333333331781129, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT32_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_INT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT32_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_INT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT32_VEC4", function () { + const propertyName = "example_UINT32_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1431655764, 2863311530, 4294967295]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT32_VEC4_array", function () { + const propertyName = "example_variable_length_UINT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT32_VEC4_array", function () { + const propertyName = "example_fixed_length_UINT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT32_VEC4", function () { + const propertyName = "example_normalized_UINT32_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.33333333310050267, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT32_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_UINT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT32_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT64_VEC4", function () { + const propertyName = "example_INT64_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT64_VEC4_array", function () { + const propertyName = "example_variable_length_INT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT64_VEC4_array", function () { + const propertyName = "example_fixed_length_INT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT64_VEC4", function () { + const propertyName = "example_normalized_INT64_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT64_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_INT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT64_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_INT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT64_VEC4", function () { + const propertyName = "example_UINT64_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, + 6148914690621625000n, + 12297829383087925000n, + 18446744073709552000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT64_VEC4_array", function () { + const propertyName = "example_variable_length_UINT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT64_VEC4_array", function () { + const propertyName = "example_fixed_length_UINT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT64_VEC4", function () { + const propertyName = "example_normalized_UINT64_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.3333333333, 0.6666666667, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT64_VEC4_array", function () { + const propertyName = "example_variable_length_normalized_UINT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT64_VEC4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT32_VEC4", function () { + const propertyName = "example_FLOAT32_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT32_VEC4_array", function () { + const propertyName = "example_variable_length_FLOAT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT32_VEC4_array", function () { + const propertyName = "example_fixed_length_FLOAT32_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT64_VEC4", function () { + const propertyName = "example_FLOAT64_VEC4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT64_VEC4_array", function () { + const propertyName = "example_variable_length_FLOAT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT64_VEC4_array", function () { + const propertyName = "example_fixed_length_FLOAT64_VEC4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT8_MAT2", function () { + const propertyName = "example_INT8_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-128, -43, 42, 127]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT8_MAT2_array", function () { + const propertyName = "example_variable_length_INT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT8_MAT2_array", function () { + const propertyName = "example_fixed_length_INT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + [-128, -43, 42, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT8_MAT2", function () { + const propertyName = "example_normalized_INT8_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.33858267716535434, 0.33070866141732286, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT8_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_INT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT8_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_INT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + [-1, -0.33858267716535434, 0.33070866141732286, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT8_MAT2", function () { + const propertyName = "example_UINT8_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 84, 170, 255]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT8_MAT2_array", function () { + const propertyName = "example_variable_length_UINT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT8_MAT2_array", function () { + const propertyName = "example_fixed_length_UINT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + [0, 84, 170, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT8_MAT2", function () { + const propertyName = "example_normalized_UINT8_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.32941176470588235, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT8_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_UINT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT8_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT8_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + [0, 0.32941176470588235, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT16_MAT2", function () { + const propertyName = "example_INT16_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-32768, -10923, 10922, 32767]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT16_MAT2_array", function () { + const propertyName = "example_variable_length_INT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT16_MAT2_array", function () { + const propertyName = "example_fixed_length_INT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + [-32768, -10923, 10922, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT16_MAT2", function () { + const propertyName = "example_normalized_INT16_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.33335367900631735, 0.33332316049684135, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT16_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_INT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT16_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_INT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + [-1, -0.33335367900631735, 0.33332316049684135, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT16_MAT2", function () { + const propertyName = "example_UINT16_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 21844, 43690, 65535]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT16_MAT2_array", function () { + const propertyName = "example_variable_length_UINT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT16_MAT2_array", function () { + const propertyName = "example_fixed_length_UINT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + [0, 21844, 43690, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT16_MAT2", function () { + const propertyName = "example_normalized_UINT16_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.3333180743114366, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT16_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_UINT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT16_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT16_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + [0, 0.3333180743114366, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT32_MAT2", function () { + const propertyName = "example_INT32_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-2147483648, -715827883, 715827882, 2147483647]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT32_MAT2_array", function () { + const propertyName = "example_variable_length_INT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT32_MAT2_array", function () { + const propertyName = "example_fixed_length_INT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + [-2147483648, -715827883, 715827882, 2147483647], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT32_MAT2", function () { + const propertyName = "example_normalized_INT32_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333336437742, 0.3333333331781129, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT32_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_INT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT32_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_INT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + [-1, -0.3333333336437742, 0.3333333331781129, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT32_MAT2", function () { + const propertyName = "example_UINT32_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 1431655764, 2863311530, 4294967295]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT32_MAT2_array", function () { + const propertyName = "example_variable_length_UINT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT32_MAT2_array", function () { + const propertyName = "example_fixed_length_UINT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + [0, 1431655764, 2863311530, 4294967295], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT32_MAT2", function () { + const propertyName = "example_normalized_UINT32_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.33333333310050267, 0.6666666666666666, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT32_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_UINT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT32_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + [0, 0.33333333310050267, 0.6666666666666666, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT64_MAT2", function () { + const propertyName = "example_INT64_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT64_MAT2_array", function () { + const propertyName = "example_variable_length_INT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT64_MAT2_array", function () { + const propertyName = "example_fixed_length_INT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -3074457346233150000n, + 3074457346233150000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT64_MAT2", function () { + const propertyName = "example_normalized_INT64_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT64_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_INT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT64_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_INT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT64_MAT2", function () { + const propertyName = "example_UINT64_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, + 6148914690621625000n, + 12297829383087925000n, + 18446744073709552000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT64_MAT2_array", function () { + const propertyName = "example_variable_length_UINT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT64_MAT2_array", function () { + const propertyName = "example_fixed_length_UINT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + [0, 6148914690621625000n, 12297829383087925000n, 18446744073709552000n], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT64_MAT2", function () { + const propertyName = "example_normalized_UINT64_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.3333333333, 0.6666666667, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT64_MAT2_array", function () { + const propertyName = "example_variable_length_normalized_UINT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT64_MAT2_array", function () { + const propertyName = "example_fixed_length_normalized_UINT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + [0, 0.3333333333, 0.6666666667, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT32_MAT2", function () { + const propertyName = "example_FLOAT32_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT32_MAT2_array", function () { + const propertyName = "example_variable_length_FLOAT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT32_MAT2_array", function () { + const propertyName = "example_fixed_length_FLOAT32_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT64_MAT2", function () { + const propertyName = "example_FLOAT64_MAT2"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.3333333334, 0.3333333334, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT64_MAT2_array", function () { + const propertyName = "example_variable_length_FLOAT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT64_MAT2_array", function () { + const propertyName = "example_fixed_length_FLOAT64_MAT2_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + [-1, -0.3333333334, 0.3333333334, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT8_MAT3", function () { + const propertyName = "example_INT8_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-128, -96, -64, -32, 0, 31, 63, 95, 127]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT8_MAT3_array", function () { + const propertyName = "example_variable_length_INT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT8_MAT3_array", function () { + const propertyName = "example_fixed_length_INT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + [-128, -96, -64, -32, 0, 31, 63, 95, 127], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT8_MAT3", function () { + const propertyName = "example_normalized_INT8_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT8_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_INT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT8_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_INT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + [ + -1, -0.7559055118110236, -0.5039370078740157, -0.25196850393700787, 0, + 0.2440944881889764, 0.49606299212598426, 0.7480314960629921, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT8_MAT3", function () { + const propertyName = "example_UINT8_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 31, 63, 95, 127, 159, 191, 223, 255]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT8_MAT3_array", function () { + const propertyName = "example_variable_length_UINT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 31, 63, 95, 127, 159, 191, 223, 255], + [0, 31, 63, 95, 127, 159, 191, 223, 255], + [0, 31, 63, 95, 127, 159, 191, 223, 255], + [0, 31, 63, 95, 127, 159, 191, 223, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT8_MAT3_array", function () { + const propertyName = "example_fixed_length_UINT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 31, 63, 95, 127, 159, 191, 223, 255], + [0, 31, 63, 95, 127, 159, 191, 223, 255], + [0, 31, 63, 95, 127, 159, 191, 223, 255], + [0, 31, 63, 95, 127, 159, 191, 223, 255], + [0, 31, 63, 95, 127, 159, 191, 223, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT8_MAT3", function () { + const propertyName = "example_normalized_UINT8_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT8_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_UINT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT8_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT8_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + [ + 0, 0.12156862745098039, 0.24705882352941178, 0.37254901960784315, + 0.4980392156862745, 0.6235294117647059, 0.7490196078431373, + 0.8745098039215686, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT16_MAT3", function () { + const propertyName = "example_INT16_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT16_MAT3_array", function () { + const propertyName = "example_variable_length_INT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT16_MAT3_array", function () { + const propertyName = "example_fixed_length_INT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + [-32768, -24576, -16384, -8192, 0, 8191, 16383, 24575, 32767], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT16_MAT3", function () { + const propertyName = "example_normalized_INT16_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT16_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_INT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT16_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_INT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + [ + -1, -0.750022888882107, -0.500015259254738, -0.250007629627369, 0, + 0.249977111117893, 0.499984740745262, 0.749992370372631, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT16_MAT3", function () { + const propertyName = "example_UINT16_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT16_MAT3_array", function () { + const propertyName = "example_variable_length_UINT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT16_MAT3_array", function () { + const propertyName = "example_fixed_length_UINT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + [0, 8191, 16383, 24575, 32767, 40959, 49151, 57343, 65535], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT16_MAT3", function () { + const propertyName = "example_normalized_UINT16_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT16_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_UINT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT16_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT16_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + [ + 0, 0.12498664835584039, 0.24998855573357748, 0.37499046311131456, + 0.49999237048905165, 0.6249942778667887, 0.7499961852445258, + 0.8749980926222629, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT32_MAT3", function () { + const propertyName = "example_INT32_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT32_MAT3_array", function () { + const propertyName = "example_variable_length_INT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT32_MAT3_array", function () { + const propertyName = "example_fixed_length_INT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + [ + -2147483648, -1610612736, -1073741824, -536870912, 0, 536870911, + 1073741823, 1610612735, 2147483647, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT32_MAT3", function () { + const propertyName = "example_normalized_INT32_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT32_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_INT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT32_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_INT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + [ + -1, -0.750000000349246, -0.5000000002328306, -0.2500000001164153, 0, + 0.24999999965075403, 0.49999999976716936, 0.7499999998835847, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT32_MAT3", function () { + const propertyName = "example_UINT32_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, 3221225471, + 3758096383, 4294967295, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT32_MAT3_array", function () { + const propertyName = "example_variable_length_UINT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT32_MAT3_array", function () { + const propertyName = "example_fixed_length_UINT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + [ + 0, 536870911, 1073741823, 1610612735, 2147483647, 2684354559, + 3221225471, 3758096383, 4294967295, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT32_MAT3", function () { + const propertyName = "example_normalized_UINT32_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT32_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_UINT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT32_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + [ + 0, 0.12499999979627319, 0.24999999982537702, 0.37499999985448085, + 0.4999999998835847, 0.6249999999126885, 0.7499999999417923, + 0.8749999999708962, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT64_MAT3", function () { + const propertyName = "example_INT64_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT64_MAT3_array", function () { + const propertyName = "example_variable_length_INT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT64_MAT3_array", function () { + const propertyName = "example_fixed_length_INT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -6917529027641082000n, + -4611686018427388000n, + -2305843009213694000n, + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT64_MAT3", function () { + const propertyName = "example_normalized_INT64_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT64_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_INT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT64_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_INT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT64_MAT3", function () { + const propertyName = "example_UINT64_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT64_MAT3_array", function () { + const propertyName = "example_variable_length_UINT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT64_MAT3_array", function () { + const propertyName = "example_fixed_length_UINT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + [ + 0, + 2305843009213694000n, + 4611686018427388000n, + 6917529027641082000n, + 9223372036854776000n, + 11529215046068470000n, + 13835058055282164000n, + 16140901064495858000n, + 18446744073709552000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT64_MAT3", function () { + const propertyName = "example_normalized_UINT64_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT64_MAT3_array", function () { + const propertyName = "example_variable_length_normalized_UINT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT64_MAT3_array", function () { + const propertyName = "example_fixed_length_normalized_UINT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT32_MAT3", function () { + const propertyName = "example_FLOAT32_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT32_MAT3_array", function () { + const propertyName = "example_variable_length_FLOAT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT32_MAT3_array", function () { + const propertyName = "example_fixed_length_FLOAT32_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT64_MAT3", function () { + const propertyName = "example_FLOAT64_MAT3"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT64_MAT3_array", function () { + const propertyName = "example_variable_length_FLOAT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT64_MAT3_array", function () { + const propertyName = "example_fixed_length_FLOAT64_MAT3_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + [-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT8_MAT4", function () { + const propertyName = "example_INT8_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, 127, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT8_MAT4_array", function () { + const propertyName = "example_variable_length_INT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT8_MAT4_array", function () { + const propertyName = "example_fixed_length_INT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + [ + -128, -110, -94, -77, -59, -43, -26, -8, 7, 25, 42, 58, 76, 93, 109, + 127, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT8_MAT4", function () { + const propertyName = "example_normalized_INT8_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT8_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_INT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT8_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_INT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + [ + -1, -0.8661417322834646, -0.7401574803149606, -0.6062992125984252, + -0.4645669291338583, -0.33858267716535434, -0.2047244094488189, + -0.06299212598425197, 0.05511811023622047, 0.1968503937007874, + 0.33070866141732286, 0.4566929133858268, 0.5984251968503937, + 0.7322834645669292, 0.8582677165354331, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT8_MAT4", function () { + const propertyName = "example_UINT8_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT8_MAT4_array", function () { + const propertyName = "example_variable_length_UINT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT8_MAT4_array", function () { + const propertyName = "example_fixed_length_UINT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + [0, 17, 33, 51, 68, 84, 102, 119, 135, 153, 170, 186, 204, 221, 237, 255], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT8_MAT4", function () { + const propertyName = "example_normalized_UINT8_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT8_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_UINT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT8_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT8_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + [ + 0, 0.06666666666666667, 0.12941176470588237, 0.2, 0.26666666666666666, + 0.32941176470588235, 0.4, 0.4666666666666667, 0.5294117647058824, 0.6, + 0.6666666666666666, 0.7294117647058823, 0.8, 0.8666666666666667, + 0.9294117647058824, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT16_MAT4", function () { + const propertyName = "example_INT16_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, 6553, + 10922, 15290, 19660, 24029, 28397, 32767, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT16_MAT4_array", function () { + const propertyName = "example_variable_length_INT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT16_MAT4_array", function () { + const propertyName = "example_fixed_length_INT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + [ + -32768, -28398, -24030, -19661, -15291, -10923, -6554, -2184, 2183, + 6553, 10922, 15290, 19660, 24029, 28397, 32767, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT16_MAT4", function () { + const propertyName = "example_normalized_INT16_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT16_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_INT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT16_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_INT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + [ + -1, -0.8666646320993683, -0.7333597827082126, -0.6000244148075808, + -0.46665852839747307, -0.33335367900631735, -0.2000183111056856, + -0.06665242469557787, 0.06662190618610186, 0.1999877925962096, + 0.33332316049684135, 0.4666280098879971, 0.5999938962981048, + 0.7333292641987366, 0.8666341135898923, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT16_MAT4", function () { + const propertyName = "example_UINT16_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT16_MAT4_array", function () { + const propertyName = "example_variable_length_UINT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT16_MAT4_array", function () { + const propertyName = "example_fixed_length_UINT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + [ + 0, 4369, 8737, 13107, 17476, 21844, 26214, 30583, 34951, 39321, 43690, + 48058, 52428, 56797, 61165, 65535, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT16_MAT4", function () { + const propertyName = "example_normalized_UINT16_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT16_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_UINT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT16_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT16_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + [ + 0, 0.06666666666666667, 0.13331807431143664, 0.2, 0.26666666666666666, + 0.3333180743114366, 0.4, 0.4666666666666667, 0.5333180743114366, 0.6, + 0.6666666666666666, 0.7333180743114366, 0.8, 0.8666666666666667, + 0.9333180743114367, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT32_MAT4", function () { + const propertyName = "example_INT32_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT32_MAT4_array", function () { + const propertyName = "example_variable_length_INT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT32_MAT4_array", function () { + const propertyName = "example_fixed_length_INT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + [ + -2147483648, -1861152494, -1574821342, -1288490189, -1002159035, + -715827883, -429496730, -143165576, 143165575, 429496729, 715827882, + 1002159034, 1288490188, 1574821341, 1861152493, 2147483647, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT32_MAT4", function () { + const propertyName = "example_normalized_INT32_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT32_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_INT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT32_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_INT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + [ + -1, -0.8666666666356225, -0.7333333337369065, -0.600000000372529, + -0.46666666654249034, -0.3333333336437742, -0.20000000027939677, + -0.06666666644935806, 0.06666666598369678, 0.19999999981373548, + 0.3333333331781129, 0.46666666607682905, 0.5999999999068677, + 0.7333333332712452, 0.8666666661699612, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT32_MAT4", function () { + const propertyName = "example_UINT32_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT32_MAT4_array", function () { + const propertyName = "example_variable_length_UINT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT32_MAT4_array", function () { + const propertyName = "example_fixed_length_UINT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + [ + 0, 286331153, 572662305, 858993459, 1145324612, 1431655764, 1717986918, + 2004318071, 2290649223, 2576980377, 2863311530, 3149642682, 3435973836, + 3722304989, 4008636141, 4294967295, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT32_MAT4", function () { + const propertyName = "example_normalized_UINT32_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT32_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_UINT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT32_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + [ + 0, 0.06666666666666667, 0.1333333331005027, 0.2, 0.26666666666666666, + 0.33333333310050267, 0.4, 0.4666666666666667, 0.5333333331005027, 0.6, + 0.6666666666666666, 0.7333333331005026, 0.8, 0.8666666666666667, + 0.9333333331005027, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_INT64_MAT4", function () { + const propertyName = "example_INT64_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_INT64_MAT4_array", function () { + const propertyName = "example_variable_length_INT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_INT64_MAT4_array", function () { + const propertyName = "example_fixed_length_INT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + [ + -9223372036854776000n, + -7993589097992581000n, + -6763806160975060000n, + -5534023222112865000n, + -4304240283250670600n, + -3074457346233150000n, + -1844674407370955300n, + -614891468508760200n, + 614891468508760200n, + 1844674407370955300n, + 3074457346233150000n, + 4304240283250670600n, + 5534023222112865000n, + 6763806160975060000n, + 7993589097992581000n, + 9223372036854776000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_INT64_MAT4", function () { + const propertyName = "example_normalized_INT64_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_INT64_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_INT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_INT64_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_INT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_UINT64_MAT4", function () { + const propertyName = "example_UINT64_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_UINT64_MAT4_array", function () { + const propertyName = "example_variable_length_UINT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_UINT64_MAT4_array", function () { + const propertyName = "example_fixed_length_UINT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + [ + 0, + 1229782938862195000n, + 2459565875879715300n, + 3689348814741910500n, + 4919131753604105000n, + 6148914690621625000n, + 7378697629483821000n, + 8608480568346016000n, + 9838263505363536000n, + 11068046444225730000n, + 12297829383087925000n, + 13527612320105445000n, + 14757395258967642000n, + 15987178197829837000n, + 17216961134847357000n, + 18446744073709552000n, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_normalized_UINT64_MAT4", function () { + const propertyName = "example_normalized_UINT64_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_normalized_UINT64_MAT4_array", function () { + const propertyName = "example_variable_length_normalized_UINT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_normalized_UINT64_MAT4_array", function () { + const propertyName = "example_fixed_length_normalized_UINT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + [ + 0, 0.0666666667, 0.1333333333, 0.2, 0.2666666667, 0.3333333333, 0.4, + 0.4666666667, 0.5333333333, 0.6, 0.6666666667, 0.7333333333, 0.8, + 0.8666666667, 0.9333333333, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT32_MAT4", function () { + const propertyName = "example_FLOAT32_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT32_MAT4_array", function () { + const propertyName = "example_variable_length_FLOAT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT32_MAT4_array", function () { + const propertyName = "example_fixed_length_FLOAT32_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_FLOAT64_MAT4", function () { + const propertyName = "example_FLOAT64_MAT4"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_variable_length_FLOAT64_MAT4_array", function () { + const propertyName = "example_variable_length_FLOAT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); + + it("obtains the right value for example_fixed_length_FLOAT64_MAT4_array", function () { + const propertyName = "example_fixed_length_FLOAT64_MAT4_array"; + const value = metadataEntityModel.getPropertyValue(propertyName); + const expected = [ + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + [ + -1, -0.8666666666, -0.7333333334, -0.6, -0.4666666666, -0.3333333334, + -0.2, -0.0666666666, 0.0666666666, 0.2, 0.3333333334, 0.4666666666, 0.6, + 0.7333333334, 0.8666666666, 1, + ], + ]; + expect(genericEquals(value, expected, epsilon)).toBeTrue(); + }); +}); diff --git a/specs/metadata/MetadataEntityModelSpec.ts b/specs/metadata/MetadataEntityModelSpec.ts new file mode 100644 index 00000000..001a01c8 --- /dev/null +++ b/specs/metadata/MetadataEntityModelSpec.ts @@ -0,0 +1,253 @@ +import { MetadataEntityModels } from "../../src/metadata/MetadataEntityModels"; +import { MetadataClass } from "../../src/structure/Metadata/MetadataClass"; + +// NOTE: The tests here aim at testing the handling of default- and noData +// values, as well as the handling of offset/scale and the mechanism of +// overriding the offset/scale from the property definition with an +// offset/scale in the entity itself. The values are chosen to not +// require any "epslion" of the comparisons. + +describe("metadata/MetadataEntityModel", function () { + it("throws when the value of an unknown property is accessed", function () { + expect(function () { + const testMetadataClass: MetadataClass = { + properties: {}, + }; + const entityJson = { + testProperty: 1234, + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + entity.getPropertyValue("testProperty"); + }).toThrow(); + }); + + it("obtains a default value for a scalar int32 value", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "SCALAR", + componentType: "INT32", + default: 1234, + }, + }, + }; + const entityJson = { + testProperty: undefined, + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + expect(value).toBe(1234); + }); + + it("obtains a default value for a scalar int32 noData value", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "SCALAR", + componentType: "INT32", + noData: 2345, + default: 1234, + }, + }, + }; + const entityJson = { + testProperty: 2345, + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + expect(value).toBe(1234); + }); + + it("obtains a value for a vec3 float32 value with offset in property definition", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + offset: [1.0, 2.0, 3.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [4.0, 6.0, 8.0]; + expect(value).toEqual(expected); + }); + + it("obtains a value for a vec3 float32 value with scale in property definition", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + scale: [2.0, 3.0, 4.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [6.0, 12.0, 20.0]; + expect(value).toEqual(expected); + }); + + it("obtains a value for a vec3 float32 value with offset and scale in property definition", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + offset: [1.0, 2.0, 3.0], + scale: [2.0, 3.0, 4.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [7.0, 14.0, 23.0]; + expect(value).toEqual(expected); + }); + + it("obtains a value for a vec3 float32 value with offset in property definition and scale in entity", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + offset: [1.0, 2.0, 3.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + scale: [2.0, 3.0, 4.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [7.0, 14.0, 23.0]; + expect(value).toEqual(expected); + }); + + it("obtains a value for a vec3 float32 value with offset in entity and scale in property definition", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + scale: [2.0, 3.0, 4.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + offset: [1.0, 2.0, 3.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [7.0, 14.0, 23.0]; + expect(value).toEqual(expected); + }); + + it("obtains a value for a vec3 float32 value with offset in property definition, and overriding offset in entity", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + offset: [100.0, 200.0, 300.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + offset: [1.0, 2.0, 3.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [4.0, 6.0, 8.0]; + expect(value).toEqual(expected); + }); + + it("obtains a value for a vec3 float32 value with scale in property definition, and overriding scale in entity", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + scale: [200.0, 300.0, 400.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + scale: [2.0, 3.0, 4.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [6.0, 12.0, 20.0]; + expect(value).toEqual(expected); + }); + + it("obtains a value for a vec3 float32 value with offset and scale in property definition, and overriding offset and scale in entity", function () { + const testMetadataClass: MetadataClass = { + properties: { + testProperty: { + type: "VEC3", + componentType: "FLOAT32", + offset: [100.0, 200.0, 300.0], + scale: [200.0, 300.0, 400.0], + }, + }, + }; + const entityJson = { + testProperty: [3.0, 4.0, 5.0], + offset: [1.0, 2.0, 3.0], + scale: [2.0, 3.0, 4.0], + }; + const entity = MetadataEntityModels.createFromClass( + testMetadataClass, + entityJson + ); + const value = entity.getPropertyValue("testProperty"); + const expected = [7.0, 14.0, 23.0]; + expect(value).toEqual(expected); + }); +}); diff --git a/specs/metadata/PropertyTableModelsSpec.ts b/specs/metadata/PropertyTableModelsSpec.ts new file mode 100644 index 00000000..b4e30538 --- /dev/null +++ b/specs/metadata/PropertyTableModelsSpec.ts @@ -0,0 +1,541 @@ +import { genericEquals } from "./genericEquals"; + +import { BinaryPropertyTables } from "../../src/metadata/binary/BinaryPropertyTables"; +import { BinaryPropertyTableModel } from "../../src/metadata/binary/BinaryPropertyTableModel"; + +import { ClassProperty } from "../../src/structure/Metadata/ClassProperty"; + +/** + * Test for the `PropertyTableModels` class. + * + * These tests just verify the "roundtrip": + * - They create a `PropertyTableModel` from a single property + * and its associated data + * - They obtain the `MetadataEntityModel` instances from the + * property table model + * - They check whether the elements of the input data and the + * values from the entity model are generically equal. + */ +describe("metadata/PropertyTableModelSpec", function () { + const epsilon = 0.000001; + + it("correctly represents example_INT16_SCALAR", function () { + const example_INT16_SCALAR: ClassProperty = { + type: "SCALAR", + componentType: "INT16", + }; + const example_INT16_SCALAR_values = [-32768, 32767]; + + const classProperty = example_INT16_SCALAR; + const values = example_INT16_SCALAR_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_variable_length_INT16_SCALAR_array", function () { + const example_variable_length_INT16_SCALAR_array: ClassProperty = { + type: "SCALAR", + componentType: "INT16", + array: true, + }; + const example_variable_length_INT16_SCALAR_array_values = [ + [-32768, 32767], + [-1, 0, 1], + ]; + + const classProperty = example_variable_length_INT16_SCALAR_array; + const values = example_variable_length_INT16_SCALAR_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_fixed_length_INT16_SCALAR_array", function () { + const example_fixed_length_INT16_SCALAR_array: ClassProperty = { + type: "SCALAR", + componentType: "INT16", + array: true, + count: 2, + }; + const example_fixed_length_INT16_SCALAR_array_values = [ + [-32768, 32767], + [-1, 1], + ]; + + const classProperty = example_fixed_length_INT16_SCALAR_array; + const values = example_fixed_length_INT16_SCALAR_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_BOOLEAN", function () { + const example_BOOLEAN: ClassProperty = { + type: "BOOLEAN", + }; + const example_BOOLEAN_values = [true, false]; + + const classProperty = example_BOOLEAN; + const values = example_BOOLEAN_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_variable_length_BOOLEAN_array", function () { + const example_variable_length_BOOLEAN_array: ClassProperty = { + type: "BOOLEAN", + array: true, + }; + const example_variable_length_BOOLEAN_array_values = [ + [true, false], + [false, true, false, true], + ]; + + const classProperty = example_variable_length_BOOLEAN_array; + const values = example_variable_length_BOOLEAN_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_fixed_length_BOOLEAN_array", function () { + const example_fixed_length_BOOLEAN_array: ClassProperty = { + type: "BOOLEAN", + array: true, + }; + const example_fixed_length_BOOLEAN_array_values = [ + [true, false, true], + [false, true, false], + ]; + + const classProperty = example_fixed_length_BOOLEAN_array; + const values = example_fixed_length_BOOLEAN_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_STRING", function () { + const example_STRING: ClassProperty = { + type: "STRING", + }; + const example_STRING_values = ["Test string", "Another string"]; + + const classProperty = example_STRING; + const values = example_STRING_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_variable_length_STRING_array", function () { + const example_variable_length_STRING_array: ClassProperty = { + type: "STRING", + array: true, + }; + const example_variable_length_STRING_array_values = [ + ["A0", "A1", "A2"], + ["B0", "B1"], + ]; + + const classProperty = example_variable_length_STRING_array; + const values = example_variable_length_STRING_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_fixed_length_STRING_array", function () { + const example_fixed_length_STRING_array: ClassProperty = { + type: "STRING", + array: true, + count: 3, + }; + const example_fixed_length_STRING_array_values = [ + ["A0", "A1", "A2"], + ["B0", "B1", "B2"], + ]; + + const classProperty = example_fixed_length_STRING_array; + const values = example_fixed_length_STRING_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_FLOAT32_VEC2", function () { + const example_FLOAT32_VEC2: ClassProperty = { + type: "VEC2", + componentType: "FLOAT32", + }; + const example_FLOAT32_VEC2_values = [ + [0.0, 1.0], + [2.0, 3.0], + ]; + + const classProperty = example_FLOAT32_VEC2; + const values = example_FLOAT32_VEC2_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_variable_length_UINT32_VEC2_array", function () { + const example_variable_length_UINT32_VEC2_array: ClassProperty = { + type: "VEC2", + componentType: "FLOAT32", + array: true, + }; + const example_variable_length_UINT32_VEC2_array_values = [ + [ + [0.0, 1.0], + [2.0, 3.0], + ], + [ + [4.0, 5.0], + [6.0, 7.0], + [8.0, 9.0], + ], + ]; + + const classProperty = example_variable_length_UINT32_VEC2_array; + const values = example_variable_length_UINT32_VEC2_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_fixed_length_UINT32_VEC2_array", function () { + const example_fixed_length_UINT32_VEC2_array: ClassProperty = { + type: "VEC2", + componentType: "FLOAT32", + array: true, + count: 2, + }; + const example_fixed_length_UINT32_VEC2_array_values = [ + [ + [0.0, 1.0], + [2.0, 3.0], + ], + [ + [4.0, 5.0], + [6.0, 7.0], + ], + ]; + + const classProperty = example_fixed_length_UINT32_VEC2_array; + const values = example_fixed_length_UINT32_VEC2_array_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_UINT64_MAT2", function () { + const example_UINT64_MAT2: ClassProperty = { + type: "MAT2", + componentType: "UINT64", + }; + const example_UINT64_MAT2_values = [ + [0n, 6148914690621625735n, 12297829383087925879n, 18446744073709551615n], + [18446744073709551615n, 12297829383087925879n, 6148914690621625735n, 0n], + ]; + + const classProperty = example_UINT64_MAT2; + const values = example_UINT64_MAT2_values; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = values[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); + + it("correctly represents example_normalized_UINT64_VEC2 with offset", function () { + const example_normalized_UINT64_VEC2: ClassProperty = { + type: "VEC2", + componentType: "UINT64", + normalized: true, + offset: [10, 20], + }; + const example_normalized_UINT64_VEC2_values = [ + [0n, 6148914690621625735n], + [6148914690621625735n, 12297829383087925879n], + ]; + const example_normalized_UINT64_VEC2_values_expected = [ + [10.0, 20.3333333333], + [10.3333333333, 20.6666666666], + ]; + + const classProperty = example_normalized_UINT64_VEC2; + const values = example_normalized_UINT64_VEC2_values; + const valuesExpected = example_normalized_UINT64_VEC2_values_expected; + + const arrayOffsetType = "UINT32"; + const stringOffsetType = "UINT32"; + const binaryPropertyTable = + BinaryPropertyTables.createBinaryPropertyTableFromProperty( + "testProperty", + classProperty, + values, + arrayOffsetType, + stringOffsetType, + undefined + ); + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + const count = values.length; + for (let i = 0; i < count; i++) { + const entity = propertyTableModel.getMetadataEntityModel(i); + const expected = valuesExpected[i]; + const actual = entity.getPropertyValue("testProperty"); + expect(genericEquals(actual, expected, epsilon)).toBeTrue(); + } + }); +}); diff --git a/specs/metadata/genericEquals.ts b/specs/metadata/genericEquals.ts new file mode 100644 index 00000000..d74b98df --- /dev/null +++ b/specs/metadata/genericEquals.ts @@ -0,0 +1,58 @@ +import { defaultValue } from "../../src/base/defaultValue"; + +/** + * Returns whether two numbers are equal, up to a certain epsilon + * + * @param left - The first value + * @param right - The second value + * @param relativeEpsilon - The maximum inclusive delta for the relative tolerance test. + * @param absoluteEpsilon - The maximum inclusive delta for the absolute tolerance test. + * @returns Whether the values are equal within the epsilon + */ +function equalsEpsilon( + left: number, + right: number, + relativeEpsilon: number, + absoluteEpsilon?: number +) { + relativeEpsilon = defaultValue(relativeEpsilon, 0.0); + absoluteEpsilon = defaultValue(absoluteEpsilon, relativeEpsilon); + const absDiff = Math.abs(left - right); + return ( + absDiff <= absoluteEpsilon || + absDiff <= relativeEpsilon * Math.max(Math.abs(left), Math.abs(right)) + ); +} + +/** + * A function for checking values for equality, taking into account the + * possibility that the values are (potentially multi- dimensional) + * arrays, and recursively comparing the elements in this case. + * If the eventual elements are numbers, they are compared for + * equality up to the given relative epsilon. + * + * This is ONLY used in the specs, to compare metadata values. + * + * @param a - The first element + * @param b - The second element + * @param epsilon - A relative epsilon + * @returns Whether the objects are equal + */ +export function genericEquals(a: any, b: any, epsilon: number): boolean { + if (Array.isArray(a) && Array.isArray(b)) { + if (a.length !== b.length) { + return false; + } + + for (let i = 0; i < a.length; ++i) { + if (!genericEquals(a[i], b[i], epsilon)) { + return false; + } + } + return true; + } + if (typeof a === "number") { + return equalsEpsilon(a, Number(b), epsilon); + } + return a === b; +} diff --git a/specs/metadata/readJsonUnchecked.ts b/specs/metadata/readJsonUnchecked.ts new file mode 100644 index 00000000..6596ea65 --- /dev/null +++ b/specs/metadata/readJsonUnchecked.ts @@ -0,0 +1,27 @@ +import fs from "fs"; + +/** + * Only for internal use and basic tests: + * + * Reads a JSON file, parses it, and returns the result. + * If the file cannot be read or parsed, then an error + * message will be printed and `undefined` is returned. + * + * @param filePath - The path to the file + * @returns A promise that resolves with the result or `undefined` + */ +export async function readJsonUnchecked(filePath: string): Promise { + try { + const data = fs.readFileSync(filePath); + if (!data) { + console.error("Could not read " + filePath); + return undefined; + } + const jsonString = data.toString(); + const result = JSON.parse(jsonString); + return result; + } catch (error) { + console.error("Could not parse JSON", error); + return undefined; + } +} diff --git a/src/ToolsMain.ts b/src/ToolsMain.ts index 0e733156..d34b75ae 100644 --- a/src/ToolsMain.ts +++ b/src/ToolsMain.ts @@ -8,8 +8,8 @@ import { Tilesets } from "./tilesets/Tilesets"; import { TileFormats } from "./tileFormats/TileFormats"; -import { ContentOps } from "./contentOperations/ContentOps"; -import { GltfUtilities } from "./contentOperations/GtlfUtilities"; +import { ContentOps } from "./contentProcessing/ContentOps"; +import { GltfUtilities } from "./contentProcessing/GtlfUtilities"; import { ContentDataTypes } from "./contentTypes/ContentDataTypes"; diff --git a/src/base/Buffers.ts b/src/base/Buffers.ts index 24171a26..a77d45c7 100644 --- a/src/base/Buffers.ts +++ b/src/base/Buffers.ts @@ -1,5 +1,9 @@ +import zlib from "zlib"; + import { defined } from "./defined"; +import { DataError } from "./DataError"; + /** * Methods related to buffers. * @@ -10,6 +14,43 @@ import { defined } from "./defined"; * @internal */ export class Buffers { + /** + * Applies GZIP compression to the given buffer, and returns + * the result. + * + * @param inputBuffer - The input buffer + * @returns The resulting buffer + */ + static gzip(inputBuffer: Buffer): Buffer { + const outputBuffer = zlib.gzipSync(inputBuffer); + return outputBuffer; + } + + /** + * If the given buffer is compressed with GZIP, then it is + * unzipped, and the result is returned. Otherwise, the + * given buffer is returned as it is. + * + * @param inputBuffer - The input buffer + * @returns The resulting buffer + * @throws DataError If the buffer looked like GZIPped + * data, but could not be decompressed. + */ + static gunzip(inputBuffer: Buffer): Buffer { + let outputBuffer: Buffer; + if (Buffers.isGzipped(inputBuffer)) { + try { + outputBuffer = zlib.gunzipSync(inputBuffer); + } catch (e) { + const message = `Could not gunzip buffer: ${e}`; + throw new DataError(message); + } + } else { + outputBuffer = inputBuffer; + } + return outputBuffer; + } + /** * Obtains the magic header from the given buffer. * @@ -81,13 +122,18 @@ export class Buffers { * * @param buffer - The buffer * @returns The parsed object - * @throws Possible errors from `JSON:parse` + * @throws DataError If the JSON could not be parsed */ static getJson(buffer: Buffer): any { if (buffer.length === 0) { return {}; } - return JSON.parse(buffer.toString("utf8")); + try { + return JSON.parse(buffer.toString("utf8")); + } catch (e) { + const message = `Could not parse JSON from buffer: ${e}`; + throw new DataError(message); + } } /** @@ -191,4 +237,19 @@ export class Buffers { } return true; } + + /** + * Creates a string representation of the given buffer where each + * byte is encoded in its binary form, consisting of 8 bits. + * + * Warning: This is primarily intended for debugging. The resulting + * string may be very long... + * + * @param buffer - The input buffer + * @returns The resulting string + */ + static createBinaryString(buffer: Buffer): string { + const s = [...buffer].map((b) => b.toString(2).padStart(8, "0")).join(""); + return s; + } } diff --git a/src/base/DataError.ts b/src/base/DataError.ts new file mode 100644 index 00000000..7583154f --- /dev/null +++ b/src/base/DataError.ts @@ -0,0 +1,24 @@ +/** + * An error that may be thrown to indicate that input + * data was invalid. + * + * This may refer to buffers that have been expected to + * contain a certain type of data, but did not. For + * example, a buffer that looked like a GZIpped buffer, + * but turned out to be invalid, or a buffer that + * looked like it contained valid JSON, but did not. + * + * @internal + */ +export class DataError extends Error { + constructor(message: string) { + super(message); + // See https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes + // #extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, DataError.prototype); + } + + override toString = (): string => { + return `${this.name}: ${this.message}`; + }; +} diff --git a/src/base/defined.ts b/src/base/defined.ts index 08e0b74d..c612a46e 100644 --- a/src/base/defined.ts +++ b/src/base/defined.ts @@ -15,8 +15,8 @@ * const value = 0; * if (defined(value)) console.log('defined'); * else console.log('not defined'); - * if (value) console.log('truthy); - * else console.log('not truthy); + * if (value) console.log('truthy'); + * else console.log('not truthy'); * ``` * will be * ``` @@ -28,6 +28,6 @@ * @returns `true` if the value is not `undefined` and not `null` * @internal */ -export function defined(value: any): value is NonNullable { +export function defined(value: T): value is NonNullable { return value !== undefined && value !== null; } diff --git a/src/binary/BinaryBufferData.ts b/src/binary/BinaryBufferData.ts new file mode 100644 index 00000000..22ed6da5 --- /dev/null +++ b/src/binary/BinaryBufferData.ts @@ -0,0 +1,23 @@ +/** + * A basic structure holding binary data that consists of + * buffers that are split into buffer views. This is the + * actual data that corresponds to a `BinaryBufferStructure` + * + * @internal + */ +export interface BinaryBufferData { + /** + * An array of buffers that contain the data that correspond + * to `BufferView` objects. + * + * These are usually (but not necessarily) slices of + * the 'buffersData' elements. + */ + bufferViewsData: Buffer[]; + + /** + * An array of buffers that contain the data that correspond + * to `BufferObject` objects. + */ + buffersData: Buffer[]; +} diff --git a/src/binary/BinaryBufferDataResolver.ts b/src/binary/BinaryBufferDataResolver.ts new file mode 100644 index 00000000..44849b58 --- /dev/null +++ b/src/binary/BinaryBufferDataResolver.ts @@ -0,0 +1,84 @@ +import { defined } from "../base/defined"; + +import { ResourceResolver } from "../io/ResourceResolver"; + +import { BinaryBufferData } from "./BinaryBufferData"; +import { BinaryBufferStructure } from "./BinaryBufferStructure"; +import { BinaryDataError } from "./BinaryDataError"; + +/** + * A class for resolving binary buffer data. + * + * @internal + */ +export class BinaryBufferDataResolver { + /** + * Resolves the buffer data that is defined in the given structure. + * + * It receives a `BinaryBufferStructure` that contains the + * `BufferObject` and `BufferView` definitions, resolves the + * data from the buffer URIs using the given resource resolver, + * and returns a `BinaryBufferData` that contains the actual + * binary buffer data. + * + * The given `binaryBuffer` will be used as the buffer data + * for any buffer that does not have a URI (intended for + * binary subtree files)) + * + * @param binaryBufferStructure - The `BinaryBufferStructure` + * @param binaryBuffer - The optional binary buffer + * @param resourceResolver - The `ResourceResolver` + * @returns The `BinaryBufferData` + * @throws BinaryDataError If the data could not be resolved + */ + static async resolve( + binaryBufferStructure: BinaryBufferStructure, + binaryBuffer: Buffer | undefined, + resourceResolver: ResourceResolver + ): Promise { + // Obtain the buffer data objects: One `Buffer` for + // each `BufferObject` + const buffersData: Buffer[] = []; + const buffers = binaryBufferStructure.buffers; + if (buffers) { + for (const buffer of buffers) { + if (!defined(buffer.uri)) { + if (!binaryBuffer) { + throw new BinaryDataError( + "Expected a binary buffer, but got undefined" + ); + } + buffersData.push(binaryBuffer); + } else { + //console.log("Obtaining buffer data from " + buffer.uri); + const bufferData = await resourceResolver.resolveData(buffer.uri); + if (!bufferData) { + const message = `Could not resolve buffer ${buffer.uri}`; + throw new BinaryDataError(message); + } + buffersData.push(bufferData); + } + } + } + + // Obtain the buffer view data objects: One `Buffer` for + // each `BufferView` + const bufferViewsData = []; + const bufferViews = binaryBufferStructure.bufferViews; + if (bufferViews) { + for (const bufferView of bufferViews) { + const bufferData = buffersData[bufferView.buffer]; + const start = bufferView.byteOffset; + const end = start + bufferView.byteLength; + const bufferViewData = bufferData.subarray(start, end); + bufferViewsData.push(bufferViewData); + } + } + + const binarybBufferData: BinaryBufferData = { + buffersData: buffersData, + bufferViewsData: bufferViewsData, + }; + return binarybBufferData; + } +} diff --git a/src/binary/BinaryBufferStructure.ts b/src/binary/BinaryBufferStructure.ts new file mode 100644 index 00000000..766efac5 --- /dev/null +++ b/src/binary/BinaryBufferStructure.ts @@ -0,0 +1,14 @@ +import { BufferObject } from "../structure/BufferObject"; +import { BufferView } from "../structure/BufferView"; + +/** + * A basic class holding information about the structure of + * buffers that are split into buffer views, for example, + * from a `Subtree` object. + * + * @internal + */ +export interface BinaryBufferStructure { + buffers: BufferObject[]; + bufferViews: BufferView[]; +} diff --git a/src/binary/BinaryBuffers.ts b/src/binary/BinaryBuffers.ts new file mode 100644 index 00000000..56fbf13d --- /dev/null +++ b/src/binary/BinaryBuffers.ts @@ -0,0 +1,99 @@ +import { BufferObject } from "../structure/BufferObject"; +import { BufferView } from "../structure/BufferView"; + +import { BinaryBufferStructure } from "./BinaryBufferStructure"; +import { BinaryBufferData } from "./BinaryBufferData"; + +/** + * Methods related to binary buffers. + * + * This class can be used for building a basic `BinaryBufferData` structure + * from a sequence of buffers that represent buffer views. + * + * @internal + */ +export class BinaryBuffers { + /** + * Add a set of buffer views to the given `BinaryBufferData`, and return + * a `BinaryBufferStructure` that describes their layout. + * + * This will combine the given buffer views into a single buffer, and add the + * buffer views and the generated buffer to the given `BinaryBufferData`. + * + * The layout (byte offset and lengths, and the `buffer` index) will be + * returned via the `BinaryBufferStructure`. + * + * NOTE: This function could be generalized in many ways. Right now, it + * creates a single `BufferObject` for the given data, without a `uri`. + * Further configuration options might be added in the future. + * + * @param binaryBufferData - The `BinaryBufferData` + * @param newBufferViewsData - The buffer views that should be added + * @returns A `BinaryBufferStructure` that describes the structure + * of the buffer views, after they have been assembled into a buffer. + */ + static createBinaryBufferStructure( + binaryBufferData: BinaryBufferData, + newBufferViewsData: Buffer[] + ): BinaryBufferStructure { + const alignment = 8; + const bufferViewsData = binaryBufferData.bufferViewsData; + const buffersData = binaryBufferData.buffersData; + + // The arrays for the output data + const buffers: BufferObject[] = []; + const bufferViews: BufferView[] = []; + const currentBufferIndex = buffersData.length; + + // Create a new buffer data combines all the given buffer views, + // including possible padding bytes + let currentBufferData = Buffer.alloc(0); + let currentByteOffset = 0; + for (let i = 0; i < newBufferViewsData.length; i++) { + const newBufferViewData = newBufferViewsData[i]; + const requiredPadding = + (alignment - (currentByteOffset % alignment)) % alignment; + if (requiredPadding != 0) { + const paddingBuffer = Buffer.alloc(requiredPadding); + currentBufferData = Buffer.concat([currentBufferData, paddingBuffer]); + currentByteOffset += requiredPadding; + } + currentBufferData = Buffer.concat([currentBufferData, newBufferViewData]); + + // Store the buffer view + const bufferView: BufferView = { + buffer: currentBufferIndex, + byteOffset: currentByteOffset, + byteLength: newBufferViewData.length, + }; + bufferViews.push(bufferView); + + // Store the data of the buffer view. This should have the same + // contents as the `newBufferViewData`, but will be a subarray + // of the newly created buffer + const bufferViewData = currentBufferData.subarray( + currentByteOffset, + currentByteOffset + newBufferViewData.length + ); + bufferViewsData.push(bufferViewData); + + currentByteOffset += newBufferViewData.length; + } + + // Store the buffer + const buffer: BufferObject = { + byteLength: currentBufferData.length, + }; + buffers.push(buffer); + + // Store the buffer data + buffersData.push(currentBufferData); + + // Return the resulting buffer structure + const binaryBufferStructure: BinaryBufferStructure = { + buffers: buffers, + bufferViews: bufferViews, + }; + return binaryBufferStructure; + } +} diff --git a/src/binary/BinaryDataError.ts b/src/binary/BinaryDataError.ts new file mode 100644 index 00000000..a6a28aba --- /dev/null +++ b/src/binary/BinaryDataError.ts @@ -0,0 +1,17 @@ +/** + * An error that indicates that binary data was structurally invalid. + * + * @internal + */ +export class BinaryDataError extends Error { + constructor(message: string) { + super(message); + // See https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes + // #extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, BinaryDataError.prototype); + } + + override toString = (): string => { + return `${this.name}: ${this.message}`; + }; +} diff --git a/src/contentOperations/ContentOps.ts b/src/contentProcessing/ContentOps.ts similarity index 83% rename from src/contentOperations/ContentOps.ts rename to src/contentProcessing/ContentOps.ts index 332c28b9..b7e22e67 100644 --- a/src/contentOperations/ContentOps.ts +++ b/src/contentProcessing/ContentOps.ts @@ -1,26 +1,8 @@ -import zlib from "zlib"; - -import { Buffers } from "../base/Buffers"; import { GltfUtilities } from "./GtlfUtilities"; import { TileFormats } from "../tileFormats/TileFormats"; export class ContentOps { - static gzipBuffer(inputBuffer: Buffer): Buffer { - const outputBuffer = zlib.gzipSync(inputBuffer); - return outputBuffer; - } - - static gunzipBuffer(inputBuffer: Buffer): Buffer { - let outputBuffer: Buffer; - if (Buffers.isGzipped(inputBuffer)) { - outputBuffer = zlib.gunzipSync(inputBuffer); - } else { - outputBuffer = inputBuffer; - } - return outputBuffer; - } - static b3dmToGlbBuffer(inputBuffer: Buffer): Buffer { const inputTileData = TileFormats.readTileData(inputBuffer); const outputBuffer = inputTileData.payload; diff --git a/src/contentOperations/GltfPipelineLegacy.ts b/src/contentProcessing/GltfPipelineLegacy.ts similarity index 100% rename from src/contentOperations/GltfPipelineLegacy.ts rename to src/contentProcessing/GltfPipelineLegacy.ts diff --git a/src/contentOperations/GtlfUtilities.ts b/src/contentProcessing/GtlfUtilities.ts similarity index 100% rename from src/contentOperations/GtlfUtilities.ts rename to src/contentProcessing/GtlfUtilities.ts diff --git a/src/contentTypes/LazyContentData.ts b/src/contentTypes/LazyContentData.ts index 6cf5c92e..7e2da7fd 100644 --- a/src/contentTypes/LazyContentData.ts +++ b/src/contentTypes/LazyContentData.ts @@ -79,7 +79,7 @@ export class LazyContentData implements ContentData { * the given resource resolver. * * @param uri - The URI of the content data - * @param resourceResolver The `ResourceResolver` that will be + * @param resourceResolver - The `ResourceResolver` that will be * used for resolving the data from the given URI */ constructor(uri: string, resourceResolver: ResourceResolver) { diff --git a/src/implicitTiling/AvailabilityInfo.ts b/src/implicitTiling/AvailabilityInfo.ts new file mode 100644 index 00000000..5680ea23 --- /dev/null +++ b/src/implicitTiling/AvailabilityInfo.ts @@ -0,0 +1,25 @@ +/** + * An interface that describes the availability information + * in a subtree. This is used for tile, content, and child + * subtree availability. + * + * @internal + */ +export interface AvailabilityInfo { + /** + * Returns the length of the availability information. + * + * @returns The length + */ + get length(): number; + + /** + * Returns whether the element at the specified index is + * available. + * + * @param index - The index + * @throws RangeError If the index is negative or not smaller + * than the length. + */ + isAvailable(index: number): boolean; +} diff --git a/src/implicitTiling/AvailabilityInfos.ts b/src/implicitTiling/AvailabilityInfos.ts new file mode 100644 index 00000000..da874208 --- /dev/null +++ b/src/implicitTiling/AvailabilityInfos.ts @@ -0,0 +1,92 @@ +import { defined } from "../base/defined"; + +import { AvailabilityInfo } from "./AvailabilityInfo"; +import { BufferAvailabilityInfo } from "./BufferAvailabilityInfo"; +import { ConstantAvailabilityInfo } from "./ConstantAvailabilityInfo"; +import { ImplicitTilings } from "./ImplicitTilings"; +import { ImplicitTilingError } from "./ImplicitTilingError"; + +import { Availability } from "../structure/Availability"; +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; + +/** + * Methods for creating `AvailabilityInfo` instances + * + * @internal + */ +export class AvailabilityInfos { + /** + * Creates a new `AvailabilityInfo` for the given availability + * information, for tile- or content availability. + * + * @param availability - The `Availability` object + * @param bufferViewDatas - The `BufferView` data chunks + * @param implicitTiling - The `TileImplicitTiling` object + * @returns The `AvailabilityInfo` object + * @throws ImplicitTilingError If the given data is structurally + * invalid. + */ + static createTileOrContent( + availability: Availability, + bufferViewDatas: Buffer[], + implicitTiling: TileImplicitTiling + ): AvailabilityInfo { + const length = + ImplicitTilings.computeNumberOfNodesPerSubtree(implicitTiling); + return AvailabilityInfos.create(availability, bufferViewDatas, length); + } + + /** + * Creates a new `AvailabilityInfo` for the given availability + * information, for child subtree availability + * + * @param availability - The `Availability` object + * @param bufferViewDatas - The `BufferView` data chunks + * @param implicitTiling - The `TileImplicitTiling` object + * @returns The `AvailabilityInfo` object + * @throws ImplicitTilingError If the given data is structurally + * invalid. + */ + static createChildSubtree( + availability: Availability, + bufferViewDatas: Buffer[], + implicitTiling: TileImplicitTiling + ): AvailabilityInfo { + const length = ImplicitTilings.computeNumberOfNodesInLevel( + implicitTiling, + implicitTiling.subtreeLevels + ); + return AvailabilityInfos.create(availability, bufferViewDatas, length); + } + + /** + * Creates a new `AvailabilityInfo` for the given availability + * information, for child subtree availability + * + * @param availability - The `Availability` object + * @param bufferViewDatas - The `BufferView` data chunks + * @param length - The length of the availability info + * @returns The `AvailabilityInfo` object + * @throws ImplicitTilingError If the data is structurally invalid + */ + private static create( + availability: Availability, + bufferViewDatas: Buffer[], + length: number + ): AvailabilityInfo { + const constant = availability.constant; + if (defined(constant)) { + const available = constant === 1; + return new ConstantAvailabilityInfo(available, length); + } + // The bitstream MUST be defined when constant is undefined + const bitstream = availability.bitstream; + if (!defined(bitstream)) { + throw new ImplicitTilingError( + "The availability neither defines a constant nor a bitstream" + ); + } + const bufferViewData = bufferViewDatas[bitstream]; + return new BufferAvailabilityInfo(bufferViewData, length); + } +} diff --git a/src/implicitTiling/BinarySubtreeData.ts b/src/implicitTiling/BinarySubtreeData.ts new file mode 100644 index 00000000..507c0f2d --- /dev/null +++ b/src/implicitTiling/BinarySubtreeData.ts @@ -0,0 +1,34 @@ +import { BinaryBufferData } from "../binary/BinaryBufferData"; +import { BinaryBufferStructure } from "../binary/BinaryBufferStructure"; + +import { Subtree } from "../structure/Subtree"; + +/** + * An interface summarizing the binary data that is associated + * with a subtree. + * + * Instances of this interface are created with the + * `BinarySubtreeDataResolver`, which will resolve + * the URIs of external buffers, and create an instance + * of this class that combines all the resolved binary + * buffer data. + * + * @internal + */ +export interface BinarySubtreeData { + /** + * The `Subtree` that this data belongs to + */ + subtree: Subtree; + + /** + * The structure of the binary buffers. These are + * the buffers and buffer views from the subtree. + */ + binaryBufferStructure: BinaryBufferStructure; + + /** + * The resolved binary buffer data. + */ + binaryBufferData: BinaryBufferData; +} diff --git a/src/implicitTiling/BinarySubtreeDataResolver.ts b/src/implicitTiling/BinarySubtreeDataResolver.ts new file mode 100644 index 00000000..847392c1 --- /dev/null +++ b/src/implicitTiling/BinarySubtreeDataResolver.ts @@ -0,0 +1,145 @@ +import { Buffers } from "../base/Buffers"; + +import { ResourceResolver } from "../io/ResourceResolver"; + +import { BinaryBufferDataResolver } from "../binary/BinaryBufferDataResolver"; +import { BinaryBufferStructure } from "../binary/BinaryBufferStructure"; +import { BinaryDataError } from "../binary/BinaryDataError"; + +import { Subtree } from "../structure/Subtree"; + +import { BinarySubtreeData } from "./BinarySubtreeData"; +import { ImplicitTilingError } from "./ImplicitTilingError"; + +/** + * A class for resolving the binary data that is associated with + * a subtree. + * + * @internal + */ +export class BinarySubtreeDataResolver { + /** + * Creates a new `BinarySubtreeData` from the given subtree + * that was parsed from a subtree JSON file. + * + * This will resolve all buffer references that are + * contained in the subtree JSON. + * + * @param subtree - The `Subtree` + * @param resourceResolver - The `ResourceResolver` that + * will be used to resolve buffer URIs + * @returns A promise with the `BinarySubtreeData` + * @throws An ImplicitTilingError when there was a buffer without + * a URI (which is not valid when no binary buffer was given), + * or one of the requested buffers could not be resolved. + */ + static async resolveFromJson( + subtree: Subtree, + resourceResolver: ResourceResolver + ): Promise { + const binarySubtreeData = await BinarySubtreeDataResolver.resolveInternal( + subtree, + undefined, + resourceResolver + ); + return binarySubtreeData; + } + + /** + * Creates a new `BinarySubtreeData` from the given binary subtree + * data that was directly read from a ".subtree" file. + * + * This will extract the JSON- and binary buffer part of the + * subtree data, and resolve all buffer references that are + * contained in the subtree JSON. + * + * @param input - The whole buffer of a binary subtree file + * @param resourceResolver - The `ResourceResolver` that + * will be used to resolve buffer URIs + * @returns A promise with the `BinarySubtreeData` + * @throws An ImplicitTilingError when the subtree JSON could + * not be parsed, or there was a buffer without a URI + * and no binary buffer was given, or one of the requested + * buffers could not be resolved. + */ + static async resolveFromBuffer( + input: Buffer, + resourceResolver: ResourceResolver + ): Promise { + const headerByteLength = 24; + const jsonByteLength = input.readBigUint64LE(8); + const binaryByteLength = input.readBigUint64LE(16); + + // Extract the JSON data + const jsonStartByteOffset = headerByteLength; + const jsonEndByteOffset = jsonStartByteOffset + Number(jsonByteLength); + const jsonBuffer = input.subarray(jsonStartByteOffset, jsonEndByteOffset); + let subtreeJson: any; + let subtree: Subtree; + try { + subtreeJson = Buffers.getJson(jsonBuffer); + subtree = subtreeJson; + } catch (error) { + throw new ImplicitTilingError("Could not parse subtree JSON data"); + } + + // Extract the binary buffer + const binaryStartByteOffset = jsonEndByteOffset; + const binaryEndByteOffset = + binaryStartByteOffset + Number(binaryByteLength); + const binaryBufferSlice = input.subarray( + binaryStartByteOffset, + binaryEndByteOffset + ); + const binaryBuffer = + binaryBufferSlice.length > 0 ? binaryBufferSlice : undefined; + + const binarySubtreeData = await BinarySubtreeDataResolver.resolveInternal( + subtree, + binaryBuffer, + resourceResolver + ); + return binarySubtreeData; + } + + /** + * A thin wrapper around `BinaryBufferDataResolver.resolve` + * that obtains the binary buffer structure information from + * the subtree, resolves it, and returns it as part of + * the `BinarySubtreeData` + * + * @param subtree - The `Subtree` + * @param binaryBuffer - The binary buffer of the subtree + * @param resourceResolver - The resource resolver + * @returns A promise to the resolved binary subtree data + */ + static async resolveInternal( + subtree: Subtree, + binaryBuffer: Buffer | undefined, + resourceResolver: ResourceResolver + ): Promise { + const binaryBufferStructure: BinaryBufferStructure = { + buffers: subtree.buffers ?? [], + bufferViews: subtree.bufferViews ?? [], + }; + let binaryBufferData; + try { + binaryBufferData = await BinaryBufferDataResolver.resolve( + binaryBufferStructure, + binaryBuffer, + resourceResolver + ); + } catch (error) { + if (error instanceof BinaryDataError) { + const message = `Could not read subtree data: ${error.message}`; + throw new ImplicitTilingError(message); + } + throw error; + } + return { + subtree: subtree, + binaryBufferStructure: binaryBufferStructure, + binaryBufferData: binaryBufferData, + }; + } +} diff --git a/src/implicitTiling/BufferAvailabilityInfo.ts b/src/implicitTiling/BufferAvailabilityInfo.ts new file mode 100644 index 00000000..aa70894f --- /dev/null +++ b/src/implicitTiling/BufferAvailabilityInfo.ts @@ -0,0 +1,35 @@ +import { AvailabilityInfo } from "./AvailabilityInfo"; + +/** + * Implementation of an `AvailabilityInfo` that is backed by + * a Buffer. + */ +export class BufferAvailabilityInfo implements AvailabilityInfo { + private readonly _buffer: Buffer; + private readonly _length: number; + + constructor(buffer: Buffer, length: number) { + this._buffer = buffer; + this._length = length; + } + + /** {@inheritDoc AvailabilityInfo.length} */ + get length(): number { + return this._length; + } + + /** {@inheritDoc AvailabilityInfo.isAvailable} */ + isAvailable(index: number): boolean { + if (index < 0 || index >= this.length) { + throw new RangeError( + `Index must be in [0,${this.length}), but is ${index}` + ); + } + const byteIndex = index >> 3; + const bitIndex = index % 8; + const b = this._buffer[byteIndex]; + const bit = 1 << bitIndex; + const result = (b & bit) != 0; + return result; + } +} diff --git a/src/implicitTiling/ConstantAvailabilityInfo.ts b/src/implicitTiling/ConstantAvailabilityInfo.ts new file mode 100644 index 00000000..9d2e2f96 --- /dev/null +++ b/src/implicitTiling/ConstantAvailabilityInfo.ts @@ -0,0 +1,29 @@ +import { AvailabilityInfo } from "./AvailabilityInfo"; + +/** + * Implementation of an `AvailabilityInfo` that has a constant value. + */ +export class ConstantAvailabilityInfo implements AvailabilityInfo { + private readonly _available: boolean; + private readonly _length: number; + + constructor(available: boolean, length: number) { + this._available = available; + this._length = length; + } + + /** {@inheritDoc AvailabilityInfo.length} */ + get length(): number { + return this._length; + } + + /** {@inheritDoc AvailabilityInfo.isAvailable} */ + isAvailable(index: number): boolean { + if (index < 0 || index >= this.length) { + throw new RangeError( + `Index must be in [0,${this.length}), but is ${index}` + ); + } + return this._available; + } +} diff --git a/src/implicitTiling/ImplicitTilingError.ts b/src/implicitTiling/ImplicitTilingError.ts new file mode 100644 index 00000000..b3453f93 --- /dev/null +++ b/src/implicitTiling/ImplicitTilingError.ts @@ -0,0 +1,21 @@ +/** + * An error that indicates that implicit tiling data was structurally + * invalid. + * + * This may be thrown by methods that create the convenience classes + * for this package, when the given resources are not valid. + * + * @internal + */ +export class ImplicitTilingError extends Error { + constructor(message: string) { + super(message); + // See https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes + // #extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, ImplicitTilingError.prototype); + } + + override toString = (): string => { + return `${this.name}: ${this.message}`; + }; +} diff --git a/src/implicitTiling/ImplicitTilings.ts b/src/implicitTiling/ImplicitTilings.ts new file mode 100644 index 00000000..6f3f7595 --- /dev/null +++ b/src/implicitTiling/ImplicitTilings.ts @@ -0,0 +1,293 @@ +import { TreeCoordinates } from "../spatial/TreeCoordinates"; +import { Quadtrees } from "../spatial/Quadtrees"; +import { QuadtreeCoordinates } from "../spatial/QuadtreeCoordinates"; +import { Octrees } from "../spatial/Octrees"; +import { OctreeCoordinates } from "../spatial/OctreeCoordinates"; + +import { TemplateUris } from "./TemplateUris"; +import { ImplicitTilingError } from "./ImplicitTilingError"; + +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; + +/** + * Utility methods related to `TileImplicitTiling` instances. + * + * Preliminary! + * + * The purpose of these methods is mainly to hide the differences + * between `QUADTREE` and `OCTREE` subdivision schemes. It is + * possible to completely hide these differences with the + * appropriate abstractions. But the resulting structures may + * involve interfaces that have to be passed all the way to the + * point where they are used for seemingly trivial computations, and + * this may look obscure and overengineered at the first glance. + * However, these methods in this class might eventually be moved + * into something like an instantiable `ImplicitTilingInfo` class. + * + * The methods usually assume that the subdivison scheme is + * either `QUADTREE` and `OCTREE`, and will throw an + * `ImplicitTilingError` if this is not the case. + * + * @internal + */ +export class ImplicitTilings { + /** + * Returns a generator for the tile coordinates of a single subtree + * for the given implicit tiling object. + * + * @param implicitTiling - The `TileImplicitTiling` object + * @returns The generator + * @throws ImplicitTilingError if the given object does not + * have a valid `subdivisionScheme`. + */ + static createSubtreeCoordinatesIterator( + implicitTiling: TileImplicitTiling + ): IterableIterator { + const r = this.createRootCoordinates(implicitTiling); + const depthFirst = false; + return r.descendants(implicitTiling.subtreeLevels - 1, depthFirst); + } + + /** + * Returns the total number of nodes in one subtree for the given + * implicit tiling object. + * + * @param implicitTiling - The `TileImplicitTiling` object + * @returns The number of nodes + * @throws ImplicitTilingError if the given object does not + * have a valid `subdivisionScheme`. + */ + static computeNumberOfNodesPerSubtree( + implicitTiling: TileImplicitTiling + ): number { + const levels = implicitTiling.subtreeLevels; + if (implicitTiling.subdivisionScheme === "QUADTREE") { + return Quadtrees.computeNumberOfNodesForLevels(levels); + } + if (implicitTiling.subdivisionScheme === "OCTREE") { + return Octrees.computeNumberOfNodesForLevels(levels); + } + throw new ImplicitTilingError( + `Invalid subdivisionScheme: ${implicitTiling.subdivisionScheme}` + ); + } + + /** + * Returns the number of nodes in the specified level of a + * tree with the given implicit tiling + * + * @param implicitTiling - The `TileImplicitTiling` object + * @param level - The level + * @returns The number of nodes + * @throws ImplicitTilingError if the given object does not + * have a valid `subdivisionScheme`, or the level is negative. + */ + static computeNumberOfNodesInLevel( + implicitTiling: TileImplicitTiling, + level: number + ): number { + if (level < 0) { + throw new ImplicitTilingError(`Invalid level: ${level}`); + } + const size = 1 << level; + if (implicitTiling.subdivisionScheme === "QUADTREE") { + return size * size; + } + if (implicitTiling.subdivisionScheme === "OCTREE") { + return size * size * size; + } + throw new ImplicitTilingError( + `Invalid subdivisionScheme: ${implicitTiling.subdivisionScheme}` + ); + } + + /** + * Substitutes the given coordinates into the given template URI. + * + * @param subdivisionScheme - The subdivision scheme + * @param templateUri - The template URI + * @param coordinates - The tree coordinates + * @returns The resulting URI + * @throws ImplicitTilingError if the `subdivisionScheme` is not valid. + */ + static substituteTemplateUri( + subdivisionScheme: string, + templateUri: string, + coordinates: TreeCoordinates + ): string { + if (subdivisionScheme === "QUADTREE") { + const quadtreeCoordinates = coordinates as QuadtreeCoordinates; + return TemplateUris.substituteQuadtree(templateUri, quadtreeCoordinates); + } + if (subdivisionScheme === "OCTREE") { + const octreeCoordinates = coordinates as OctreeCoordinates; + return TemplateUris.substituteOctree(templateUri, octreeCoordinates); + } + throw new ImplicitTilingError( + `Invalid subdivisionScheme: ${subdivisionScheme}` + ); + } + + /** + * Creates a string representation for the given coordinates, describing + * them as coordinates of a tile within an implicit tileset. + * + * Details about the returned string are not specified. But it is + * supposed to be a string that contains the level,x,y,[z] components + * of the given coordinates for `QuadtreeCoordinates` and + * `OctreeCoordinates`. + * + * @param coordinates - The tree coordinates + * @returns The result + * @throws ImplicitTilingError if the coordinates are neither + * `QuadtreeCoordinates` nor `OctreeCoordinates`. + */ + static createString(coordinates: TreeCoordinates): string { + if (coordinates instanceof QuadtreeCoordinates) { + const quadtreeCoordinates = coordinates as QuadtreeCoordinates; + const level = quadtreeCoordinates.level; + const x = quadtreeCoordinates.x; + const y = quadtreeCoordinates.y; + const result = `at[${level}][${x},${y}]`; + return result; + } + if (coordinates instanceof OctreeCoordinates) { + const octreeCoordinates = coordinates as OctreeCoordinates; + const level = octreeCoordinates.level; + const x = octreeCoordinates.x; + const y = octreeCoordinates.y; + const z = octreeCoordinates.z; + const result = `at[${level}][${x},${y},${z}]`; + return result; + } + throw new ImplicitTilingError(`Invalid coordinates type: ${coordinates}`); + } + + /** + * Returns the root coordinates for the specified implicit tileset. + * + * @param implicitTiling - The `TileImplicitTiling` object + * @returns The root coordinates + * @throws ImplicitTilingError if the given object does not + * have a valid `subdivisionScheme`. + */ + static createRootCoordinates( + implicitTiling: TileImplicitTiling + ): TreeCoordinates { + const subdivisionScheme = implicitTiling.subdivisionScheme; + if (subdivisionScheme === "QUADTREE") { + return new QuadtreeCoordinates(0, 0, 0); + } + if (subdivisionScheme === "OCTREE") { + return new OctreeCoordinates(0, 0, 0, 0); + } + throw new ImplicitTilingError( + `Invalid subdivisionScheme: ${subdivisionScheme}` + ); + } + + /** + * Computes the global coordinates from the given local ones. + * + * The `rootCoordinates` are the root coordinates of a subtree + * in the given implicit tiling. The `coordinates` are the local + * coordinates of a node within this subtree. + * The result will be the global coordinates for the node within + * the given implicit tiling. + * + * @param implicitTiling - The `TileImplicitTiling` object + * @param rootCoordinates - The root coordinates + * @param coordinates - The coordinates + * @returns The global coordinates + * @throws ImplicitTilingError if the given object does not + * have a valid `subdivisionScheme`. + */ + static globalizeCoordinates( + implicitTiling: TileImplicitTiling, + rootCoordinates: TreeCoordinates, + coordinates: TreeCoordinates + ): TreeCoordinates { + const subdivisionScheme = implicitTiling.subdivisionScheme; + if (subdivisionScheme === "QUADTREE") { + const quadtreeRootCoordinates = rootCoordinates as QuadtreeCoordinates; + const quadtreeCoordinates = coordinates as QuadtreeCoordinates; + return ImplicitTilings.globalizeQuadtreeCoords( + quadtreeRootCoordinates, + quadtreeCoordinates + ); + } + if (subdivisionScheme === "OCTREE") { + const octreeRootCoordinates = rootCoordinates as OctreeCoordinates; + const octreeCoordinates = coordinates as OctreeCoordinates; + return ImplicitTilings.globalizeOctreeCoords( + octreeRootCoordinates, + octreeCoordinates + ); + } + throw new ImplicitTilingError( + `Invalid subdivisionScheme: ${subdivisionScheme}` + ); + } + + /** + * Compute the global quadtree coordinates for the given coordinates. + * + * @param rootCoords - The (global) root coordinates of the subtree + * @param localCoords - The local coordinates inside the subtree + * @returns The global coordinates + */ + private static globalizeQuadtreeCoords( + rootCoords: QuadtreeCoordinates, + localCoords: QuadtreeCoordinates + ): QuadtreeCoordinates { + const rootLevel = rootCoords.level; + const rootX = rootCoords.x; + const rootY = rootCoords.y; + + const localLevel = localCoords.level; + const localX = localCoords.x; + const localY = localCoords.y; + + const globalLevel = rootLevel + localLevel; + const globalX = (rootX << localLevel) + localX; + const globalY = (rootY << localLevel) + localY; + + const globalCoords = new QuadtreeCoordinates(globalLevel, globalX, globalY); + return globalCoords; + } + + /** + * Compute the global octree coordinates for the given coordinates. + * + * @param rootCoords - The (global) root coordinates of the subtree + * @param localCoords - The local coordinates inside the subtree + * @returns The global coordinates + */ + private static globalizeOctreeCoords( + rootCoords: OctreeCoordinates, + localCoords: OctreeCoordinates + ): OctreeCoordinates { + const rootLevel = rootCoords.level; + const rootX = rootCoords.x; + const rootY = rootCoords.y; + const rootZ = rootCoords.z; + + const localLevel = localCoords.level; + const localX = localCoords.x; + const localY = localCoords.y; + const localZ = localCoords.z; + + const globalLevel = rootLevel + localLevel; + const globalX = (rootX << localLevel) + localX; + const globalY = (rootY << localLevel) + localY; + const globalZ = (rootZ << localLevel) + localZ; + + const globalCoords = new OctreeCoordinates( + globalLevel, + globalX, + globalY, + globalZ + ); + return globalCoords; + } +} diff --git a/src/implicitTiling/SubtreeInfo.ts b/src/implicitTiling/SubtreeInfo.ts new file mode 100644 index 00000000..0887d619 --- /dev/null +++ b/src/implicitTiling/SubtreeInfo.ts @@ -0,0 +1,27 @@ +import { AvailabilityInfo } from "./AvailabilityInfo"; + +/** + * Summarizes the information about the elements that are + * available in a subtree. + * + * It offers the availability information for tiles, child + * subtrees, and contents, as `AvailabilityInfo` objects. + * + * @internal + */ +export interface SubtreeInfo { + /** + * The AvailabilityInfo for the tiles + */ + tileAvailabilityInfo: AvailabilityInfo; + + /** + * The AvailabilityInfo for the content + */ + contentAvailabilityInfos: AvailabilityInfo[]; + + /** + * The AvailabilityInfo for the child subtrees + */ + childSubtreeAvailabilityInfo: AvailabilityInfo; +} diff --git a/src/implicitTiling/SubtreeInfos.ts b/src/implicitTiling/SubtreeInfos.ts new file mode 100644 index 00000000..906fbea1 --- /dev/null +++ b/src/implicitTiling/SubtreeInfos.ts @@ -0,0 +1,134 @@ +import { ResourceResolver } from "../io/ResourceResolver"; + +import { SubtreeInfo } from "./SubtreeInfo"; +import { AvailabilityInfos } from "./AvailabilityInfos"; +import { BinarySubtreeData } from "./BinarySubtreeData"; +import { BinarySubtreeDataResolver } from "./BinarySubtreeDataResolver"; + +import { Subtree } from "../structure/Subtree"; +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; + +/** + * Methods to create `SubtreeInfo` instances. + * + * @internal + */ +export class SubtreeInfos { + /** + * Creates a new `SubtreeInfo` from the given binary subtree data + * that was directly read from a ".subtree" file. + * + * This method assumes that the given binary data is consistent + * and valid. + * + * @param input - The whole buffer of a binary subtree file + * @param implicitTiling - The `TileImplicitTiling` that + * defines the expected structure of the subtree data + * @param resourceResolver - The `ResourceResolver` that + * will be used to resolve buffer URIs + * @returns A promise with the `SubtreeInfo` + * @throws An ImplicitTilingError when the subtree JSON could + * not be parsed, or there was a buffer without a URI + * and no binary buffer was given, or one of the requested + * buffers could not be resolved. + */ + static async createFromBuffer( + input: Buffer, + implicitTiling: TileImplicitTiling, + resourceResolver: ResourceResolver + ): Promise { + const binarySubtreeData = await BinarySubtreeDataResolver.resolveFromBuffer( + input, + resourceResolver + ); + const result = SubtreeInfos.create(binarySubtreeData, implicitTiling); + return result; + } + + /** + * Creates a new `SubtreeInfo` from the given subtree + * that was read from a subtree JSON file. + * + * @param subtree - The parsed subtree + * @param implicitTiling - The `TileImplicitTiling` that + * defines the expected structure of the subtree data + * @param resourceResolver - The `ResourceResolver` that + * will be used to resolve buffer URIs + * @returns A promise with the `SubtreeInfo` + * @throws An ImplicitTilingError when there was a buffer without + * a URI, or one of the requested buffers could not be resolved. + */ + static async createFromJson( + subtree: Subtree, + implicitTiling: TileImplicitTiling, + resourceResolver: ResourceResolver + ): Promise { + const binarySubtreeData = await BinarySubtreeDataResolver.resolveFromJson( + subtree, + resourceResolver + ); + const result = SubtreeInfos.create(binarySubtreeData, implicitTiling); + return result; + } + + /** + * Creates a new `SubtreeInfo` from the given binary subtree data. + * + * This method assumes that the given data is consistent + * and valid. + * + * @param binarySubtreeData - The `BinarySubtreeData` + * @param implicitTiling - The `TileImplicitTiling` that + * defines the expected structure of the subtree data + * @returns The `SubtreeInfo` + * @throws A ImplicitTilingError when there was a buffer without + * a URI and no binary buffer was given, or the requested buffer + * data could not be resolved. + */ + static create( + binarySubtreeData: BinarySubtreeData, + implicitTiling: TileImplicitTiling + ): SubtreeInfo { + const subtree = binarySubtreeData.subtree; + const binaryBufferData = binarySubtreeData.binaryBufferData; + const bufferViewsData = binaryBufferData.bufferViewsData; + + // Create the `AvailabilityInfo` for the tile availability + const tileAvailability = subtree.tileAvailability; + const tileAvailabilityInfo = AvailabilityInfos.createTileOrContent( + tileAvailability, + bufferViewsData, + implicitTiling + ); + + // Create the `AvailabilityInfo` objects, one for + // each content availability + const contentAvailabilityInfos = []; + const contentAvailabilities = subtree.contentAvailability; + if (contentAvailabilities) { + for (const contentAvailability of contentAvailabilities) { + const contentAvailabilityInfo = AvailabilityInfos.createTileOrContent( + contentAvailability, + bufferViewsData, + implicitTiling + ); + contentAvailabilityInfos.push(contentAvailabilityInfo); + } + } + + // Create the `AvailabilityInfo` for the child subtree availability + const childSubtreeAvailability = subtree.childSubtreeAvailability; + const childSubtreeAvailabilityInfo = AvailabilityInfos.createChildSubtree( + childSubtreeAvailability, + bufferViewsData, + implicitTiling + ); + + const result: SubtreeInfo = { + tileAvailabilityInfo: tileAvailabilityInfo, + contentAvailabilityInfos: contentAvailabilityInfos, + childSubtreeAvailabilityInfo: childSubtreeAvailabilityInfo, + }; + return result; + } +} diff --git a/src/implicitTiling/TemplateUris.ts b/src/implicitTiling/TemplateUris.ts new file mode 100644 index 00000000..e10b08fa --- /dev/null +++ b/src/implicitTiling/TemplateUris.ts @@ -0,0 +1,100 @@ +import { OctreeCoordinates } from "../spatial/OctreeCoordinates"; +import { QuadtreeCoordinates } from "../spatial/QuadtreeCoordinates"; + +/** + * Method related to template URIs for implicit tiling. + * + * @internal + */ +export class TemplateUris { + /** + * Substitute all appearances of \{level\}, \{x\}, and \{y\} in + * the given string with the respective value from the given + * coordinates. + * + * @param templateUri - The template URI string + * @param coordinates - The coordinates + * @returns The string with the substitutions applied + */ + static substituteQuadtree( + templateUri: string, + coordinates: QuadtreeCoordinates + ) { + return TemplateUris.substituteQuadtreeInternal( + templateUri, + coordinates.level, + coordinates.x, + coordinates.y + ); + } + + /** + * Resolves each appearance of \{level\}, \{x\}, + * and \{y\} in the given template string with the + * respective parameters. + * + * @param templateUri - The template URI + * @param level - The level + * @param x - The x-coordinate + * @param y - The y-coordinate + * @returns The result + */ + static substituteQuadtreeInternal( + templateUri: string, + level: number, + x: number, + y: number + ) { + let result = templateUri; + result = result.replace(/{level}/g, `${level}`); + result = result.replace(/{x}/g, `${x}`); + result = result.replace(/{y}/g, `${y}`); + return result; + } + + /** + * Substitute all appearances of \{level\}, \{x\}, \{y\}, and \{z\} in + * the given string with the respective value from the given + * coordinates. + * + * @param templateUri - The template URI string + * @param coordinates - The coordinates + * @returns The string with the substitutions applied + */ + static substituteOctree(templateUri: string, coordinates: OctreeCoordinates) { + return TemplateUris.substituteOctreeInternal( + templateUri, + coordinates.level, + coordinates.x, + coordinates.y, + coordinates.z + ); + } + + /** + * Resolves each appearance of \{level\}, \{x\}, + * \{y\}, and \{z\} in the given template string + * with the respective parameters. + * + * @param templateUri - The template URI + * @param level - The level + * @param x - The x-coordinate + * @param y - The y-coordinate + * @param z - The z-coordinate + * @returns The result + */ + static substituteOctreeInternal( + templateUri: string, + level: number, + x: number, + y: number, + z: number + ) { + let result = templateUri; + result = result.replace(/{level}/g, `${level}`); + result = result.replace(/{x}/g, `${x}`); + result = result.replace(/{y}/g, `${y}`); + result = result.replace(/{z}/g, `${z}`); + return result; + } +} diff --git a/src/index.ts b/src/index.ts index 7cc75141..ca45c409 100644 --- a/src/index.ts +++ b/src/index.ts @@ -63,3 +63,56 @@ export * from "./io/UnzippingResourceResolver"; export * from "./contentTypes/ContentData"; export * from "./contentTypes/ContentDataTypeRegistry"; +export * from "./contentTypes/LazyContentData"; + +export * from "./binary/BinaryBufferData"; +export * from "./binary/BinaryBufferDataResolver"; +export * from "./binary/BinaryBuffers"; +export * from "./binary/BinaryBufferStructure"; +export * from "./binary/BinaryDataError"; + +export * from "./implicitTiling/AvailabilityInfo"; +export * from "./implicitTiling/AvailabilityInfos"; +export * from "./implicitTiling/BinarySubtreeData"; +export * from "./implicitTiling/BinarySubtreeDataResolver"; +export * from "./implicitTiling/ImplicitTilingError"; +export * from "./implicitTiling/ImplicitTilings"; +export * from "./implicitTiling/SubtreeInfo"; +export * from "./implicitTiling/SubtreeInfos"; +export * from "./implicitTiling/TemplateUris"; + +export * from "./spatial/OctreeCoordinates"; +export * from "./spatial/Octrees"; +export * from "./spatial/QuadtreeCoordinates"; +export * from "./spatial/Quadtrees"; +export * from "./spatial/TreeCoordinates"; + +export * from "./metadata/ArrayValues"; +export * from "./metadata/ClassProperties"; +export * from "./metadata/DefaultMetadataEntityModel"; +export * from "./metadata/MetadataComponentTypes"; +export * from "./metadata/MetadataUtilities"; +export * from "./metadata/MetadataEntityModel"; +export * from "./metadata/MetadataEntityModels"; +export * from "./metadata/MetadataError"; +export * from "./metadata/MetadataTypes"; +export * from "./metadata/MetadataUtilities"; +export * from "./metadata/MetadataValues"; +export * from "./metadata/PropertyModel"; +export * from "./metadata/PropertyTableModel"; + +export * from "./metadata/binary/BinaryPropertyTable"; +export * from "./metadata/binary/BinaryPropertyTables"; +export * from "./metadata/binary/BinaryPropertyTableModel"; +export * from "./metadata/binary/NumericBuffers"; + +export * from "./traversal/ExplicitTraversedTile"; +export * from "./traversal/ExplicitTraversedTiles"; +export * from "./traversal/ImplicitTraversedTile"; +export * from "./traversal/SubtreeMetadataModel"; +export * from "./traversal/SubtreeMetadataModels"; +export * from "./traversal/SubtreeModel"; +export * from "./traversal/SubtreeModels"; +export * from "./traversal/TilesetTraverser"; +export * from "./traversal/TraversedTile"; +export * from "./traversal/TraversalCallback"; diff --git a/src/io/FileResourceResolver.ts b/src/io/FileResourceResolver.ts index 3b2165fa..6211ed1d 100644 --- a/src/io/FileResourceResolver.ts +++ b/src/io/FileResourceResolver.ts @@ -17,12 +17,14 @@ export class FileResourceResolver implements ResourceResolver { this._basePath = basePath; } + /** {@inheritDoc ResourceResolver.resolveUri} */ resolveUri(uri: string): string { let resolved = path.resolve(this._basePath, decodeURIComponent(uri)); resolved = resolved.replace(/\\/g, "/"); return resolved; } + /** {@inheritDoc ResourceResolver.resolveDataPartial} */ async resolveDataPartial( uri: string, maxBytes: number @@ -46,6 +48,7 @@ export class FileResourceResolver implements ResourceResolver { } } + /** {@inheritDoc ResourceResolver.resolveData} */ async resolveData(uri: string): Promise { if (Uris.isDataUri(uri)) { const data = Buffer.from(uri.split(",")[1], "base64"); @@ -66,6 +69,8 @@ export class FileResourceResolver implements ResourceResolver { ); return Buffer.from(actualData); } + + /** {@inheritDoc ResourceResolver.derive} */ derive(uri: string): ResourceResolver { const resolved = path.join(this._basePath, decodeURIComponent(uri)); return new FileResourceResolver(resolved); diff --git a/src/io/TilesetSourceResourceResolver.ts b/src/io/TilesetSourceResourceResolver.ts index cdd42603..4aa44548 100644 --- a/src/io/TilesetSourceResourceResolver.ts +++ b/src/io/TilesetSourceResourceResolver.ts @@ -14,24 +14,20 @@ import { ResourceResolver } from "./ResourceResolver"; */ export class TilesetSourceResourceResolver implements ResourceResolver { private readonly _basePath: string; - private readonly _tilesetSourceFileName: string; private readonly _tilesetSource: TilesetSource; - constructor( - basePath: string, - tilesetSourceFileName: string, - tilesetSource: TilesetSource - ) { + constructor(basePath: string, tilesetSource: TilesetSource) { this._basePath = basePath; - this._tilesetSourceFileName = tilesetSourceFileName; this._tilesetSource = tilesetSource; } + /** {@inheritDoc ResourceResolver.resolveUri} */ resolveUri(uri: string): string { const resolved = path.resolve(this._basePath, decodeURIComponent(uri)); return resolved; } + /** {@inheritDoc ResourceResolver.resolveData} */ async resolveData(uri: string): Promise { if (Uris.isDataUri(uri)) { const data = Buffer.from(uri.split(",")[1], "base64"); @@ -48,6 +44,7 @@ export class TilesetSourceResourceResolver implements ResourceResolver { return value; } + /** {@inheritDoc ResourceResolver.resolveDataPartial} */ async resolveDataPartial( uri: string, // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -56,11 +53,11 @@ export class TilesetSourceResourceResolver implements ResourceResolver { return await this.resolveData(uri); } + /** {@inheritDoc ResourceResolver.derive} */ derive(uri: string): ResourceResolver { const resolved = Paths.join(this._basePath, decodeURIComponent(uri)); const result = new TilesetSourceResourceResolver( resolved, - this._tilesetSourceFileName, this._tilesetSource ); return result; diff --git a/src/io/UnzippingResourceResolver.ts b/src/io/UnzippingResourceResolver.ts index c67dc165..2676d28b 100644 --- a/src/io/UnzippingResourceResolver.ts +++ b/src/io/UnzippingResourceResolver.ts @@ -17,10 +17,12 @@ export class UnzippingResourceResolver implements ResourceResolver { this._delegate = delegate; } + /** {@inheritDoc ResourceResolver.resolveUri} */ resolveUri(uri: string): string { return this._delegate.resolveUri(uri); } + /** {@inheritDoc ResourceResolver.resolveData} */ async resolveData(uri: string): Promise { const delegateData = await this._delegate.resolveData(uri); if (delegateData === null) { @@ -34,6 +36,7 @@ export class UnzippingResourceResolver implements ResourceResolver { return data; } + /** {@inheritDoc ResourceResolver.resolveDataPartial} */ async resolveDataPartial( uri: string, maxBytes: number @@ -56,6 +59,8 @@ export class UnzippingResourceResolver implements ResourceResolver { const data = zlib.gunzipSync(fullDelegateData); return data; } + + /** {@inheritDoc ResourceResolver.derive} */ derive(uri: string): ResourceResolver { return new UnzippingResourceResolver(this._delegate.derive(uri)); } diff --git a/src/metadata/ArrayValues.ts b/src/metadata/ArrayValues.ts new file mode 100644 index 00000000..a218a4ba --- /dev/null +++ b/src/metadata/ArrayValues.ts @@ -0,0 +1,391 @@ +import { MetadataError } from "./MetadataError"; + +/** + * Type definition for numeric values (number or bigint) + */ +type NumericScalar = number | bigint; + +/** + * Type definition for numeric values or n-dimensional + * arrays of numeric values. + */ +type NumericND = NumericScalar | NumericND[]; + +/** + * A type definition for numbers + */ +type NumberScalar = number; + +/** + * A type definition for numbers or n-dimensional + * arrays of numbers + */ +type NumberND = NumberScalar | NumberND[]; + +/** + * Utility functions for generic operations on values that + * may be numbers or (potentially multi-dimensional) arrays + * of numbers. + * + * These methods are mainly used for performing operations + * on metadata values that have been found to be numeric + * values (i.e. SCALAR values, VECn or MATn values, or + * arrays thereof) + * + * When two values are involved, then the methods assume + * that the values have the same structure, i.e. they are + * both numeric/numbers or arrays with the same length. If this + * is not the case, then a `MetadataError` will be thrown. + * + * @internal + */ +export class ArrayValues { + // Implementation note: + // The methods here are supposed to be called in a context + // where no (compile-time) type information is available. + // Thes are offered to operate on "any" types, but usually + // delegate to "...Internal" methods with more specific + // type signatures. This does not imply any compile-time + // checks, but these specific signatures might be exposed + // as public methods at some point. + + /** + * Returns whether the given value is a Numeric scalar + * (i.e. number or bigint) + * + * @param value - The value + * @returns Whether the value is Numeric + */ + private static isNumericScalar(value: any): value is NumericScalar { + if (typeof value === "number") { + return true; + } + if (typeof value === "bigint") { + return true; + } + return true; + } + + /** + * Multiplies the given input value with the given factor. + * + * @param value - The input value + * @param factor - The factor + * @returns The resulting value + * @throws MetadataError If the parameters have incompatible types + */ + static deepMultiply(value: any, factor: any): any { + return ArrayValues.deepMultiplyInternal(value, factor); + } + + /** + * Multiplies the given input value with the given factor. + * + * @param value - The input value + * @param factor - The factor + * @returns The resulting value + * @throws MetadataError If the parameters have incompatible types + */ + private static deepMultiplyInternal( + value: T, + factor: T + ): T { + if (Array.isArray(value) && Array.isArray(factor)) { + if (value.length != factor.length) { + throw new MetadataError( + `Values ${value} and ${factor} have different lengths` + ); + } + const result = value.slice(); + for (let i = 0; i < result.length; i++) { + result[i] = ArrayValues.deepMultiplyInternal(result[i], factor[i]); + } + return result as T; + } + if (typeof value === "number" && typeof factor === "number") { + return (value * factor) as T; + } + throw new MetadataError( + `Values ${value} and ${factor} have invalid ` + + `types ${typeof value} and ${typeof factor}` + ); + } + + /** + * Adds the given addend to the given input value. + * + * @param value - The input value + * @param addend - The optional addend + * @returns The resulting value + * @throws MetadataError If the parameters have incompatible types + */ + static deepAdd(value: any, addend: any): any { + return ArrayValues.deepAddInternal(value, addend); + } + + /** + * Adds the given addend to the given input value. + * + * @param value - The input value + * @param addend - The optional addend + * @returns The resulting value + * @throws MetadataError If the parameters have incompatible types + */ + private static deepAddInternal(value: T, addend: T): T { + if (Array.isArray(value) && Array.isArray(addend)) { + if (value.length != addend.length) { + throw new MetadataError( + `Values ${value} and ${addend} have different lengths` + ); + } + const result = value.slice(); + for (let i = 0; i < result.length; i++) { + result[i] = ArrayValues.deepAddInternal(result[i], addend[i]); + } + return result as T; + } + if (typeof value === "number" && typeof addend === "number") { + return (value + addend) as T; + } + throw new MetadataError( + `Values ${value} and ${addend} have invalid ` + + `types ${typeof value} and ${typeof addend}` + ); + } + + /** + * Computes the minimum of the given values. + * + * For arrays, it computes the component-wise minimum. + * + * @param a - The first value + * @param b - The second value + * @returns The mimimum value + * @throws MetadataError If the parameters have incompatible types + */ + static deepMin(a: any, b: any): any { + return ArrayValues.deepMinInternal(a, b); + } + + /** + * Computes the minimum of the given values. + * + * For arrays, it computes the component-wise minimum. + * + * @param a - The first value + * @param b - The second value + * @returns The mimimum value + * @throws MetadataError If the parameters have incompatible types + */ + private static deepMinInternal(a: T, b: T): T { + if (Array.isArray(a) && Array.isArray(b)) { + if (a.length != b.length) { + throw new MetadataError(`Values ${a} and ${b} have different lengths`); + } + const result = a.slice(); + for (let i = 0; i < a.length; ++i) { + result[i] = ArrayValues.deepMinInternal(a[i], b[i]); + } + return result as T; + } + if (ArrayValues.isNumericScalar(a) && ArrayValues.isNumericScalar(b)) { + return a < b ? a : b; + } + throw new MetadataError( + `Values ${a} and ${b} have invalid ` + `types ${typeof a} and ${typeof b}` + ); + } + + /** + * Computes the maximum of the given values. + * + * For arrays, it computes the component-wise maximum. + * + * @param a - The first value + * @param b - The second value + * @returns The maximum value + * @throws MetadataError If the parameters have incompatible types + */ + static deepMax(a: any, b: any): any { + return ArrayValues.deepMaxInternal(a, b); + } + + /** + * Computes the maximum of the given values. + * + * For arrays, it computes the component-wise maximum. + * + * @param a - The first value + * @param b - The second value + * @returns The maximum value + * @throws MetadataError If the parameters have incompatible types + */ + private static deepMaxInternal(a: T, b: T): T { + if (Array.isArray(a) && Array.isArray(b)) { + const result = a.slice(); + for (let i = 0; i < a.length; ++i) { + result[i] = ArrayValues.deepMaxInternal(a[i], b[i]); + } + return result as T; + } + if (ArrayValues.isNumericScalar(a) && ArrayValues.isNumericScalar(b)) { + return a > b ? a : b; + } + throw new MetadataError( + `Values ${a} and ${b} have invalid ` + `types ${typeof a} and ${typeof b}` + ); + } + + /** + * Checks whether two values are equal. + * + * This is only supposed to be used for scalars (number or bigint) + * or (potentially multi-dimensional) arrays of scalars. + * + * @param a - The first value + * @param b - The second value + * @returns Whether the values are equal + */ + static deepEquals(a: any, b: any): boolean { + return ArrayValues.deepEqualsInternal(a, b); + } + + /** + * Checks whether two values are equal. + * + * @param a - The first value + * @param b - The second value + * @returns Whether the values are equal + */ + private static deepEqualsInternal(a: T, b: T): boolean { + if (Array.isArray(a) && Array.isArray(b)) { + if (a.length !== b.length) { + return false; + } + for (let i = 0; i < a.length; i++) { + if (!ArrayValues.deepEqualsInternal(a[i], b[i])) { + return false; + } + } + return true; + } + // Do a loose comparison, for the case of mixing bigint and number: + return a == b; + } + + /** + * Returns a deep clone of the given value. + * + * When the value is an array, then its elements are + * deep-cloned. Otherwise, the value itself is returned. + * + * @param value - The input value + * @returns The result value + */ + static deepClone(value: any) { + if (!Array.isArray(value)) { + return value; + } + const result = value.slice(); + for (let i = 0; i < value.length; i++) { + result[i] = ArrayValues.deepClone(value[i]); + } + return result; + } + + /** + * Returns whether one value is less than another. + * + * It returns whether the first value is smaller than + * the second value. For arrays, it recursively checks + * whether ANY element of the first array is smaller + * than the corresponding element of the second array. + * + * @param a - The first value + * @param b - The second value + * @returns Whether the first value is less than the second + * @throws MetadataError If the parameters have incompatible types + */ + static anyDeepLessThan(a: any, b: any): boolean { + return ArrayValues.anyDeepLessThanInternal(a, b); + } + + /** + * Returns whether one value is less than another. + * + * It returns whether the first value is smaller than + * the second value. For arrays, it recursively checks + * whether ANY element of the first array is smaller + * than the corresponding element of the second array. + * + * @param a - The first value + * @param b - The second value + * @returns Whether the first value is less than the second + * @throws MetadataError If the parameters have incompatible types + */ + private static anyDeepLessThanInternal( + a: T, + b: T + ): boolean { + if (Array.isArray(a) && Array.isArray(b)) { + if (a.length != b.length) { + throw new MetadataError(`Values ${a} and ${b} have different lengths`); + } + for (let i = 0; i < a.length; ++i) { + if (ArrayValues.anyDeepLessThanInternal(a[i], b[i])) { + return true; + } + } + return false; + } + return a < b; + } + + /** + * Returns whether one value is greater than another. + * + * It returns whether the first value is greater than + * the second value. For arrays, it recursively checks + * whether ANY element of the first array is greater + * than the corresponding element of the second array. + * + * @param a - The first value + * @param b - The second value + * @returns Whether the first value is greater than the second + * @throws MetadataError If the parameters have incompatible types + */ + static anyDeepGreaterThan(a: any, b: any): boolean { + return ArrayValues.anyDeepGreaterThanInternal(a, b); + } + + /** + * Returns whether one value is greater than another. + * + * It returns whether the first value is greater than + * the second value. For arrays, it recursively checks + * whether ANY element of the first array is greater + * than the corresponding element of the second array. + * + * @param a - The first value + * @param b - The second value + * @returns Whether the first value is greater than the second + * @throws MetadataError If the parameters have incompatible types + */ + private static anyDeepGreaterThanInternal( + a: T, + b: T + ): boolean { + if (Array.isArray(a) && Array.isArray(b)) { + if (a.length != b.length) { + throw new MetadataError(`Values ${a} and ${b} have different lengths`); + } + for (let i = 0; i < a.length; ++i) { + if (ArrayValues.anyDeepGreaterThanInternal(a[i], b[i])) { + return true; + } + } + return false; + } + return a > b; + } +} diff --git a/src/metadata/ClassProperties.ts b/src/metadata/ClassProperties.ts new file mode 100644 index 00000000..91913ca8 --- /dev/null +++ b/src/metadata/ClassProperties.ts @@ -0,0 +1,74 @@ +import { defined } from "../base/defined"; + +import { MetadataTypes } from "./MetadataTypes"; +import { MetadataComponentTypes } from "./MetadataComponentTypes"; + +import { ClassProperty } from "../structure/Metadata/ClassProperty"; + +/** + * Utility methods related to `ClassProperty` objects + * + * @internal + */ +export class ClassProperties { + /** + * Returns whether the given property effectively describes a floating + * point type. + * + * These are the properties for which 'offset' and 'scale' may be defined. + * + * This means that the value has the type SCALAR, VECn, or MATn, and + * - either has the componentType FLOAT32 or FLOAT46 + * - or has an integer component type AND is 'normalized' + * + * @param property - The property + * @returns Whether the property is a floating point property + */ + static hasEffectivelyFloatingPointType(property: ClassProperty): boolean { + const type = property.type; + if (!MetadataTypes.numericTypes.includes(type)) { + return false; + } + const componentType = property.componentType; + if (!defined(componentType)) { + return false; + } + if (componentType === "FLOAT32" || componentType === "FLOAT64") { + return true; + } + if (MetadataComponentTypes.isIntegerComponentType(componentType)) { + const normalized = property.normalized; + if (!defined(normalized)) { + return false; + } + return normalized; + } + return false; + } + + /** + * Returns whether the given property describes a numeric type. + * + * These are the properties for which 'max' and 'min' may be defined. + * + * This means tha the value has the type SCALAR, VECn, or MATn, and + * one of the allowed component types. + * + * @param property - The property + * @returns Whether the property is a numeric property + */ + static hasNumericType(property: ClassProperty): boolean { + const type = property.type; + if (!MetadataTypes.numericTypes.includes(type)) { + return false; + } + const componentType = property.componentType; + if (!defined(componentType)) { + return false; + } + if (!MetadataComponentTypes.allComponentTypes.includes(componentType)) { + return false; + } + return true; + } +} diff --git a/src/metadata/DefaultMetadataEntityModel.ts b/src/metadata/DefaultMetadataEntityModel.ts new file mode 100644 index 00000000..64a4eefa --- /dev/null +++ b/src/metadata/DefaultMetadataEntityModel.ts @@ -0,0 +1,59 @@ +import { defined } from "../base/defined"; + +import { MetadataEntityModel } from "./MetadataEntityModel"; +import { MetadataValues } from "./MetadataValues"; +import { MetadataError } from "./MetadataError"; + +import { MetadataClass } from "../structure/Metadata/MetadataClass"; + +/** + * Default implementation of a `MetadataEntityModel` that is backed + * by the JSON representation of the metadata. + * + * (The JSON representation are just the `metadataEntity.properties` + * from the input JSON) + * + * @internal + */ +export class DefaultMetadataEntityModel implements MetadataEntityModel { + private readonly _metadataClass: MetadataClass; + private readonly _json: any; + private readonly _semanticToPropertyId: { [key: string]: string }; + + constructor( + metadataClass: MetadataClass, + semanticToPropertyId: { [key: string]: string }, + json: any + ) { + this._metadataClass = metadataClass; + this._semanticToPropertyId = semanticToPropertyId; + this._json = json; + } + + /** {@inheritDoc MetadataEntityModel.getPropertyValue} */ + getPropertyValue(propertyId: string): any { + const properties = this._metadataClass.properties; + if (!properties) { + throw new MetadataError(`Metadata class does not have any properties`); + } + const property = properties[propertyId]; + if (!property) { + throw new MetadataError( + `Metadata class does not have property ${propertyId}` + ); + } + const value = this._json[propertyId]; + const offset = this._json.offset; + const scale = this._json.scale; + return MetadataValues.processValue(property, offset, scale, value); + } + + /** {@inheritDoc MetadataEntityModel.getPropertyValueBySemantic} */ + getPropertyValueBySemantic(semantic: string): any { + const propertyId = this._semanticToPropertyId[semantic]; + if (!defined(propertyId)) { + return undefined; + } + return this.getPropertyValue(propertyId); + } +} diff --git a/src/metadata/MetadataComponentTypes.ts b/src/metadata/MetadataComponentTypes.ts new file mode 100644 index 00000000..5aa668dc --- /dev/null +++ b/src/metadata/MetadataComponentTypes.ts @@ -0,0 +1,157 @@ +import { defined } from "../base/defined"; +import { MetadataError } from "./MetadataError"; + +/** + * Internal utilities related to the `componentType` of the + * `ClassProperty` instances of `MetadataClass` objects + * + * @internal + */ +export class MetadataComponentTypes { + /** + * The valid values for the `class.property.componentType` property + */ + static allComponentTypes: string[] = [ + "INT8", + "UINT8", + "INT16", + "UINT16", + "INT32", + "UINT32", + "INT64", + "UINT64", + "FLOAT32", + "FLOAT64", + ]; + + /** + * Integer component types. + * These are the types for which a property can be `normalized`, + * and the valid values for the `enum.valueType` property + */ + static integerComponentTypes: string[] = [ + "INT8", + "UINT8", + "INT16", + "UINT16", + "INT32", + "UINT32", + "INT64", + "UINT64", + ]; + + /** + * Unsigned component types. + */ + static unsignedComponentTypes: string[] = [ + "UINT8", + "UINT16", + "UINT32", + "UINT64", + ]; + + /** + * Returns whether the given component type is an integer component + * type. + * + * @param componentType - The component type + * @returns Whether the component type is an integer component type + */ + static isIntegerComponentType(componentType: string | undefined) { + if (!defined(componentType)) { + return false; + } + return MetadataComponentTypes.integerComponentTypes.includes(componentType); + } + + /** + * Returns whether the given component type is an unsigned component + * type. + * + * @param componentType - The component type + * @returns Whether the component type is an unsigned component type + */ + static isUnsignedComponentType(componentType: string | undefined) { + if (!defined(componentType)) { + return false; + } + return MetadataComponentTypes.unsignedComponentTypes.includes( + componentType + ); + } + + /** + * Returns the size of the given component type in bytes + * + * @param componentType - The type + * @returns The size in bytes + * @throws MetadataError If the given component type is not + * one of the `allComponentTypes` + */ + static byteSizeForComponentType(componentType: string): number { + switch (componentType) { + case "INT8": + return 1; + case "UINT8": + return 1; + case "INT16": + return 2; + case "UINT16": + return 2; + case "INT32": + return 4; + case "UINT32": + return 4; + case "INT64": + return 8; + case "UINT64": + return 8; + case "FLOAT32": + return 4; + case "FLOAT64": + return 8; + } + throw new MetadataError(`Invalid component type: ${componentType}`); + } + + // Partially adapted from CesiumJS + static normalize(value: number, componentType: string | undefined): number { + if (MetadataComponentTypes.isIntegerComponentType(componentType)) { + return Math.max( + Number(value) / + Number(MetadataComponentTypes.maximumValue(componentType)), + -1.0 + ); + } + return value; + } + + // Partially adapted from CesiumJS + private static maximumValue( + componentType: string | undefined + ): number | bigint | undefined { + switch (componentType) { + case "INT8": + return 127; + case "UINT8": + return 255; + case "INT16": + return 32767; + case "UINT16": + return 65535; + case "INT32": + return 2147483647; + case "UINT32": + return 4294967295; + case "INT64": + return BigInt("9223372036854775807"); + case "UINT64": + return BigInt("18446744073709551615"); + case "FLOAT32": + return 340282346638528859811704183484516925440.0; + case "FLOAT64": + return Number.MAX_VALUE; + } + throw new MetadataError(`Invalid component type: ${componentType}`); + } +} diff --git a/src/metadata/MetadataEntityModel.ts b/src/metadata/MetadataEntityModel.ts new file mode 100644 index 00000000..4cf9d86d --- /dev/null +++ b/src/metadata/MetadataEntityModel.ts @@ -0,0 +1,38 @@ +/** + * A minimalistic interface for a model that describes a + * metadata entity, in the context of the 3D Metadata + * specification. + * + * @internal + */ +export interface MetadataEntityModel { + /** + * Obtains the value of the metadata property with the given name/ID. + * + * This will return the final, actual value of the property, based + * on the input data and the type definition of the respective + * property. This includes normalization, offset and scale for + * the type, as well as the handling of possible default values. + * + * @param propertyId - The name/ID of the property + * @returns The property value + * @throws MetadataError If the schema class that this entity + * is an instance of does not define a property with the given + * name/ID. + */ + getPropertyValue(propertyId: string): any; + + /** + * Obtains the value of the metadata property with the given semantic. + * + * This return the result of calling `getPropertyValue` with the + * name/ID of the property that has the given semantic, or + * `undefined` if there is no property with this semantic. + * + * @param semantic - The semantic + * @throws MetadataError If the schema class that this entity + * is an instance of does not define a property with the + * resulting name/ID. + */ + getPropertyValueBySemantic(semantic: string): any; +} diff --git a/src/metadata/MetadataEntityModels.ts b/src/metadata/MetadataEntityModels.ts new file mode 100644 index 00000000..8554302a --- /dev/null +++ b/src/metadata/MetadataEntityModels.ts @@ -0,0 +1,103 @@ +import { defined } from "../base/defined"; + +import { DefaultMetadataEntityModel } from "./DefaultMetadataEntityModel"; +import { MetadataEntityModel } from "./MetadataEntityModel"; +import { MetadataError } from "./MetadataError"; + +import { Schema } from "../structure/Metadata/Schema"; +import { MetadataEntity } from "../structure/MetadataEntity"; +import { MetadataClass } from "../structure/Metadata/MetadataClass"; + +/** + * Methods related to `MetadataEntityModel` instances. + * + * @internal + */ +export class MetadataEntityModels { + /** + * Creates a new `MetadataEntityModel` from the given schema and + * metadata entity. + * + * This receives the raw `Schema`, and the `MetadataEntity` that + * may, for example, have been found in the JSON input as the + * `tileset.metadata`. It will create an instance of the model + * class that can be used to access the property values. + * + * This assumes that the schema and entity have already been + * ensured to be structurally valid. This means that the class + * of the entity must appear in the schema, and the values + * that are stored in the entity have a structure that matches + * the required structure according to the type of the respective + * metadata class properties. + * + * @param schema - The `Schema` + * @param entity - The `MetadataEntity` + * @returns The `MetadataEntityModel` + * @throws MetadataError If the metadata entity refers to a class + * that is not found in the given schema. + */ + static create(schema: Schema, entity: MetadataEntity): MetadataEntityModel { + const classes = schema.classes; + if (!classes) { + throw new MetadataError( + `Schema does not define any classes, ` + + `but expected ${entity.class} to be defined` + ); + } + const metadataClass = classes[entity.class]; + if (!metadataClass) { + throw new MetadataError(`Schema does not contain class ${entity.class}`); + } + const entityProperties = entity.properties ?? {}; + return this.createFromClass(metadataClass, entityProperties); + } + + /** + * Creates a new `MetadataEntityModel` from the given schema class and + * metadata entity properties. + * + * See the `create` method for details. + * + * @param metadataClass - The `MetadataClass` + * @param entityProperties - The properties of the `MetadataEntity` + * @returns The `MetadataEntityModel` + */ + static createFromClass( + metadataClass: MetadataClass, + entityProperties: { [key: string]: any } + ) { + // TODO This should not be done for each entity. The lookup + // should be computed once, and associated with the class. + const semanticToPropertyId = + MetadataEntityModels.computeSemanticToPropertyIdMapping(metadataClass); + const metadataEntityModel = new DefaultMetadataEntityModel( + metadataClass, + semanticToPropertyId, + entityProperties + ); + return metadataEntityModel; + } + + /** + * Compute the mapping from 'semantic' strings to property IDs + * that have the respective semantic in the given metadata class. + * + * @param metadataClass - The `MetadataClass` + * @returns The mapping + */ + static computeSemanticToPropertyIdMapping(metadataClass: MetadataClass): { + [key: string]: string; + } { + const semanticToPropertyId: { [key: string]: string } = {}; + const classProperties = metadataClass.properties; + if (classProperties) { + for (const classPropertyId of Object.keys(classProperties)) { + const property = classProperties[classPropertyId]; + if (defined(property.semantic)) { + semanticToPropertyId[property.semantic] = classPropertyId; + } + } + } + return semanticToPropertyId; + } +} diff --git a/src/metadata/MetadataError.ts b/src/metadata/MetadataError.ts new file mode 100644 index 00000000..40da61c3 --- /dev/null +++ b/src/metadata/MetadataError.ts @@ -0,0 +1,20 @@ +/** + * An error that indicates that metadata was structurally invalid. + * + * This may be thrown by methods that create the convenience classes + * for this package, when the given inputs are not valid. + * + * @internal + */ +export class MetadataError extends Error { + constructor(message: string) { + super(message); + // See https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes + // #extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, MetadataError.prototype); + } + + override toString = (): string => { + return `${this.name}: ${this.message}`; + }; +} diff --git a/src/metadata/MetadataTypes.ts b/src/metadata/MetadataTypes.ts new file mode 100644 index 00000000..44ef0002 --- /dev/null +++ b/src/metadata/MetadataTypes.ts @@ -0,0 +1,82 @@ +import { MetadataError } from "./MetadataError"; + +/** + * Internal utilities related to the `type` of the + * `ClassProperty` instances of `MetadataClass` objects + * + * @internal + */ +export class MetadataTypes { + /** + * The valid values for the `class.property.type` property + */ + static allTypes: string[] = [ + "SCALAR", + "VEC2", + "VEC3", + "VEC4", + "MAT2", + "MAT3", + "MAT4", + "STRING", + "BOOLEAN", + "ENUM", + ]; + + /** + * The valid values for the `class.property.type` property + * that count as "numeric" types. These are the ones where + * a `class.property.componentType` is given + */ + static numericTypes: string[] = [ + "SCALAR", + "VEC2", + "VEC3", + "VEC4", + "MAT2", + "MAT3", + "MAT4", + ]; + + /** + * Returns whether the given type is numeric, i.e. whether + * it is SCALAR, VECn, or MATn. + * + * @param type - The type + * @returns Whether the type is numeric + */ + static isNumericType(type: string) { + return MetadataTypes.numericTypes.includes(type); + } + + /** + * Returns the number of components for the given type + * + * @param type - The type + * @returns The number of components + * @throws MetadataError If the given string is not one + * of the types contained in `allTypes` + */ + static componentCountForType(type: string): number { + switch (type) { + case "SCALAR": + case "STRING": + case "ENUM": + case "BOOLEAN": + return 1; + case "VEC2": + return 2; + case "VEC3": + return 3; + case "VEC4": + return 4; + case "MAT2": + return 4; + case "MAT3": + return 9; + case "MAT4": + return 16; + } + throw new MetadataError(`Invalid type: ${type}`); + } +} diff --git a/src/metadata/MetadataUtilities.ts b/src/metadata/MetadataUtilities.ts new file mode 100644 index 00000000..a8e4a0d8 --- /dev/null +++ b/src/metadata/MetadataUtilities.ts @@ -0,0 +1,129 @@ +import { defined } from "../base/defined"; + +import { BinaryEnumInfo } from "./binary/BinaryEnumInfo"; + +import { Schema } from "../structure/Metadata/Schema"; +import { ClassProperty } from "../structure/Metadata/ClassProperty"; + +/** + * Internal utilities related to metadata + * + * @internal + */ +export class MetadataUtilities { + /** + * Computes the `BianaryEnumInfo` that summarizes information + * about the binary representation of `MetadataEnum` values + * from the given schema. + * + * @param schema - The metadata `Schema` + * @returns The `BinaryEnumInfo` + */ + static computeBinaryEnumInfo(schema: Schema): BinaryEnumInfo { + const binaryEnumInfo: BinaryEnumInfo = { + enumValueTypes: MetadataUtilities.computeEnumValueTypes(schema), + enumValueNameValues: MetadataUtilities.computeEnumValueNameValues(schema), + }; + return binaryEnumInfo; + } + + /** + * Computes a mapping from enum type names to the `valueType` that + * the respective `MetdataEnum` has (defaulting to `UINT16` if it + * did not define one) + * + * @param schema - The metadata `Schema` + * @returns The mapping from enum type names to enum value types + */ + private static computeEnumValueTypes(schema: Schema): { + [key: string]: string; + } { + const enumValueTypes: { [key: string]: string } = {}; + const enums = schema.enums; + if (enums) { + for (const enumName of Object.keys(enums)) { + const metadataEnum = enums[enumName]; + const valueType = metadataEnum.valueType ?? "UINT16"; + enumValueTypes[enumName] = valueType; + } + } + return enumValueTypes; + } + + /** + * Computes a mapping from enum type names to the dictionaries + * that map the enum values names to the enum value values. + * + * @param schema - The metadata `Schema` + * @returns The mapping from enum type names to dictionaries + */ + private static computeEnumValueNameValues(schema: Schema): { + [key: string]: { + [key: string]: number; + }; + } { + const enumValueNameValues: { + [key: string]: { + [key: string]: number; + }; + } = {}; + const enums = schema.enums; + if (enums) { + for (const enumName of Object.keys(enums)) { + const metadataEnum = enums[enumName]; + const nameValues: { + [key: string]: number; + } = {}; + for (let i = 0; i < metadataEnum.values.length; i++) { + const enumValue = metadataEnum.values[i]; + const value = enumValue.value; + const name = enumValue.name; + nameValues[name] = value; + } + enumValueNameValues[enumName] = nameValues; + } + } + return enumValueNameValues; + } + + /** + * Internal method to obtain the names of enum values for the + * given property. + * + * This tries to return the list of all + * `schema.enums[classProperty.enumType].values[i].name` + * values, returning the empty list if the property does not + * have an enum type or any element is not defined. + * + * @param classProperty - The `ClassProperty` + * @param schema - The `Schema` + * @returns The enum value names + */ + static obtainEnumValueNames( + classProperty: ClassProperty, + schema: Schema + ): string[] { + const type = classProperty.type; + if (type !== "ENUM") { + return []; + } + const enumType = classProperty.enumType; + if (!defined(enumType)) { + return []; + } + const enums = schema.enums; + if (!enums) { + return []; + } + const theEnum = enums[enumType]; + if (!defined(theEnum)) { + return []; + } + const enumValues = theEnum.values; + if (!enumValues) { + return []; + } + const enumValueNames = enumValues.map((e: { name: string }) => e.name); + return enumValueNames; + } +} diff --git a/src/metadata/MetadataValues.ts b/src/metadata/MetadataValues.ts new file mode 100644 index 00000000..a2afdbb9 --- /dev/null +++ b/src/metadata/MetadataValues.ts @@ -0,0 +1,97 @@ +import { defined } from "../base/defined"; + +import { ClassProperty } from "../structure/Metadata/ClassProperty"; + +import { MetadataComponentTypes } from "./MetadataComponentTypes"; +import { ArrayValues } from "./ArrayValues"; + +/** + * Internal methods related to metadata values. + * + * @internal + */ +export class MetadataValues { + /** + * Processes the given "raw" value that was obtained for a metadata + * property (e.g. from the JSON representation), and returns the + * processed value according to the type definition that is given + * by the given class property. + * + * If the type defines a `noData` value, and the given value + * is the `noData` value, then the `default` value of the type + * is returned. + * + * If the type defines the value to be `normalized`, then the + * normalization is applied to the given values. + * + * If the type defines an `offset`, then the offset is added + * to the value. + * + * If the type defines a `scale`, then this is multiplied + * with the value. + * + * @param classProperty - The `ClassProperty` + * @param offsetOverride -: An optional override for the + * `offset` of the `ClassProperty`. If this is defined, then + * it will be used instead of the one from the class property. + * @param scaleOverride -: An optional override for the + * `scale` of the `ClassProperty`. If this is defined, then + * it will be used instead of the one from the class property. + * @param value - The value + * @returns The processed value + */ + static processValue( + classProperty: ClassProperty, + offsetOverride: any, + scaleOverride: any, + value: any + ): any { + const noData = classProperty.noData; + const defaultValue = classProperty.default; + if (defined(noData)) { + if (ArrayValues.deepEquals(value, noData)) { + return ArrayValues.deepClone(defaultValue); + } + } + if (!defined(value)) { + return ArrayValues.deepClone(defaultValue); + } + value = ArrayValues.deepClone(value); + + if (classProperty.normalized === true) { + const componentType = classProperty.componentType; + value = MetadataValues.normalize(value, componentType); + } + const offset = defined(offsetOverride) + ? offsetOverride + : classProperty.offset; + const scale = defined(scaleOverride) ? scaleOverride : classProperty.scale; + + if (defined(scale)) { + value = ArrayValues.deepMultiply(value, scale); + } + if (defined(offset)) { + value = ArrayValues.deepAdd(value, offset); + } + return value; + } + + /** + * Normalize the given input value, based on the given component type. + * + * If example, the value of `255` for `UINT8` will be normalized to `1.0`. + * + * @param value - The input value + * @param componentType - The component type + * @returns The normalized value + */ + private static normalize(value: any, componentType: string | undefined): any { + if (!Array.isArray(value)) { + return MetadataComponentTypes.normalize(value, componentType); + } + for (let i = 0; i < value.length; i++) { + value[i] = MetadataValues.normalize(value[i], componentType); + } + return value; + } +} diff --git a/src/metadata/PropertyModel.ts b/src/metadata/PropertyModel.ts new file mode 100644 index 00000000..869bb38f --- /dev/null +++ b/src/metadata/PropertyModel.ts @@ -0,0 +1,30 @@ +/** + * A basic interface for a property in a property table. + * + * This can be imagined as one "column" in the table. + * + * @internal + */ +export interface PropertyModel { + /** + * Obtains the property value at the given index. + * + * The index corresponds to a "row" in the property table. + * + * The type of the returned object depends on the type of + * the property: + * - For `STRING` properties, it will be a `string` + * - For `BOOLEAN` properties, it will be a `boolean` + * - For `ENUM` properties, it will be the numeric value + * that corresponds to the respective enum constant. + * - For `SCALAR` properties, it will be a `number` or `bigint` + * - For `VECn`- or `MATn` properties, it will be an array + * of `number`- or `bigint` elements + * - For array properties, it will be an array of the + * respective elements + * + * @param index - The index + * @returns The property value + */ + getPropertyValue(index: number): any; +} diff --git a/src/metadata/PropertyTableModel.ts b/src/metadata/PropertyTableModel.ts new file mode 100644 index 00000000..cf668416 --- /dev/null +++ b/src/metadata/PropertyTableModel.ts @@ -0,0 +1,55 @@ +import { PropertyModel } from "./PropertyModel"; +import { MetadataEntityModel } from "./MetadataEntityModel"; + +import { ClassProperty } from "../structure/Metadata/ClassProperty"; +import { PropertyTableProperty } from "../structure/PropertyTableProperty"; + +/** + * A basic interface for a property table + * + * @internal + */ +export interface PropertyTableModel { + /** + * Returns the `MetadataEntityModel` that corresponds to the + * row of the table with the given index. + * + * @param index - The index (i.e. the table row) + * @returns The `MetdataEntityModel` + * @throws MetadataError If the index is out of range + */ + getMetadataEntityModel(index: number): MetadataEntityModel; + + /** + * Returns the `PropertyModel` for the property with the given ID. + * This is the "column" of the table that contains the property + * data. Returns `undefined` if this table was created for + * a `MetadataClass` that does not define this property. + * + * @param propertyId - The property ID + * @returns The `PropertyModel` + */ + getPropertyModel(propertyId: string): PropertyModel | undefined; + + /** + * Returns the `ClassProperty` that defines the structure of the + * property with the given ID, or `undefined` if this table was + * created for a `MetadataClass` that does not define this property. + * + * @param propertyId - The property ID + * @returns The `ClassProperty` + */ + getClassProperty(propertyId: string): ClassProperty | undefined; + + /** + * Returns the `PropertyTableProperty` that defines the structure of the + * property with the given ID, or `undefined` if this table was + * created for a `PropertyTable` that does not define this property. + * + * @param propertyId - The property ID + * @returns The `PropertyTableProperty` + */ + getPropertyTableProperty( + propertyId: string + ): PropertyTableProperty | undefined; +} diff --git a/src/metadata/binary/ArrayBuffers.ts b/src/metadata/binary/ArrayBuffers.ts new file mode 100644 index 00000000..b87db371 --- /dev/null +++ b/src/metadata/binary/ArrayBuffers.ts @@ -0,0 +1,25 @@ +/** + * Utility methods for buffer handling + * + * @internal + */ +export class ArrayBuffers { + /** + * Returns an `ArrayBuffer` that corresponds to the given buffer. + * + * @param buffer - The `Buffer` + * @returns The `ArrayBuffer` + */ + static fromBuffer(buffer: Buffer): ArrayBuffer { + // NOTE: The `buffer.buffer` may be totally unrelated to + // the `buffer` itself, because the buffer might have been + // allocated with one of the "unsafe" methods that use + // the internal buffer pool. This obscure line makes sure + // that the result is an `ArrayBuffer` that actually + // has the same contents as the `buffer`.... + return buffer.buffer.slice( + buffer.byteOffset, + buffer.byteOffset + buffer.byteLength + ); + } +} diff --git a/src/metadata/binary/BinaryEnumInfo.ts b/src/metadata/binary/BinaryEnumInfo.ts new file mode 100644 index 00000000..727f7fe6 --- /dev/null +++ b/src/metadata/binary/BinaryEnumInfo.ts @@ -0,0 +1,24 @@ +/** + * A basic structure holding information about `MetadataEnum` + * instances that appear in a `Schema`. + * + * It summarizes the information that is required for reading + * and writing the metadata values in binary form. + * + * @internal + */ +export interface BinaryEnumInfo { + /** + * A mapping from enum type names (enum IDs) to the + * `metadataEnum.valueType` of the respective enum, + * defaulting to `UINT16` when it was not defined. + */ + enumValueTypes: { [key: string]: string }; + + /** + * A mapping from enum type names (enum IDs) to + * dictionaries that map the `enum.values[i].value` + * to the `enum.values[i].value` + */ + enumValueNameValues: { [key: string]: { [key: string]: number } }; +} diff --git a/src/metadata/binary/BinaryMetadataEntityModel.ts b/src/metadata/binary/BinaryMetadataEntityModel.ts new file mode 100644 index 00000000..546b6584 --- /dev/null +++ b/src/metadata/binary/BinaryMetadataEntityModel.ts @@ -0,0 +1,70 @@ +import { defined } from "../../base/defined"; + +import { MetadataEntityModel } from "../MetadataEntityModel"; +import { MetadataValues } from "../MetadataValues"; +import { MetadataError } from "../MetadataError"; +import { PropertyTableModel } from "../PropertyTableModel"; + +/** + * Implementation of a `MetadataEntityModel` that is backed by binary + * data (specifically, by a `PropertyTableModel`) + * + * @internal + */ +export class BinaryMetadataEntityModel implements MetadataEntityModel { + private readonly _propertyTableModel: PropertyTableModel; + private readonly _entityIndex: number; + private readonly _semanticToPropertyId: { [key: string]: string }; + + constructor( + propertyTableModel: PropertyTableModel, + entityIndex: number, + semanticToPropertyId: { [key: string]: string } + ) { + this._propertyTableModel = propertyTableModel; + this._entityIndex = entityIndex; + this._semanticToPropertyId = semanticToPropertyId; + } + + /** {@inheritDoc MetadataEntityModel.getPropertyValue} */ + getPropertyValue(propertyId: string): any { + const propertyTableModel = this._propertyTableModel; + const classProperty = propertyTableModel.getClassProperty(propertyId); + if (!defined(classProperty)) { + const message = `The class does not define a property ${propertyId}`; + throw new MetadataError(message); + } + const propertyTableProperty = + propertyTableModel.getPropertyTableProperty(propertyId); + if (!defined(propertyTableProperty)) { + const message = `The property table does not define a property ${propertyId}`; + throw new MetadataError(message); + } + const propertyModel = propertyTableModel.getPropertyModel(propertyId); + if (!propertyModel) { + const message = + `The property table does not ` + + `define a property model for ${propertyId}`; + throw new MetadataError(message); + } + const value = propertyModel.getPropertyValue(this._entityIndex); + const offsetOverride = propertyTableProperty.offset; + const scaleOverride = propertyTableProperty.scale; + const processedValue = MetadataValues.processValue( + classProperty, + offsetOverride, + scaleOverride, + value + ); + return processedValue; + } + + /** {@inheritDoc MetadataEntityModel.getPropertyValueBySemantic} */ + getPropertyValueBySemantic(semantic: string): any { + const propertyId = this._semanticToPropertyId[semantic]; + if (!defined(propertyId)) { + return undefined; + } + return this.getPropertyValue(propertyId); + } +} diff --git a/src/metadata/binary/BinaryPropertyModels.ts b/src/metadata/binary/BinaryPropertyModels.ts new file mode 100644 index 00000000..3bc148c3 --- /dev/null +++ b/src/metadata/binary/BinaryPropertyModels.ts @@ -0,0 +1,297 @@ +import { defined } from "../../base/defined"; + +import { PropertyModel } from "../PropertyModel"; +import { MetadataError } from "../MetadataError"; + +import { BinaryPropertyTable } from "./BinaryPropertyTable"; +import { StringPropertyModel } from "./StringPropertyModel"; +import { BooleanPropertyModel } from "./BooleanPropertyModel"; +import { NumericPropertyModel } from "./NumericPropertyModel"; +import { NumericArrayPropertyModel } from "./NumericArrayPropertyModel"; +import { StringArrayPropertyModel } from "./StringArrayPropertyModel"; +import { BooleanArrayPropertyModel } from "./BooleanArrayPropertyModel"; +import { NumericBuffers } from "./NumericBuffers"; + +/** + * Methods related to `PropertyModel` instances that are created + * from binary data. + * + * @internal + */ +export class BinaryPropertyModels { + /** + * Creates a `PropertyModel` for the specified property in + * the given `BinaryPropertyTable`. + * + * This assumes that the input is structurally valid. + * + * This will determine the type of the property and access its + * associated data (i.e. the required buffer views data) from + * the given `BinaryPropertyTable`. For each type of property, + * this will return a matching implementation of the + * `PropertyModel` interface. + * + * @param binaryPropertyTable - The `BinaryPropertyTable` + * @param propertyId - The property ID + * @returns The `PropertyModel` + * @throws MetadataError If the input data is not structurally + * valid + */ + static createPropertyModel( + binaryPropertyTable: BinaryPropertyTable, + propertyId: string + ): PropertyModel { + // Implementation note: + // It would be nice to do some of the sanity checks upfront (e.g. + // checking that the string offsets have been defined properly + // when the type is 'STRING'). But in order to exploit the + // TypeScript definedness checks, and avoid the use of the + // non-null-assertion '!', some checks have to be done right + // before a certain value is used. It might be possible to + // find a more "elegant" solution here, but it's unlikely + // that the final, nested `if(isArray) { if (type===X) {}}` + // check could be avoided. + + // Obtain the `ClassProperty` + const metadataClass = binaryPropertyTable.metadataClass; + const classProperties = metadataClass.properties; + if (!classProperties) { + throw new MetadataError(`The class does not define any properties`); + } + const classProperty = classProperties[propertyId]; + if (!classProperty) { + throw new MetadataError( + `The class does not define property ${propertyId}` + ); + } + + // Obtain the `PropertyTableProperty` + const propertyTable = binaryPropertyTable.propertyTable; + const propertyTableProperties = propertyTable.properties; + if (!propertyTableProperties) { + throw new MetadataError( + `The property table does not define any properties` + ); + } + const propertyTableProperty = propertyTableProperties[propertyId]; + if (!propertyTableProperty) { + throw new MetadataError( + `The property table does not define property ${propertyId}` + ); + } + + // Obtain the required buffers from the binary data: + const binaryBufferData = binaryPropertyTable.binaryBufferData; + const bufferViewsData = binaryBufferData.bufferViewsData; + + // Obtain the `values` buffer view data + const valuesBufferViewIndex = propertyTableProperty.values; + const valuesBufferViewData = bufferViewsData[valuesBufferViewIndex]; + + // Obtain the `arrayOffsets` buffer view data + const arrayOffsetsBufferViewIndex = propertyTableProperty.arrayOffsets; + let arrayOffsetsBufferViewData = undefined; + if (defined(arrayOffsetsBufferViewIndex)) { + arrayOffsetsBufferViewData = bufferViewsData[arrayOffsetsBufferViewIndex]; + } + const arrayOffsetType = propertyTableProperty.arrayOffsetType ?? "UINT32"; + + // Obtain the `stringOffsets` buffer view data + const stringOffsetsBufferViewIndex = propertyTableProperty.stringOffsets; + let stringOffsetsBufferViewData = undefined; + if (defined(stringOffsetsBufferViewIndex)) { + stringOffsetsBufferViewData = + bufferViewsData[stringOffsetsBufferViewIndex]; + } + const stringOffsetType = propertyTableProperty.stringOffsetType ?? "UINT32"; + + // Determine the `enumValueType` of the property + const enumType = classProperty.enumType; + let enumValueType = undefined; + if (defined(enumType)) { + const binaryEnumInfo = binaryPropertyTable.binaryEnumInfo; + const enumValueTypes = binaryEnumInfo.enumValueTypes; + enumValueType = enumValueTypes[enumType] ?? "UINT16"; + } + + // Create the `PropertyModel` implementation that matches + // the type of the property + const type = classProperty.type; + const componentType = classProperty.componentType; + const count = classProperty.count; + const isArray = classProperty.array === true; + if (isArray) { + if (type === "STRING") { + if (!stringOffsetsBufferViewData) { + throw new MetadataError( + `The property ${propertyId} is an array of strings, ` + + `but no string offsets have been defined` + ); + } + + const propertyModel = new StringArrayPropertyModel( + valuesBufferViewData, + arrayOffsetsBufferViewData, + arrayOffsetType, + stringOffsetsBufferViewData, + stringOffsetType, + count + ); + return propertyModel; + } + if (type === "BOOLEAN") { + const propertyModel = new BooleanArrayPropertyModel( + valuesBufferViewData, + arrayOffsetsBufferViewData, + arrayOffsetType, + count + ); + return propertyModel; + } + if (type === "ENUM") { + if (!enumValueType) { + throw new MetadataError( + `The property ${propertyId} is an enum, ` + + `but no enum value type has been defined` + ); + } + + const propertyModel = new NumericArrayPropertyModel( + type, + valuesBufferViewData, + enumValueType, + arrayOffsetsBufferViewData, + arrayOffsetType, + count + ); + return propertyModel; + } + // The 'type' must be a numeric (array) type here + + if (!defined(componentType)) { + throw new MetadataError( + `The property ${propertyId} is a numeric array, ` + + `but no component type has been defined` + ); + } + + const propertyModel = new NumericArrayPropertyModel( + type, + valuesBufferViewData, + componentType, + arrayOffsetsBufferViewData, + arrayOffsetType, + count + ); + return propertyModel; + } + + // The property must be a non-array property here: + if (type === "STRING") { + if (!stringOffsetsBufferViewData) { + throw new MetadataError( + `The property ${propertyId} has the type 'STRING', ` + + `but no string offsets have been defined` + ); + } + + const propertyModel = new StringPropertyModel( + valuesBufferViewData, + stringOffsetsBufferViewData, + stringOffsetType + ); + return propertyModel; + } + if (type === "BOOLEAN") { + const propertyModel = new BooleanPropertyModel(valuesBufferViewData); + return propertyModel; + } + if (type === "ENUM") { + if (!enumValueType) { + throw new MetadataError( + `The property ${propertyId} is an enum, ` + + `but no enum value type has been defined` + ); + } + + const propertyModel = new NumericPropertyModel( + type, + valuesBufferViewData, + enumValueType + ); + return propertyModel; + } + + // The property must be a (non-array) numeric property here + + if (!defined(componentType)) { + throw new MetadataError( + `The property ${propertyId} is numeric, ` + + `but no component type has been defined` + ); + } + + const propertyModel = new NumericPropertyModel( + type, + valuesBufferViewData, + componentType + ); + return propertyModel; + } + + /** + * Returns the 'slice' information that is given by an offsets + * buffer or a fixed number. + * + * This returns `{ offset, length }` for the `arrayOffsets` or + * `stringOffsets` of a property, for a given index. + * + * When the given `count` is defined, then the result will + * just be `{ index * count, count }`. + * + * Otherwise, the result will be `{ offset, length }`, where `offset` + * is the offset that is read from the given buffer at index `index`, + * and `length` is `offset[index+1] - offset[index]`. + * + * @param index - The index + * @param offsetsBuffer - The offsets + * @param offsetType - The `componentType` for the offsets + * @param count - The count + * @returns The slice information + * @throws MetadataError If both the `count` and the `offsetsBuffer` + * are `undefined`. + */ + static computeSlice( + index: number, + offsetsBuffer: Buffer | undefined, + offsetType: string, + count: number | undefined + ): { offset: number; length: number } { + if (defined(count)) { + return { + offset: index * count, + length: count, + }; + } + if (!offsetsBuffer) { + throw new MetadataError( + `Neither the 'count' nor the offsets buffer have been defined` + ); + } + const offset = NumericBuffers.getNumericFromBuffer( + offsetsBuffer, + index, + offsetType + ); + const nextOffset = NumericBuffers.getNumericFromBuffer( + offsetsBuffer, + index + 1, + offsetType + ); + const length = nextOffset - offset; + return { + offset: offset, + length: length, + }; + } +} diff --git a/src/metadata/binary/BinaryPropertyTable.ts b/src/metadata/binary/BinaryPropertyTable.ts new file mode 100644 index 00000000..5a536e93 --- /dev/null +++ b/src/metadata/binary/BinaryPropertyTable.ts @@ -0,0 +1,53 @@ +import { BinaryBufferData } from "../../binary/BinaryBufferData"; +import { BinaryBufferStructure } from "../../binary/BinaryBufferStructure"; + +import { BinaryEnumInfo } from "./BinaryEnumInfo"; + +import { MetadataClass } from "../../structure/Metadata/MetadataClass"; +import { PropertyTable } from "../../structure/PropertyTable"; + +/** + * A basic structure summarizing the (raw) elements of a binary + * property table. + * + * It contains information about the structure of the table itself, + * consisting of the `PropertyTable` and the `MetadataClass`, as + * well as the binary data, stored in `Buffer` objects. + * + * Instances of this interface serve as the input for the + * construction of a `PropertyTableModel`. + * + * @internal + */ +export interface BinaryPropertyTable { + /** + * The actual `PropertyTable` object + */ + propertyTable: PropertyTable; + + /** + * The `MetadataClass` that corresponds to the `propertyTable.class` + */ + metadataClass: MetadataClass; + + /** + * Information about the binary representation of `MetadataEnum` + * values + */ + binaryEnumInfo: BinaryEnumInfo; + + /** + * The binary buffer structure, containing the `BufferObject` and + * `BufferView` objects. The `PropertyTableProperty` objects + * from the `PropertyTable` contain indices (e.g. the `values` + * index) that refer to this structure. + */ + binaryBufferStructure: BinaryBufferStructure; + + /** + * The binary buffer data. These are the actual buffers with + * the binary data that correspond to the elements of the + * `BinaryBufferStructure`. + */ + binaryBufferData: BinaryBufferData; +} diff --git a/src/metadata/binary/BinaryPropertyTableModel.ts b/src/metadata/binary/BinaryPropertyTableModel.ts new file mode 100644 index 00000000..92e884d5 --- /dev/null +++ b/src/metadata/binary/BinaryPropertyTableModel.ts @@ -0,0 +1,108 @@ +import { BinaryPropertyModels } from "./BinaryPropertyModels"; +import { BinaryPropertyTable } from "./BinaryPropertyTable"; +import { BinaryMetadataEntityModel } from "./BinaryMetadataEntityModel"; + +import { MetadataEntityModel } from "../MetadataEntityModel"; +import { MetadataEntityModels } from "../MetadataEntityModels"; +import { MetadataError } from "../MetadataError"; +import { PropertyModel } from "../PropertyModel"; +import { PropertyTableModel } from "../PropertyTableModel"; + +import { ClassProperty } from "../../structure/Metadata/ClassProperty"; +import { PropertyTableProperty } from "../../structure/PropertyTableProperty"; + +/** + * Implementation of the `PropertyTableModel` interface that is backed + * by binary data. + * + * @internal + */ +export class BinaryPropertyTableModel implements PropertyTableModel { + /** + * The structure containing the raw data of the binary + * property table + */ + private readonly _binaryPropertyTable: BinaryPropertyTable; + + /** + * A mapping from property IDs to the `PropertyModel` + * instances that provide the property values. These + * are the "columns" of the table + */ + private readonly _propertyIdToModel: { [key: string]: PropertyModel } = {}; + + /** + * A mapping from 'semantic' strings to the 'propertyId' + * strings of the properties that have the respective + * semantic + */ + private readonly _semanticToPropertyId: { [key: string]: string }; + + constructor(binaryPropertyTable: BinaryPropertyTable) { + this._binaryPropertyTable = binaryPropertyTable; + + // Initialize the `PropertyModel` instances for + // the property table properties + const propertyTable = this._binaryPropertyTable.propertyTable; + const propertyTableProperties = propertyTable.properties; + if (propertyTableProperties) { + for (const propertyId of Object.keys(propertyTableProperties)) { + const propertyModel = BinaryPropertyModels.createPropertyModel( + this._binaryPropertyTable, + propertyId + ); + this._propertyIdToModel[propertyId] = propertyModel; + } + } + + const metadataClass = binaryPropertyTable.metadataClass; + this._semanticToPropertyId = + MetadataEntityModels.computeSemanticToPropertyIdMapping(metadataClass); + } + + /** {@inheritDoc PropertyTableModel.getMetadataEntityModel} */ + getMetadataEntityModel(index: number): MetadataEntityModel { + const propertyTable = this._binaryPropertyTable.propertyTable; + const count = propertyTable.count; + if (index < 0 || index >= count) { + const message = `The index must be in [0,${count}), but is ${index}`; + throw new MetadataError(message); + } + const semanticToPropertyId = this._semanticToPropertyId; + const metadataEntityModel = new BinaryMetadataEntityModel( + this, + index, + semanticToPropertyId + ); + return metadataEntityModel; + } + + /** {@inheritDoc PropertyTableModel.getPropertyModel} */ + getPropertyModel(propertyId: string): PropertyModel | undefined { + return this._propertyIdToModel[propertyId]; + } + + /** {@inheritDoc PropertyTableModel.getClassProperty} */ + getClassProperty(propertyId: string): ClassProperty | undefined { + const binaryPropertyTable = this._binaryPropertyTable; + const metadataClass = binaryPropertyTable.metadataClass; + const classProperties = metadataClass.properties; + if (!classProperties) { + return undefined; + } + return classProperties[propertyId]; + } + + /** {@inheritDoc PropertyTableModel.getPropertyTableProperty} */ + getPropertyTableProperty( + propertyId: string + ): PropertyTableProperty | undefined { + const binaryPropertyTable = this._binaryPropertyTable; + const propertyTable = binaryPropertyTable.propertyTable; + const propertyTableProperties = propertyTable.properties; + if (!propertyTableProperties) { + return undefined; + } + return propertyTableProperties[propertyId]; + } +} diff --git a/src/metadata/binary/BinaryPropertyTables.ts b/src/metadata/binary/BinaryPropertyTables.ts new file mode 100644 index 00000000..f4cc90db --- /dev/null +++ b/src/metadata/binary/BinaryPropertyTables.ts @@ -0,0 +1,551 @@ +import { defined } from "../../base/defined"; +import { defaultValue } from "../../base/defaultValue"; + +import { BinaryPropertyTable } from "./BinaryPropertyTable"; + +import { BinaryBufferData } from "../../binary/BinaryBufferData"; +import { BinaryBuffers } from "../../binary/BinaryBuffers"; + +import { MetadataUtilities } from "../MetadataUtilities"; +import { MetadataError } from "../MetadataError"; + +import { PropertyTable } from "../../structure/PropertyTable"; +import { PropertyTableProperty } from "../../structure/PropertyTableProperty"; + +import { Schema } from "../../structure/Metadata/Schema"; +import { MetadataClass } from "../../structure/Metadata/MetadataClass"; +import { ClassProperty } from "../../structure/Metadata/ClassProperty"; +import { EnumValue } from "../../structure/Metadata/EnumValue"; +import { MetadataEnum } from "../../structure/Metadata/MetadataEnum"; + +/** + * Methods to create `BinaryPropertyTable` instances from individual + * properties and their associated data. + * + * Right now, the methods in this class are mainly intended for + * generating test data. They can be used to create property + * tables based on single properties and their associated values. + * + * When a method expects such `values` to be passed in, then the + * structure is assumed to be a "JSON-representation" of the data + * that corresponds to one column of the table: + * + * - scalar properties are given as an array of values + * - properties of structured types (VECn or MATn) are given + * as an array of arrays + * - array properties are given as an array of the aforementioned + * inputs. + * + * For example: + * - a string property will be ["row0", "row1"] + * - a string array property will be + * [ ["row0-col0", "row0-col1"], + * ["row1-col0", "row1-col1"] ] + * - a VEC2 property will be [ [0,0], [1,1] ] + * - a VEC2 array property will be + * [ [ [0,0], [0,1], [0,2] ], + * [ [1,0], [1,1], [1,2] ] ] + * + * + * TODO Some methods in this class are creating plain JSON + * structures programmatically (e.g. a Schema that contains + * a single class with a single property). Some of these + * methods may be omitted in the future, if these structures + * have to be created manually for unit tests anyhow. + * + * @internal + */ +export class BinaryPropertyTables { + /** + * Creates a (dummy) `MetadataClass` that only contains the given property + * + * @param propertyName - The property name + * @param classProperty - The `ClassProperty` + * @returns The `MetadataClass` + */ + private static createMetadataClassFromClassProperty( + propertyName: string, + classProperty: ClassProperty + ): MetadataClass { + const classProperties: { [key: string]: ClassProperty } = {}; + classProperties[propertyName] = classProperty; + + const metadataClass: MetadataClass = { + name: "testMetadataClass", + properties: classProperties, + }; + return metadataClass; + } + + /** + * Creates a (dummy) `Schema` that only contains the given class + * + * @param className - The class name + * @param metadataClass - The `MetadataClass` + * @returns The metadata `Schema` + */ + private static createSchemaFromMetadataClass( + className: string, + metadataClass: MetadataClass + ): Schema { + const classes: { [key: string]: MetadataClass } = {}; + classes[className] = metadataClass; + const metadataSchema: Schema = { + id: "testMetadataMetadataSchemaId", + name: "testMetadataSchema", + classes: classes, + }; + return metadataSchema; + } + + /** + * Creates a `PropertyTable` from the given input. + * + * This creates a dummy `PropertyTable` with a single property, + * which is used for the other methods in this class that can + * create `BinaryPropertyTable` or `PropertyTableModel` objects + * from single properties. + * + * @param className - The class name + * @param propertyName - The property name + * @param count - The count (number of rows) of the table + * @param propertyTableProperty - The `PropertyTableProperty` + * @returns The `PropertyTable` + */ + private static createPropertyTableFromProperty( + className: string, + propertyName: string, + count: number, + propertyTableProperty: PropertyTableProperty + ): PropertyTable { + const propertyTableProperties: { [key: string]: PropertyTableProperty } = + {}; + propertyTableProperties[propertyName] = propertyTableProperty; + const propertyTable: PropertyTable = { + name: "testPropertyTable", + class: className, + count: count, + properties: propertyTableProperties, + }; + return propertyTable; + } + + /** + * Creates a `PropertyTableProperty` from the given inputs. + * + * This receives the `ClassProperty` itself and the associated values, + * and generates the `PropertyTableProperty` and its associated + * binary data. The binary data will include the buffer views for the + * `values`, `arrayOffsets`, and `stringOffsets`, which will be + * added to the given `bufferViewsData` array. + * + * @param classProperty - The `ClassProperty` + * @param schema - The metadata `Schema`. This is only used internally + * for looking up information about (binary) enum values, if the + * given property is an ENUM property. + * @param values - The values for the property + * @param arrayOffsetType - The `arrayOffsetType` for the property + * (only used when the property is a variable-length array, + * defaulting to `UINT32`) + * @param stringOffsetType - The `stringOffsetType` for the property + * (only used when the property is a STRING property, + * defaulting to `UINT32`)) + * @param bufferViewsData - The array that will receive the buffer + * view buffers + * @returns The `PropertyTableProperty` + */ + private static createPropertyTableProperty( + classProperty: ClassProperty, + schema: Schema, + values: any, + arrayOffsetType: string | undefined, + stringOffsetType: string | undefined, + bufferViewsData: Buffer[] + ): PropertyTableProperty { + const valuesBuffer = BinaryPropertyTables.createValuesBuffer( + classProperty, + schema, + values + ); + const valuesBufferView = bufferViewsData.length; + bufferViewsData.push(valuesBuffer); + + const propertyTableProperty: PropertyTableProperty = { + values: valuesBufferView, + offset: undefined, + scale: undefined, + max: undefined, + min: undefined, + }; + + const isVariableLengthArray = + classProperty.array && !defined(classProperty.count); + if (isVariableLengthArray) { + const arrayOffsetBuffer = BinaryPropertyTables.createArrayOffsetBuffer( + values, + arrayOffsetType + ); + const arrayOffsetBufferView = bufferViewsData.length; + bufferViewsData.push(arrayOffsetBuffer); + propertyTableProperty.arrayOffsets = arrayOffsetBufferView; + } + + if (classProperty.type === "STRING") { + const stringOffsetBuffer = BinaryPropertyTables.createStringOffsetBuffer( + values, + stringOffsetType + ); + const stringOffsetBufferView = bufferViewsData.length; + bufferViewsData.push(stringOffsetBuffer); + propertyTableProperty.stringOffsets = stringOffsetBufferView; + } + + return propertyTableProperty; + } + + /** + * Creates a `Schema` from the given input. + * + * This function is mainly intended for generating test data. + * It generates a "dummy" schema that only contains a class + * with the given property, and the given enum. + * + * @param propertyName - The property name + * @param classProperty - The `ClassProperty` + * @param metadataEnum - The optional `MetadataEnum` when the + * property is an enum property + * @returns The schema + */ + static createSchemaFromClassProperty( + propertyName: string, + classProperty: ClassProperty, + metadataEnum: MetadataEnum | undefined + ): Schema { + const className = "testMetadataClass"; + const metadataClass = + BinaryPropertyTables.createMetadataClassFromClassProperty( + propertyName, + classProperty + ); + const schema = BinaryPropertyTables.createSchemaFromMetadataClass( + className, + metadataClass + ); + if (metadataEnum) { + const enums: { [key: string]: MetadataEnum } = {}; + enums["testMetadataEnum"] = metadataEnum; + schema.enums = enums; + } + return schema; + } + + /** + * Creates a `BinaryPropertyTable` from the given input. + * + * This function is mainly intended for generating test data: + * It receives a predefined `ClassProperty` and associated + * values, and generates a ("dummy") class, schema, and + * property table for exactly this single property, together + * with the associated binary data. + * + * @param propertyName - The property name + * @param classProperty - The `ClassProperty` + * @param values - The property values + * @param arrayOffsetType - The `arrayOffsetType`, only used + * for variable-length array properties, defaulting to `UINT32` + * @param stringOffsetType - The `stringOffsetType`, only used + * for STRING properties, defaulting to `UINT32` + * @param metadataEnum - The optional `MetadataEnum` that defines + * the (numeric) values that are written into the binary data, + * based on the (string) values from the `values` parameter + * @returns The `BinaryPropertyTable` + */ + static createBinaryPropertyTableFromProperty( + propertyName: string, + classProperty: ClassProperty, + values: any, + arrayOffsetType: string | undefined, + stringOffsetType: string | undefined, + metadataEnum: MetadataEnum | undefined + ): BinaryPropertyTable { + const schema = BinaryPropertyTables.createSchemaFromClassProperty( + propertyName, + classProperty, + metadataEnum + ); + const className = "testMetadataClass"; + const binaryPropertyTable = BinaryPropertyTables.createBinaryPropertyTable( + schema, + className, + propertyName, + values, + arrayOffsetType, + stringOffsetType + ); + return binaryPropertyTable; + } + + /** + * Creates a `BinaryPropertyTable` from the given input. + * + * This function is mainly intended for generating test data. + * It receives information about the property (via the `className` + * and the `propertyName`, referring to the given schema), and the + * values for the property, and generates a property table for + * exactly this single property, together with the associated + * binary data. + * + * @param schema - The `Schema` + * @param className - The class name + * @param propertyName - The property name + * @param values - The property values + * @param arrayOffsetType - The `arrayOffsetType`, only used + * for variable-length array properties, defaulting to `UINT32` + * @param stringOffsetType - The `stringOffsetType`, only used + * for STRING properties, defaulting to `UINT32` + * @returns The `BinaryPropertyTable` + * @throws MetadataError If the input is not structurally valid + */ + static createBinaryPropertyTable( + schema: Schema, + className: string, + propertyName: string, + values: any, + arrayOffsetType: string | undefined, + stringOffsetType: string | undefined + ) { + const classes = schema.classes; + if (!classes) { + throw new MetadataError(`The schema does not define any classes`); + } + const metadataClass = classes[className]; + if (!metadataClass) { + throw new MetadataError( + `The schema does not define the class ${className}` + ); + } + const classProperties = metadataClass.properties; + if (!classProperties) { + throw new MetadataError( + `The schema class ${className} does not define any properties` + ); + } + const classProperty = classProperties[propertyName]; + if (!classProperty) { + throw new MetadataError( + `The schema class ${className} does not define property ${propertyName}` + ); + } + + const createdBufferViewsData: Buffer[] = []; + const propertyTableProperty = + BinaryPropertyTables.createPropertyTableProperty( + classProperty, + schema, + values, + arrayOffsetType, + stringOffsetType, + createdBufferViewsData + ); + const count = values.length; + const propertyTable = BinaryPropertyTables.createPropertyTableFromProperty( + className, + propertyName, + count, + propertyTableProperty + ); + + const binaryBufferData: BinaryBufferData = { + bufferViewsData: [], + buffersData: [], + }; + + const binaryBufferStructure = BinaryBuffers.createBinaryBufferStructure( + binaryBufferData, + createdBufferViewsData + ); + + const binaryEnumInfo = MetadataUtilities.computeBinaryEnumInfo(schema); + + const binaryPropertyTable: BinaryPropertyTable = { + metadataClass: metadataClass, + propertyTable: propertyTable, + binaryEnumInfo: binaryEnumInfo, + binaryBufferStructure: binaryBufferStructure, + binaryBufferData: binaryBufferData, + }; + return binaryPropertyTable; + } + + // Parts of the following are ""ported""" from the CesiumJS 'MetadataTester' class at + // https://github.com/CesiumGS/cesium/blob/b4097de3b8d3d007ed38b3b6fb83717ab6de43ba/Specs/MetadataTester.js + // A rewrite would have been taken less time and resulted in cleaner code, + // but it should do what it is supposed to do for now... + + private static toBuffer(arrayBuffer: ArrayBuffer): Buffer { + const buffer = Buffer.from(arrayBuffer); + return buffer; + } + + private static createBuffer( + values: any, + componentType: string | undefined + ): Buffer { + const buffer = BinaryPropertyTables.toBuffer( + BinaryPropertyTables.createBufferInternal(values, componentType) + ); + return buffer; + } + + private static createBufferInternal( + values: any, + componentType: string | undefined + ): ArrayBuffer { + const flatValues = BinaryPropertyTables.flattenFully(values); + switch (componentType) { + case "INT8": + return new Int8Array(flatValues).buffer; + case "UINT8": + return new Uint8Array(flatValues).buffer; + case "INT16": + return new Int16Array(flatValues).buffer; + case "UINT16": + return new Uint16Array(flatValues).buffer; + case "INT32": + return new Int32Array(flatValues).buffer; + case "UINT32": + return new Uint32Array(flatValues).buffer; + case "INT64": + return new BigInt64Array(flatValues.map((v: any) => BigInt(v))).buffer; + case "UINT64": + return new BigUint64Array(flatValues.map((v: any) => BigInt(v))).buffer; + case "FLOAT32": + return new Float32Array(flatValues).buffer; + case "FLOAT64": + return new Float64Array(flatValues).buffer; + } + throw new MetadataError(`${componentType} is not a valid component type`); + } + + private static createStringBuffer(values: any): Buffer { + return BinaryPropertyTables.toBuffer( + BinaryPropertyTables.createStringBufferInternal(values) + ); + } + + private static createStringBufferInternal(inputValues: any): Uint8Array { + const values = BinaryPropertyTables.flattenFully(inputValues); + const encoder = new TextEncoder(); + return encoder.encode(values.join("")); + } + + private static createBooleanBuffer(values: any): Buffer { + return BinaryPropertyTables.toBuffer( + BinaryPropertyTables.createBooleanBufferInternal(values) + ); + } + + private static createBooleanBufferInternal(inputValues: any): Uint8Array { + const values = BinaryPropertyTables.flattenFully(inputValues); + const length = Math.ceil(values.length / 8); + const typedArray = new Uint8Array(length); // Initialized as 0's + for (let i = 0; i < values.length; ++i) { + const byteIndex = i >> 3; + const bitIndex = i % 8; + if (values[i]) { + typedArray[byteIndex] |= 1 << bitIndex; + } + } + return typedArray; + } + + private static flatten(values: any): any { + return [...values]; + } + + private static flattenFully(values: any): any { + let result = values; + if (Array.isArray(result)) { + result = []; + for (let i = 0; i < values.length; i++) { + result = result.concat(BinaryPropertyTables.flattenFully(values[i])); + } + } + return result; + } + + private static createValuesBuffer( + classProperty: ClassProperty, + schema: Schema, + values: any + ): Buffer { + const type = classProperty.type; + let componentType = classProperty.componentType; + const enumType = classProperty.enumType; + let flattenedValues = BinaryPropertyTables.flatten(values); + + if (type === "STRING") { + return BinaryPropertyTables.createStringBuffer(flattenedValues); + } + + if (type === "BOOLEAN") { + return BinaryPropertyTables.createBooleanBuffer(flattenedValues); + } + + if (defined(enumType)) { + flattenedValues = BinaryPropertyTables.flattenFully(flattenedValues); + const length = flattenedValues.length; + const metadataEnums = schema.enums; + if (!metadataEnums) { + throw new MetadataError(`The schema does not define any enums`); + } + const metadataEnum = metadataEnums[enumType]; + if (!metadataEnum) { + throw new MetadataError(`The schema does not define enum ${enumType}`); + } + const valueNames = metadataEnum.values.map((v: EnumValue) => v.name); + componentType = defaultValue(metadataEnum.valueType, "UINT16"); + for (let i = 0; i < length; ++i) { + const valueName = flattenedValues[i]; + const index = valueNames.indexOf(valueName); + flattenedValues[i] = index; + } + } + + return BinaryPropertyTables.createBuffer(flattenedValues, componentType); + } + + private static createStringOffsetBuffer( + values: any, + offsetType: string | undefined + ) { + const encoder = new TextEncoder(); + const strings = BinaryPropertyTables.flattenFully(values); + const length = strings.length; + const offsets = new Array(length + 1); + let offset = 0; + for (let i = 0; i < length; ++i) { + offsets[i] = offset; + offset += encoder.encode(strings[i]).length; + } + offsets[length] = offset; + offsetType = defaultValue(offsetType, "UINT32"); + return BinaryPropertyTables.createBuffer(offsets, offsetType); + } + + private static createArrayOffsetBuffer( + values: any, + offsetType: string | undefined + ) { + const length = values.length; + const offsets = new Array(length + 1); + let offset = 0; + for (let i = 0; i < length; ++i) { + offsets[i] = offset; + offset += values[i].length; + } + offsets[length] = offset; + offsetType = defaultValue(offsetType, "UINT32"); + return BinaryPropertyTables.createBuffer(offsets, offsetType); + } +} diff --git a/src/metadata/binary/BooleanArrayPropertyModel.ts b/src/metadata/binary/BooleanArrayPropertyModel.ts new file mode 100644 index 00000000..014934fb --- /dev/null +++ b/src/metadata/binary/BooleanArrayPropertyModel.ts @@ -0,0 +1,56 @@ +import { PropertyModel } from "../PropertyModel"; + +import { BinaryPropertyModels } from "./BinaryPropertyModels"; +import { BooleanPropertyModel } from "./BooleanPropertyModel"; + +/** + * Implementation of a `PropertyModel` for boolean arrays + * + * @internal + */ +export class BooleanArrayPropertyModel implements PropertyModel { + private readonly _valuesBuffer: Buffer; + private readonly _arrayOffsetsBuffer: Buffer | undefined; + private readonly _arrayOffsetType: string; + private readonly _count: number | undefined; + + constructor( + valuesBuffer: Buffer, + arrayOffsetsBuffer: Buffer | undefined, + arrayOffsetType: string, + count: number | undefined + ) { + this._valuesBuffer = valuesBuffer; + this._arrayOffsetsBuffer = arrayOffsetsBuffer; + this._arrayOffsetType = arrayOffsetType; + this._count = count; + } + + /** {@inheritDoc PropertyModel.getPropertyValue} */ + getPropertyValue(index: number): any { + const valuesBuffer = this._valuesBuffer; + const arrayOffsetsBuffer = this._arrayOffsetsBuffer; + const arrayOffsetType = this._arrayOffsetType; + const count = this._count; + + const arraySlice = BinaryPropertyModels.computeSlice( + index, + arrayOffsetsBuffer, + arrayOffsetType, + count + ); + const arrayOffset = arraySlice.offset; + const arrayLength = arraySlice.length; + + const result = new Array(arrayLength); + for (let i = 0; i < arrayLength; i++) { + const n = arrayOffset + i; + const element = BooleanPropertyModel.getBooleanFromBuffer( + valuesBuffer, + n + ); + result[i] = element; + } + return result; + } +} diff --git a/src/metadata/binary/BooleanPropertyModel.ts b/src/metadata/binary/BooleanPropertyModel.ts new file mode 100644 index 00000000..daca8b6a --- /dev/null +++ b/src/metadata/binary/BooleanPropertyModel.ts @@ -0,0 +1,39 @@ +import { PropertyModel } from "../PropertyModel"; + +import { NumericBuffers } from "./NumericBuffers"; + +/** + * Implementation of a `PropertyModel` for booleans + * + * @internal + */ +export class BooleanPropertyModel implements PropertyModel { + private readonly _valuesBuffer: Buffer; + + constructor(valuesBuffer: Buffer) { + this._valuesBuffer = valuesBuffer; + } + + /** {@inheritDoc PropertyModel.getPropertyValue} */ + getPropertyValue(index: number): any { + const valuesBuffer = this._valuesBuffer; + const result = BooleanPropertyModel.getBooleanFromBuffer( + valuesBuffer, + index + ); + return result; + } + + static getBooleanFromBuffer(buffer: Buffer, index: number): boolean { + const byteIndex = Math.floor(index / 8); + const bitIndex = index % 8; + const byte = NumericBuffers.getNumericFromBuffer( + buffer, + byteIndex, + "UINT8" + ); + const bit = 1 << bitIndex; + const result = (byte & bit) !== 0; + return result; + } +} diff --git a/src/metadata/binary/NumericArrayPropertyModel.ts b/src/metadata/binary/NumericArrayPropertyModel.ts new file mode 100644 index 00000000..e9f2e047 --- /dev/null +++ b/src/metadata/binary/NumericArrayPropertyModel.ts @@ -0,0 +1,82 @@ +import { PropertyModel } from "../PropertyModel"; +import { MetadataTypes } from "../MetadataTypes"; + +import { NumericBuffers } from "./NumericBuffers"; +import { BinaryPropertyModels } from "./BinaryPropertyModels"; + +/** + * Implementation of a `PropertyModel` for numeric array types. + * + * This includes all types that have numeric component types, + * i.e. the `SCALAR`, `VECn` and `MATn` types, and the + * (binary, and therefore numeric) representation of `ENUM`. + * + * @internal + */ +export class NumericArrayPropertyModel implements PropertyModel { + private readonly _type: string; + private readonly _valuesBuffer: Buffer; + private readonly _componentType: string; + private readonly _arrayOffsetsBuffer: Buffer | undefined; + private readonly _arrayOffsetType: string; + private readonly _count: number | undefined; + + constructor( + type: string, + valuesBuffer: Buffer, + componentType: string, + arrayOffsetsBuffer: Buffer | undefined, + arrayOffsetType: string, + count: number | undefined + ) { + this._type = type; + this._valuesBuffer = valuesBuffer; + this._componentType = componentType; + this._arrayOffsetsBuffer = arrayOffsetsBuffer; + this._arrayOffsetType = arrayOffsetType; + this._count = count; + } + + /** {@inheritDoc PropertyModel.getPropertyValue} */ + getPropertyValue(index: number): any { + const type = this._type; + const valuesBuffer = this._valuesBuffer; + const componentType = this._componentType; + const arrayOffsetsBuffer = this._arrayOffsetsBuffer; + const arrayOffsetType = this._arrayOffsetType; + const count = this._count; + const componentCount = MetadataTypes.componentCountForType(type); + + const arraySlice = BinaryPropertyModels.computeSlice( + index, + arrayOffsetsBuffer, + arrayOffsetType, + count + ); + const arrayOffset = arraySlice.offset; + const arrayLength = arraySlice.length; + + const result = new Array(arrayLength); + for (let i = 0; i < arrayLength; i++) { + const n = arrayOffset + i; + + let element = undefined; + if (type === "SCALAR" || type === "ENUM") { + element = NumericBuffers.getNumericFromBuffer( + valuesBuffer, + n, + componentType + ); + } else { + element = NumericBuffers.getNumericArrayFromBuffer( + valuesBuffer, + n, + componentCount, + componentType + ); + } + result[i] = element; + } + return result; + } +} diff --git a/src/metadata/binary/NumericBuffers.ts b/src/metadata/binary/NumericBuffers.ts new file mode 100644 index 00000000..53eb73f4 --- /dev/null +++ b/src/metadata/binary/NumericBuffers.ts @@ -0,0 +1,151 @@ +import { ArrayBuffers } from "./ArrayBuffers"; + +import { MetadataComponentTypes } from "../MetadataComponentTypes"; +import { MetadataError } from "../MetadataError"; + +/** + * Methods for extracting `number`- or `bigint` values or arrays thereof + * from `Buffer` objects + * + * @internal + */ +export class NumericBuffers { + /** + * Obtains a single number or bigint from the given buffer, + * at the given index, based on the given component type. + * + * @param buffer - The buffer + * @param index - The index + * @param componentType - The component type + * @returns The number or bigint + * @throws MetadataError If the given `componentType` is not valid + */ + static getNumericFromBuffer( + buffer: Buffer, + index: number, + componentType: string + ): any { + const byteSize = + MetadataComponentTypes.byteSizeForComponentType(componentType); + const byteOffset = index * byteSize; + switch (componentType) { + case "INT8": + return buffer.readInt8(byteOffset); + case "UINT8": + return buffer.readUint8(byteOffset); + case "INT16": + return buffer.readInt16LE(byteOffset); + case "UINT16": + return buffer.readUInt16LE(byteOffset); + case "INT32": + return buffer.readInt32LE(byteOffset); + case "UINT32": + return buffer.readUInt32LE(byteOffset); + case "INT64": + return buffer.readBigInt64LE(byteOffset); + case "UINT64": + return buffer.readBigUInt64LE(byteOffset); + case "FLOAT32": + return buffer.readFloatLE(byteOffset); + case "FLOAT64": + return buffer.readDoubleLE(byteOffset); + } + throw new MetadataError(`Unknown component type: ${componentType}`); + } + + /** + * Obtains an array of number or bigint values from the given buffer, + * starting at the given index, based on the given component type. + * + * @param buffer - The buffer + * @param index - The index + * @param arrayLength - The length of the array, in number of elements + * @param componentType - The component type + * @returns The number or bigint array + * @throws MetadataError If the given `componentType` is not valid + */ + static getNumericArrayFromBuffer( + buffer: Buffer, + index: number, + arrayLength: number, + componentType: string + ): any { + const typedArray = NumericBuffers.getTypedArrayFromBuffer( + buffer, + index, + arrayLength, + componentType + ); + const array = [...typedArray]; + return array; + } + + /** + * Obtains a typed array of number or bigint values from the given buffer, + * starting at the given index, based on the given component type. + * + * @param buffer - The buffer + * @param index - The index + * @param arrayLength - The length of the array, in number of elements + * @param componentType - The component type + * @returns The number or bigint typed array + * @throws MetadataError If the given `componentType` is not valid + */ + private static getTypedArrayFromBuffer( + buffer: Buffer, + index: number, + arrayLength: number, + componentType: string + ) { + const componentSize = + MetadataComponentTypes.byteSizeForComponentType(componentType); + const elementSize = arrayLength * componentSize; + const byteOffset = index * elementSize; + const arrayBuffer = ArrayBuffers.fromBuffer(buffer); + switch (componentType) { + case "INT8": + return new Int8Array(arrayBuffer, byteOffset, arrayLength); + case "UINT8": + return new Uint8Array(arrayBuffer, byteOffset, arrayLength); + case "INT16": + return new Int16Array(arrayBuffer, byteOffset, arrayLength); + case "UINT16": + return new Uint16Array(arrayBuffer, byteOffset, arrayLength); + case "INT32": + return new Int32Array(arrayBuffer, byteOffset, arrayLength); + case "UINT32": + return new Uint32Array(arrayBuffer, byteOffset, arrayLength); + case "INT64": + return new BigInt64Array(arrayBuffer, byteOffset, arrayLength); + case "UINT64": + return new BigUint64Array(arrayBuffer, byteOffset, arrayLength); + case "FLOAT32": + return new Float32Array(arrayBuffer, byteOffset, arrayLength); + case "FLOAT64": + return new Float64Array(arrayBuffer, byteOffset, arrayLength); + } + throw new MetadataError(`Unknown component type: ${componentType}`); + } + + /** + * Returns an array that contains the `number`- or `bigint` values + * that are stored in the given buffer + * + * @param buffer - The buffer + * @param componentType - The component type + * @returns The number or bigint array + * @throws MetadataError If the given `componentType` is not valid + */ + static getNumericBufferAsArray(buffer: Buffer, componentType: string): any { + const size = MetadataComponentTypes.byteSizeForComponentType(componentType); + const arrayLength = buffer.length / size; + const typedArray = NumericBuffers.getTypedArrayFromBuffer( + buffer, + 0, + arrayLength, + componentType + ); + const array = [...typedArray]; + return array; + } +} diff --git a/src/metadata/binary/NumericPropertyModel.ts b/src/metadata/binary/NumericPropertyModel.ts new file mode 100644 index 00000000..81cae276 --- /dev/null +++ b/src/metadata/binary/NumericPropertyModel.ts @@ -0,0 +1,47 @@ +import { NumericBuffers } from "./NumericBuffers"; + +import { PropertyModel } from "../PropertyModel"; +import { MetadataTypes } from "../MetadataTypes"; + +/** + * Implementation of a `PropertyModel` for numeric types. + * + * This includes all types that have numeric component types, + * i.e. the `SCALAR`, `VECn` and `MATn` types, and the + * (binary, and therefore numeric) representation of `ENUM`. + * + * @internal + */ +export class NumericPropertyModel implements PropertyModel { + private readonly _type: string; + private readonly _valuesBuffer: Buffer; + private readonly _componentType: string; + + constructor(type: string, valuesBuffer: Buffer, componentType: string) { + this._type = type; + this._valuesBuffer = valuesBuffer; + this._componentType = componentType; + } + + /** {@inheritDoc PropertyModel.getPropertyValue} */ + getPropertyValue(index: number): any { + const valuesBuffer = this._valuesBuffer; + const componentType = this._componentType; + const type = this._type; + + if (type === "SCALAR" || type === "ENUM") { + return NumericBuffers.getNumericFromBuffer( + valuesBuffer, + index, + componentType + ); + } + const componentCount = MetadataTypes.componentCountForType(type); + return NumericBuffers.getNumericArrayFromBuffer( + valuesBuffer, + index, + componentCount, + componentType + ); + } +} diff --git a/src/metadata/binary/StringArrayPropertyModel.ts b/src/metadata/binary/StringArrayPropertyModel.ts new file mode 100644 index 00000000..56488dae --- /dev/null +++ b/src/metadata/binary/StringArrayPropertyModel.ts @@ -0,0 +1,81 @@ +import { PropertyModel } from "../PropertyModel"; + +import { BinaryPropertyModels } from "./BinaryPropertyModels"; +import { ArrayBuffers } from "./ArrayBuffers"; + +/** + * Implementation of a `PropertyModel` for string arrays + * + * @internal + */ +export class StringArrayPropertyModel implements PropertyModel { + // Implementation note: + // Either the `arrayOffsetsBuffer` or the `count` may be undefined. + // When `arrayOffsetsBuffer` is defined, then this indicates a + // variable-length array. When the `count` is defined, then this + // indicates a fixed-length array. + + private static readonly decoder = new TextDecoder(); + + private readonly _valuesBuffer: Buffer; + private readonly _arrayOffsetsBuffer: Buffer | undefined; + private readonly _arrayOffsetType: string; + private readonly _stringOffsetsBuffer: Buffer; + private readonly _stringOffsetType: string; + private readonly _count: number | undefined; + + constructor( + valuesBuffer: Buffer, + arrayOffsetsBuffer: Buffer | undefined, + arrayOffsetType: string, + stringOffsetsBuffer: Buffer, + stringOffsetType: string, + count: number | undefined + ) { + this._valuesBuffer = valuesBuffer; + this._arrayOffsetsBuffer = arrayOffsetsBuffer; + this._arrayOffsetType = arrayOffsetType; + this._stringOffsetsBuffer = stringOffsetsBuffer; + this._stringOffsetType = stringOffsetType; + this._count = count; + } + + /** {@inheritDoc PropertyModel.getPropertyValue} */ + getPropertyValue(index: number): any { + const valuesBuffer = this._valuesBuffer; + const arrayOffsetsBuffer = this._arrayOffsetsBuffer; + const arrayOffsetType = this._arrayOffsetType; + const stringOffsetsBuffer = this._stringOffsetsBuffer; + const stringOffsetType = this._stringOffsetType; + const count = this._count; + + const arraySlice = BinaryPropertyModels.computeSlice( + index, + arrayOffsetsBuffer, + arrayOffsetType, + count + ); + const arrayOffset = arraySlice.offset; + const arrayLength = arraySlice.length; + + const result = new Array(arrayLength); + for (let i = 0; i < arrayLength; i++) { + const n = arrayOffset + i; + + const stringSlice = BinaryPropertyModels.computeSlice( + n, + stringOffsetsBuffer, + stringOffsetType, + undefined + ); + const stringOffset = stringSlice.offset; + const stringLength = stringSlice.length; + const arrayBuffer = ArrayBuffers.fromBuffer(valuesBuffer); + const element = StringArrayPropertyModel.decoder.decode( + arrayBuffer.slice(stringOffset, stringOffset + stringLength) + ); + result[i] = element; + } + return result; + } +} diff --git a/src/metadata/binary/StringPropertyModel.ts b/src/metadata/binary/StringPropertyModel.ts new file mode 100644 index 00000000..0f669c42 --- /dev/null +++ b/src/metadata/binary/StringPropertyModel.ts @@ -0,0 +1,49 @@ +import { PropertyModel } from "../PropertyModel"; + +import { BinaryPropertyModels } from "./BinaryPropertyModels"; +import { ArrayBuffers } from "./ArrayBuffers"; + +/** + * Implementation of a `PropertyModel` for strings + * + * @internal + */ +export class StringPropertyModel implements PropertyModel { + private static readonly decoder = new TextDecoder(); + + private readonly _valuesBuffer: Buffer; + private readonly _stringOffsetsBuffer: Buffer; + private readonly _stringOffsetType: string; + + constructor( + valuesBuffer: Buffer, + stringOffsetsBuffer: Buffer, + stringOffsetType: string + ) { + this._valuesBuffer = valuesBuffer; + this._stringOffsetsBuffer = stringOffsetsBuffer; + this._stringOffsetType = stringOffsetType; + } + + /** {@inheritDoc PropertyModel.getPropertyValue} */ + getPropertyValue(index: number): any { + const valuesBuffer = this._valuesBuffer; + const stringOffsetsBuffer = this._stringOffsetsBuffer; + const stringOffsetType = this._stringOffsetType; + + const stringSlice = BinaryPropertyModels.computeSlice( + index, + stringOffsetsBuffer, + stringOffsetType, + undefined + ); + const stringOffset = stringSlice.offset; + const stringLength = stringSlice.length; + + const arrayBuffer = ArrayBuffers.fromBuffer(valuesBuffer); + const result = StringPropertyModel.decoder.decode( + arrayBuffer.slice(stringOffset, stringOffset + stringLength) + ); + return result; + } +} diff --git a/src/packages/TilesetSource3dtiles.ts b/src/packages/TilesetSource3dtiles.ts index 3d4024be..bedda030 100644 --- a/src/packages/TilesetSource3dtiles.ts +++ b/src/packages/TilesetSource3dtiles.ts @@ -25,6 +25,7 @@ export class TilesetSource3dtiles implements TilesetSource { this.db = undefined; } + /** {@inheritDoc TilesetSource.open} */ open(fullInputName: string): void { if (this.db) { throw new TilesetError("Database already opened"); @@ -32,6 +33,7 @@ export class TilesetSource3dtiles implements TilesetSource { this.db = new DatabaseConstructor(fullInputName); } + /** {@inheritDoc TilesetSource.getKeys} */ getKeys(): IterableIterator { if (!this.db) { throw new TilesetError("Source is not opened. Call 'open' first."); @@ -41,6 +43,7 @@ export class TilesetSource3dtiles implements TilesetSource { return Iterables.map(iterator, (row) => row.key); } + /** {@inheritDoc TilesetSource.getValue} */ getValue(key: string): Buffer | undefined { if (!this.db) { throw new Error("Source is not opened. Call 'open' first."); @@ -53,6 +56,7 @@ export class TilesetSource3dtiles implements TilesetSource { return undefined; } + /** {@inheritDoc TilesetSource.close} */ close() { if (!this.db) { throw new Error("Source is not opened. Call 'open' first."); diff --git a/src/packages/TilesetSource3tz.ts b/src/packages/TilesetSource3tz.ts index 529a21da..37b9e614 100644 --- a/src/packages/TilesetSource3tz.ts +++ b/src/packages/TilesetSource3tz.ts @@ -41,6 +41,7 @@ export class TilesetSource3tz implements TilesetSource { return this.zipIndex; } + /** {@inheritDoc TilesetSource.open} */ open(fullInputName: string) { if (defined(this.fd)) { throw new TilesetError("Source already opened"); @@ -50,6 +51,7 @@ export class TilesetSource3tz implements TilesetSource { this.zipIndex = ArchiveFunctions3tz.readZipIndex(this.fd); } + /** {@inheritDoc TilesetSource.getKeys} */ getKeys(): IterableIterator { if (!defined(this.fd) || !this.zipIndex) { throw new TilesetError("Source is not opened. Call 'open' first."); @@ -81,7 +83,8 @@ export class TilesetSource3tz implements TilesetSource { return iterator; } - getValue(key: string) { + /** {@inheritDoc TilesetSource.getValue} */ + getValue(key: string): Buffer | undefined { if (!defined(this.fd) || !this.zipIndex) { throw new TilesetError("Source is not opened. Call 'open' first."); } @@ -93,6 +96,7 @@ export class TilesetSource3tz implements TilesetSource { return entryData; } + /** {@inheritDoc TilesetSource.close} */ close() { if (!defined(this.fd) || !this.zipIndex) { throw new TilesetError("Source is not opened. Call 'open' first."); diff --git a/src/packages/TilesetTarget3dtiles.ts b/src/packages/TilesetTarget3dtiles.ts index 7445975a..965f258b 100644 --- a/src/packages/TilesetTarget3dtiles.ts +++ b/src/packages/TilesetTarget3dtiles.ts @@ -26,6 +26,7 @@ export class TilesetTarget3dtiles implements TilesetTarget { this.db = undefined; } + /** {@inheritDoc TilesetTarget.begin} */ begin(fullOutputName: string, overwrite: boolean): void { if (fs.existsSync(fullOutputName)) { if (overwrite) { @@ -51,6 +52,7 @@ export class TilesetTarget3dtiles implements TilesetTarget { .run(); } + /** {@inheritDoc TilesetTarget.addEntry} */ addEntry(key: string, content: Buffer): void { if (!this.db) { throw new TilesetError("Target is not opened. Call 'begin' first."); @@ -59,6 +61,7 @@ export class TilesetTarget3dtiles implements TilesetTarget { insertion.run(key, content); } + /** {@inheritDoc TilesetTarget.end} */ async end(): Promise { if (!this.db) { throw new TilesetError("Target is not opened. Call 'begin' first."); diff --git a/src/packages/TilesetTarget3tz.ts b/src/packages/TilesetTarget3tz.ts index 3cf4f07b..3827d565 100644 --- a/src/packages/TilesetTarget3tz.ts +++ b/src/packages/TilesetTarget3tz.ts @@ -45,6 +45,7 @@ export class TilesetTarget3tz implements TilesetTarget { this.indexBuilder = new IndexBuilder(); } + /** {@inheritDoc TilesetTarget.begin} */ begin(fullOutputName: string, overwrite: boolean) { if (fs.existsSync(fullOutputName)) { if (overwrite) { @@ -83,6 +84,17 @@ export class TilesetTarget3tz implements TilesetTarget { }); } + /** + * Creates a promise that is fulfilled when the data has fully been + * written to the target. Or maybe not. In any case, one has to wait + * for the promise that is returned from "archiver.finalize()" AND for + * this promise, to make sure that everything is written. For details, + * see https://github.com/archiverjs/node-archiver/issues/476 ... + * + * @param archive - The archiver archive + * @param outputStream - The output stream that the archive is writing to + * @returns The promise that has to be waited for in "close" + */ private static createFinishedPromise( archive: archiver.Archiver, outputStream: fs.WriteStream @@ -95,6 +107,7 @@ export class TilesetTarget3tz implements TilesetTarget { return finishedPromise; } + /** {@inheritDoc TilesetTarget.addEntry} */ addEntry(key: string, content: Buffer) { if (!this.archive) { throw new TilesetError("Target is not opened. Call 'begin' first."); @@ -103,6 +116,7 @@ export class TilesetTarget3tz implements TilesetTarget { this.indexBuilder.addEntry(key, content.length); } + /** {@inheritDoc TilesetTarget.end} */ async end() { if (!this.archive) { throw new TilesetError("Target is not opened. Call 'begin' first."); @@ -111,7 +125,7 @@ export class TilesetTarget3tz implements TilesetTarget { // Create the index data, and add it as the LAST entry of the ZIP const indexData = this.indexBuilder.createBuffer(); this.archive.append(indexData, { name: "@3dtilesIndex1@" }); - this.archive.finalize(); + await this.archive.finalize(); await this.finishedPromise; this.finishedPromise = undefined; diff --git a/src/pipelines/TilesetEntries.ts b/src/pipelines/TilesetEntries.ts index 3257e728..d7beae81 100644 --- a/src/pipelines/TilesetEntries.ts +++ b/src/pipelines/TilesetEntries.ts @@ -1,4 +1,4 @@ -import { ContentOps } from "../contentOperations/ContentOps"; +import { Buffers } from "../base/Buffers"; import { TilesetEntry } from "../tilesetData/TilesetEntry"; @@ -7,7 +7,7 @@ export class TilesetEntries { const inputKey = inputEntry.key; const inputValue = inputEntry.value; const outputKey = inputKey; - const outputValue = ContentOps.gzipBuffer(inputValue); + const outputValue = Buffers.gzip(inputValue); return { key: outputKey, value: outputValue, @@ -18,7 +18,7 @@ export class TilesetEntries { const inputKey = inputEntry.key; const inputValue = inputEntry.value; const outputKey = inputKey; - const outputValue = ContentOps.gunzipBuffer(inputValue); + const outputValue = Buffers.gunzip(inputValue); return { key: outputKey, value: outputValue, diff --git a/src/spatial/MortonOrder.ts b/src/spatial/MortonOrder.ts new file mode 100644 index 00000000..3509dfd8 --- /dev/null +++ b/src/spatial/MortonOrder.ts @@ -0,0 +1,105 @@ +// Ported from https://github.com/CesiumGS/cesium/blob/4b333bc145fa9f7aed0c7ad7e0f46cb001a94ddd/Source/Core/MortonOrder.js + +/** + * Morton Order (aka Z-Order Curve) helper functions. + * @see {@link https://en.wikipedia.org/wiki/Z-order_curve} + * + * @internal + */ +export class MortonOrder { + /** + * Inserts one 0 bit of spacing between a number's bits. This is the opposite of removeOneSpacing. + * + * Example: + * input: 6 + * input (binary): 110 + * output (binary): 10100 + * ^ ^ (added) + * output: 20 + * + * @param v - A 16-bit unsigned integer. + * @returns A 32-bit unsigned integer. + * @see {@link https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/} + */ + private static insertOneSpacing(v: number): number { + v = (v ^ (v << 8)) & 0x00ff00ff; + v = (v ^ (v << 4)) & 0x0f0f0f0f; + v = (v ^ (v << 2)) & 0x33333333; + v = (v ^ (v << 1)) & 0x55555555; + return v; + } + + /** + * Inserts two 0 bits of spacing between a number's bits. This is the opposite of removeTwoSpacing. + * + * Example: + * input: 6 + * input (binary): 110 + * output (binary): 1001000 + * ^^ ^^ (added) + * output: 72 + * + * @internal + * @param v - A 10-bit unsigned integer. + * @returns A 30-bit unsigned integer. + * @see {@link https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/} + */ + private static insertTwoSpacing(v: number): number { + v = (v ^ (v << 16)) & 0x030000ff; + v = (v ^ (v << 8)) & 0x0300f00f; + v = (v ^ (v << 4)) & 0x030c30c3; + v = (v ^ (v << 2)) & 0x09249249; + return v; + } + + /** + * Computes the Morton index from 2D coordinates. This is equivalent to interleaving their bits. + * The inputs must be 16-bit unsigned integers (resulting in 32-bit Morton index) due to 32-bit bitwise operator limitation in JavaScript. + * + * @param x - The X coordinate in the range [0, (2^16)-1]. + * @param y - The Y coordinate in the range [0, (2^16)-1]. + * @returns The Morton index. + * @internal + */ + static encode2D(x: number, y: number): number { + //>>includeStart('debug', pragmas.debug); + if (x < 0 || x > 65535 || y < 0 || y > 65535) { + throw new Error("inputs must be 16-bit unsigned integers"); + } + //>>includeEnd('debug'); + + // Note: JavaScript bitwise operations return signed 32-bit integers, so the + // final result needs to be reintepreted as an unsigned integer using >>> 0. + // This is not needed for encode3D because the result is guaranteed to be at most + // 30 bits and thus will always be interpreted as an unsigned value. + return ( + (MortonOrder.insertOneSpacing(x) | + (MortonOrder.insertOneSpacing(y) << 1)) >>> + 0 + ); + } + + /** + * Computes the Morton index from 3D coordinates. This is equivalent to interleaving their bits. + * The inputs must be 10-bit unsigned integers (resulting in 30-bit Morton index) due to 32-bit bitwise operator limitation in JavaScript. + * + * @param x - The X coordinate in the range [0, (2^10)-1]. + * @param y - The Y coordinate in the range [0, (2^10)-1]. + * @param z - The Z coordinate in the range [0, (2^10)-1]. + * @returns The Morton index. + * @internal + */ + static encode3D(x: number, y: number, z: number): number { + //>>includeStart('debug', pragmas.debug); + if (x < 0 || x > 1023 || y < 0 || y > 1023 || z < 0 || z > 1023) { + throw new Error("inputs must be 10-bit unsigned integers"); + } + //>>includeEnd('debug'); + + return ( + MortonOrder.insertTwoSpacing(x) | + (MortonOrder.insertTwoSpacing(y) << 1) | + (MortonOrder.insertTwoSpacing(z) << 2) + ); + } +} diff --git a/src/spatial/OctreeCoordinates.ts b/src/spatial/OctreeCoordinates.ts new file mode 100644 index 00000000..27dfaf23 --- /dev/null +++ b/src/spatial/OctreeCoordinates.ts @@ -0,0 +1,113 @@ +import { MortonOrder } from "./MortonOrder"; +import { Octrees } from "./Octrees"; +import { TreeCoordinates } from "./TreeCoordinates"; + +/** + * An implementation of `TreeCoordinates` for octrees + * + * @internal + */ +export class OctreeCoordinates implements TreeCoordinates { + private readonly _level: number; + private readonly _x: number; + private readonly _y: number; + private readonly _z: number; + + constructor(level: number, x: number, y: number, z: number) { + this._level = level; + this._x = x; + this._y = y; + this._z = z; + } + + /** {@inheritDoc TreeCoordinates.level} */ + get level(): number { + return this._level; + } + + get x(): number { + return this._x; + } + + get y(): number { + return this._y; + } + + get z(): number { + return this._z; + } + + /** {@inheritDoc TreeCoordinates.parent} */ + parent(): OctreeCoordinates | null { + if (this._level === 0) { + return null; + } + const pLevel = this._level - 1; + const px = this._x >> 1; + const py = this._y >> 1; + const pz = this._z >> 1; + return new OctreeCoordinates(pLevel, px, py, pz); + } + + /** {@inheritDoc TreeCoordinates.children} */ + *children(): IterableIterator { + const nLevel = this._level + 1; + const nX = this._x << 1; + const nY = this._y << 1; + const nZ = this._z << 1; + yield new OctreeCoordinates(nLevel, nX + 0, nY + 0, nZ + 0); + yield new OctreeCoordinates(nLevel, nX + 1, nY + 0, nZ + 0); + yield new OctreeCoordinates(nLevel, nX + 0, nY + 1, nZ + 0); + yield new OctreeCoordinates(nLevel, nX + 1, nY + 1, nZ + 0); + yield new OctreeCoordinates(nLevel, nX + 0, nY + 0, nZ + 1); + yield new OctreeCoordinates(nLevel, nX + 1, nY + 0, nZ + 1); + yield new OctreeCoordinates(nLevel, nX + 0, nY + 1, nZ + 1); + yield new OctreeCoordinates(nLevel, nX + 1, nY + 1, nZ + 1); + } + + /** {@inheritDoc TreeCoordinates.descendants} */ + descendants( + maxLevelInclusive: number, + depthFirst: boolean + ): IterableIterator { + const queue: OctreeCoordinates[] = [this]; + const result = { + [Symbol.iterator]() { + return this; + }, + next(): IteratorResult { + const element = depthFirst ? queue.pop() : queue.shift(); + if (!element) { + return { value: undefined, done: true }; + } + if (element.level < maxLevelInclusive) { + for (const c of element.children()) { + queue.push(c); + } + } + return { value: element, done: false }; + }, + }; + return result; + } + + /** {@inheritDoc TreeCoordinates.toArray} */ + toArray(): number[] { + return [this.level, this.x, this.y, this.z]; + } + + /** {@inheritDoc TreeCoordinates.toIndex} */ + toIndex(): number { + const offset = Octrees.computeNumberOfNodesForLevels(this._level); + return offset + this.toIndexInLevel(); + } + + /** {@inheritDoc TreeCoordinates.toIndexInLevel} */ + toIndexInLevel(): number { + return MortonOrder.encode3D(this._x, this._y, this._z); + } + + toString = (): string => { + return `(level ${this.level}, (${this._x},${this._y},${this._z}))`; + }; +} diff --git a/src/spatial/Octrees.ts b/src/spatial/Octrees.ts new file mode 100644 index 00000000..e2f0012d --- /dev/null +++ b/src/spatial/Octrees.ts @@ -0,0 +1,65 @@ +import { OctreeCoordinates } from "./OctreeCoordinates"; + +/** + * Methods related to octrees + * + * @internal + */ +export class Octrees { + /** + * Computes the number of nodes of an octree with the given number of + * levels. + * + * @param levels - The number of levels + * @returns The number of nodes + */ + static computeNumberOfNodesForLevels(levels: number) { + return ((1 << (levels * 3)) - 1) / (8 - 1); + } + + /** + * Returns a generator over all coordinates in the given level. + * + * @param level - The level + * @returns The coordinates + */ + static *coordinatesForLevel(level: number) { + const size = 1 << level; + for (let z = 0; z < size; z++) { + for (let y = 0; y < size; y++) { + for (let x = 0; x < size; x++) { + yield new OctreeCoordinates(level, x, y, z); + } + } + } + } + + /** + * Returns whether the given coordinates are valid. This means + * that the x, y, and z components are in the range that is + * determined by the level of the coordinates. + * + * @param c - The coordinates + * @returns Whether the coordinates are valid + */ + static isValid(c: OctreeCoordinates) { + const level = c.level; + const x = c.x; + const y = c.y; + const z = c.z; + if (level < 0) { + return false; + } + const size = 1 << level; + if (x < 0 || x >= size) { + return false; + } + if (y < 0 || y >= size) { + return false; + } + if (z < 0 || z >= size) { + return false; + } + return true; + } +} diff --git a/src/spatial/QuadtreeCoordinates.ts b/src/spatial/QuadtreeCoordinates.ts new file mode 100644 index 00000000..5292a45e --- /dev/null +++ b/src/spatial/QuadtreeCoordinates.ts @@ -0,0 +1,101 @@ +import { MortonOrder } from "./MortonOrder"; +import { Quadtrees } from "./Quadtrees"; +import { TreeCoordinates } from "./TreeCoordinates"; + +/** + * An implementation of `TreeCoordinates` for octrees + * + * @internal + */ +export class QuadtreeCoordinates implements TreeCoordinates { + private readonly _level: number; + private readonly _x: number; + private readonly _y: number; + + constructor(level: number, x: number, y: number) { + this._level = level; + this._x = x; + this._y = y; + } + + /** {@inheritDoc TreeCoordinates.level} */ + get level(): number { + return this._level; + } + + get x(): number { + return this._x; + } + + get y(): number { + return this._y; + } + + /** {@inheritDoc TreeCoordinates.parent} */ + parent(): QuadtreeCoordinates | null { + if (this._level === 0) { + return null; + } + const pLevel = this._level - 1; + const px = this._x >> 1; + const py = this._y >> 1; + return new QuadtreeCoordinates(pLevel, px, py); + } + + /** {@inheritDoc TreeCoordinates.children} */ + *children(): IterableIterator { + const nLevel = this._level + 1; + const nX = this._x << 1; + const nY = this._y << 1; + yield new QuadtreeCoordinates(nLevel, nX + 0, nY + 0); + yield new QuadtreeCoordinates(nLevel, nX + 1, nY + 0); + yield new QuadtreeCoordinates(nLevel, nX + 0, nY + 1); + yield new QuadtreeCoordinates(nLevel, nX + 1, nY + 1); + } + + /** {@inheritDoc TreeCoordinates.descendants} */ + descendants( + maxLevelInclusive: number, + depthFirst: boolean + ): IterableIterator { + const queue: QuadtreeCoordinates[] = [this]; + const result = { + [Symbol.iterator]() { + return this; + }, + next(): IteratorResult { + const element = depthFirst ? queue.pop() : queue.shift(); + if (!element) { + return { value: undefined, done: true }; + } + if (element.level < maxLevelInclusive) { + for (const c of element.children()) { + queue.push(c); + } + } + return { value: element, done: false }; + }, + }; + return result; + } + + /** {@inheritDoc TreeCoordinates.toArray} */ + toArray(): number[] { + return [this.level, this.x, this.y]; + } + + /** {@inheritDoc TreeCoordinates.toIndex} */ + toIndex(): number { + const offset = Quadtrees.computeNumberOfNodesForLevels(this._level); + return offset + this.toIndexInLevel(); + } + + /** {@inheritDoc TreeCoordinates.toIndexInLevel} */ + toIndexInLevel(): number { + return MortonOrder.encode2D(this._x, this._y); + } + + toString = (): string => { + return `(level ${this.level}, (${this._x},${this._y}))`; + }; +} diff --git a/src/spatial/Quadtrees.ts b/src/spatial/Quadtrees.ts new file mode 100644 index 00000000..4a6a8e98 --- /dev/null +++ b/src/spatial/Quadtrees.ts @@ -0,0 +1,59 @@ +import { QuadtreeCoordinates } from "./QuadtreeCoordinates"; + +/** + * Methods related to quadtrees. + * + * @internal + */ +export class Quadtrees { + /** + * Computes the number of nodes of a quadtree with the given number of + * levels. + * + * @param levels - The number of levels + * @returns The number of nodes + */ + static computeNumberOfNodesForLevels(levels: number) { + return ((1 << (levels * 2)) - 1) / (4 - 1); + } + + /** + * Returns a generator over all coordinates in the given level. + * + * @param level - The level + * @returns The coordinates + */ + static *coordinatesForLevel(level: number) { + const size = 1 << level; + for (let y = 0; y < size; y++) { + for (let x = 0; x < size; x++) { + yield new QuadtreeCoordinates(level, x, y); + } + } + } + + /** + * Returns whether the given coordinates are valid. This means + * that the x and y components are in the range that is + * determined by the level of the coordinates. + * + * @param c - The coordinates + * @returns Whether the coordinates are valid + */ + static isValid(c: QuadtreeCoordinates) { + const level = c.level; + const x = c.x; + const y = c.y; + if (level < 0) { + return false; + } + const size = 1 << level; + if (x < 0 || x >= size) { + return false; + } + if (y < 0 || y >= size) { + return false; + } + return true; + } +} diff --git a/src/spatial/TreeCoordinates.ts b/src/spatial/TreeCoordinates.ts new file mode 100644 index 00000000..50018d41 --- /dev/null +++ b/src/spatial/TreeCoordinates.ts @@ -0,0 +1,80 @@ +/** + * An interface for coordinates within a tree structure. + * + * @internal + */ +export interface TreeCoordinates { + /** + * Returns the level of the coordinates, with 0 being + * the root node. + * + * @returns The level + */ + get level(): number; + + /** + * Returns the parent coordinates of these coordinates, + * or `null` if this is the root. + * + * @returns The parent coordinates + */ + parent(): TreeCoordinates | null; + + /** + * Returns a generator for the child coordinates of these coordinates + * + * @returns The child coordinates + */ + children(): IterableIterator; + + /** + * Returns a generator for all coordinates that are descendants + * of these coordinates, up to the given level, **inclusive!**. + * + * @param maxLevelInclusive - The maximum level, **inclusive** + * @param depthFirst - Whether the traversal should be depth first + * @returns The child coordinates + */ + descendants( + maxLevelInclusive: number, + depthFirst: boolean + ): IterableIterator; + + /** + * Preliminary: + * + * Returns these coordinates as an array. This returns the + * level, x, and y coordinates (and z for octrees) in one + * array. + * + * @returns The coordinates as an array + */ + toArray(): number[]; + + /** + * Preliminary: + * + * Returns the index that corresponds to these coordinates. + * + * This returns the (stacked) Morton index. This could be considered + * as an implementation detail, but is frequently used in implicit + * tiling, and therefore, part of this interface. + * + * @returns The coordinates as an index + */ + toIndex(): number; + + /** + * Preliminary: + * + * Returns the index that corresponds to these coordinates, within + * their level. + * + * This returns the local Morton index. This could be considered + * as an implementation detail, but is frequently used in implicit + * tiling, and therefore, part of this interface. + * + * @returns The index of these coordinates within their level + */ + toIndexInLevel(): number; +} diff --git a/src/structure/extensions/BoundingVolumeS2.ts b/src/structure/extensions/BoundingVolumeS2.ts new file mode 100644 index 00000000..f78c2b28 --- /dev/null +++ b/src/structure/extensions/BoundingVolumeS2.ts @@ -0,0 +1,7 @@ +import { RootProperty } from "../RootProperty"; + +export interface BoundingVolumeS2 extends RootProperty { + token: string; + minimumHeight: number; + maximumHeight: number; +} diff --git a/src/tilesetData/TilesetSourceFs.ts b/src/tilesetData/TilesetSourceFs.ts index ce41a949..4fe827ff 100644 --- a/src/tilesetData/TilesetSourceFs.ts +++ b/src/tilesetData/TilesetSourceFs.ts @@ -26,6 +26,7 @@ export class TilesetSourceFs implements TilesetSource { this.fullInputName = undefined; } + /** {@inheritDoc TilesetSource.open} */ open(fullInputName: string) { if (this.fullInputName) { throw new TilesetError("Source already opened"); @@ -33,6 +34,7 @@ export class TilesetSourceFs implements TilesetSource { this.fullInputName = fullInputName; } + /** {@inheritDoc TilesetSource.getKeys} */ getKeys() { if (!this.fullInputName) { throw new TilesetError("Source is not opened. Call 'open' first."); @@ -45,7 +47,8 @@ export class TilesetSourceFs implements TilesetSource { ); } - getValue(key: string) { + /** {@inheritDoc TilesetSource.getValue} */ + getValue(key: string): Buffer | undefined { if (!this.fullInputName) { throw new TilesetError("Source is not opened. Call 'open' first."); } @@ -54,9 +57,13 @@ export class TilesetSourceFs implements TilesetSource { return undefined; } const data = fs.readFileSync(fullFileName); + if (data === null) { + return undefined; + } return data; } + /** {@inheritDoc TilesetSource.close} */ close() { if (!this.fullInputName) { throw new TilesetError("Source is not opened. Call 'open' first."); diff --git a/src/tilesetData/TilesetTargetFs.ts b/src/tilesetData/TilesetTargetFs.ts index dcd7f9ef..9681be63 100644 --- a/src/tilesetData/TilesetTargetFs.ts +++ b/src/tilesetData/TilesetTargetFs.ts @@ -30,6 +30,7 @@ export class TilesetTargetFs implements TilesetTarget { this.overwrite = false; } + /** {@inheritDoc TilesetTarget.begin} */ begin(fullOutputName: string, overwrite: boolean) { if (this.fullOutputName) { throw new TilesetError("Target already opened"); @@ -41,6 +42,7 @@ export class TilesetTargetFs implements TilesetTarget { } } + /** {@inheritDoc TilesetTarget.addEntry} */ addEntry(key: string, content: Buffer) { if (!this.fullOutputName) { throw new TilesetError("Target is not opened. Call 'begin' first."); @@ -56,6 +58,7 @@ export class TilesetTargetFs implements TilesetTarget { fs.writeFileSync(fullOutputFileName, content); } + /** {@inheritDoc TilesetTarget.end} */ async end() { if (!this.fullOutputName) { throw new TilesetError("Target is not opened. Call 'begin' first."); diff --git a/src/tilesetProcessing/TilesetUpgrader.ts b/src/tilesetProcessing/TilesetUpgrader.ts index 2e99d87c..eb7c1309 100644 --- a/src/tilesetProcessing/TilesetUpgrader.ts +++ b/src/tilesetProcessing/TilesetUpgrader.ts @@ -19,8 +19,7 @@ import { Tilesets } from "../tilesets/Tilesets"; import { TileFormats } from "../tileFormats/TileFormats"; -import { GltfUtilities } from "../contentOperations/GtlfUtilities"; -import { ContentOps } from "../contentOperations/ContentOps"; +import { GltfUtilities } from "../contentProcessing/GtlfUtilities"; /** * The options for the upgrade. This is only used internally, @@ -164,7 +163,7 @@ export class TilesetUpgrader { let tilesetJsonBufferWasZipped = false; if (Buffers.isGzipped(tilesetJsonBuffer)) { tilesetJsonBufferWasZipped = true; - tilesetJsonBuffer = ContentOps.gunzipBuffer(tilesetJsonBuffer); + tilesetJsonBuffer = Buffers.gunzip(tilesetJsonBuffer); } const tileset = JSON.parse(tilesetJsonBuffer.toString()) as Tileset; @@ -176,7 +175,7 @@ export class TilesetUpgrader { const resultTilesetJsonString = JSON.stringify(tileset, null, 2); let resultTilesetJsonBuffer = Buffer.from(resultTilesetJsonString); if (tilesetJsonBufferWasZipped) { - resultTilesetJsonBuffer = ContentOps.gzipBuffer(resultTilesetJsonBuffer); + resultTilesetJsonBuffer = Buffers.gzip(resultTilesetJsonBuffer); } this.tilesetTarget.addEntry( tilesetTargetJsonFileName, diff --git a/src/traversal/ExplicitTraversedTile.ts b/src/traversal/ExplicitTraversedTile.ts new file mode 100644 index 00000000..5d014ab7 --- /dev/null +++ b/src/traversal/ExplicitTraversedTile.ts @@ -0,0 +1,236 @@ +import { ResourceResolver } from "../io/ResourceResolver"; + +import { TraversedTile } from "./TraversedTile"; +import { ExplicitTraversedTiles } from "./ExplicitTraversedTiles"; +import { MetadataSemanticOverrides } from "./MetadataSemanticOverrides"; + +import { Tile } from "../structure/Tile"; +import { Content } from "../structure/Content"; +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; +import { MetadataEntity } from "../structure/MetadataEntity"; +import { Schema } from "../structure/Metadata/Schema"; + +import { ImplicitTilings } from "../implicitTiling/ImplicitTilings"; + +/** + * An implementation of a `TraversedTile` that reflects a tile + * that actually appears as a JSON representation in the tileset. + * + * @internal + */ +export class ExplicitTraversedTile implements TraversedTile { + /** + * The parent tile, or `undefined` if this is the root + */ + private readonly _parent: TraversedTile | undefined; + + /** + * The `Tile` object that this traversed tile was created for + */ + private readonly _tile: Tile; + + /** + * A JSON-path like path identifying this tile + */ + private readonly _path: string; + + /** + * The global level. This is the level starting at the + * root of the tileset. + */ + private readonly _level: number; + + /** + * The metadata schema in the context of which this tile + * is created. This is the schema that was obtained from + * the `tileset.schema` or `tileset.schemaUri`. If this + * is defined, it is assumed to be valid. If it is + * undefined and a tile with metadata is encountered, + * then an error will be thrown in `asTile`. + */ + private readonly _schema: Schema | undefined; + + /** + * The `ResourceResolver` that will resolve resources + * that may be required if this is the root of an + * implicit tileset (e.g. the subtree files). + */ + private readonly _resourceResolver; + + constructor( + tile: Tile, + path: string, + level: number, + parent: TraversedTile | undefined, + schema: Schema | undefined, + resourceResolver: ResourceResolver + ) { + this._tile = tile; + this._path = path; + this._level = level; + this._parent = parent; + this._schema = schema; + this._resourceResolver = resourceResolver; + } + + /** {@inheritDoc TraversedTile.asRawTile} */ + asRawTile(): Tile { + return this._tile; + } + + /** {@inheritDoc TraversedTile.asFinalTile} */ + asFinalTile(): Tile { + const tile = this._tile; + + const contents = this.getFinalContents(); + + const finalTile = { + boundingVolume: tile.boundingVolume, + viewerRequestVolume: tile.viewerRequestVolume, + geometricError: tile.geometricError, + refine: tile.refine, + transform: tile.transform, + content: undefined, + contents: contents, + children: tile.children, + metadata: tile.metadata, + implicitTiling: tile.implicitTiling, + extensions: tile.extensions, + extras: tile.extras, + }; + + const schema = this._schema; + if (schema) { + MetadataSemanticOverrides.applyExplicitTileMetadataSemanticOverrides( + finalTile, + schema + ); + } + return finalTile; + } + + /** {@inheritDoc TraversedTile.path} */ + get path(): string { + return this._path; + } + + /** {@inheritDoc TraversedTile.level} */ + get level(): number { + return this._level; + } + + /** {@inheritDoc TraversedTile.getParent} */ + getParent(): TraversedTile | undefined { + return this._parent; + } + + /** {@inheritDoc TraversedTile.getChildren} */ + async getChildren(): Promise { + const implicitTiling = this._tile.implicitTiling; + const schema = this._schema; + if (implicitTiling) { + const children = await ExplicitTraversedTiles.createTraversedChildren( + implicitTiling, + schema, + this, + this._resourceResolver + ); + return children; + } + + if (!this._tile.children) { + return []; + } + const children = this._tile.children; + const childLevel = this._level + 1; + const traversedChildren = []; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + const childPath = this.path + "/children/" + i; + const traversedChild = new ExplicitTraversedTile( + child, + childPath, + childLevel, + this, + this._schema, + this._resourceResolver + ); + traversedChildren.push(traversedChild); + } + return traversedChildren; + } + + /** {@inheritDoc TraversedTile.getRawContents} */ + getRawContents(): Content[] { + if (this._tile.content) { + return [this._tile.content]; + } + if (this._tile.contents) { + return this._tile.contents; + } + return []; + } + + /** {@inheritDoc TraversedTile.getFinalContents} */ + getFinalContents(): Content[] { + const rawContents = this.getRawContents(); + const schema = this._schema; + if (!schema) { + return rawContents; + } + const finalContents: Content[] = []; + for (let i = 0; i < rawContents.length; i++) { + const rawContent = rawContents[i]; + const finalContent: Content = { + boundingVolume: rawContent.boundingVolume, + uri: rawContent.uri, + metadata: rawContent.metadata, + group: rawContent.group, + extensions: rawContent.extensions, + extras: rawContent.extras, + }; + MetadataSemanticOverrides.applyExplicitContentMetadataSemanticOverrides( + finalContent, + schema + ); + finalContents.push(finalContent); + } + return finalContents; + } + + /** {@inheritDoc TraversedTile.getSubtreeUri} */ + getSubtreeUri(): string | undefined { + const implicitTiling = this._tile.implicitTiling; + if (!implicitTiling) { + return undefined; + } + const rootCoordinates = + ImplicitTilings.createRootCoordinates(implicitTiling); + const subtreeUri = ImplicitTilings.substituteTemplateUri( + implicitTiling.subdivisionScheme, + implicitTiling.subtrees.uri, + rootCoordinates + ); + return subtreeUri; + } + + /** {@inheritDoc TraversedTile.getImplicitTiling} */ + getImplicitTiling(): TileImplicitTiling | undefined { + return this._tile.implicitTiling; + } + + /** {@inheritDoc TraversedTile.getMetadata} */ + getMetadata(): MetadataEntity | undefined { + return this._tile.metadata; + } + + /** {@inheritDoc TraversedTile.resolveUri} */ + resolveUri(uri: string): string { + return this._resourceResolver.resolveUri(uri); + } + + // TODO For debugging + toString = (): string => { + return `ExplicitTraversedTile, level ${this.level}, path ${this.path}`; + }; +} diff --git a/src/traversal/ExplicitTraversedTiles.ts b/src/traversal/ExplicitTraversedTiles.ts new file mode 100644 index 00000000..65f2e7e0 --- /dev/null +++ b/src/traversal/ExplicitTraversedTiles.ts @@ -0,0 +1,163 @@ +import { ResourceResolver } from "../io/ResourceResolver"; + +import { TraversedTile } from "./TraversedTile"; +import { ExplicitTraversedTile } from "./ExplicitTraversedTile"; +import { ImplicitTraversedTile } from "./ImplicitTraversedTile"; +import { SubtreeModels } from "./SubtreeModels"; + +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; +import { Schema } from "../structure/Metadata/Schema"; + +import { ImplicitTilingError } from "../implicitTiling/ImplicitTilingError"; +import { ImplicitTilings } from "../implicitTiling/ImplicitTilings"; + +/** + * Internal methods used in the `ExplicitTraversedTile` class. + * + * (Specifically: Methods to create the children of explicit + * tiles, when these explicit tiles define the root of an + * implicit tileset) + * + * @internal + */ +export class ExplicitTraversedTiles { + /** + * Create the traversed children for the given explicit traversed tile. + * + * This method will be called from `ExplicitTraversedTile` instances + * when the contain `implicitTiling` information, in order to create + * the traversed children. + * + * The children will then be a single-element array that contains the + * root node of the implicit tileset, as an `ImplicitTraversedTile`. + * + * @param implicitTiling - The `TileImplicitTiling` + * @param parent - The `ExplicitTraversedTile` + * @param schema - The optional metadata schema + * @param resourceResolver - The `ResourceResolver` that + * will be used e.g. for subtree files + * @returns The traversed children + * @throws ImplicitTilingError If the input was structurally invalid + */ + static async createTraversedChildren( + implicitTiling: TileImplicitTiling, + schema: Schema | undefined, + parent: ExplicitTraversedTile, + resourceResolver: ResourceResolver + ): Promise { + const subdivisionScheme = implicitTiling.subdivisionScheme; + if (subdivisionScheme === "QUADTREE") { + const child = await ExplicitTraversedTiles.createImplicitQuadtreeRoot( + implicitTiling, + schema, + parent, + resourceResolver + ); + return [child]; + } + if (subdivisionScheme === "OCTREE") { + const child = await ExplicitTraversedTiles.createImplicitOctreeRoot( + implicitTiling, + schema, + parent, + resourceResolver + ); + return [child]; + } + throw new ImplicitTilingError( + "Invalid subdivisionScheme: " + subdivisionScheme + ); + } + + /** + * Creates the root node for the traversal of an implicit quadtree. + * + * @param implicitTiling - The `TileImplicitTiling` + * @param schema - The optional metadata schema + * @param parent - The `ExplicitTraversedTile` + * @param resourceResolver - The `ResourceResolver` that + * will be used e.g. for subtree files + * @returns The root of an implicit quadtree + * @throws ImplicitTilingError If the input was structurally invalid + */ + private static async createImplicitQuadtreeRoot( + implicitTiling: TileImplicitTiling, + schema: Schema | undefined, + parent: ExplicitTraversedTile, + resourceResolver: ResourceResolver + ): Promise { + const rootCoordinates = + ImplicitTilings.createRootCoordinates(implicitTiling); + + const subtreeModel = await SubtreeModels.resolve( + implicitTiling, + schema, + resourceResolver, + rootCoordinates + ); + + // The path is composed from the path of the parent and the string + // representation of the root coordinates + const coordinateString = ImplicitTilings.createString(rootCoordinates); + const path = `${parent.path}/${coordinateString}`; + const root = new ImplicitTraversedTile( + implicitTiling, + resourceResolver, + parent, + path, + subtreeModel, + parent.level + 1, + rootCoordinates, + rootCoordinates, + rootCoordinates, + parent + ); + return root; + } + + /** + * Creates the root node for the traversal of an implicit octree. + * + * @param implicitTiling - The `TileImplicitTiling` + * @param schema - The optional metadata schema + * @param parent - The `ExplicitTraversedTile` + * @param resourceResolver - The `ResourceResolver` that + * will be used e.g. for subtree files + * @returns The root of an implicit octree + * @throws ImplicitTilingError If the input was structurally invalid + */ + private static async createImplicitOctreeRoot( + implicitTiling: TileImplicitTiling, + schema: Schema | undefined, + parent: ExplicitTraversedTile, + resourceResolver: ResourceResolver + ): Promise { + const rootCoordinates = + ImplicitTilings.createRootCoordinates(implicitTiling); + + const subtreeModel = await SubtreeModels.resolve( + implicitTiling, + schema, + resourceResolver, + rootCoordinates + ); + + // The path is composed from the path of the parent and the string + // representation of the root coordinates + const coordinateString = ImplicitTilings.createString(rootCoordinates); + const path = `${parent.path}/${coordinateString}`; + const root = new ImplicitTraversedTile( + implicitTiling, + resourceResolver, + parent, + path, + subtreeModel, + parent.level + 1, + rootCoordinates, + rootCoordinates, + rootCoordinates, + parent + ); + return root; + } +} diff --git a/src/traversal/ImplicitTraversedTile.ts b/src/traversal/ImplicitTraversedTile.ts new file mode 100644 index 00000000..32bbd144 --- /dev/null +++ b/src/traversal/ImplicitTraversedTile.ts @@ -0,0 +1,426 @@ +import { defined } from "../base/defined"; + +import { ResourceResolver } from "../io/ResourceResolver"; + +import { TraversedTile } from "./TraversedTile"; +import { SubtreeModel } from "./SubtreeModel"; +import { SubtreeModels } from "./SubtreeModels"; + +import { Tile } from "../structure/Tile"; +import { Content } from "../structure/Content"; +import { MetadataEntity } from "../structure/MetadataEntity"; +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; + +import { TreeCoordinates } from "../spatial/TreeCoordinates"; + +import { ImplicitTilingError } from "../implicitTiling/ImplicitTilingError"; +import { ImplicitTilings } from "../implicitTiling/ImplicitTilings"; + +import { BoundingVolumeDerivation } from "./cesium/BoundingVolumeDerivation"; +import { MetadataSemanticOverrides } from "./MetadataSemanticOverrides"; + +/** + * An implementation of a `TraversedTile` that represents a tile + * within an implicit tileset during its traversal. + * + * @internal + */ +export class ImplicitTraversedTile implements TraversedTile { + /** + * The `TileImplicitTiling` that this tile belongs to + */ + private readonly _implicitTiling: TileImplicitTiling; + + /** + * The `ResourceResolver` that will be used for loading + * subtree files. + */ + private readonly _resourceResolver: ResourceResolver; + + /** + * The tile that corresponds to the root tile from the + * tileset JSON (i.e. the one that contained the + * `TileImplicitTiling` object) + */ + private readonly _root: TraversedTile; + + /** + * A JSON-path like path identifying this tile + */ + private readonly _path: string; + + /** + * The `SubtreeModel` object that will be used for accessing + * the availability information and metadata for the subtree + * that this tile belongs to. + */ + private readonly _subtreeModel: SubtreeModel; + + /** + * The global level of this tile. This refers to the + * root of the tileset. + */ + private readonly _globalLevel: number; + + /** + * The global coordinate of this tile within the implicit tileset. + */ + private readonly _globalCoordinate: TreeCoordinates; + + /** + * The root coordinate of the subtree that this tile belongs + * to, within the whole implicit tileset. + */ + private readonly _rootCoordinate: TreeCoordinates; + + /** + * The local coordinate of this tile within the subtree that + * starts at the `_rootCoordinate` + */ + private readonly _localCoordinate: TreeCoordinates; + + /** + * The parent tile + */ + private readonly _parent: TraversedTile; + + constructor( + implicitTiling: TileImplicitTiling, + resourceResolver: ResourceResolver, + root: TraversedTile, + path: string, + subtreeModel: SubtreeModel, + globalLevel: number, + globalCoordinate: TreeCoordinates, + rootCoordinate: TreeCoordinates, + localCoordinate: TreeCoordinates, + parent: TraversedTile + ) { + this._implicitTiling = implicitTiling; + this._resourceResolver = resourceResolver; + this._root = root; + this._path = path; + this._subtreeModel = subtreeModel; + this._globalLevel = globalLevel; + this._globalCoordinate = globalCoordinate; + this._rootCoordinate = rootCoordinate; + this._localCoordinate = localCoordinate; + this._parent = parent; + } + + /** {@inheritDoc TraversedTile.asRawTile} */ + asRawTile(): Tile { + const rootTile = this._root.asFinalTile(); + + const boundingVolume = BoundingVolumeDerivation.deriveBoundingVolume( + rootTile.boundingVolume, + this._globalCoordinate.toArray() + ); + if (!boundingVolume) { + // The bounding volume was not a region, box, or S2 Cell. + throw new ImplicitTilingError("Could not subdivide bounding volume"); + } + const level = this._globalCoordinate.level; + const geometricError = rootTile.geometricError / Math.pow(2, level); + + const viewerRequestVolume = rootTile.viewerRequestVolume; + const refine = rootTile.refine; + const transform = undefined; + const metadata = undefined; + const contents = this.getRawContents(); + const implicitTiling = undefined; + const extensions = undefined; + const extras = undefined; + + return { + boundingVolume: boundingVolume, + viewerRequestVolume: viewerRequestVolume, + geometricError: geometricError, + refine: refine, + transform: transform, + metadata: metadata, + contents: contents, + implicitTiling: implicitTiling, + extensions: extensions, + extras: extras, + }; + } + + /** {@inheritDoc TraversedTile.asFinalTile} */ + asFinalTile(): Tile { + const tile = this.asRawTile(); + tile.contents = this.getFinalContents(); + const subtreeMetadataModel = this._subtreeModel.subtreeMetadataModel; + if (subtreeMetadataModel) { + const tileIndex = this._localCoordinate.toIndex(); + MetadataSemanticOverrides.applyImplicitTileMetadataSemanticOverrides( + tile, + tileIndex, + subtreeMetadataModel + ); + } + return tile; + } + + /** {@inheritDoc TraversedTile.path} */ + get path(): string { + return this._path; + } + + /** {@inheritDoc TraversedTile.level} */ + get level(): number { + return this._globalLevel; + } + + /** + * Returns the local coordinate of this implicit tile. + * + * This is the coordinate referring to the nearest subtree root. + * + * @returns The local coordinate + */ + getLocalCoordinate(): TreeCoordinates { + return this._localCoordinate; + } + + /** + * Returns the global coordinate of this implicit tile. + * + * This is the coordinate referring to the root of the + * implicit tile hierarchy. + * + * @returns The global coordinate + */ + getGlobalCoordinate(): TreeCoordinates { + return this._globalCoordinate; + } + + /** {@inheritDoc TraversedTile.getParent} */ + getParent(): TraversedTile | undefined { + return this._parent; + } + + /** {@inheritDoc TraversedTile.getChildren} */ + async getChildren(): Promise { + const localLevel = this._localCoordinate.level; + if (localLevel === this._implicitTiling.subtreeLevels - 1) { + const children = await this.createNextSubtreeLevelChildren(); + return children; + } + const children = await this.createDirectChildren(); + return children; + } + + /** + * Creates the children for this tile at which a new subtree starts. + * + * This assumes that this tile is in the last level of the subtree + * that it belongs to. This method will create one child tile for + * each available child subtree. These children will be the "local + * roots" of their respective subtree. + * + * @returns The children + * @throws ImplicitTilingError If the input data was invalid + */ + private async createNextSubtreeLevelChildren(): Promise { + const subtreeInfo = this._subtreeModel.subtreeInfo; + const traversedChildren = []; + const localChildCoordinates = this._localCoordinate.children(); + for (const localChildCoordinate of localChildCoordinates) { + const globalChildCoordinate = ImplicitTilings.globalizeCoordinates( + this._implicitTiling, + this._rootCoordinate, + localChildCoordinate + ); + const childSubtreeAvailability = subtreeInfo.childSubtreeAvailabilityInfo; + const childSubtreeAvailable = childSubtreeAvailability.isAvailable( + localChildCoordinate.toIndexInLevel() + ); + if (childSubtreeAvailable) { + const schema = this._subtreeModel.subtreeMetadataModel?.schema; + + const childSubtreeModel = await SubtreeModels.resolve( + this._implicitTiling, + schema, + this._resourceResolver, + globalChildCoordinate + ); + + const childLocalCoordinate = ImplicitTilings.createRootCoordinates( + this._implicitTiling + ); + // The path is composed from the path of the root and the string + // representation of the global coordinates of the child + const coordinateString = ImplicitTilings.createString( + globalChildCoordinate + ); + const childPath = `${this._root.path}/${coordinateString}`; + + const traversedChild = new ImplicitTraversedTile( + this._implicitTiling, + this._resourceResolver, + this._root, + childPath, + childSubtreeModel, + this._globalLevel + 1, + globalChildCoordinate, + globalChildCoordinate, + childLocalCoordinate, + this + ); + traversedChildren.push(traversedChild); + } + } + return traversedChildren; + } + + /** + * Creates the children for this tile that are still within the same subtree. + * + * This assumes that this tile is **NOT** in the last level of the subtree. + * It will return all children that are marked as available, via the + * tile availability information in the subtree that this tile belongs to. + * + * @returns The children + * @throws ImplicitTilingError If the input data was invalid + */ + private async createDirectChildren(): Promise { + const subtreeInfo = this._subtreeModel.subtreeInfo; + const tileAvailabilityInfo = subtreeInfo.tileAvailabilityInfo; + const localChildCoordinates = this._localCoordinate.children(); + const traversedChildren = []; + for (const localChildCoordinate of localChildCoordinates) { + const available = tileAvailabilityInfo.isAvailable( + localChildCoordinate.toIndex() + ); + if (available) { + const globalChildCoordinate = ImplicitTilings.globalizeCoordinates( + this._implicitTiling, + this._rootCoordinate, + localChildCoordinate + ); + + // The path is composed from the path of the root and the string + // representation of the global coordinates of the child + const coordinateString = ImplicitTilings.createString( + globalChildCoordinate + ); + const childPath = `${this._root.path}/${coordinateString}`; + + const traversedChild = new ImplicitTraversedTile( + this._implicitTiling, + this._resourceResolver, + this._root, + childPath, + this._subtreeModel, + this._globalLevel + 1, + globalChildCoordinate, + this._rootCoordinate, + localChildCoordinate, + this + ); + traversedChildren.push(traversedChild); + } + } + return traversedChildren; + } + + /** {@inheritDoc TraversedTile.getRawContents} */ + getRawContents(): Content[] { + const contents = []; + const subtreeInfo = this._subtreeModel.subtreeInfo; + const contentAvailabilityInfos = subtreeInfo.contentAvailabilityInfos; + for (const contentAvailabilityInfo of contentAvailabilityInfos) { + const available = contentAvailabilityInfo.isAvailable( + this._localCoordinate.toIndex() + ); + if (available) { + // TODO The existence of the root content URI should + // have been validated. So this could also throw + // an error if the template URI is not found. + const templateUri = this._root.asRawTile().content?.uri; + if (defined(templateUri)) { + const contentUri = ImplicitTilings.substituteTemplateUri( + this._implicitTiling.subdivisionScheme, + templateUri, + this._globalCoordinate + ); + const content: Content = { + boundingVolume: undefined, + uri: contentUri, + metadata: undefined, + group: undefined, + }; + contents.push(content); + } + } + } + return contents; + } + + /** {@inheritDoc TraversedTile.getFinalContents} */ + getFinalContents(): Content[] { + const contents = this.getRawContents(); + const subtreeMetadataModel = this._subtreeModel.subtreeMetadataModel; + if (!subtreeMetadataModel) { + return contents; + } + for (let i = 0; i < contents.length; i++) { + const content = contents[i]; + const tileIndex = this._localCoordinate.toIndex(); + MetadataSemanticOverrides.applyImplicitContentMetadataSemanticOverrides( + content, + i, + tileIndex, + subtreeMetadataModel + ); + } + return contents; + } + + /** {@inheritDoc TraversedTile.getSubtreeUri} */ + getSubtreeUri(): string | undefined { + const localCoordinate = this._localCoordinate; + if (localCoordinate.level === 0) { + const globalCoordinate = this._globalCoordinate; + const implicitTiling = this._implicitTiling; + const subtreeUri = ImplicitTilings.substituteTemplateUri( + implicitTiling.subdivisionScheme, + implicitTiling.subtrees.uri, + globalCoordinate + ); + return subtreeUri; + } + return undefined; + } + + /** {@inheritDoc TraversedTile.getImplicitTiling} */ + getImplicitTiling(): TileImplicitTiling | undefined { + const localCoordinate = this._localCoordinate; + if (localCoordinate.level === 0) { + return this._implicitTiling; + } + } + + /** {@inheritDoc TraversedTile.getMetadata} */ + getMetadata(): MetadataEntity | undefined { + return undefined; + } + + /** {@inheritDoc TraversedTile.resolveUri} */ + resolveUri(uri: string): string { + return this._resourceResolver.resolveUri(uri); + } + + // TODO For debugging + toString = (): string => { + return ( + `ImplicitTraversedTile, ` + + `level ${this._globalLevel}, ` + + `global: ${this._globalCoordinate}, ` + + `root: ${this._rootCoordinate}, ` + + `local: ${this._localCoordinate}` + //`path ${this.path}` + ); + }; +} diff --git a/src/traversal/MetadataSemanticOverrides.ts b/src/traversal/MetadataSemanticOverrides.ts new file mode 100644 index 00000000..fde547fb --- /dev/null +++ b/src/traversal/MetadataSemanticOverrides.ts @@ -0,0 +1,267 @@ +import { defined } from "../base/defined"; + +import { Tile } from "../structure/Tile"; +import { Content } from "../structure/Content"; +import { Schema } from "../structure/Metadata/Schema"; + +import { MetadataEntityModel } from "../metadata/MetadataEntityModel"; +import { MetadataEntityModels } from "../metadata/MetadataEntityModels"; + +import { SubtreeMetadataModel } from "./SubtreeMetadataModel"; + +import { ImplicitTilingError } from "../implicitTiling/ImplicitTilingError"; + +/** + * Methods for overriding properties in `Tile` and `Content` objects, + * based on metadata semantics. + * + * @internal + */ +export class MetadataSemanticOverrides { + // TODO There are far too few error checks (e.g. for invalid + // indices) here. This COULD be delegated to the assumption + // that the input is "valid" (as determined by the validator), + // but the error handling here should still be improvev. + + /** + * Perform the overrides of the properties of the given tile that + * are given by metadata semantics. + * + * If the given tile contains a `MetadataEntity`, then the property + * values of that metadata entity are examined. The property values + * that have a semantic will be used to override the corresponding + * values in the given tile. + * + * For example, when the metadata entity has a property with the + * semantic `TILE_GEOMETRIC_ERROR`, then the `geometricError` in + * the given tile will be replaced with the corresponding value + * from the metadata entity. + * + * @param tile - The tile + * @param schema - The metadata schema + * @throws ImplicitTilingError If the input (for example, the + * schema and the metadata entity) are not structurally valid. + */ + static applyExplicitTileMetadataSemanticOverrides( + tile: Tile, + schema: Schema + ) { + const metadata = tile.metadata; + if (!metadata) { + return; + } + let metadataEntityModel = undefined; + try { + metadataEntityModel = MetadataEntityModels.create(schema, metadata); + } catch (error) { + const message = `Error while traversing tileset: ${error}`; + throw new ImplicitTilingError(message); + } + MetadataSemanticOverrides.applyToTile(tile, metadataEntityModel); + } + + /** + * Perform the overrides of the properties of the given content that + * are given by metadata semantics. + * + * If the given content contains `MetadataEntity`, then the property + * values of that metadata entity are examined. The property values + * that have a semantic will be used to override the corresponding + * values in the given content. + * + * @param content - The content + * @param schema - The metadata schema + * @throws ImplicitTilingError If the input (for example, the + * schema and the metadata entity) are not structurally valid. + */ + static applyExplicitContentMetadataSemanticOverrides( + content: Content, + schema: Schema + ) { + const metadata = content.metadata; + if (!metadata) { + return; + } + + let metadataEntityModel = undefined; + try { + metadataEntityModel = MetadataEntityModels.create(schema, metadata); + } catch (error) { + const message = `Error while traversing tileset: ${error}`; + throw new ImplicitTilingError(message); + } + MetadataSemanticOverrides.applyToContent(content, metadataEntityModel); + } + + /** + * Perform the overrides of the properties of the given tile that + * are given by metadata semantics. + * + * If the given subtreeMetadataModel contains tile metadata, then + * the values of the metadata entity for the given tile are examined. + * The property values that have a semantic will be used to override + * the corresponding values in the given tile. + * + * @param tile - The tile + * @param tileIndex - The tile index (referring to availability indexing) + * @param subtreeMetadataModel - The `SubtreeMetadataModel` + * @throws ImplicitTilingError If the input (for example, the + * schema and the metadata entity) are not structurally valid. + */ + static applyImplicitTileMetadataSemanticOverrides( + tile: Tile, + tileIndex: number, + subtreeMetadataModel: SubtreeMetadataModel + ) { + if ( + subtreeMetadataModel.tileMetadataModel && + subtreeMetadataModel.tileIndexMapping + ) { + const metadataIndex = subtreeMetadataModel.tileIndexMapping[tileIndex]; + const tileMetadataModel = subtreeMetadataModel.tileMetadataModel; + const metadataEntityModel = + tileMetadataModel.getMetadataEntityModel(metadataIndex); + MetadataSemanticOverrides.applyToTile(tile, metadataEntityModel); + } + } + + /** + * Perform the overrides of the properties of the given content that + * are given by metadata semantics. + * + * If the given subtreeMetadataModel contains content metadata, then + * the values of the metadata entity for the given content are examined. + * The property values that have a semantic will be used to override + * the corresponding values in the given content. + * + * @param content - The content + * @param contentSetIndex - The content set index, which is `0` for + * single contents, `0` or `1` for two contents, and so on. + * @param tileIndex - The tile index (referring to availability indexing) + * @param subtreeMetadataModel - The `SubtreeMetadataModel` + * @throws ImplicitTilingError If the input (for example, the + * schema and the metadata entity) are not structurally valid. + */ + static applyImplicitContentMetadataSemanticOverrides( + content: Content, + contentSetIndex: number, + tileIndex: number, + subtreeMetadataModel: SubtreeMetadataModel + ) { + if ( + subtreeMetadataModel.contentMetadataModels && + subtreeMetadataModel.contentIndexMappings && + contentSetIndex < subtreeMetadataModel.contentMetadataModels.length + ) { + const metadataIndex = + subtreeMetadataModel.contentIndexMappings[contentSetIndex][tileIndex]; + const contentMetadataModel = + subtreeMetadataModel.contentMetadataModels[contentSetIndex]; + const metadataEntityModel = + contentMetadataModel.getMetadataEntityModel(metadataIndex); + MetadataSemanticOverrides.applyToContent(content, metadataEntityModel); + } + } + + /** + * Applies all overrides to the given tile, based in the property + * values that are found in the given metadata entity model. + * + * @param tile - The tile that will be modified + * @param metadataEntityModel - The `MetadataEntityModel` + */ + private static applyToTile( + tile: Tile, + metadataEntityModel: MetadataEntityModel + ) { + const semanticBoundingBox = + metadataEntityModel.getPropertyValueBySemantic("TILE_BOUNDING_BOX"); + if (semanticBoundingBox) { + tile.boundingVolume.box = semanticBoundingBox; + } + + const semanticBoundingRegion = + metadataEntityModel.getPropertyValueBySemantic("TILE_BOUNDING_REGION"); + if (semanticBoundingRegion) { + tile.boundingVolume.region = semanticBoundingRegion; + } + + const semanticBoundingSphere = + metadataEntityModel.getPropertyValueBySemantic("TILE_BOUNDING_SPHERE"); + if (semanticBoundingSphere) { + tile.boundingVolume.sphere = semanticBoundingSphere; + } + + const semanticGeometricError = + metadataEntityModel.getPropertyValueBySemantic("TILE_GEOMETRIC_ERROR"); + if (defined(semanticGeometricError)) { + tile.geometricError = semanticGeometricError as number; + } + + const semanticRefine = + metadataEntityModel.getPropertyValueBySemantic("TILE_REFINE"); + if (semanticRefine === 0) { + tile.refine = "ADD"; + } else if (semanticRefine === 1) { + tile.refine = "REPLACE"; + } + + const semanticTransform = + metadataEntityModel.getPropertyValueBySemantic("TILE_TRANSFORM"); + if (semanticTransform) { + tile.transform = semanticTransform; + } + } + + /** + * Applies all overrides to the given content, based in the property + * values that are found in the given metadata entity model. + * + * @param content - The content that will be modified + * @param metadataEntityModel - The `MetadataEntityModel` + */ + private static applyToContent( + content: Content, + metadataEntityModel: MetadataEntityModel + ) { + const semanticBoundingBox = metadataEntityModel.getPropertyValueBySemantic( + "CONTENT_BOUNDING_BOX" + ); + if (semanticBoundingBox) { + if (!content.boundingVolume) { + content.boundingVolume = {}; + } + content.boundingVolume.box = semanticBoundingBox; + } + + const semanticBoundingRegion = + metadataEntityModel.getPropertyValueBySemantic("CONTENT_BOUNDING_REGION"); + if (semanticBoundingRegion) { + if (!content.boundingVolume) { + content.boundingVolume = {}; + } + content.boundingVolume.region = semanticBoundingRegion; + } + + const semanticBoundingSphere = + metadataEntityModel.getPropertyValueBySemantic("CONTENT_BOUNDING_SPHERE"); + if (semanticBoundingSphere) { + if (!content.boundingVolume) { + content.boundingVolume = {}; + } + content.boundingVolume.sphere = semanticBoundingSphere; + } + + const semanticUri = + metadataEntityModel.getPropertyValueBySemantic("CONTENT_URI"); + if (defined(semanticUri)) { + content.uri = semanticUri as string; + } + + const semanticGroupId = + metadataEntityModel.getPropertyValueBySemantic("CONTENT_GROUP_ID"); + if (defined(semanticGroupId)) { + content.group = semanticGroupId as number; + } + } +} diff --git a/src/traversal/SubtreeMetadataModel.ts b/src/traversal/SubtreeMetadataModel.ts new file mode 100644 index 00000000..2a42b4ec --- /dev/null +++ b/src/traversal/SubtreeMetadataModel.ts @@ -0,0 +1,71 @@ +import { PropertyTableModel } from "../metadata/PropertyTableModel"; +import { Schema } from "../structure/Metadata/Schema"; + +/** + * An interface summarizing the metadata that may be associated + * with a subtree. + * + * Note: One could consider to offer something like this in the + * `implicitTiling` package, alongside the `SubtreeInfo`. But + * the structure of this interface is too much tailored for + * its use in the traversal right now. If it was supposed to + * be offered as a public interface, then the 'index mappings' + * should probably be hidden behind some function like + * m = getMetadataEntityModelForTile(tileIndex); + * that does the index lookup internally. + * + * @internal + */ +export interface SubtreeMetadataModel { + /** + * The schema to which this metadata complies + */ + schema: Schema; + + /** + * The tile metadata. + * + * This is the property table that is indexed via `subtree.tileMetadata` + * in the array of property tables that are defined by the subtree + * (or `undefined` when the subtree does not have tile metadata) + */ + tileMetadataModel: PropertyTableModel | undefined; + + /** + * The mapping from tile indices to the rows of the + * tileMetadataModel that contain the metadata for + * the respective tile. + * + * (See SubtreeMetadataModels.computeAvailabilityIndexingMapping + * for details) + */ + tileIndexMapping: number[] | undefined; + + /** + * The content metadata. + * + * These are the property tables that are indexed via `subtree.contentMetadata` + * in the array of property tables that are defined by the subtree, or + * the empty array when the subtree does not have content metadata. + */ + contentMetadataModels: PropertyTableModel[]; + + /** + * The mappings from content indices to the rows of the + * contentMetadataModels that contain the metadata for + * the respective content. + * + * The order is + * `contentIndexMappings[contentSetIndex][contentIndex]` + * where + * - the `contentSetIndex` is `0` for single contents, + * `0` or `1` for two contents, and so on + * - the `contentIndex` is `n` for the `n-th` available content + * + * (Yes, this should really be hidden behind an interface...) + * + * (See SubtreeMetadataModels.computeAvailabilityIndexingMapping + * for details) + */ + contentIndexMappings: number[][]; +} diff --git a/src/traversal/SubtreeMetadataModels.ts b/src/traversal/SubtreeMetadataModels.ts new file mode 100644 index 00000000..8d083d64 --- /dev/null +++ b/src/traversal/SubtreeMetadataModels.ts @@ -0,0 +1,181 @@ +import { defined } from "../base/defined"; + +import { Schema } from "../structure/Metadata/Schema"; + +import { MetadataError } from "../metadata/MetadataError"; +import { MetadataUtilities } from "../metadata/MetadataUtilities"; +import { PropertyTableModel } from "../metadata/PropertyTableModel"; + +import { BinaryPropertyTable } from "../metadata/binary/BinaryPropertyTable"; +import { BinaryPropertyTableModel } from "../metadata/binary/BinaryPropertyTableModel"; + +import { BinarySubtreeData } from "../implicitTiling/BinarySubtreeData"; +import { SubtreeInfo } from "../implicitTiling/SubtreeInfo"; +import { AvailabilityInfo } from "../implicitTiling/AvailabilityInfo"; + +import { SubtreeMetadataModel } from "./SubtreeMetadataModel"; + +/** + * Methods to create `SubtreeMetadataModel` instances + * + * @internal + */ +export class SubtreeMetadataModels { + /** + * Creates a `SubtreeMetadataModel` from the given data. + * + * TODO Maybe add some proper comment here... + * + * @param binarySubtreeData - The `BinarySubtreeData` + * @param subtreeInfo - The `SubtreeInfo` + * @param schema - The metadata `Schema` + * @returns The `SubtreeMetadataModel` + */ + static create( + binarySubtreeData: BinarySubtreeData, + subtreeInfo: SubtreeInfo, + schema: Schema + ): SubtreeMetadataModel { + const subtree = binarySubtreeData.subtree; + const binaryBufferStructure = binarySubtreeData.binaryBufferStructure; + const binaryBufferData = binarySubtreeData.binaryBufferData; + + // Obtain the structural information about the schema that + // is required for creating the property table models + const propertyTableModels = []; + const binaryEnumInfo = MetadataUtilities.computeBinaryEnumInfo(schema); + const propertyTables = subtree.propertyTables; + if (propertyTables) { + const classes = schema.classes ?? {}; + + for (const propertyTable of propertyTables) { + const classId = propertyTable.class; + const metadataClass = classes[classId]; + if (!metadataClass) { + throw new MetadataError( + `The property table refers to class ${classId}, ` + + `but the schema does not define this class` + ); + } + + // Create the `BinaryPropertyTable` for each property table, + // which contains everything that is required for creating + // the binary PropertyTableModel + const binaryPropertyTable: BinaryPropertyTable = { + propertyTable: propertyTable, + metadataClass: metadataClass, + binaryEnumInfo: binaryEnumInfo, + binaryBufferStructure: binaryBufferStructure, + binaryBufferData: binaryBufferData, + }; + const propertyTableModel = new BinaryPropertyTableModel( + binaryPropertyTable + ); + propertyTableModels.push(propertyTableModel); + } + } + + // Obtain the property table model that is pointed to + // by subtree.tileMetadata + let tileMetadataModel = undefined; + if (defined(subtree.tileMetadata)) { + tileMetadataModel = propertyTableModels[subtree.tileMetadata]; + if (!tileMetadataModel) { + throw new MetadataError( + `The subtree tileMetadata refers to property ` + + `table ${subtree.tileMetadata}, but the subtree only ` + + `defines ${propertyTableModels.length} property tables` + ); + } + } + + // Obtain the property table models that are pointed to + // by subtree.contentMetadata + const contentMetadataModels: PropertyTableModel[] = []; + if (subtree.contentMetadata) { + for (const contentMetadata of subtree.contentMetadata) { + const contentMetadataModel = propertyTableModels[contentMetadata]; + if (!contentMetadataModel) { + throw new MetadataError( + `The subtree contentMetadata refers to property ` + + `table ${contentMetadata}, but the subtree only ` + + `defines ${propertyTableModels.length} property tables` + ); + } + } + } + + // Compute the mapping from (available) tiles to the indices + // of their metadata (i.e. the row index in the property table + // that contains the metadata for the respective tile) + const tileAvailabilityInfo = subtreeInfo.tileAvailabilityInfo; + const tileMetadataIndexMapping = + SubtreeMetadataModels.computeAvailabilityIndexingMapping( + tileAvailabilityInfo + ); + + // Compute the mapping from (available) contents to the indices + // of their metadata (i.e. the row index in the property table + // that contains the metadata for the respective content) + const contentMetadataIndexMappings: number[][] = []; + const contentAvailabilityInfos = subtreeInfo.contentAvailabilityInfos; + for (const contentAvailabilityInfo of contentAvailabilityInfos) { + const contentMetadataIndexMapping = + SubtreeMetadataModels.computeAvailabilityIndexingMapping( + contentAvailabilityInfo + ); + contentMetadataIndexMappings.push(contentMetadataIndexMapping); + } + + const subtreeMetadataModel: SubtreeMetadataModel = { + schema: schema, + tileMetadataModel: tileMetadataModel, + tileIndexMapping: tileMetadataIndexMapping, + contentMetadataModels: contentMetadataModels, + contentIndexMappings: contentMetadataIndexMappings, + }; + return subtreeMetadataModel; + } + + /** + * Computes the mapping of indices inside the availability + * information to the number that says how many elements + * have been available up to this index, if the element + * at the respective index is available. + * + * Yes, that sounds complicated. But it is used for accessing + * the metadata that is stored in the subtree (see the 3D Tiles + * specification, "ImplicitTiling - Tile Metadata"). + * + * Quote: + * "If `i` available tiles occur before a particular tile, that + * tile’s property values are stored at index `i` of each + * property value array." + * + * This means that when the availability bitstream is + * [1, 0, 1, 1, 0] then this method will return an array + * [0, _, 1, 2, _]. + * + * The value of the `_` entries will be set to `-1`. + * + * @param availabilityInfo - The `AvailabilityInfo` + * @returns The index mapping + */ + private static computeAvailabilityIndexingMapping( + availabilityInfo: AvailabilityInfo + ): number[] { + const n = availabilityInfo.length; + const indexMapping = new Array(n); + let index = 0; + for (let i = 0; i < n; i++) { + const available = availabilityInfo.isAvailable(i); + if (available) { + indexMapping[i] = index; + index++; + } else { + indexMapping[i] = -1; + } + } + return indexMapping; + } +} diff --git a/src/traversal/SubtreeModel.ts b/src/traversal/SubtreeModel.ts new file mode 100644 index 00000000..b29719b1 --- /dev/null +++ b/src/traversal/SubtreeModel.ts @@ -0,0 +1,20 @@ +import { SubtreeInfo } from "../implicitTiling/SubtreeInfo"; +import { SubtreeMetadataModel } from "./SubtreeMetadataModel"; + +/** + * An interface that summarizes the information for a subtree. + * + * @internal + */ +export interface SubtreeModel { + /** + * The `SubtreeInfo` that summarizes the availability information + */ + subtreeInfo: SubtreeInfo; + + /** + * The optional `SubtreeMetadataModel` that contains the metadata + * associated with this subtree. + */ + subtreeMetadataModel: SubtreeMetadataModel | undefined; +} diff --git a/src/traversal/SubtreeModels.ts b/src/traversal/SubtreeModels.ts new file mode 100644 index 00000000..8c90170e --- /dev/null +++ b/src/traversal/SubtreeModels.ts @@ -0,0 +1,166 @@ +import path from "path"; + +import { defined } from "../base/defined"; +import { Buffers } from "../base/Buffers"; + +import { ResourceResolver } from "../io/ResourceResolver"; + +import { BinarySubtreeData } from "../implicitTiling/BinarySubtreeData"; +import { BinarySubtreeDataResolver } from "../implicitTiling/BinarySubtreeDataResolver"; +import { ImplicitTilingError } from "../implicitTiling/ImplicitTilingError"; +import { ImplicitTilings } from "../implicitTiling/ImplicitTilings"; +import { SubtreeInfos } from "../implicitTiling/SubtreeInfos"; + +import { TreeCoordinates } from "../spatial/TreeCoordinates"; + +import { Subtree } from "../structure/Subtree"; +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; +import { Schema } from "../structure/Metadata/Schema"; + +import { SubtreeModel } from "./SubtreeModel"; +import { SubtreeMetadataModels } from "./SubtreeMetadataModels"; + +/** + * Methods to resolve subtree information. + * + * The methods will resolve the data for a subtree, based on the template + * URI from the implicit tiling and the root coordinates of the subtree, + * and offer this information as `SubtreeModel` objects. + * + * @internal + */ +export class SubtreeModels { + /** + * Resolve the `SubtreeModel` for the subtree with the given root coordinates. + * + * This will substitute the given coordinates into the subtree template + * URI from the given implicit tiling object. Then it will attempt to load + * the subtree data from this URI. The resulting data will be used to + * construct the `SubtreeModel` object. + * + * @param implicitTiling - The `TileImplicitTiling` + * @param schema - The optional metadata schema + * @param resourceResolver - The `ResourceResolver` for the subtree + * files and buffers + * @param coordinates - The root coordinates of the subtree + * @returns The `SubtreeModel` + * @throws ImplicitTilingError If the input was structurally invalid + */ + static async resolve( + implicitTiling: TileImplicitTiling, + schema: Schema | undefined, + resourceResolver: ResourceResolver, + coordinates: TreeCoordinates + ): Promise { + // Obtain the raw subtree data by resolving the data from + // the URI that is created from the template URI and the + // coordinates + const subtreeUri = ImplicitTilings.substituteTemplateUri( + implicitTiling.subdivisionScheme, + implicitTiling.subtrees.uri, + coordinates + ); + if (!defined(subtreeUri)) { + const message = + `Could not substitute coordinates ${coordinates} in ` + + `subtree template URI ${implicitTiling.subtrees.uri}`; + throw new ImplicitTilingError(message); + } + const subtreeData = await resourceResolver.resolveData(subtreeUri); + if (!subtreeData) { + const message = + `Could not resolve subtree URI ${subtreeUri} that was ` + + `created from template URI ${implicitTiling.subtrees.uri} ` + + `for coordinates ${coordinates}`; + throw new ImplicitTilingError(message); + } + + // Create the resource resolver that will be used + // for resolving references (buffer URIs) relative + // to the directory that contained the subtree data + const subtreeDirectory = path.dirname(subtreeUri); + const subtreeResourceResolver = resourceResolver.derive(subtreeDirectory); + + // If the subtree data was JSON, just parse it and + // create a SubtreeModel from it + const isJson = Buffers.isProbablyJson(subtreeData); + if (isJson) { + let subtreeJson: any; + let subtree: Subtree; + try { + subtreeJson = Buffers.getJson(subtreeData); + subtree = subtreeJson; + } catch (error) { + const message = + `Could not parse subtree JSON from URI ${subtreeUri} that was ` + + `created from template URI ${implicitTiling.subtrees.uri} ` + + `for coordinates ${coordinates}`; + throw new ImplicitTilingError(message); + } + + const binarySubtreeData = await BinarySubtreeDataResolver.resolveFromJson( + subtree, + subtreeResourceResolver + ); + const subtreeModel = SubtreeModels.create( + binarySubtreeData, + implicitTiling, + schema + ); + return subtreeModel; + } + + // For SUBT (binary subtree data), create the SubtreeModel + // from the whole buffer + const isSubt = Buffers.getMagic(subtreeData) === "subt"; + if (isSubt) { + const binarySubtreeData = + await BinarySubtreeDataResolver.resolveFromBuffer( + subtreeData, + subtreeResourceResolver + ); + const subtreeModel = SubtreeModels.create( + binarySubtreeData, + implicitTiling, + schema + ); + return subtreeModel; + } + + const message = + `Subtree data from URI ${subtreeUri} that was created from ` + + `template URI ${implicitTiling.subtrees.uri} for coordinates ` + + `${coordinates} did neither contain JSON nor binary subtree data`; + throw new ImplicitTilingError(message); + } + + /** + * Creates the `SubtreeModel` from the given binary subtree data + * + * @param binarySubtreeData - The binary subtree data + * @param implicitTiling - The `TileImplicitTiling` + * @param schema - The optional metadata schema + * @returns The `SubtreeModel` + * @throws ImplicitTilingError If the input was structurally invalid + */ + private static create( + binarySubtreeData: BinarySubtreeData, + implicitTiling: TileImplicitTiling, + schema: Schema | undefined + ): SubtreeModel { + const subtreeInfo = SubtreeInfos.create(binarySubtreeData, implicitTiling); + let subtreeMetadataModel = undefined; + if (schema) { + subtreeMetadataModel = SubtreeMetadataModels.create( + binarySubtreeData, + subtreeInfo, + schema + ); + } + const subtreeModel: SubtreeModel = { + subtreeInfo: subtreeInfo, + subtreeMetadataModel: subtreeMetadataModel, + }; + return subtreeModel; + } +} diff --git a/src/traversal/TilesetTraverser.ts b/src/traversal/TilesetTraverser.ts new file mode 100644 index 00000000..fb3ac562 --- /dev/null +++ b/src/traversal/TilesetTraverser.ts @@ -0,0 +1,75 @@ +import { ResourceResolver } from "../io/ResourceResolver"; + +import { Tileset } from "../structure/Tileset"; +import { Schema } from "../structure/Metadata/Schema"; + +import { TraversedTile } from "./TraversedTile"; +import { ExplicitTraversedTile } from "./ExplicitTraversedTile"; +import { TraversalCallback } from "./TraversalCallback"; +import { DeveloperError } from "../base/DeveloperError"; + +/** + * A class that can traverse the tiles of a tileset. + * + * @internal + */ +export class TilesetTraverser { + /** + * Traverses the tiles in the given tileset. + * + * This will traverse the tiles of the given tileset, starting + * at the root. It will pass all tiles to the given callback, + * as `TraversedTile` instances. + * + * @param tileset - The `Tileset` + * @param schema - The schema from the `tileset.schema` or the + * `tileset.schemaUri`. If this is defined, then it is assumed + * to be a valid schema definition. + * @param resourceResolver - The `ResourceResolver` that is used to + * resolve resources for implicit tilesets (subtree files) + * @param traversalCallback - The `TraversalCallback` + * @param depthFirst - Whether the traversal should be depth-first + * @returns A Promise that resolves when the traversal finished + */ + static async traverse( + tileset: Tileset, + schema: Schema | undefined, + resourceResolver: ResourceResolver, + traversalCallback: TraversalCallback, + depthFirst: boolean + ): Promise { + const root = tileset.root; + if (!root) { + return; + } + const stack: TraversedTile[] = []; + + const traversedRoot = new ExplicitTraversedTile( + root, + "/root", + 0, + undefined, + schema, + resourceResolver + ); + stack.push(traversedRoot); + + while (stack.length > 0) { + const traversedTile = depthFirst ? stack.pop() : stack.shift(); + if (!traversedTile) { + // This cannot happen, but TypeScript does not know this: + throw new DeveloperError("Empty stack during traversal"); + } + const traverseChildren = await traversalCallback(traversedTile); + + if (traverseChildren) { + const children = await traversedTile.getChildren(); + const length = children.length; + for (let i = 0; i < length; i++) { + const traversedChild = children[i]; + stack.push(traversedChild); + } + } + } + } +} diff --git a/src/traversal/TraversalCallback.ts b/src/traversal/TraversalCallback.ts new file mode 100644 index 00000000..cf27b0f9 --- /dev/null +++ b/src/traversal/TraversalCallback.ts @@ -0,0 +1,20 @@ +import { TraversedTile } from "./TraversedTile"; + +/** + * An interface with a function that will be called by + * a `TilesetTraverser` + * + * @internal + */ +export interface TraversalCallback { + /** + * Will be called with each traversed tile during the + * traversal process. + * + * @param traversedTile - The `TraversedTile` instance + * @returns A promise that resolves to `true` if the + * traversal should continue, and to `false` if the + * traversal should stop. + */ + (traversedTile: TraversedTile): Promise; +} diff --git a/src/traversal/TraversedTile.ts b/src/traversal/TraversedTile.ts new file mode 100644 index 00000000..f9a34591 --- /dev/null +++ b/src/traversal/TraversedTile.ts @@ -0,0 +1,129 @@ +import { Tile } from "../structure/Tile"; +import { Content } from "../structure/Content"; +import { MetadataEntity } from "../structure/MetadataEntity"; +import { TileImplicitTiling } from "../structure/TileImplicitTiling"; + +/** + * An interface that summarizes context information for + * a tile during traversal. + * + * @internal + */ +export interface TraversedTile { + /** + * Returns a `Tile` object that contains the "JSON"-representation + * of the tile. This is just a plain data structure corresponding + * to the tile. + * + * The returned object reflects the "raw" state of the tile that + * is either contained in the tileset JSON, or derived from the + * subdivision rules of implicit tiles. + * + * Specifically: This is the state BEFORE any semantic-based + * overrides have been applied. When there is metadata + * associated with the tile, and this metadata has semantics + * that override certain tile properties, then these overrides + * are NOT reflected in the returned tile. + * + * In order to obtain a tile where the semantic-based overrides + * are applied, `asFinalTile` can be used. + * + * Note that there are no guarantees about identities for the + * returned object. This means that callers should NOT modify + * the returned object or any of its properties, because they + * may be the actual objects that are stored in the tileset + * JSON. + * + * @returns A `Tile` with information about this traversed tile + * @throws ImplicitTilingError If the representation of this traversed + * tile could not be created due to invalid input structures. + */ + asRawTile(): Tile; + + /** + * Returns a `Tile` object that contains the "JSON"-representation + * of the tile. This is just a plain data structure corresponding + * the tile. + * + * In contrast to `asRawTile`, this method returns a `Tile` object + * where semantic-based overrides have already been applied. When + * there is metadata associated with the tile, and this metadata + * has semantics that override certain tile properties, then these + * overrides ARE reflected in the returned tile. + * + * @returns A `Tile` with information about this traversed tile + * @throws ImplicitTilingError If the representation of this traversed + * tile could not be created due to invalid input structures. + */ + asFinalTile(): Tile; + + /** + * Returns the level of the tile in the traversed hierarchy, with + * 0 being the root tile. + * + * @returns The level + */ + get level(): number; + + /** + * Returns a path that identifies this tile within the hierarchy. + * + * This resembles a JSON path. But for cases like implicit tilesets, + * it may contain elements that are not part of the JSONPath format. + * It may therefore only be used as a semi-human-readable identifier. + * The exact format is not specified. Callers should not rely on + * the format. + * + * @returns The path + */ + get path(): string; + + /** + * Returns the parent of this tile, or `undefined` if this is the + * root tile. + * + * @returns The parent tile + */ + getParent(): TraversedTile | undefined; + + /** + * Returns the children of this tile. + * + * For external tilesets or implicit tiling, this may have to + * resolve external resources, and therefore, returns a promise + * that is resolved when the required child tiles are available. + * + * @returns The children + * @throws ImplicitTilingError When there was an error while + * trying to obtain the traversed children. This may be caused + * by invalid input structures, or when a required resource + * (like a subtree file or one of its buffers) could not + * be resolved. + */ + getChildren(): Promise; + + /** + * Returns the `Content` objects of the tile. + * + * This is either an empty array (when the tile does not have + * content), or a single-element array (when the tile has a + * single `tile.content` object), or an array that resembles + * the `tile.contents` array. + * + * @returns The contents + */ + getRawContents(): Content[]; + + // TODO Document or improve this - the same difference as between + // asRawTile and asFinalTile + getFinalContents(): Content[]; + + // TODO Some information has to be exposed here solely + // for the validation. This should preferably not be + // visible in this interface. The traversal might be + // refactored to hide this information here. + getSubtreeUri(): string | undefined; + getImplicitTiling(): TileImplicitTiling | undefined; + getMetadata(): MetadataEntity | undefined; + resolveUri(uri: string): string; +} diff --git a/src/traversal/cesium/BoundingVolumeDerivation.ts b/src/traversal/cesium/BoundingVolumeDerivation.ts new file mode 100644 index 00000000..5175baf2 --- /dev/null +++ b/src/traversal/cesium/BoundingVolumeDerivation.ts @@ -0,0 +1,327 @@ +import { Cartesian3, Math as CesiumMath, Matrix3, Rectangle } from "cesium"; +import { defined } from "../../base/defined"; + +import { BoundingVolume } from "../../structure/BoundingVolume"; + +import { HilbertOrder } from "./HilbertOrder"; +import { S2Cell } from "./S2Cell"; + +import { BoundingVolumeS2 } from "../../structure/extensions/BoundingVolumeS2"; + +/** + * Methods to derive bounding volumes of implicit tiles. + * + * Largely ported from CesiumJS Implicit3DTileContent.js + * + * @internal + */ +export class BoundingVolumeDerivation { + /** + * Given the coordinates of a tile, derive its bounding volume from the root. + * + * @param rootBoundingVolume - The root bounding volume + * @param implicitCoordinates - The coordinates of the child tile, as an + * array [level,x,y] for quadtrees or [level,x,y,z] for octrees. + * @returns An object containing the JSON for a bounding volume, + * or `undefined` if the given bounding volume was of a type from + * which no other bounding volume can be derived (i.e. when it + * was a bounding sphere) + */ + static deriveBoundingVolume( + rootBoundingVolume: BoundingVolume, + implicitCoordinates: number[] + ): BoundingVolume | undefined { + const level = implicitCoordinates[0]; + const x = implicitCoordinates[1]; + const y = implicitCoordinates[2]; + const z = + implicitCoordinates.length > 3 ? implicitCoordinates[3] : undefined; + + if ( + rootBoundingVolume.extensions && + BoundingVolumeDerivation.hasExtension( + rootBoundingVolume, + "3DTILES_bounding_volume_S2" + ) + ) { + const extensions = rootBoundingVolume.extensions; + const s2Object = extensions["3DTILES_bounding_volume_S2"]; + const boundingVolumeS2 = s2Object as BoundingVolumeS2; + const childBoundingVolumeS2 = + BoundingVolumeDerivation.deriveBoundingVolumeS2( + boundingVolumeS2, + level, + x, + y, + z + ); + return { + extensions: { + "3DTILES_bounding_volume_S2": childBoundingVolumeS2, + }, + }; + } + + if (rootBoundingVolume.region) { + const childRegion = BoundingVolumeDerivation.deriveBoundingRegion( + rootBoundingVolume.region, + level, + x, + y, + z + ); + + return { + region: childRegion, + }; + } + if (rootBoundingVolume.box) { + const childBox = BoundingVolumeDerivation.deriveBoundingBox( + rootBoundingVolume.box, + level, + x, + y, + z + ); + + return { + box: childBox, + }; + } + + // Bounding spheres cannot be derived: + return undefined; + } + + /** + * Check if a specific extension is present on a JSON object. This can be used + * for either 3D Tiles extensions or glTF extensions + * @param json - The JSON object + * @param extensionName - The name of the extension, e.g. '3DTILES_implicit_tiling' + * @returns True if the extension is present + * @internal + */ + private static hasExtension(json: any, extensionName: string): boolean { + return json && json.extensions && json.extensions[extensionName]; + } + + private static readonly scratchScaleFactors = new Cartesian3(); + private static readonly scratchRootCenter = new Cartesian3(); + private static readonly scratchCenter = new Cartesian3(); + private static readonly scratchHalfAxes = new Matrix3(); + + /** + * Derive a bounding volume for a descendant tile (child, grandchild, etc.), + * assuming a quadtree or octree implicit tiling scheme. The (level, x, y, [z]) + * coordinates are given to select the descendant tile and compute its position + * and dimensions. + *

+ * If z is present, octree subdivision is used. Otherwise, quadtree subdivision + * is used. Quadtrees are always divided at the midpoint of the the horizontal + * dimensions, i.e. (x, y), leaving the z axis unchanged. + *

+ *

+ * This computes the child volume directly from the root bounding volume rather + * than recursively subdividing to minimize floating point error. + *

+ * + * @param rootBox - An array of 12 numbers representing the bounding box of the root tile + * @param level - The level of the descendant tile relative to the root implicit tile + * @param x - The x coordinate of the descendant tile + * @param y - The y coordinate of the descendant tile + * @param z - The z coordinate of the descendant tile (octree only) + * @returns An array of 12 numbers representing the bounding box of the descendant tile. + */ + private static deriveBoundingBox( + rootBox: number[], + level: number, + x: number, + y: number, + z: number | undefined + ): number[] { + if (level === 0) { + return rootBox; + } + + const rootCenter = Cartesian3.unpack( + rootBox, + 0, + BoundingVolumeDerivation.scratchRootCenter + ); + const rootHalfAxes = Matrix3.unpack( + rootBox, + 3, + BoundingVolumeDerivation.scratchHalfAxes + ); + + const tileScale = Math.pow(2, -level); + const modelSpaceX = -1 + (2 * x + 1) * tileScale; + const modelSpaceY = -1 + (2 * y + 1) * tileScale; + + let modelSpaceZ = 0; + const scaleFactors = Cartesian3.fromElements( + tileScale, + tileScale, + 1, + BoundingVolumeDerivation.scratchScaleFactors + ); + + if (defined(z)) { + modelSpaceZ = -1 + (2 * z + 1) * tileScale; + scaleFactors.z = tileScale; + } + + let center = Cartesian3.fromElements( + modelSpaceX, + modelSpaceY, + modelSpaceZ, + BoundingVolumeDerivation.scratchCenter + ); + center = Matrix3.multiplyByVector( + rootHalfAxes, + center, + BoundingVolumeDerivation.scratchCenter + ); + center = Cartesian3.add( + center, + rootCenter, + BoundingVolumeDerivation.scratchCenter + ); + + let halfAxes = Matrix3.clone(rootHalfAxes); + halfAxes = Matrix3.multiplyByScale(halfAxes, scaleFactors, halfAxes); + + const childBox = new Array(12); + Cartesian3.pack(center, childBox); + Matrix3.pack(halfAxes, childBox, 3); + return childBox; + } + + private static readonly scratchRectangle = new Rectangle(); + /** + * Derive a bounding volume for a descendant tile (child, grandchild, etc.), + * assuming a quadtree or octree implicit tiling scheme. The (level, x, y, [z]) + * coordinates are given to select the descendant tile and compute its position + * and dimensions. + *

+ * If z is present, octree subdivision is used. Otherwise, quadtree subdivision + * is used. Quadtrees are always divided at the midpoint of the the horizontal + * dimensions, i.e. (mid_longitude, mid_latitude), leaving the height values + * unchanged. + *

+ *

+ * This computes the child volume directly from the root bounding volume rather + * than recursively subdividing to minimize floating point error. + *

+ * @param rootRegion - An array of 6 numbers representing the root implicit tile + * @param level - The level of the descendant tile relative to the root implicit tile + * @param x - The x coordinate of the descendant tile + * @param y - The x coordinate of the descendant tile + * @param z - The z coordinate of the descendant tile (octree only) + * @returns An array of 6 numbers representing the bounding region of the descendant tile + * @internal + */ + private static deriveBoundingRegion( + rootRegion: number[], + level: number, + x: number, + y: number, + z: number | undefined + ): number[] { + if (level === 0) { + return rootRegion.slice(); + } + + const rectangle = Rectangle.unpack( + rootRegion, + 0, + BoundingVolumeDerivation.scratchRectangle + ); + const rootMinimumHeight = rootRegion[4]; + const rootMaximumHeight = rootRegion[5]; + const tileScale = Math.pow(2, -level); + + const childWidth = tileScale * rectangle.width; + const west = CesiumMath.negativePiToPi(rectangle.west + x * childWidth); + const east = CesiumMath.negativePiToPi(west + childWidth); + + const childHeight = tileScale * rectangle.height; + const south = CesiumMath.negativePiToPi(rectangle.south + y * childHeight); + const north = CesiumMath.negativePiToPi(south + childHeight); + + // Height is only subdivided for octrees; It remains constant for quadtrees. + let minimumHeight = rootMinimumHeight; + let maximumHeight = rootMaximumHeight; + if (defined(z)) { + const childThickness = + tileScale * (rootMaximumHeight - rootMinimumHeight); + minimumHeight += z * childThickness; + maximumHeight = minimumHeight + childThickness; + } + + return [west, south, east, north, minimumHeight, maximumHeight]; + } + + /** + * Derive a bounding volume for a descendant tile (child, grandchild, etc.), + * assuming a quadtree or octree implicit tiling scheme. The (level, x, y, [z]) + * coordinates are given to select the descendant tile and compute its position + * and dimensions. + *

+ * If z is present, octree subdivision is used. Otherwise, quadtree subdivision + * is used. Quadtrees are always divided at the midpoint of the the horizontal + * dimensions, i.e. (x, y), leaving the z axis unchanged. + *

+ * + * @param level - The level of the descendant tile relative to the root implicit tile + * @param x - The x coordinate of the descendant tile + * @param y - The y coordinate of the descendant tile + * @param z - The z coordinate of the descendant tile (octree only) + * @returns The new bounding volume + * @internal + */ + private static deriveBoundingVolumeS2( + boundingVolumeS2: BoundingVolumeS2, + level: number, + x: number, + y: number, + z: number | undefined + ): BoundingVolumeS2 { + if (level === 0) { + return boundingVolumeS2; + } + // Extract the first 3 face bits from the 64-bit S2 cell ID. + // eslint-disable-next-line no-undef + const baseCellId = S2Cell.getIdFromToken(boundingVolumeS2.token); + const face = Number(baseCellId >> BigInt(61)); + // The Hilbert curve is rotated for the "odd" faces on the S2 Earthcube. + // See http://s2geometry.io/devguide/img/s2cell_global.jpg + const position = + face % 2 === 0 + ? HilbertOrder.encode2D(level, x, y) + : HilbertOrder.encode2D(level, y, x); + const cellId = S2Cell.fromFacePositionLevel(face, BigInt(position), level); + + let minHeight, maxHeight; + if (defined(z)) { + // In CesiumJS, this information was computed from + // the "childIndex" that was passed along, i.e. this + // is equivalent to the condition "childIndex < 4" + const lower = (z & 1) === 0; + + const midpointHeight = + (boundingVolumeS2.maximumHeight + boundingVolumeS2.minimumHeight) / 2; + minHeight = lower ? boundingVolumeS2.minimumHeight : midpointHeight; + maxHeight = lower ? midpointHeight : boundingVolumeS2.maximumHeight; + } else { + minHeight = boundingVolumeS2.minimumHeight; + maxHeight = boundingVolumeS2.maximumHeight; + } + + return { + token: S2Cell.getTokenFromId(cellId), + minimumHeight: minHeight, + maximumHeight: maxHeight, + }; + } +} diff --git a/src/traversal/cesium/HilbertOrder.ts b/src/traversal/cesium/HilbertOrder.ts new file mode 100644 index 00000000..f8cd53a9 --- /dev/null +++ b/src/traversal/cesium/HilbertOrder.ts @@ -0,0 +1,104 @@ +// Ported from https://github.com/CesiumGS/cesium/blob/4b333bc145fa9f7aed0c7ad7e0f46cb001a94ddd/Source/Core/HilbertOrder.js + +import { DeveloperError } from "../../base/DeveloperError"; + +/** + * Hilbert Order helper functions. + */ +export class HilbertOrder { + /** + * Computes the Hilbert index at the given level from 2D coordinates. + * + * @param level - The level of the curve + * @param x - The X coordinate + * @param y - The Y coordinate + * @returns The Hilbert index. + */ + static encode2D(level: number, x: number, y: number): bigint { + const n = Math.pow(2, level); + if (level < 1) { + throw new DeveloperError("Hilbert level cannot be less than 1."); + } + if (x < 0 || x >= n || y < 0 || y >= n) { + throw new DeveloperError("Invalid coordinates for given level."); + } + + const p = { + x: x, + y: y, + }; + let rx, + ry, + s, + index = BigInt(0); + + for (s = n / 2; s > 0; s /= 2) { + rx = (p.x & s) > 0 ? 1 : 0; + ry = (p.y & s) > 0 ? 1 : 0; + index += BigInt(((3 * rx) ^ ry) * s * s); + HilbertOrder.rotate(n, p, rx, ry); + } + + return index; + } + + /** + * Computes the 2D coordinates from the Hilbert index at the given level. + * + * @param level - The level of the curve + * @param index - The Hilbert index + * @returns An array containing the 2D coordinates ([x, y]) corresponding to the Morton index. + * @internal + */ + static decode2D(level: number, index: bigint): number[] { + if (level < 1) { + throw new DeveloperError("Hilbert level cannot be less than 1."); + } + if (index < BigInt(0) || index >= BigInt(Math.pow(4, level))) { + throw new DeveloperError( + "Hilbert index exceeds valid maximum for given level." + ); + } + + const n = Math.pow(2, level); + const p = { + x: 0, + y: 0, + }; + let rx, ry, s, t; + + for (s = 1, t = index; s < n; s *= 2) { + rx = 1 & Number(t / BigInt(2)); + ry = 1 & Number(t ^ BigInt(rx)); + HilbertOrder.rotate(s, p, rx, ry); + p.x += s * rx; + p.y += s * ry; + t /= BigInt(4); + } + + return [p.x, p.y]; + } + + /** + * @internal + */ + private static rotate( + n: number, + p: { x: number; y: number }, + rx: number, + ry: number + ) { + if (ry !== 0) { + return; + } + + if (rx === 1) { + p.x = n - 1 - p.x; + p.y = n - 1 - p.y; + } + + const t = p.x; + p.x = p.y; + p.y = t; + } +} diff --git a/src/traversal/cesium/S2Cell.ts b/src/traversal/cesium/S2Cell.ts new file mode 100644 index 00000000..bcb2b023 --- /dev/null +++ b/src/traversal/cesium/S2Cell.ts @@ -0,0 +1,106 @@ +// Relevant functions ported from https://github.com/CesiumGS/cesium/blob/4b333bc145fa9f7aed0c7ad7e0f46cb001a94ddd/Source/Core/S2Cell.js + +import { DeveloperError } from "../../base/DeveloperError"; + +/** + * Functions related to S2 cells + */ +export class S2Cell { + // The maximum level supported within an S2 cell ID. Each level is represented by two bits in the final cell ID + private static readonly S2_MAX_LEVEL = 30; + + // The number of bits in a S2 cell ID used for specifying the position along the Hilbert curve + private static readonly S2_POSITION_BITS = 2 * S2Cell.S2_MAX_LEVEL + 1; + + // Lookup table for getting trailing zero bits. + // https://graphics.stanford.edu/~seander/bithacks.html + private static readonly Mod67BitPosition = [ + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, 4, 64, 13, 10, + 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, 47, 5, 32, 65, 38, 14, 22, 11, + 58, 18, 53, 63, 9, 61, 27, 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, + 45, 36, 56, 7, 48, 35, 6, 34, 33, 0, + ]; + + /** + * Converts a 64-bit S2 cell ID to an S2 cell token. + * + * @param cellId - The S2 cell ID. + * @returns Returns hexadecimal representation of an S2CellId. + * @internal + */ + static getTokenFromId = function (cellId: bigint): string { + const trailingZeroHexChars = Math.floor( + S2Cell.countTrailingZeroBits(cellId) / 4 + ); + const hexString = cellId.toString(16).replace(/0*$/, ""); + + const zeroString = Array(17 - trailingZeroHexChars - hexString.length).join( + "0" + ); + return zeroString + hexString; + }; + + /** + * Return the number of trailing zeros in number. + * @internal + */ + private static countTrailingZeroBits(x: bigint) { + const index = (-x & x) % BigInt(67); + return S2Cell.Mod67BitPosition[Number(index)]; + } + + /** + * Converts an S2 cell token to a 64-bit S2 cell ID. + * + * @param token - The hexadecimal representation of an S2CellId. Expected to be a valid S2 token. + * @returns Returns the S2 cell ID. + * @internal + */ + static getIdFromToken = function (token: string): bigint { + return BigInt("0x" + token + "0".repeat(16 - token.length)); + }; + + /** + * Creates an S2Cell from its face, position along the Hilbert curve for a given level. + * + * @param face - The root face of S2 this cell is on. Must be in the range [0-5]. + * @param position - The position along the Hilbert curve. Must be in the range [0-4**level). + * @param level - The level of the S2 curve. Must be in the range [0-30]. + * @returns A new S2Cell ID from the given parameters. + * @internal + */ + static fromFacePositionLevel( + face: number, + position: bigint, + level: number + ): bigint { + if (face < 0 || face > 5) { + throw new DeveloperError("Invalid S2 Face (must be within 0-5)"); + } + + if (level < 0 || level > S2Cell.S2_MAX_LEVEL) { + throw new DeveloperError("Invalid level (must be within 0-30)"); + } + if (position < 0 || position >= Math.pow(4, level)) { + throw new DeveloperError("Invalid Hilbert position for level"); + } + + const faceBitString = + (face < 4 ? "0" : "") + (face < 2 ? "0" : "") + face.toString(2); + const positionBitString = position.toString(2); + const positionPrefixPadding = Array( + 2 * level - positionBitString.length + 1 + ).join("0"); + const positionSuffixPadding = Array( + S2Cell.S2_POSITION_BITS - 2 * level + ).join("0"); + + const cellId = BigInt( + `0b${faceBitString}${positionPrefixPadding}${positionBitString}1${ + // Adding the sentinel bit that always follows the position bits. + positionSuffixPadding + }` + ); + return cellId; + } +} diff --git a/tsconfig.json b/tsconfig.json index 688a9221..6bffe9dd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,6 @@ "*": [ "./src/*.d.ts"] } }, - "include": ["src", "demos" ], + "include": ["src" ], "exclude": ["node_modules"] }