@loaders.gl/i3s
Version:
i3s .
1,372 lines (1,349 loc) • 56.6 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// dist/index.js
var dist_exports = {};
__export(dist_exports, {
ArcGISWebSceneLoader: () => ArcGISWebSceneLoader,
COORDINATE_SYSTEM: () => COORDINATE_SYSTEM,
I3SAttributeLoader: () => I3SAttributeLoader,
I3SBuildingSceneLayerLoader: () => I3SBuildingSceneLayerLoader,
I3SContentLoader: () => I3SContentLoader,
I3SLoader: () => I3SLoader,
I3SNodePageLoader: () => I3SNodePageLoader,
LayerError: () => LayerError,
SLPKArchive: () => SLPKArchive,
SLPKLoader: () => SLPKLoader,
customizeColors: () => customizeColors,
loadFeatureAttributes: () => loadFeatureAttributes,
parseSLPKArchive: () => parseSLPKArchive
});
module.exports = __toCommonJS(dist_exports);
// dist/lib/parsers/constants.js
var import_math = require("@loaders.gl/math");
function getConstructorForDataFormat(dataType) {
switch (dataType) {
case "UInt8":
return Uint8Array;
case "UInt16":
return Uint16Array;
case "UInt32":
return Uint32Array;
case "Float32":
return Float32Array;
case "UInt64":
return Float64Array;
default:
throw new Error(`parse i3s tile content: unknown type of data: ${dataType}`);
}
}
var GL_TYPE_MAP = {
UInt8: import_math.GL.UNSIGNED_BYTE,
UInt16: import_math.GL.UNSIGNED_SHORT,
Float32: import_math.GL.FLOAT,
UInt32: import_math.GL.UNSIGNED_INT,
UInt64: import_math.GL.DOUBLE
};
function sizeOf(dataType) {
switch (dataType) {
case "UInt8":
return 1;
case "UInt16":
case "Int16":
return 2;
case "UInt32":
case "Int32":
case "Float32":
return 4;
case "UInt64":
case "Int64":
case "Float64":
return 8;
default:
throw new Error(`parse i3s tile content: unknown size of data: ${dataType}`);
}
}
var STRING_ATTRIBUTE_TYPE = "String";
var OBJECT_ID_ATTRIBUTE_TYPE = "Oid32";
var FLOAT_64_TYPE = "Float64";
var INT_16_ATTRIBUTE_TYPE = "Int16";
var COORDINATE_SYSTEM;
(function(COORDINATE_SYSTEM2) {
COORDINATE_SYSTEM2[COORDINATE_SYSTEM2["DEFAULT"] = -1] = "DEFAULT";
COORDINATE_SYSTEM2[COORDINATE_SYSTEM2["LNGLAT"] = 1] = "LNGLAT";
COORDINATE_SYSTEM2[COORDINATE_SYSTEM2["METER_OFFSETS"] = 2] = "METER_OFFSETS";
COORDINATE_SYSTEM2[COORDINATE_SYSTEM2["LNGLAT_OFFSETS"] = 3] = "LNGLAT_OFFSETS";
COORDINATE_SYSTEM2[COORDINATE_SYSTEM2["CARTESIAN"] = 0] = "CARTESIAN";
})(COORDINATE_SYSTEM || (COORDINATE_SYSTEM = {}));
// dist/i3s-loader.js
var import_core5 = require("@loaders.gl/core");
// dist/lib/parsers/parse-i3s-tile-content.js
var import_core = require("@loaders.gl/core");
var import_core2 = require("@math.gl/core");
var import_geospatial = require("@math.gl/geospatial");
var import_loader_utils = require("@loaders.gl/loader-utils");
var import_images = require("@loaders.gl/images");
var import_draco = require("@loaders.gl/draco");
var import_textures = require("@loaders.gl/textures");
// dist/types.js
var HeaderAttributeProperty;
(function(HeaderAttributeProperty2) {
HeaderAttributeProperty2["vertexCount"] = "vertexCount";
HeaderAttributeProperty2["featureCount"] = "featureCount";
})(HeaderAttributeProperty || (HeaderAttributeProperty = {}));
// dist/lib/utils/url-utils.js
function getUrlWithoutParams(url) {
let urlWithoutParams;
try {
const urlObj = new URL(url);
urlWithoutParams = `${urlObj.origin}${urlObj.pathname}`;
if (urlWithoutParams.startsWith("null")) {
urlWithoutParams = null;
}
} catch (e) {
urlWithoutParams = null;
}
return urlWithoutParams || url;
}
function getUrlWithToken(url, token = null) {
return token ? `${url}?token=${token}` : url;
}
function generateTileAttributeUrls(url, tile) {
const { attributeData = [] } = tile;
const attributeUrls = [];
for (let index = 0; index < attributeData.length; index++) {
const attributeUrl = attributeData[index].href.replace("./", "");
attributeUrls.push(`${url}/${attributeUrl}`);
}
return attributeUrls;
}
function generateTilesetAttributeUrls(tileset, url, resource) {
const attributeUrls = [];
const { attributeStorageInfo = [] } = tileset;
for (let index = 0; index < attributeStorageInfo.length; index++) {
const fileName = attributeStorageInfo[index].key;
attributeUrls.push(`${url}/nodes/${resource}/attributes/${fileName}/0`);
}
return attributeUrls;
}
// dist/lib/parsers/parse-i3s-tile-content.js
var scratchVector = new import_core2.Vector3([0, 0, 0]);
function getLoaderForTextureFormat(textureFormat) {
switch (textureFormat) {
case "ktx-etc2":
case "dds":
return import_textures.CompressedTextureLoader;
case "ktx2":
return import_textures.BasisLoader;
case "jpg":
case "png":
default:
return import_images.ImageLoader;
}
}
var I3S_ATTRIBUTE_TYPE = "i3s-attribute-type";
async function parseI3STileContent(arrayBuffer, tileOptions, tilesetOptions, options, context) {
var _a;
const content = {
attributes: {},
indices: null,
featureIds: [],
vertexCount: 0,
modelMatrix: new import_core2.Matrix4(),
coordinateSystem: 0,
byteLength: 0,
texture: null
};
if (tileOptions.textureUrl) {
const url = getUrlWithToken(tileOptions.textureUrl, (_a = options == null ? void 0 : options.i3s) == null ? void 0 : _a.token);
const loader = getLoaderForTextureFormat(tileOptions.textureFormat);
const fetchFunc = (context == null ? void 0 : context.fetch) || fetch;
const response = await fetchFunc(url);
const arrayBuffer2 = await response.arrayBuffer();
if (options == null ? void 0 : options.i3s.decodeTextures) {
if (loader === import_images.ImageLoader) {
const options2 = { ...tileOptions.textureLoaderOptions, image: { type: "data" } };
try {
const texture = await (0, import_loader_utils.parseFromContext)(arrayBuffer2, [], options2, context);
content.texture = texture;
} catch (e) {
const texture = await (0, import_core.parse)(arrayBuffer2, loader, options2, context);
content.texture = texture;
}
} else if (loader === import_textures.CompressedTextureLoader || loader === import_textures.BasisLoader) {
let texture = await (0, import_core.load)(arrayBuffer2, loader, tileOptions.textureLoaderOptions);
if (loader === import_textures.BasisLoader) {
texture = texture[0];
}
content.texture = {
compressed: true,
mipmaps: false,
width: texture[0].width,
height: texture[0].height,
data: texture
};
}
} else {
content.texture = arrayBuffer2;
}
}
content.material = makePbrMaterial(tileOptions.materialDefinition, content.texture);
if (content.material) {
content.texture = null;
}
return await parseI3SNodeGeometry(arrayBuffer, content, tileOptions, tilesetOptions, options);
}
async function parseI3SNodeGeometry(arrayBuffer, content, tileOptions, tilesetOptions, options) {
var _a, _b;
const contentByteLength = arrayBuffer.byteLength;
let attributes;
let vertexCount;
let byteOffset = 0;
let featureCount = 0;
let indices;
if (tileOptions.isDracoGeometry) {
const decompressedGeometry = await (0, import_core.parse)(arrayBuffer, import_draco.DracoLoader, {
draco: {
attributeNameEntry: I3S_ATTRIBUTE_TYPE
}
});
vertexCount = decompressedGeometry.header.vertexCount;
indices = (_a = decompressedGeometry.indices) == null ? void 0 : _a.value;
const { POSITION, NORMAL, COLOR_0, TEXCOORD_0, ["feature-index"]: featureIndex, ["uv-region"]: uvRegion } = decompressedGeometry.attributes;
attributes = {
position: POSITION,
normal: NORMAL,
color: COLOR_0,
uv0: TEXCOORD_0,
uvRegion,
id: featureIndex
};
updateAttributesMetadata(attributes, decompressedGeometry);
const featureIds = getFeatureIdsFromFeatureIndexMetadata(featureIndex);
if (featureIds) {
flattenFeatureIdsByFeatureIndices(attributes, featureIds);
}
} else {
const { vertexAttributes, ordering: attributesOrder, featureAttributes, featureAttributeOrder } = tilesetOptions.store.defaultGeometrySchema;
const headers = parseHeaders(arrayBuffer, tilesetOptions);
byteOffset = headers.byteOffset;
vertexCount = headers.vertexCount;
featureCount = headers.featureCount;
const { attributes: normalizedVertexAttributes, byteOffset: offset } = normalizeAttributes(arrayBuffer, byteOffset, vertexAttributes, vertexCount, attributesOrder);
const { attributes: normalizedFeatureAttributes } = normalizeAttributes(arrayBuffer, offset, featureAttributes, featureCount, featureAttributeOrder);
flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes);
attributes = concatAttributes(normalizedVertexAttributes, normalizedFeatureAttributes);
}
if (!((_b = options == null ? void 0 : options.i3s) == null ? void 0 : _b.coordinateSystem) || // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
options.i3s.coordinateSystem === COORDINATE_SYSTEM.METER_OFFSETS) {
const enuMatrix = parsePositions(attributes.position, tileOptions);
content.modelMatrix = enuMatrix.invert();
content.coordinateSystem = COORDINATE_SYSTEM.METER_OFFSETS;
} else {
content.modelMatrix = getModelMatrix(attributes.position);
content.coordinateSystem = COORDINATE_SYSTEM.LNGLAT_OFFSETS;
}
content.attributes = {
positions: attributes.position,
normals: attributes.normal,
colors: normalizeAttribute(attributes.color),
// Normalize from UInt8
texCoords: attributes.uv0,
uvRegions: normalizeAttribute(attributes.uvRegion || attributes.region)
// Normalize from UInt16
};
content.indices = indices || null;
if (attributes.id && attributes.id.value) {
content.featureIds = attributes.id.value;
}
for (const attributeIndex in content.attributes) {
if (!content.attributes[attributeIndex]) {
delete content.attributes[attributeIndex];
}
}
content.vertexCount = vertexCount;
content.byteLength = contentByteLength;
return content;
}
function updateAttributesMetadata(attributes, decompressedGeometry) {
for (const key in decompressedGeometry.loaderData.attributes) {
const dracoAttribute = decompressedGeometry.loaderData.attributes[key];
switch (dracoAttribute.name) {
case "POSITION":
attributes.position.metadata = dracoAttribute.metadata;
break;
case "feature-index":
attributes.id.metadata = dracoAttribute.metadata;
break;
default:
break;
}
}
}
function concatAttributes(normalizedVertexAttributes, normalizedFeatureAttributes) {
return { ...normalizedVertexAttributes, ...normalizedFeatureAttributes };
}
function normalizeAttribute(attribute) {
if (!attribute) {
return attribute;
}
attribute.normalized = true;
return attribute;
}
function parseHeaders(arrayBuffer, options) {
let byteOffset = 0;
let vertexCount = 0;
let featureCount = 0;
for (const { property, type } of options.store.defaultGeometrySchema.header) {
const TypedArrayTypeHeader = getConstructorForDataFormat(type);
switch (property) {
case HeaderAttributeProperty.vertexCount.toString():
vertexCount = new TypedArrayTypeHeader(arrayBuffer, 0, 4)[0];
byteOffset += sizeOf(type);
break;
case HeaderAttributeProperty.featureCount.toString():
featureCount = new TypedArrayTypeHeader(arrayBuffer, 4, 4)[0];
byteOffset += sizeOf(type);
break;
default:
break;
}
}
return {
vertexCount,
featureCount,
byteOffset
};
}
function normalizeAttributes(arrayBuffer, byteOffset, vertexAttributes, attributeCount, attributesOrder) {
const attributes = {};
for (const attribute of attributesOrder) {
if (vertexAttributes[attribute]) {
const { valueType, valuesPerElement } = vertexAttributes[attribute];
if (byteOffset + attributeCount * valuesPerElement * sizeOf(valueType) <= arrayBuffer.byteLength) {
const buffer = arrayBuffer.slice(byteOffset);
let value;
if (valueType === "UInt64") {
value = parseUint64Values(buffer, attributeCount * valuesPerElement, sizeOf(valueType));
} else {
const TypedArrayType = getConstructorForDataFormat(valueType);
value = new TypedArrayType(buffer, 0, attributeCount * valuesPerElement);
}
attributes[attribute] = {
value,
type: GL_TYPE_MAP[valueType],
size: valuesPerElement
};
switch (attribute) {
case "color":
attributes.color.normalized = true;
break;
case "position":
case "region":
case "normal":
default:
}
byteOffset = byteOffset + attributeCount * valuesPerElement * sizeOf(valueType);
} else if (attribute !== "uv0") {
break;
}
}
}
return { attributes, byteOffset };
}
function parseUint64Values(buffer, elementsCount, attributeSize) {
const values = [];
const dataView = new DataView(buffer);
let offset = 0;
for (let index = 0; index < elementsCount; index++) {
const left = dataView.getUint32(offset, true);
const right = dataView.getUint32(offset + 4, true);
const value = left + 2 ** 32 * right;
values.push(value);
offset += attributeSize;
}
return new Uint32Array(values);
}
function parsePositions(attribute, options) {
const mbs = options.mbs;
const value = attribute.value;
const metadata = attribute.metadata;
const enuMatrix = new import_core2.Matrix4();
const cartographicOrigin = new import_core2.Vector3(mbs[0], mbs[1], mbs[2]);
const cartesianOrigin = new import_core2.Vector3();
import_geospatial.Ellipsoid.WGS84.cartographicToCartesian(cartographicOrigin, cartesianOrigin);
import_geospatial.Ellipsoid.WGS84.eastNorthUpToFixedFrame(cartesianOrigin, enuMatrix);
attribute.value = offsetsToCartesians(value, metadata, cartographicOrigin);
return enuMatrix;
}
function offsetsToCartesians(vertices, metadata = {}, cartographicOrigin) {
const positions = new Float64Array(vertices.length);
const scaleX = metadata["i3s-scale_x"] && metadata["i3s-scale_x"].double || 1;
const scaleY = metadata["i3s-scale_y"] && metadata["i3s-scale_y"].double || 1;
for (let i = 0; i < positions.length; i += 3) {
positions[i] = vertices[i] * scaleX + cartographicOrigin.x;
positions[i + 1] = vertices[i + 1] * scaleY + cartographicOrigin.y;
positions[i + 2] = vertices[i + 2] + cartographicOrigin.z;
}
for (let i = 0; i < positions.length; i += 3) {
import_geospatial.Ellipsoid.WGS84.cartographicToCartesian(positions.subarray(i, i + 3), scratchVector);
positions[i] = scratchVector.x;
positions[i + 1] = scratchVector.y;
positions[i + 2] = scratchVector.z;
}
return positions;
}
function getModelMatrix(positions) {
var _a, _b;
const metadata = positions.metadata;
const scaleX = ((_a = metadata == null ? void 0 : metadata["i3s-scale_x"]) == null ? void 0 : _a.double) || 1;
const scaleY = ((_b = metadata == null ? void 0 : metadata["i3s-scale_y"]) == null ? void 0 : _b.double) || 1;
const modelMatrix = new import_core2.Matrix4();
modelMatrix[0] = scaleX;
modelMatrix[5] = scaleY;
return modelMatrix;
}
function makePbrMaterial(materialDefinition, texture) {
let pbrMaterial;
if (materialDefinition) {
pbrMaterial = {
...materialDefinition,
pbrMetallicRoughness: materialDefinition.pbrMetallicRoughness ? { ...materialDefinition.pbrMetallicRoughness } : { baseColorFactor: [255, 255, 255, 255] }
};
} else {
pbrMaterial = {
pbrMetallicRoughness: {}
};
if (texture) {
pbrMaterial.pbrMetallicRoughness.baseColorTexture = { texCoord: 0 };
} else {
pbrMaterial.pbrMetallicRoughness.baseColorFactor = [255, 255, 255, 255];
}
}
pbrMaterial.alphaCutoff = pbrMaterial.alphaCutoff || 0.25;
if (pbrMaterial.alphaMode) {
pbrMaterial.alphaMode = pbrMaterial.alphaMode.toUpperCase();
}
if (pbrMaterial.emissiveFactor) {
pbrMaterial.emissiveFactor = convertColorFormat(pbrMaterial.emissiveFactor);
}
if (pbrMaterial.pbrMetallicRoughness && pbrMaterial.pbrMetallicRoughness.baseColorFactor) {
pbrMaterial.pbrMetallicRoughness.baseColorFactor = convertColorFormat(pbrMaterial.pbrMetallicRoughness.baseColorFactor);
}
if (texture) {
setMaterialTexture(pbrMaterial, texture);
}
return pbrMaterial;
}
function convertColorFormat(colorFactor) {
const normalizedColor = [...colorFactor];
for (let index = 0; index < colorFactor.length; index++) {
normalizedColor[index] = colorFactor[index] / 255;
}
return normalizedColor;
}
function setMaterialTexture(material, image) {
const texture = { source: { image } };
if (material.pbrMetallicRoughness && material.pbrMetallicRoughness.baseColorTexture) {
material.pbrMetallicRoughness.baseColorTexture = {
...material.pbrMetallicRoughness.baseColorTexture,
texture
};
} else if (material.emissiveTexture) {
material.emissiveTexture = { ...material.emissiveTexture, texture };
} else if (material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture) {
material.pbrMetallicRoughness.metallicRoughnessTexture = {
...material.pbrMetallicRoughness.metallicRoughnessTexture,
texture
};
} else if (material.normalTexture) {
material.normalTexture = { ...material.normalTexture, texture };
} else if (material.occlusionTexture) {
material.occlusionTexture = { ...material.occlusionTexture, texture };
}
}
function flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes) {
const { id, faceRange } = normalizedFeatureAttributes;
if (!id || !faceRange) {
return;
}
const featureIds = id.value;
const range = faceRange.value;
const featureIdsLength = range[range.length - 1] + 1;
const orderedFeatureIndices = new Uint32Array(featureIdsLength * 3);
let featureIndex = 0;
let startIndex = 0;
for (let index = 1; index < range.length; index += 2) {
const fillId = Number(featureIds[featureIndex]);
const endValue = range[index];
const prevValue = range[index - 1];
const trianglesCount = endValue - prevValue + 1;
const endIndex = startIndex + trianglesCount * 3;
orderedFeatureIndices.fill(fillId, startIndex, endIndex);
featureIndex++;
startIndex = endIndex;
}
normalizedFeatureAttributes.id.value = orderedFeatureIndices;
}
function flattenFeatureIdsByFeatureIndices(attributes, featureIds) {
const featureIndices = attributes.id.value;
const result = new Float32Array(featureIndices.length);
for (let index = 0; index < featureIndices.length; index++) {
result[index] = featureIds[featureIndices[index]];
}
attributes.id.value = result;
}
function getFeatureIdsFromFeatureIndexMetadata(featureIndex) {
var _a, _b;
return (_b = (_a = featureIndex == null ? void 0 : featureIndex.metadata) == null ? void 0 : _a["i3s-feature-ids"]) == null ? void 0 : _b.intArray;
}
// dist/i3s-content-loader.js
var VERSION = true ? "4.3.2" : "latest";
var I3SContentLoader = {
dataType: null,
batchType: null,
name: "I3S Content (Indexed Scene Layers)",
id: "i3s-content",
module: "i3s",
worker: true,
version: VERSION,
mimeTypes: ["application/octet-stream"],
parse: parse2,
extensions: ["bin"],
options: {
"i3s-content": {}
}
};
async function parse2(data, options, context) {
const { tile, _tileOptions, tileset, _tilesetOptions } = (options == null ? void 0 : options.i3s) || {};
const tileOptions = _tileOptions || tile;
const tilesetOptions = _tilesetOptions || tileset;
if (!tileOptions || !tilesetOptions) {
return null;
}
return await parseI3STileContent(data, tileOptions, tilesetOptions, options, context);
}
// dist/lib/parsers/parse-i3s.js
var import_culling = require("@math.gl/culling");
var import_geospatial2 = require("@math.gl/geospatial");
var import_core4 = require("@loaders.gl/core");
var import_tiles = require("@loaders.gl/tiles");
// dist/lib/helpers/i3s-nodepages-tiles.js
var import_core3 = require("@loaders.gl/core");
var import_textures2 = require("@loaders.gl/textures");
// dist/i3s-node-page-loader.js
var VERSION2 = true ? "4.3.2" : "latest";
var I3SNodePageLoader = {
dataType: null,
batchType: null,
name: "I3S Node Page",
id: "i3s-node-page",
module: "i3s",
version: VERSION2,
mimeTypes: ["application/json"],
parse: parseNodePage,
extensions: ["json"],
options: {
i3s: {}
}
};
async function parseNodePage(data, options) {
return JSON.parse(new TextDecoder().decode(data));
}
// dist/lib/helpers/i3s-nodepages-tiles.js
var I3SNodePagesTiles = class {
tileset;
nodePages = [];
pendingNodePages = [];
nodesPerPage;
options;
lodSelectionMetricType;
textureDefinitionsSelectedFormats = [];
nodesInNodePages;
url;
textureLoaderOptions = {};
/**
* @constructs
* Create a I3SNodePagesTiles instance.
* @param tileset - i3s tileset header ('layers/0')
* @param url - tileset url
* @param options - i3s loader options
*/
constructor(tileset, url = "", options) {
var _a, _b;
this.tileset = { ...tileset };
this.url = url;
this.nodesPerPage = ((_a = tileset.nodePages) == null ? void 0 : _a.nodesPerPage) || 64;
this.lodSelectionMetricType = (_b = tileset.nodePages) == null ? void 0 : _b.lodSelectionMetricType;
this.options = options;
this.nodesInNodePages = 0;
this.initSelectedFormatsForTextureDefinitions(tileset);
}
/**
* Loads some nodePage and return a particular node from it
* @param id - id of node through all node pages
*/
async getNodeById(id) {
var _a;
const pageIndex = Math.floor(id / this.nodesPerPage);
if (!this.nodePages[pageIndex] && !this.pendingNodePages[pageIndex]) {
const nodePageUrl = getUrlWithToken(
`${this.url}/nodepages/${pageIndex}`,
// @ts-expect-error this.options is not properly typed
(_a = this.options.i3s) == null ? void 0 : _a.token
);
this.pendingNodePages[pageIndex] = {
status: "Pending",
promise: (0, import_core3.load)(nodePageUrl, I3SNodePageLoader, this.options)
};
this.nodePages[pageIndex] = await this.pendingNodePages[pageIndex].promise;
this.nodesInNodePages += this.nodePages[pageIndex].nodes.length;
this.pendingNodePages[pageIndex].status = "Done";
}
if (this.pendingNodePages[pageIndex].status === "Pending") {
this.nodePages[pageIndex] = await this.pendingNodePages[pageIndex].promise;
}
const nodeIndex = id % this.nodesPerPage;
return this.nodePages[pageIndex].nodes[nodeIndex];
}
/**
* Forms tile header using node and tileset data
* @param id - id of node through all node pages
*/
// eslint-disable-next-line complexity, max-statements
async formTileFromNodePages(id) {
const node = await this.getNodeById(id);
const children = [];
const childNodesPromises = [];
for (const child of node.children || []) {
childNodesPromises.push(this.getNodeById(child));
}
const childNodes = await Promise.all(childNodesPromises);
for (const childNode of childNodes) {
children.push({
id: childNode.index.toString(),
obb: childNode.obb
});
}
let contentUrl;
let textureUrl;
let materialDefinition;
let textureFormat = "jpg";
let attributeUrls = [];
let isDracoGeometry = false;
if (node && node.mesh) {
const { url, isDracoGeometry: isDracoGeometryResult } = node.mesh.geometry && this.getContentUrl(node.mesh.geometry) || { isDracoGeometry: false };
contentUrl = url;
isDracoGeometry = isDracoGeometryResult;
const { textureData, materialDefinition: nodeMaterialDefinition } = this.getInformationFromMaterial(node.mesh.material);
materialDefinition = nodeMaterialDefinition;
textureFormat = textureData.format || textureFormat;
if (textureData.name) {
textureUrl = `${this.url}/nodes/${node.mesh.material.resource}/textures/${textureData.name}`;
}
if (this.tileset.attributeStorageInfo) {
attributeUrls = generateTilesetAttributeUrls(this.tileset, this.url, node.mesh.attribute.resource);
}
}
const lodSelection = this.getLodSelection(node);
return normalizeTileNonUrlData({
id: id.toString(),
lodSelection,
obb: node.obb,
contentUrl,
textureUrl,
attributeUrls,
materialDefinition,
textureFormat,
textureLoaderOptions: this.textureLoaderOptions,
children,
isDracoGeometry
});
}
/**
* Forms url and type of geometry resource by nodepage's data and `geometryDefinitions` in the tileset
* @param - data about the node's mesh from the nodepage
* @returns -
* {string} url - url to the geometry resource
* {boolean} isDracoGeometry - whether the geometry resource contain DRACO compressed geometry
*/
getContentUrl(meshGeometryData) {
let result = null;
const geometryDefinition = this.tileset.geometryDefinitions[meshGeometryData.definition];
let geometryIndex = -1;
if (this.options.i3s && this.options.i3s.useDracoGeometry) {
geometryIndex = geometryDefinition.geometryBuffers.findIndex((buffer) => buffer.compressedAttributes && buffer.compressedAttributes.encoding === "draco");
}
if (geometryIndex === -1) {
geometryIndex = geometryDefinition.geometryBuffers.findIndex((buffer) => !buffer.compressedAttributes);
}
if (geometryIndex !== -1) {
const isDracoGeometry = Boolean(geometryDefinition.geometryBuffers[geometryIndex].compressedAttributes);
result = {
url: `${this.url}/nodes/${meshGeometryData.resource}/geometries/${geometryIndex}`,
isDracoGeometry
};
}
return result;
}
/**
* Forms 1.6 compatible LOD selection object from a nodepage's node data
* @param node - a node from nodepage
* @returns- Array of LodSelection
*/
getLodSelection(node) {
const lodSelection = [];
if (this.lodSelectionMetricType === "maxScreenThresholdSQ") {
lodSelection.push({
metricType: "maxScreenThreshold",
// @ts-ignore
maxError: Math.sqrt(node.lodThreshold / (Math.PI * 0.25))
});
}
lodSelection.push({
metricType: this.lodSelectionMetricType,
// @ts-ignore
maxError: node.lodThreshold
});
return lodSelection;
}
/**
* Returns information about texture and material from `materialDefinitions`
* @param material - material data from nodepage
* @returns - Couple {textureData, materialDefinition}
* {string} textureData.name - path name of the texture
* {string} textureData.format - format of the texture
* materialDefinition - PBR-like material definition from `materialDefinitions`
*/
getInformationFromMaterial(material) {
var _a, _b, _c;
const informationFromMaterial = { textureData: { name: null } };
if (material) {
const materialDefinition = (_a = this.tileset.materialDefinitions) == null ? void 0 : _a[material.definition];
if (materialDefinition) {
informationFromMaterial.materialDefinition = materialDefinition;
const textureSetDefinitionIndex = (_c = (_b = materialDefinition == null ? void 0 : materialDefinition.pbrMetallicRoughness) == null ? void 0 : _b.baseColorTexture) == null ? void 0 : _c.textureSetDefinitionId;
if (typeof textureSetDefinitionIndex === "number") {
informationFromMaterial.textureData = this.textureDefinitionsSelectedFormats[textureSetDefinitionIndex] || informationFromMaterial.textureData;
}
}
}
return informationFromMaterial;
}
/**
* Sets preferable and supported format for each textureDefinition of the tileset
* @param tileset - I3S layer data
* @returns
*/
initSelectedFormatsForTextureDefinitions(tileset) {
this.textureDefinitionsSelectedFormats = [];
const possibleI3sFormats = this.getSupportedTextureFormats();
const textureSetDefinitions = tileset.textureSetDefinitions || [];
for (const textureSetDefinition of textureSetDefinitions) {
const formats = textureSetDefinition && textureSetDefinition.formats || [];
let selectedFormat = null;
for (const i3sFormat of possibleI3sFormats) {
const format = formats.find((value) => value.format === i3sFormat);
if (format) {
selectedFormat = format;
break;
}
}
if (selectedFormat && selectedFormat.format === "ktx2") {
this.textureLoaderOptions.basis = {
format: (0, import_textures2.selectSupportedBasisFormat)(),
containerFormat: "ktx2",
module: "encoder"
};
}
this.textureDefinitionsSelectedFormats.push(selectedFormat);
}
}
/**
* Returns the array of supported texture format
* @returns list of format strings
*/
getSupportedTextureFormats() {
const formats = [];
if (!this.options.i3s || this.options.i3s.useCompressedTextures) {
const supportedCompressedFormats = (0, import_textures2.getSupportedGPUTextureFormats)();
if (supportedCompressedFormats.has("etc2")) {
formats.push("ktx-etc2");
}
if (supportedCompressedFormats.has("dxt")) {
formats.push("dds");
}
formats.push("ktx2");
}
formats.push("jpg");
formats.push("png");
return formats;
}
};
// dist/lib/parsers/parse-i3s.js
function normalizeTileData(tile, context) {
const url = context.url || "";
let contentUrl;
if (tile.geometryData) {
contentUrl = `${url}/${tile.geometryData[0].href}`;
}
let textureUrl;
if (tile.textureData) {
textureUrl = `${url}/${tile.textureData[0].href}`;
}
let attributeUrls;
if (tile.attributeData) {
attributeUrls = generateTileAttributeUrls(url, tile);
}
const children = tile.children || [];
return normalizeTileNonUrlData({
...tile,
children,
url,
contentUrl,
textureUrl,
textureFormat: "jpg",
// `jpg` format will cause `ImageLoader` usage that will be able to handle `png` as well
attributeUrls,
isDracoGeometry: false
});
}
function normalizeTileNonUrlData(tile) {
var _a, _b;
const boundingVolume = {};
let mbs = [0, 0, 0, 1];
if (tile.mbs) {
mbs = tile.mbs;
boundingVolume.sphere = [
...import_geospatial2.Ellipsoid.WGS84.cartographicToCartesian(tile.mbs.slice(0, 3)),
// cartesian center of sphere
tile.mbs[3]
// radius of sphere
];
} else if (tile.obb) {
boundingVolume.box = [
...import_geospatial2.Ellipsoid.WGS84.cartographicToCartesian(tile.obb.center),
// cartesian center of box
...tile.obb.halfSize,
// halfSize
...tile.obb.quaternion
// quaternion
];
const obb = new import_culling.OrientedBoundingBox().fromCenterHalfSizeQuaternion(boundingVolume.box.slice(0, 3), tile.obb.halfSize, tile.obb.quaternion);
const boundingSphere = obb.getBoundingSphere();
boundingVolume.sphere = [...boundingSphere.center, boundingSphere.radius];
mbs = [...tile.obb.center, boundingSphere.radius];
}
const lodMetricType = (_a = tile.lodSelection) == null ? void 0 : _a[0].metricType;
const lodMetricValue = (_b = tile.lodSelection) == null ? void 0 : _b[0].maxError;
const type = import_tiles.TILE_TYPE.MESH;
const refine = import_tiles.TILE_REFINEMENT.REPLACE;
return { ...tile, mbs, boundingVolume, lodMetricType, lodMetricValue, type, refine };
}
async function normalizeTilesetData(tileset, options, context) {
const url = getUrlWithoutParams(context.url || "");
let nodePagesTile;
let root;
if (tileset.nodePages) {
nodePagesTile = new I3SNodePagesTiles(tileset, url, options);
root = await nodePagesTile.formTileFromNodePages(0);
} else {
const parseOptions = options.i3s;
const rootNodeUrl = getUrlWithToken(`${url}/nodes/root`, parseOptions.token);
root = await (0, import_core4.load)(rootNodeUrl, I3SLoader, {
...options,
i3s: {
// @ts-expect-error options is not properly typed
...options.i3s,
loadContent: false,
isTileHeader: true,
isTileset: false
}
});
}
return {
...tileset,
loader: I3SLoader,
url,
basePath: url,
type: import_tiles.TILESET_TYPE.I3S,
nodePagesTile,
// @ts-expect-error
root,
lodMetricType: root.lodMetricType,
lodMetricValue: root.lodMetricValue
};
}
// dist/i3s-loader.js
var VERSION3 = true ? "4.3.2" : "latest";
var TILESET_REGEX = /layers\/[0-9]+$/;
var LOCAL_SLPK_REGEX = /\.slpk$/;
var TILE_HEADER_REGEX = /nodes\/([0-9-]+|root)$/;
var SLPK_HEX = "504b0304";
var POINT_CLOUD = "PointCloud";
var I3SLoader = {
dataType: null,
batchType: null,
name: "I3S (Indexed Scene Layers)",
id: "i3s",
module: "i3s",
version: VERSION3,
mimeTypes: ["application/octet-stream"],
parse: parseI3S,
extensions: ["bin"],
options: {
i3s: {
token: null,
isTileset: "auto",
isTileHeader: "auto",
tile: null,
tileset: null,
_tileOptions: null,
_tilesetOptions: null,
useDracoGeometry: true,
useCompressedTextures: true,
decodeTextures: true,
coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS
}
}
};
async function parseI3S(data, options = {}, context) {
const url = context.url;
options.i3s = options.i3s || {};
const magicNumber = getMagicNumber(data);
if (magicNumber === SLPK_HEX) {
throw new Error("Files with .slpk extention currently are not supported by I3SLoader");
}
const urlWithoutParams = getUrlWithoutParams(url);
let isTileset;
if (options.i3s.isTileset === "auto") {
isTileset = TILESET_REGEX.test(urlWithoutParams) || LOCAL_SLPK_REGEX.test(urlWithoutParams);
} else {
isTileset = options.i3s.isTileset;
}
let isTileHeader;
if (options.isTileHeader === "auto") {
isTileHeader = TILE_HEADER_REGEX.test(urlWithoutParams);
} else {
isTileHeader = options.i3s.isTileHeader;
}
if (isTileset) {
data = await parseTileset(data, options, context);
} else if (isTileHeader) {
data = await parseTile(data, context);
} else {
data = await parseTileContent(data, options);
}
return data;
}
async function parseTileContent(arrayBuffer, options) {
return await (0, import_core5.parse)(arrayBuffer, I3SContentLoader, options);
}
async function parseTileset(data, options, context) {
const tilesetJson = JSON.parse(new TextDecoder().decode(data));
if ((tilesetJson == null ? void 0 : tilesetJson.layerType) === POINT_CLOUD) {
throw new Error("Point Cloud layers currently are not supported by I3SLoader");
}
const tilesetPostprocessed = await normalizeTilesetData(tilesetJson, options, context);
return tilesetPostprocessed;
}
async function parseTile(data, context) {
data = JSON.parse(new TextDecoder().decode(data));
return normalizeTileData(data, context);
}
function getMagicNumber(data) {
if (data instanceof ArrayBuffer) {
return [...new Uint8Array(data, 0, 4)].map((value) => value.toString(16).padStart(2, "0")).join("");
}
return null;
}
// dist/i3s-slpk-loader.js
var import_loader_utils2 = require("@loaders.gl/loader-utils");
// dist/lib/parsers/parse-slpk/parse-slpk.js
var import_zip2 = require("@loaders.gl/zip");
// dist/lib/parsers/parse-slpk/slpk-archieve.js
var import_crypto = require("@loaders.gl/crypto");
var import_zip = require("@loaders.gl/zip");
var import_compression = require("@loaders.gl/compression");
var PATH_DESCRIPTIONS = [
{
test: /^$/,
extensions: ["3dSceneLayer.json.gz"]
},
{
test: /nodepages\/\d+$/,
extensions: [".json.gz"]
},
{
test: /sublayers\/\d+$/,
extensions: ["/3dSceneLayer.json.gz"]
},
{
test: /nodes\/(\d+|root)$/,
extensions: ["/3dNodeIndexDocument.json.gz"]
},
{
test: /nodes\/\d+\/textures\/.+$/,
extensions: [".jpg", ".png", ".bin.dds.gz", ".ktx", ".ktx2"]
},
{
test: /nodes\/\d+\/geometries\/\d+$/,
extensions: [".bin.gz", ".draco.gz"]
},
{
test: /nodes\/\d+\/attributes\/f_\d+\/\d+$/,
extensions: [".bin.gz"]
},
{
test: /statistics\/(f_\d+\/\d+|summary)$/,
extensions: [".json.gz"]
},
{
test: /nodes\/\d+\/shared$/,
extensions: ["/sharedResource.json.gz"]
}
];
var SLPKArchive = class extends import_zip.IndexedArchive {
// Maps hex-encoded md5 filename hashes to bigint offsets into the archive
hashTable;
_textEncoder = new TextEncoder();
_textDecoder = new TextDecoder();
_md5Hash = new import_crypto.MD5Hash();
/**
* Constructor
* @param fileProvider - instance of a binary data reader
* @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file
* @param fileName - name of the archive. It is used to add to an URL of a loader context
*/
constructor(fileProvider, hashTable, fileName) {
super(fileProvider, hashTable, fileName);
this.hashTable = hashTable;
}
/**
* Returns file with the given path from slpk archive
* @param path - path inside the slpk
* @param mode - currently only raw mode supported
* @returns buffer with ready to use file
*/
async getFile(path, mode = "raw") {
var _a;
if (mode === "http") {
const extensions = (_a = PATH_DESCRIPTIONS.find((val) => val.test.test(path))) == null ? void 0 : _a.extensions;
if (extensions) {
let data;
for (const ext of extensions) {
data = await this.getDataByPath(`${path}${ext}`);
if (data) {
break;
}
}
if (data) {
return data;
}
}
}
if (mode === "raw") {
const decompressedFile = await this.getDataByPath(`${path}.gz`);
if (decompressedFile) {
return decompressedFile;
}
const fileWithoutCompression = await this.getFileBytes(path);
if (fileWithoutCompression) {
return fileWithoutCompression;
}
}
throw new Error(`No such file in the archive: ${path}`);
}
/**
* returning uncompressed data for paths that ends with .gz and raw data for all other paths
* @param path - path inside the archive
* @returns buffer with the file data
*/
async getDataByPath(path) {
let data = await this.getFileBytes(path.toLocaleLowerCase());
if (!data) {
data = await this.getFileBytes(path);
}
if (!data) {
return void 0;
}
if (/\.gz$/.test(path)) {
const compression = new import_compression.GZipCompression();
const decompressedData = await compression.decompress(data);
return decompressedData;
}
return data;
}
/**
* Trying to get raw file data by address
* @param path - path inside the archive
* @returns buffer with the raw file data
*/
async getFileBytes(path) {
let compressedFile;
if (this.hashTable) {
const binaryPath = this._textEncoder.encode(path);
const nameHash = await this._md5Hash.hash(binaryPath.buffer, "hex");
const offset = this.hashTable[nameHash];
if (offset === void 0) {
return void 0;
}
const localFileHeader = await (0, import_zip.parseZipLocalFileHeader)(offset, this.fileProvider);
if (!localFileHeader) {
return void 0;
}
compressedFile = await this.fileProvider.slice(localFileHeader.fileDataOffset, localFileHeader.fileDataOffset + localFileHeader.compressedSize);
} else {
try {
compressedFile = await this.getFileWithoutHash(path);
} catch {
compressedFile = void 0;
}
}
return compressedFile;
}
};
// dist/lib/parsers/parse-slpk/parse-slpk.js
async function parseSLPKArchive(fileProvider, cb, fileName) {
const hashCDOffset = await (0, import_zip2.searchFromTheEnd)(fileProvider, import_zip2.CD_HEADER_SIGNATURE);
const cdFileHeader = await (0, import_zip2.parseZipCDFileHeader)(hashCDOffset, fileProvider);
let hashTable;
if ((cdFileHeader == null ? void 0 : cdFileHeader.fileName) !== "@specialIndexFileHASH128@") {
hashTable = await (0, import_zip2.makeHashTableFromZipHeaders)(fileProvider);
cb == null ? void 0 : cb("SLPK doesnt contain hash file, hash info has been composed according to zip archive headers");
} else {
const localFileHeader = await (0, import_zip2.parseZipLocalFileHeader)(cdFileHeader.localHeaderOffset, fileProvider);
if (!localFileHeader) {
throw new Error("corrupted SLPK");
}
const fileDataOffset = localFileHeader.fileDataOffset;
const hashFile = await fileProvider.slice(fileDataOffset, fileDataOffset + localFileHeader.compressedSize);
hashTable = (0, import_zip2.parseHashTable)(hashFile);
}
return new SLPKArchive(fileProvider, hashTable, fileName);
}
// dist/i3s-slpk-loader.js
var VERSION4 = true ? "4.3.2" : "latest";
var SLPKLoader = {
dataType: null,
batchType: null,
name: "I3S SLPK (Scene Layer Package)",
id: "slpk",
module: "i3s",
version: VERSION4,
mimeTypes: ["application/octet-stream"],
extensions: ["slpk"],
options: {},
parse: async (data, options = {}) => {
var _a, _b;
const archive = await parseSLPKArchive(new import_loader_utils2.DataViewFile(new DataView(data)));
return archive.getFile(((_a = options.slpk) == null ? void 0 : _a.path) ?? "", (_b = options.slpk) == null ? void 0 : _b.pathMode);
}
};
// dist/i3s-attribute-loader.js
var import_core6 = require("@loaders.gl/core");
// dist/lib/parsers/parse-i3s-attribute.js
function parseI3STileAttribute(arrayBuffer, options) {
const { attributeName, attributeType } = options;
if (!attributeName) {
return {};
}
return {
[attributeName]: attributeType ? parseAttribute(attributeType, arrayBuffer) : null
};
}
function parseAttribute(attributeType, arrayBuffer) {
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);
}
}
function parseShortNumberAttribute(arrayBuffer) {
const countOffset = 4;
return new Uint32Array(arrayBuffer, countOffset);
}
function parseInt16ShortNumberAttribute(arrayBuffer) {
const countOffset = 4;
return new Int16Array(arrayBuffer, countOffset);
}
function parseFloatAttribute(arrayBuffer) {
const countOffset = 8;
return new Float64Array(arrayBuffer, countOffset);
}
function parseStringsAttribute(arrayBuffer) {
const stringsCountOffset = 0;
const dataOffset = 8;
const bytesPerStringSize = 4;
const stringsArray = [];
try {
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.message);
}
return stringsArray;
}
// dist/i3s-attribute-loader.js
var VERSION5 = true ? "4.3.2" : "latest";
var EMPTY_VALUE = "";
var REJECTED_STATUS = "rejected";
var I3SAttributeLoader = {
dataType: null,
batchType: null,
name: "I3S Attribute",
id: "i3s-attribute",
module: "i3s",
version: VERSION5,
mimeTypes: ["application/binary"],
parse: async (arrayBuffer, options) => parseI3STileAttribute(arrayBuffer, options),
extensions: ["bin"],
options: {},
binary: true
};
async function loadFeatureAttributes(tile, featureId, options = {}) {
var _a;
const { attributeStorageInfo, attributeUrls, tilesetFields } = getAttributesData(tile);
if (!attributeStorageInfo || !attributeUrls || featureId < 0) {
return null;
}
let attributes = [];
const attributeLoadPromises = [];
for (let index = 0; index < attributeStorageInfo.length; index++) {
const url = getUrlWithToken(attributeUrls[index], (_a = options.i3s) == null ? void 0 : _a.token);
const attributeName = attributeStorageInfo[index].name;
const attributeType = getAttributeValueType(attributeStorageInfo[index]);
const loadOptions = { ...options, attributeName, attributeType };
const promise = (0, import_core6.load)(url, I3SAttributeLoader, loadOptions);
attributeLoadPromises.push(promise);
}
try {
attributes = await Promise.allSettled(attributeLoadPromises);
} catch (error) {
}
if (!attributes.length) {
return null;
}
return generateAttributesByFeatureId(attributes, attributeStorageInfo, featureId, tilesetFields);
}
function getAttributesData(tile) {
var _a, _b, _c, _d, _e;
const attributeStorageInfo = (_b = (_a = tile.tileset) == null ? void 0 : _a.tileset) == null ? void 0 : _b.attributeStorageInfo;
const attributeUrls = (_c = tile.header) == null ? void 0 : _c.attributeUrls;
const tilesetFields = ((_e = (_d = tile.tileset) == null ? void 0 : _d.tileset) == null ? void 0 : _e.fields) || [];
return { attributeStorageInfo, attributeUrls, tilesetFields };
}
function getAttributeValueType(attribute) {
if (attribute.hasOwnProperty("objectIds")) {
return "Oid32";
} else if (attribute.hasOwnProperty("attributeValues")) {
return attribute.attributeValues.valueType;
}
return "";
}
function getFeatureIdsAttributeName(attributeStorageInfo) {
const objectIdsAttribute = attributeStorageInfo.find((attribute) => attribute.name.includes("OBJECTID"));
return objectIdsAttribute == null ? void 0 : objectIdsAttribute.name;
}
function generateAttributesByFeatureId(attributes, attributeStorageInfo, featureId, tilesetFields) {
const objectIdsAttributeName = getFeatureIdsAttributeName(attributeStorageInfo);
const objectIds = attributes.find((attribute) => attribute.value[objectIdsAttributeName]);
if (!objectIds) {
return null;
}
const attributeIndex = objectIds.value[objectIdsAttributeName].indexOf(featureId);
if (attributeIndex < 0) {
return null;
}
return getFeatureAttributesByIndex(attributes, attributeIndex, attributeStorageInfo, tilesetFields);
}
function getFeatureAttributesByIndex(attributes, featureIdIndex, attributeStorageInfo, tilesetFields) {
const attributesObject = {};
for (let index = 0; index < attributeStorageInfo.length; index++) {
const attributeName = attributeStorageInfo[index].name;
const codedValues = getAttributeCodedValues(attributeName, tilesetFields);
const attribute = getAttributeByIndexAndAttributeName(attributes, index, attributeName);
attributesObject[attributeName] = formatAttributeValue(attribute, featureIdIndex, codedValues);
}
return attributesObject;
}
function getAttributeCodedValues(attributeName, tilesetFields) {
var _a;
const attributeField = tilesetFields.find((field) => field.name === attributeName || field.alias === attributeName);
return ((_a = attributeField == null ? void 0 : attributeField.domain) == null ? void 0 : _a.codedValues) || [];
}
function getAttributeByIndexAndAttributeName(attributes, index, attributesName) {
const attributeObject = attributes[index];
if (attributeObject.status === REJECTED_STATUS) {
return null;
}
return attributeObject.value[attributesName];
}
function formatAttributeValue(attribute, featureIdIndex, codedValues) {
let value = EMPTY_VALUE;
if (attribute && featureIdIndex in attribute) {
value = String(attribute[featureIdIndex]).replace(/\u0000|NaN/g, "").trim();
}
if (codedValues.length) {
const codeValue = codedValues.find((codedValue) => codedValue.code === Number(value));
value = (codeValue == null ? void 0 : codeValue.name) || EMPTY_VALUE;
}
return value;
}
// dist/lib/parsers/parse-i3s-building-scene-layer.js
var OBJECT_3D_LAYER_TYPE = "3DObject";
async function parseBuildingSceneLayer(data, url) {
const layer0 = JSON.parse(new TextDecoder().decode(data));
const { sublayers } = layer0;
return {
header: layer0,
sublayers: parseSublayersTree(sublayers, url)
};
}
function parseSublayersTree(sublayers, url) {
var _a;
let layers = [];
for (let index = 0; index < sublayers.length; index++) {
const subLayer = sublayers[index];
const { id, layerType, visibility = true, ...rest } = subLayer;
if (layerType === OBJECT_3D_LAYER_TYPE) {
const sublayerUrl = `${url}/sublayers/${id}`;
layers.push({
url: sublayerUrl,
id,
layerType,
visibility,
...rest
});
}
if ((_a = subLayer == null ? void 0 : subLayer.sublayers) == null ? void 0 : _a.length) {
layers = [...layers, ...p