UNPKG

@loaders.gl/i3s

Version:
122 lines (108 loc) 3.65 kB
// loaders.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import {TypedArray} from '@loaders.gl/schema'; import { STRING_ATTRIBUTE_TYPE, OBJECT_ID_ATTRIBUTE_TYPE, FLOAT_64_TYPE, INT_16_ATTRIBUTE_TYPE } from './constants'; type Attribute = string[] | TypedArray | null; export type I3STileAttributes = Record<string, Attribute>; /** * Get particular tile and creates attribute object inside. * @param arrayBuffer * @param {Object} options * @returns {Promise<object>} */ export function parseI3STileAttribute(arrayBuffer: ArrayBuffer, options): I3STileAttributes { const {attributeName, attributeType} = options; if (!attributeName) { return {}; } return { [attributeName]: attributeType ? parseAttribute(attributeType, arrayBuffer) : null }; } /** * Parse attributes based on attribute type. * @param {String} attributeType * @param arrayBuffer * @returns */ function parseAttribute(attributeType, arrayBuffer: ArrayBuffer): Attribute { switch (attributeType) { case STRING_ATTRIBUTE_TYPE: return parseStringsAttribute(arrayBuffer); case OBJECT_ID_ATTRIBUTE_TYPE: return parseShortNumberAttribute(arrayBuffer); case FLOAT_64_TYPE: return parseFloatAttribute(arrayBuffer); case INT_16_ATTRIBUTE_TYPE: return parseInt16ShortNumberAttribute(arrayBuffer); default: return parseShortNumberAttribute(arrayBuffer); } } /** * Parse short number attribute. * Short Integer spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md * @param arrayBuffer * @returns */ function parseShortNumberAttribute(arrayBuffer: ArrayBuffer): Uint32Array { const countOffset = 4; return new Uint32Array(arrayBuffer, countOffset); } /** * Parse Int16 short number attribute. * Parsing of such data is not documented. Added to handle Building Scene Layer Tileset attributes data. * @param arrayBuffer * @returns */ function parseInt16ShortNumberAttribute(arrayBuffer: ArrayBuffer): Int16Array { const countOffset = 4; return new Int16Array(arrayBuffer, countOffset); } /** * Parse float attribute. * Double Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md * @param arrayBuffer * @returns */ function parseFloatAttribute(arrayBuffer: ArrayBuffer): Float64Array { const countOffset = 8; return new Float64Array(arrayBuffer, countOffset); } /** * Parse string attribute. * String spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md * @param arrayBuffer * @returns list of strings */ function parseStringsAttribute(arrayBuffer: ArrayBuffer): string[] { const stringsCountOffset = 0; const dataOffset = 8; const bytesPerStringSize = 4; const stringsArray: string[] = []; try { // Use DataView to avoid multiple of 4 error on Uint32Array constructor const stringsCount = new DataView( arrayBuffer, stringsCountOffset, bytesPerStringSize ).getUint32(stringsCountOffset, true); const stringSizes = new Uint32Array(arrayBuffer, dataOffset, stringsCount); let stringOffset = dataOffset + stringsCount * bytesPerStringSize; for (const stringByteSize of stringSizes) { const textDecoder = new TextDecoder('utf-8'); const stringAttribute = new Uint8Array(arrayBuffer, stringOffset, stringByteSize); stringsArray.push(textDecoder.decode(stringAttribute)); stringOffset += stringByteSize; } } catch (error) { console.error('Parse string attribute error: ', (error as Error).message); // eslint-disable-line } return stringsArray; }