UNPKG

@loaders.gl/i3s

Version:
107 lines (106 loc) 4.54 kB
import { load } from '@loaders.gl/core'; import { getAttributeValueType, I3SAttributeLoader } from "../../i3s-attribute-loader.js"; import { getUrlWithToken } from "./url-utils.js"; /** * Calculate new vertex colors array to visualize 3D objects in a attribute driven way * @param colors - vertex colors attribute * @param featureIds - feature Ids attribute * @param attributeUrls - array of attribute's urls * @param fields - array of attribute's fileds * @param attributeStorageInfo - array of attributeStorageInfo * @param colorsByAttribute - attribute color options * @param token - access token * @returns new colors attribute */ // eslint-disable-next-line max-params export async function customizeColors(colors, featureIds, attributeUrls, fields, attributeStorageInfo, colorsByAttribute, token) { if (!colorsByAttribute) { return colors; } const resultColors = { ...colors, value: new Uint8Array(colors.value) }; const colorizeAttributeField = fields.find(({ name }) => name === colorsByAttribute?.attributeName); if (!colorizeAttributeField || !['esriFieldTypeDouble', 'esriFieldTypeInteger', 'esriFieldTypeSmallInteger'].includes(colorizeAttributeField.type)) { return colors; } const colorizeAttributeData = await loadFeatureAttributeData(colorizeAttributeField.name, attributeUrls, attributeStorageInfo, token); if (!colorizeAttributeData) { return colors; } const objectIdField = fields.find(({ type }) => type === 'esriFieldTypeOID'); if (!objectIdField) { return colors; } const objectIdAttributeData = await loadFeatureAttributeData(objectIdField.name, attributeUrls, attributeStorageInfo, token); if (!objectIdAttributeData) { return colors; } const attributeValuesMap = {}; // @ts-expect-error for (let i = 0; i < objectIdAttributeData[objectIdField.name].length; i++) { // @ts-expect-error attributeValuesMap[objectIdAttributeData[objectIdField.name][i]] = calculateColorForAttribute( // @ts-expect-error colorizeAttributeData[colorizeAttributeField.name][i], colorsByAttribute); } for (let i = 0; i < featureIds.length; i++) { const color = attributeValuesMap[featureIds[i]]; if (!color) { continue; // eslint-disable-line no-continue } /* eslint max-statements: ["error", 30] */ /* eslint complexity: ["error", 12] */ if (colorsByAttribute.mode === 'multiply') { // multiplying original mesh and calculated for attribute rgba colors in range 0-255 color.forEach((colorItem, index) => { resultColors.value[i * 4 + index] = (resultColors.value[i * 4 + index] * colorItem) / 255; }); } else { resultColors.value.set(color, i * 4); } } return resultColors; } /** * Calculate rgba color from the attribute value * @param attributeValue - value of the attribute * @param colorsByAttribute - attribute color options * @returns - color array for a specific attribute value */ function calculateColorForAttribute(attributeValue, colorsByAttribute) { if (!colorsByAttribute) { return [255, 255, 255, 255]; } const { minValue, maxValue, minColor, maxColor } = colorsByAttribute; const rate = (attributeValue - minValue) / (maxValue - minValue); const color = [255, 255, 255, 255]; for (let i = 0; i < minColor.length; i++) { color[i] = Math.round((maxColor[i] - minColor[i]) * rate + minColor[i]); } return color; } /** * Load feature attribute data from the ArcGIS rest service * @param attributeName - attribute name * @param attributeUrls - array of attribute's urls * @param attributeStorageInfo - array of attributeStorageInfo * @param token - access token * @returns - Array-like list of the attribute values */ async function loadFeatureAttributeData(attributeName, attributeUrls, attributeStorageInfo, token) { const attributeIndex = attributeStorageInfo.findIndex(({ name }) => attributeName === name); if (attributeIndex === -1) { return null; } const objectIdAttributeUrl = getUrlWithToken(attributeUrls[attributeIndex], token); const attributeType = getAttributeValueType(attributeStorageInfo[attributeIndex]); const objectIdAttributeData = await load(objectIdAttributeUrl, I3SAttributeLoader, { attributeName, attributeType }); return objectIdAttributeData; }