@loaders.gl/i3s 3.3.0-alpha.3 → 3.3.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/dist.min.js +260 -190
  2. package/dist/es5/arcgis-webscene-loader.js +1 -1
  3. package/dist/es5/i3s-attribute-loader.js +2 -1
  4. package/dist/es5/i3s-attribute-loader.js.map +1 -1
  5. package/dist/es5/i3s-building-scene-layer-loader.js +1 -1
  6. package/dist/es5/i3s-content-loader.js +1 -1
  7. package/dist/es5/i3s-loader.js +3 -2
  8. package/dist/es5/i3s-loader.js.map +1 -1
  9. package/dist/es5/i3s-node-page-loader.js +1 -1
  10. package/dist/es5/index.js.map +1 -1
  11. package/dist/es5/lib/parsers/parse-i3s-tile-content.js +8 -1
  12. package/dist/es5/lib/parsers/parse-i3s-tile-content.js.map +1 -1
  13. package/dist/es5/lib/utils/customizeColors.js +213 -0
  14. package/dist/es5/lib/utils/customizeColors.js.map +1 -0
  15. package/dist/es5/types.js.map +1 -1
  16. package/dist/esm/arcgis-webscene-loader.js +1 -1
  17. package/dist/esm/i3s-attribute-loader.js +2 -2
  18. package/dist/esm/i3s-attribute-loader.js.map +1 -1
  19. package/dist/esm/i3s-building-scene-layer-loader.js +1 -1
  20. package/dist/esm/i3s-content-loader.js +1 -1
  21. package/dist/esm/i3s-loader.js +3 -2
  22. package/dist/esm/i3s-loader.js.map +1 -1
  23. package/dist/esm/i3s-node-page-loader.js +1 -1
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/lib/parsers/parse-i3s-tile-content.js +2 -0
  26. package/dist/esm/lib/parsers/parse-i3s-tile-content.js.map +1 -1
  27. package/dist/esm/lib/utils/customizeColors.js +108 -0
  28. package/dist/esm/lib/utils/customizeColors.js.map +1 -0
  29. package/dist/esm/types.js.map +1 -1
  30. package/dist/i3s-attribute-loader.d.ts +6 -0
  31. package/dist/i3s-attribute-loader.d.ts.map +1 -1
  32. package/dist/i3s-attribute-loader.js +2 -1
  33. package/dist/i3s-content-nodejs-worker.js +50 -50
  34. package/dist/i3s-content-nodejs-worker.js.map +3 -3
  35. package/dist/i3s-content-worker.js +159 -11
  36. package/dist/i3s-loader.d.ts.map +1 -1
  37. package/dist/i3s-loader.js +2 -1
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/lib/parsers/parse-i3s-tile-content.d.ts.map +1 -1
  41. package/dist/lib/parsers/parse-i3s-tile-content.js +2 -0
  42. package/dist/lib/utils/customizeColors.d.ts +14 -0
  43. package/dist/lib/utils/customizeColors.d.ts.map +1 -0
  44. package/dist/lib/utils/customizeColors.js +89 -0
  45. package/dist/types.d.ts +52 -1
  46. package/dist/types.d.ts.map +1 -1
  47. package/package.json +8 -8
  48. package/src/i3s-attribute-loader.ts +1 -1
  49. package/src/i3s-loader.ts +2 -1
  50. package/src/index.ts +3 -1
  51. package/src/lib/parsers/parse-i3s-tile-content.ts +11 -1
  52. package/src/lib/utils/customizeColors.ts +129 -0
  53. package/src/types.ts +57 -1
package/src/i3s-loader.ts CHANGED
@@ -41,7 +41,8 @@ export const I3SLoader: LoaderWithParser = {
41
41
  useDracoGeometry: true,
42
42
  useCompressedTextures: true,
43
43
  decodeTextures: true,
44
- coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS
44
+ coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS,
45
+ colorsByAttribute: null
45
46
  }
46
47
  }
47
48
  };
package/src/index.ts CHANGED
@@ -26,6 +26,8 @@ export type {
26
26
  I3SMaterialDefinition,
27
27
  TextureDefinitionInfo,
28
28
  MaterialDefinitionInfo,
29
- FullExtent
29
+ FullExtent,
30
+ StatisticsInfo,
31
+ StatsInfo
30
32
  } from './types';
31
33
  export {COORDINATE_SYSTEM} from './lib/parsers/constants';
@@ -22,6 +22,8 @@ import {
22
22
  import {getUrlWithToken} from '../utils/url-utils';
23
23
 
24
24
  import {GL_TYPE_MAP, getConstructorForDataFormat, sizeOf, COORDINATE_SYSTEM} from './constants';
25
+ import {I3SLoaderOptions} from '../../i3s-loader';
26
+ import {customizeColors} from '../utils/customizeColors';
25
27
 
26
28
  const scratchVector = new Vector3([0, 0, 0]);
27
29
 
@@ -110,7 +112,7 @@ async function parseI3SNodeGeometry(
110
112
  content: I3STileContent,
111
113
  tileOptions: I3STileOptions,
112
114
  tilesetOptions: I3STilesetOptions,
113
- options?: LoaderOptions
115
+ options?: I3SLoaderOptions
114
116
  ): Promise<I3STileContent> {
115
117
  const contentByteLength = arrayBuffer.byteLength;
116
118
  let attributes: I3SMeshAttributes;
@@ -199,6 +201,14 @@ async function parseI3SNodeGeometry(
199
201
  content.coordinateSystem = COORDINATE_SYSTEM.LNGLAT_OFFSETS;
200
202
  }
201
203
 
204
+ attributes.color = await customizeColors(
205
+ attributes.color,
206
+ attributes.id,
207
+ tileOptions,
208
+ tilesetOptions,
209
+ options
210
+ );
211
+
202
212
  content.attributes = {
203
213
  positions: attributes.position,
204
214
  normals: attributes.normal,
@@ -0,0 +1,129 @@
1
+ import type {MeshAttribute} from '@loaders.gl/schema';
2
+ import type {COLOR, I3STileOptions, I3STilesetOptions} from '../../types';
3
+
4
+ import {load} from '@loaders.gl/core';
5
+ import {getAttributeValueType, I3SAttributeLoader} from '../../i3s-attribute-loader';
6
+ import {I3SLoaderOptions} from '../../i3s-loader';
7
+ import {getUrlWithToken} from '../utils/url-utils';
8
+
9
+ /**
10
+ * Modify vertex colors array to visualize 3D objects in a attribute driven way
11
+ * @param colors - vertex colors attribute
12
+ * @param featureIds - feature Ids attribute
13
+ * @param tileOptions - tile - related options
14
+ * @param tilesetOptions - tileset-related options
15
+ * @param options - loader options
16
+ * @returns midified colors attribute
17
+ */
18
+ export async function customizeColors(
19
+ colors: MeshAttribute,
20
+ featureIds: MeshAttribute,
21
+ tileOptions: I3STileOptions,
22
+ tilesetOptions: I3STilesetOptions,
23
+ options?: I3SLoaderOptions
24
+ ): Promise<MeshAttribute> {
25
+ if (!options?.i3s?.colorsByAttribute) {
26
+ return colors;
27
+ }
28
+
29
+ const colorizeAttributeField = tilesetOptions.fields.find(
30
+ ({name}) => name === options?.i3s?.colorsByAttribute?.attributeName
31
+ );
32
+ if (
33
+ !colorizeAttributeField ||
34
+ !['esriFieldTypeDouble', 'esriFieldTypeInteger', 'esriFieldTypeSmallInteger'].includes(
35
+ colorizeAttributeField.type
36
+ )
37
+ ) {
38
+ return colors;
39
+ }
40
+
41
+ const colorizeAttributeData = await loadFeatureAttributeData(
42
+ colorizeAttributeField.name,
43
+ tileOptions,
44
+ tilesetOptions,
45
+ options
46
+ );
47
+ if (!colorizeAttributeData) {
48
+ return colors;
49
+ }
50
+
51
+ const objectIdField = tilesetOptions.fields.find(({type}) => type === 'esriFieldTypeOID');
52
+ if (!objectIdField) {
53
+ return colors;
54
+ }
55
+
56
+ const objectIdAttributeData = await loadFeatureAttributeData(
57
+ objectIdField.name,
58
+ tileOptions,
59
+ tilesetOptions,
60
+ options
61
+ );
62
+ if (!objectIdAttributeData) {
63
+ return colors;
64
+ }
65
+
66
+ const attributeValuesMap: {[key: number]: COLOR} = {};
67
+ for (let i = 0; i < objectIdAttributeData[objectIdField.name].length; i++) {
68
+ attributeValuesMap[objectIdAttributeData[objectIdField.name][i]] = calculateColorForAttribute(
69
+ colorizeAttributeData[colorizeAttributeField.name][i] as number,
70
+ options
71
+ );
72
+ }
73
+
74
+ for (let i = 0; i < featureIds.value.length; i++) {
75
+ const color = attributeValuesMap[featureIds.value[i]];
76
+ if (!color) {
77
+ continue; // eslint-disable-line no-continue
78
+ }
79
+ colors.value.set(color, i * 4);
80
+ }
81
+
82
+ return colors;
83
+ }
84
+
85
+ /**
86
+ * Calculate rgba color from the attribute value
87
+ * @param attributeValue - value of the attribute
88
+ * @param options - loader options
89
+ * @returns - color array for a specific attribute value
90
+ */
91
+ function calculateColorForAttribute(attributeValue: number, options?: I3SLoaderOptions): COLOR {
92
+ if (!options?.i3s?.colorsByAttribute) {
93
+ return [255, 255, 255, 255];
94
+ }
95
+ const {minValue, maxValue, minColor, maxColor} = options.i3s.colorsByAttribute;
96
+ const rate = (attributeValue - minValue) / (maxValue - minValue);
97
+ const color: COLOR = [255, 255, 255, 255];
98
+ for (let i = 0; i < minColor.length; i++) {
99
+ color[i] = Math.round((maxColor[i] - minColor[i]) * rate + minColor[i]);
100
+ }
101
+ return color;
102
+ }
103
+
104
+ /**
105
+ * Load feature attribute data from the ArcGIS rest service
106
+ * @param attributeName - attribute name
107
+ * @param tileOptions - tile-related options
108
+ * @param tilesetOptions - tileset-related options
109
+ * @param options - loader options
110
+ * @returns - Array-like list of the attribute values
111
+ */
112
+ async function loadFeatureAttributeData(
113
+ attributeName: string,
114
+ {attributeUrls}: I3STileOptions,
115
+ {attributeStorageInfo}: I3STilesetOptions,
116
+ options?: I3SLoaderOptions
117
+ ): Promise<{[key: string]: string[] | Uint32Array | Uint16Array | Float64Array} | null> {
118
+ const attributeIndex = attributeStorageInfo.findIndex(({name}) => attributeName === name);
119
+ if (attributeIndex === -1) {
120
+ return null;
121
+ }
122
+ const objectIdAttributeUrl = getUrlWithToken(attributeUrls[attributeIndex], options?.i3s?.token);
123
+ const attributeType = getAttributeValueType(attributeStorageInfo[attributeIndex]);
124
+ const objectIdAttributeData = await load(objectIdAttributeUrl, I3SAttributeLoader, {
125
+ attributeName,
126
+ attributeType
127
+ });
128
+ return objectIdAttributeData;
129
+ }
package/src/types.ts CHANGED
@@ -13,6 +13,9 @@ export enum DATA_TYPE {
13
13
  Float32 = 'Float32',
14
14
  Float64 = 'Float64'
15
15
  }
16
+
17
+ export type COLOR = [number, number, number, number];
18
+
16
19
  /**
17
20
  * spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.8/3DSceneLayer.cmn.md
18
21
  */
@@ -110,6 +113,13 @@ export type I3SParseOptions = {
110
113
  * Supported coordinate systems: METER_OFFSETS, LNGLAT_OFFSETS
111
114
  */
112
115
  coordinateSystem?: number;
116
+ colorsByAttribute?: {
117
+ attributeName: string;
118
+ minValue: number;
119
+ maxValue: number;
120
+ minColor: COLOR;
121
+ maxColor: COLOR;
122
+ };
113
123
  };
114
124
 
115
125
  export type I3STileOptions = {
@@ -118,11 +128,14 @@ export type I3STileOptions = {
118
128
  textureFormat?: I3STextureFormat;
119
129
  textureLoaderOptions?: any;
120
130
  materialDefinition?: I3SMaterialDefinition;
131
+ attributeUrls: string[];
121
132
  mbs: Mbs;
122
133
  };
123
134
 
124
135
  export type I3STilesetOptions = {
125
136
  store: Store;
137
+ attributeStorageInfo: AttributeStorageInfo[];
138
+ fields: Field[];
126
139
  };
127
140
 
128
141
  // TODO Replace "[key: string]: any" with actual defenition
@@ -157,7 +170,7 @@ export type BoundingVolumes = {
157
170
  export type Obb = {
158
171
  center: number[] | Vector3;
159
172
  halfSize: number[] | Vector3;
160
- quaternion: Quaternion;
173
+ quaternion: number[] | Quaternion;
161
174
  };
162
175
 
163
176
  export type Mbs = [number, number, number, number];
@@ -1005,3 +1018,46 @@ type CameraPosition = {
1005
1018
  y: number;
1006
1019
  z: number;
1007
1020
  };
1021
+
1022
+ /**
1023
+ * Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.8/statsInfo.cmn.md
1024
+ */
1025
+ export type StatsInfo = {
1026
+ /** Represents the count of the value. */
1027
+ totalValuesCount?: number;
1028
+ /** Minimum attribute value for the entire layer. */
1029
+ min?: number;
1030
+ /** Maximum attribute value for the entire layer. */
1031
+ max?: number;
1032
+ /** Count for the entire layer. */
1033
+ count?: number;
1034
+ /** Sum of the attribute values over the entire layer. */
1035
+ sum?: number;
1036
+ /** Representing average or mean value. For example, sum/count. */
1037
+ avg?: number;
1038
+ /** Representing the standard deviation. */
1039
+ stddev?: number;
1040
+ /** Representing variance. For example, stats.stddev *stats.stddev. */
1041
+ variance?: number;
1042
+ /** Represents the histogram. */
1043
+ histogram?: Histogram;
1044
+ /** An array of most frequently used values within the point cloud scene layer. */
1045
+ mostFrequentValues?: ValueCount[];
1046
+ };
1047
+
1048
+ /** Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.8/histogram.cmn.md */
1049
+ export type Histogram = {
1050
+ /** Minimum attribute value for the entire layer. */
1051
+ minimum: number;
1052
+ /** Maximum attribute value for the entire layer. Maximum array size for stats.histo.counts is 256. */
1053
+ maximum: number;
1054
+ /** Count for the entire layer. */
1055
+ counts: number;
1056
+ };
1057
+
1058
+ export type ValueCount = {
1059
+ /** Type of the attribute values after decompression, if applicable. Please note that string is not supported for point cloud scene layer attributes. */
1060
+ value: number | string;
1061
+ /** Count of the number of values. May exceed 32 bits. */
1062
+ count: number;
1063
+ };