@loaders.gl/tile-converter 4.0.0 → 4.0.2

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 (39) hide show
  1. package/dist/converter.min.cjs +109 -109
  2. package/dist/i3s-converter/helpers/attribute-metadata-info.d.ts +74 -0
  3. package/dist/i3s-converter/helpers/attribute-metadata-info.d.ts.map +1 -0
  4. package/dist/i3s-converter/helpers/attribute-metadata-info.js +157 -0
  5. package/dist/i3s-converter/helpers/attribute-metadata-info.js.map +1 -0
  6. package/dist/i3s-converter/helpers/feature-attributes.d.ts +3 -28
  7. package/dist/i3s-converter/helpers/feature-attributes.d.ts.map +1 -1
  8. package/dist/i3s-converter/helpers/feature-attributes.js +16 -125
  9. package/dist/i3s-converter/helpers/feature-attributes.js.map +1 -1
  10. package/dist/i3s-converter/i3s-converter.d.ts +11 -5
  11. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  12. package/dist/i3s-converter/i3s-converter.js +31 -44
  13. package/dist/i3s-converter/i3s-converter.js.map +1 -1
  14. package/dist/i3s-converter/types.d.ts +15 -0
  15. package/dist/i3s-converter/types.d.ts.map +1 -1
  16. package/dist/i3s-converter/types.js +6 -0
  17. package/dist/i3s-converter/types.js.map +1 -1
  18. package/dist/i3s-server/app.d.ts.map +1 -1
  19. package/dist/i3s-server/app.js +3 -6
  20. package/dist/i3s-server/app.js.map +1 -1
  21. package/dist/i3s-server/bin/i3s-server.min.cjs +86 -86
  22. package/dist/i3s-server/bin/www.js.map +1 -1
  23. package/dist/i3s-server/routes/index.d.ts +1 -1
  24. package/dist/i3s-server/routes/index.d.ts.map +1 -1
  25. package/dist/i3s-server/routes/index.js +2 -5
  26. package/dist/i3s-server/routes/index.js.map +1 -1
  27. package/dist/i3s-server/routes/slpk-router.d.ts.map +1 -1
  28. package/dist/i3s-server/routes/slpk-router.js +3 -3
  29. package/dist/i3s-server/routes/slpk-router.js.map +1 -1
  30. package/dist/index.cjs +269 -173
  31. package/package.json +15 -15
  32. package/src/i3s-converter/helpers/attribute-metadata-info.ts +246 -0
  33. package/src/i3s-converter/helpers/feature-attributes.ts +18 -180
  34. package/src/i3s-converter/i3s-converter.ts +46 -65
  35. package/src/i3s-converter/types.ts +16 -0
  36. package/src/i3s-server/app.ts +9 -4
  37. package/src/i3s-server/bin/www.ts +6 -0
  38. package/src/i3s-server/routes/index.ts +2 -4
  39. package/src/i3s-server/routes/slpk-router.ts +4 -3
@@ -0,0 +1,246 @@
1
+ import type {
2
+ Attribute,
3
+ AttributeStorageInfo,
4
+ ESRIField,
5
+ Field,
6
+ FieldInfo,
7
+ PopupInfo
8
+ } from '@loaders.gl/i3s';
9
+
10
+ import {AttributeType} from '../types';
11
+
12
+ export class AttributeMetadataInfo {
13
+ private _attributeStorageInfo: AttributeStorageInfo[];
14
+ private _fields: Field[];
15
+ private _popupInfo: PopupInfo | undefined;
16
+
17
+ constructor() {
18
+ this._attributeStorageInfo = [];
19
+ this._fields = [];
20
+ }
21
+
22
+ get attributeStorageInfo(): AttributeStorageInfo[] {
23
+ return this._attributeStorageInfo;
24
+ }
25
+
26
+ get fields(): Field[] {
27
+ return this._fields;
28
+ }
29
+
30
+ get popupInfo(): PopupInfo | undefined {
31
+ return this._popupInfo;
32
+ }
33
+
34
+ /**
35
+ * Creates and stores Attribute Storage Info, Fields and PopupInfo objects based on attribute's types.
36
+ * Appends objects that have not been stored yet.
37
+ * @param attributeTypesMap - set of attribute's types
38
+ * @example AttributeStorageInfo, Fields and PopupInfo already contain objects for the following attributes:
39
+ * {
40
+ * color: 'string',
41
+ * name: 'string',
42
+ * opt_uint8: 'Int32'
43
+ * }
44
+ * Then, we call the addMetadataInfo method with the following attributeTypesMap:
45
+ * {
46
+ * // The same attributes
47
+ * color: 'string',
48
+ * name: 'string',
49
+ * opt_uint8: 'Int32',
50
+ * // New attributes
51
+ * opt_uint64: 'string',
52
+ * opt_float32: 'double',
53
+ * }
54
+ * The method creates and stores objects for opt_uint64, opt_float32 attributes.
55
+ */
56
+ addMetadataInfo(attributeTypesMap: Record<string, Attribute>): void {
57
+ if (!Object.keys(attributeTypesMap).length) {
58
+ return;
59
+ }
60
+ const attributeTypes: Record<string, Attribute> = {
61
+ OBJECTID: AttributeType.OBJECT_ID_TYPE,
62
+ ...attributeTypesMap
63
+ };
64
+
65
+ let isUpdated = false;
66
+ let attributeIndex = this._attributeStorageInfo.length;
67
+ for (const key in attributeTypes) {
68
+ /*
69
+ We will append a new attribute only in case it has not been added to the attribute storage info yet.
70
+ */
71
+ const elementFound = this._attributeStorageInfo.find((element) => element.name === key);
72
+ if (!elementFound) {
73
+ const attributeType = attributeTypes[key];
74
+
75
+ const storageAttribute = this.createStorageAttribute(attributeIndex, key, attributeType);
76
+ const fieldAttributeType = this.getFieldAttributeType(attributeType);
77
+ const fieldAttribute = this.createFieldAttribute(key, fieldAttributeType);
78
+
79
+ this._attributeStorageInfo.push(storageAttribute);
80
+ this._fields.push(fieldAttribute);
81
+ attributeIndex += 1;
82
+ isUpdated = true;
83
+ }
84
+ }
85
+ if (isUpdated) {
86
+ /*
87
+ The attributeStorageInfo is updated. So, popupInfo should be recreated.
88
+ Use attributeStorageInfo as a source of attribute names to create the popupInfo.
89
+ */
90
+ const attributeNames: string[] = [];
91
+ for (let info of this._attributeStorageInfo) {
92
+ attributeNames.push(info.name);
93
+ }
94
+ this._popupInfo = this.createPopupInfo(attributeNames);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Generates storage attribute for map segmentation.
100
+ * @param attributeIndex - order index of attribute (f_0, f_1 ...).
101
+ * @param key - attribute key from propertyTable.
102
+ * @param attributeType - attribute type.
103
+ * @return Updated storageAttribute.
104
+ */
105
+ private createStorageAttribute(
106
+ attributeIndex: number,
107
+ key: string,
108
+ attributeType: Attribute
109
+ ): AttributeStorageInfo {
110
+ const storageAttribute = {
111
+ key: `f_${attributeIndex}`,
112
+ name: key,
113
+ ordering: ['attributeValues'],
114
+ header: [{property: 'count', valueType: 'UInt32'}],
115
+ attributeValues: {valueType: 'Int32', valuesPerElement: 1}
116
+ };
117
+
118
+ switch (attributeType) {
119
+ case AttributeType.OBJECT_ID_TYPE:
120
+ this.setupIdAttribute(storageAttribute);
121
+ break;
122
+ case AttributeType.STRING_TYPE:
123
+ this.setupStringAttribute(storageAttribute);
124
+ break;
125
+ case AttributeType.DOUBLE_TYPE:
126
+ this.setupDoubleAttribute(storageAttribute);
127
+ break;
128
+ case AttributeType.SHORT_INT_TYPE:
129
+ break;
130
+ default:
131
+ this.setupStringAttribute(storageAttribute);
132
+ }
133
+
134
+ return storageAttribute;
135
+ }
136
+
137
+ /**
138
+ * Finds and returns attribute type based on key form propertyTable.
139
+ * @param attributeType
140
+ */
141
+ private getFieldAttributeType(attributeType: Attribute): ESRIField {
142
+ switch (attributeType) {
143
+ case AttributeType.OBJECT_ID_TYPE:
144
+ return 'esriFieldTypeOID';
145
+ case AttributeType.STRING_TYPE:
146
+ return 'esriFieldTypeString';
147
+ case AttributeType.SHORT_INT_TYPE:
148
+ return 'esriFieldTypeInteger';
149
+ case AttributeType.DOUBLE_TYPE:
150
+ return 'esriFieldTypeDouble';
151
+ default:
152
+ return 'esriFieldTypeString';
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Sets up Id attribute for map segmentation.
158
+ * @param storageAttribute - attribute for map segmentation .
159
+ */
160
+ private setupIdAttribute(storageAttribute: AttributeStorageInfo): void {
161
+ storageAttribute.attributeValues = {
162
+ valueType: 'Oid32',
163
+ valuesPerElement: 1
164
+ };
165
+ }
166
+
167
+ /**
168
+ * Sets up storage attribute as string.
169
+ * @param storageAttribute - attribute for map segmentation.
170
+ */
171
+ private setupStringAttribute(storageAttribute: AttributeStorageInfo): void {
172
+ // @ts-expect-error
173
+ storageAttribute.ordering.unshift('attributeByteCounts');
174
+ storageAttribute.header.push({property: 'attributeValuesByteCount', valueType: 'UInt32'});
175
+ storageAttribute.attributeValues = {
176
+ valueType: 'String',
177
+ encoding: 'UTF-8',
178
+ valuesPerElement: 1
179
+ };
180
+ storageAttribute.attributeByteCounts = {
181
+ valueType: 'UInt32',
182
+ valuesPerElement: 1
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Sets up double attribute for map segmentation.
188
+ * @param storageAttribute - attribute for map segmentation .
189
+ */
190
+ private setupDoubleAttribute(storageAttribute: AttributeStorageInfo): void {
191
+ storageAttribute.attributeValues = {
192
+ valueType: 'Float64',
193
+ valuesPerElement: 1
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Sets up field attribute for map segmentation.
199
+ * @param key - attribute for map segmentation.
200
+ * @param fieldAttributeType - esri attribute type ('esriFieldTypeString' or 'esriFieldTypeOID').
201
+ */
202
+ private createFieldAttribute(key: string, fieldAttributeType: ESRIField): Field {
203
+ return {
204
+ name: key,
205
+ type: fieldAttributeType,
206
+ alias: key
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Generates popup info to show metadata on the map.
212
+ * @param propertyNames - array of property names including OBJECTID.
213
+ * @return data for correct rendering of popup.
214
+ */
215
+ private createPopupInfo(propertyNames: string[]): PopupInfo {
216
+ const title = '{OBJECTID}';
217
+ const mediaInfos = [];
218
+ const fieldInfos: FieldInfo[] = [];
219
+ const popupElements: {
220
+ fieldInfos: FieldInfo[];
221
+ type: string;
222
+ }[] = [];
223
+ const expressionInfos = [];
224
+
225
+ for (const propertyName of propertyNames) {
226
+ fieldInfos.push({
227
+ fieldName: propertyName,
228
+ visible: true,
229
+ isEditable: false,
230
+ label: propertyName
231
+ });
232
+ }
233
+ popupElements.push({
234
+ fieldInfos,
235
+ type: 'fields'
236
+ });
237
+
238
+ return {
239
+ title,
240
+ mediaInfos,
241
+ popupElements,
242
+ fieldInfos,
243
+ expressionInfos
244
+ };
245
+ }
246
+ }
@@ -1,12 +1,5 @@
1
1
  import type {FeatureTableJson} from '@loaders.gl/3d-tiles';
2
- import type {
3
- Attribute,
4
- AttributeStorageInfo,
5
- ESRIField,
6
- Field,
7
- FieldInfo,
8
- PopupInfo
9
- } from '@loaders.gl/i3s';
2
+ import type {Attribute} from '@loaders.gl/i3s';
10
3
  import type {
11
4
  GLTFPostprocessed,
12
5
  GLTF_EXT_feature_metadata_GLTF,
@@ -15,6 +8,8 @@ import type {
15
8
  GLTF_EXT_structural_metadata_ClassProperty
16
9
  } from '@loaders.gl/gltf';
17
10
 
11
+ import {AttributeType} from '../types';
12
+
18
13
  import {EXT_FEATURE_METADATA, EXT_STRUCTURAL_METADATA} from '@loaders.gl/gltf';
19
14
 
20
15
  /**
@@ -86,174 +81,17 @@ export function checkPropertiesLength(
86
81
  return needFlatten;
87
82
  }
88
83
 
89
- /** String data type name for feature attributes */
90
- const STRING_TYPE = 'string';
91
- /** Integer data type name for feature attributes */
92
- const SHORT_INT_TYPE = 'Int32';
93
- /** Double data type name for feature attributes */
94
- const DOUBLE_TYPE = 'double';
95
- /** Type of attribute that is linked with feature ids */
96
- const OBJECT_ID_TYPE = 'OBJECTID';
97
84
  /**
98
85
  * Get the attribute type for attributeStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
99
86
  * @param attribute - attribute taken from propertyTable
100
87
  */
101
88
  export function getAttributeType(attribute: unknown): string {
102
- if (typeof attribute === STRING_TYPE || typeof attribute === 'bigint') {
103
- return STRING_TYPE;
89
+ if (typeof attribute === 'string' || typeof attribute === 'bigint') {
90
+ return AttributeType.STRING_TYPE;
104
91
  } else if (typeof attribute === 'number') {
105
- return Number.isInteger(attribute) ? SHORT_INT_TYPE : DOUBLE_TYPE;
106
- }
107
- return STRING_TYPE;
108
- }
109
-
110
- /**
111
- * Generate storage attribute for map segmentation.
112
- * @param attributeIndex - order index of attribute (f_0, f_1 ...).
113
- * @param key - attribute key from propertyTable.
114
- * @param attributeType - attribute type.
115
- * @return Updated storageAttribute.
116
- */
117
- export function createdStorageAttribute(
118
- attributeIndex: number,
119
- key: string,
120
- attributeType: Attribute
121
- ): AttributeStorageInfo {
122
- const storageAttribute = {
123
- key: `f_${attributeIndex}`,
124
- name: key,
125
- ordering: ['attributeValues'],
126
- header: [{property: 'count', valueType: 'UInt32'}],
127
- attributeValues: {valueType: 'Int32', valuesPerElement: 1}
128
- };
129
-
130
- switch (attributeType) {
131
- case OBJECT_ID_TYPE:
132
- setupIdAttribute(storageAttribute);
133
- break;
134
- case STRING_TYPE:
135
- setupStringAttribute(storageAttribute);
136
- break;
137
- case DOUBLE_TYPE:
138
- setupDoubleAttribute(storageAttribute);
139
- break;
140
- case SHORT_INT_TYPE:
141
- break;
142
- default:
143
- setupStringAttribute(storageAttribute);
92
+ return Number.isInteger(attribute) ? AttributeType.SHORT_INT_TYPE : AttributeType.DOUBLE_TYPE;
144
93
  }
145
-
146
- return storageAttribute;
147
- }
148
-
149
- /**
150
- * Find and return attribute type based on key form propertyTable.
151
- * @param attributeType
152
- */
153
- export function getFieldAttributeType(attributeType: Attribute): ESRIField {
154
- switch (attributeType) {
155
- case OBJECT_ID_TYPE:
156
- return 'esriFieldTypeOID';
157
- case STRING_TYPE:
158
- return 'esriFieldTypeString';
159
- case SHORT_INT_TYPE:
160
- return 'esriFieldTypeInteger';
161
- case DOUBLE_TYPE:
162
- return 'esriFieldTypeDouble';
163
- default:
164
- return 'esriFieldTypeString';
165
- }
166
- }
167
-
168
- /**
169
- * Setup field attribute for map segmentation.
170
- * @param key - attribute for map segmentation.
171
- * @param fieldAttributeType - esri attribute type ('esriFieldTypeString' or 'esriFieldTypeOID').
172
- */
173
- export function createFieldAttribute(key: string, fieldAttributeType: ESRIField): Field {
174
- return {
175
- name: key,
176
- type: fieldAttributeType,
177
- alias: key
178
- };
179
- }
180
-
181
- /**
182
- * Generate popup info to show metadata on the map.
183
- * @param propertyNames - array of property names including OBJECTID.
184
- * @return data for correct rendering of popup.
185
- */
186
- export function createPopupInfo(propertyNames: string[]): PopupInfo {
187
- const title = '{OBJECTID}';
188
- const mediaInfos = [];
189
- const fieldInfos: FieldInfo[] = [];
190
- const popupElements: {
191
- fieldInfos: FieldInfo[];
192
- type: string;
193
- }[] = [];
194
- const expressionInfos = [];
195
-
196
- for (const propertyName of propertyNames) {
197
- fieldInfos.push({
198
- fieldName: propertyName,
199
- visible: true,
200
- isEditable: false,
201
- label: propertyName
202
- });
203
- }
204
- popupElements.push({
205
- fieldInfos,
206
- type: 'fields'
207
- });
208
-
209
- return {
210
- title,
211
- mediaInfos,
212
- popupElements,
213
- fieldInfos,
214
- expressionInfos
215
- };
216
- }
217
-
218
- /**
219
- * Setup storage attribute as string.
220
- * @param storageAttribute - attribute for map segmentation.
221
- */
222
- function setupStringAttribute(storageAttribute: AttributeStorageInfo): void {
223
- // @ts-expect-error
224
- storageAttribute.ordering.unshift('attributeByteCounts');
225
- storageAttribute.header.push({property: 'attributeValuesByteCount', valueType: 'UInt32'});
226
- storageAttribute.attributeValues = {
227
- valueType: 'String',
228
- encoding: 'UTF-8',
229
- valuesPerElement: 1
230
- };
231
- storageAttribute.attributeByteCounts = {
232
- valueType: 'UInt32',
233
- valuesPerElement: 1
234
- };
235
- }
236
-
237
- /**
238
- * Setup Id attribute for map segmentation.
239
- * @param storageAttribute - attribute for map segmentation .
240
- */
241
- function setupIdAttribute(storageAttribute: AttributeStorageInfo): void {
242
- storageAttribute.attributeValues = {
243
- valueType: 'Oid32',
244
- valuesPerElement: 1
245
- };
246
- }
247
-
248
- /**
249
- * Setup double attribute for map segmentation.
250
- * @param storageAttribute - attribute for map segmentation .
251
- */
252
- function setupDoubleAttribute(storageAttribute: AttributeStorageInfo): void {
253
- storageAttribute.attributeValues = {
254
- valueType: 'Float64',
255
- valuesPerElement: 1
256
- };
94
+ return AttributeType.STRING_TYPE;
257
95
  }
258
96
 
259
97
  /**
@@ -266,7 +104,7 @@ function setupDoubleAttribute(storageAttribute: AttributeStorageInfo): void {
266
104
  * "opt_uint64": "string"
267
105
  * }
268
106
  */
269
- export function getAttributeTypesFromPropertyTable(
107
+ export function getAttributeTypesMapFromPropertyTable(
270
108
  propertyTable: FeatureTableJson
271
109
  ): Record<string, Attribute> {
272
110
  const attributeTypesMap: Record<string, Attribute> = {};
@@ -290,7 +128,7 @@ export function getAttributeTypesFromPropertyTable(
290
128
  * "opt_uint64": "string"
291
129
  * }
292
130
  */
293
- export const getAttributeTypesFromSchema = (
131
+ export const getAttributeTypesMapFromSchema = (
294
132
  gltfJson: GLTFPostprocessed,
295
133
  metadataClass: string
296
134
  ): Record<string, Attribute> | null => {
@@ -339,12 +177,12 @@ const getAttributeTypeFromExtFeatureMetadata = (
339
177
  case 'UINT16':
340
178
  case 'INT32':
341
179
  case 'UINT32':
342
- attributeType = SHORT_INT_TYPE;
180
+ attributeType = AttributeType.SHORT_INT_TYPE;
343
181
  break;
344
182
 
345
183
  case 'FLOAT32':
346
184
  case 'FLOAT64':
347
- attributeType = DOUBLE_TYPE;
185
+ attributeType = AttributeType.DOUBLE_TYPE;
348
186
  break;
349
187
 
350
188
  case 'INT64':
@@ -353,11 +191,11 @@ const getAttributeTypeFromExtFeatureMetadata = (
353
191
  case 'ENUM':
354
192
  case 'STRING':
355
193
  case 'ARRAY':
356
- attributeType = STRING_TYPE;
194
+ attributeType = AttributeType.STRING_TYPE;
357
195
  break;
358
196
 
359
197
  default:
360
- attributeType = STRING_TYPE;
198
+ attributeType = AttributeType.STRING_TYPE;
361
199
  break;
362
200
  }
363
201
  return attributeType;
@@ -374,7 +212,7 @@ const getAttributeTypeFromExtStructuralMetadata = (
374
212
  ): Attribute => {
375
213
  let attributeType: Attribute;
376
214
  if (property.array) {
377
- attributeType = STRING_TYPE;
215
+ attributeType = AttributeType.STRING_TYPE;
378
216
  } else {
379
217
  switch (property.componentType) {
380
218
  case 'INT8':
@@ -383,21 +221,21 @@ const getAttributeTypeFromExtStructuralMetadata = (
383
221
  case 'UINT16':
384
222
  case 'INT32':
385
223
  case 'UINT32':
386
- attributeType = SHORT_INT_TYPE;
224
+ attributeType = AttributeType.SHORT_INT_TYPE;
387
225
  break;
388
226
 
389
227
  case 'FLOAT32':
390
228
  case 'FLOAT64':
391
- attributeType = DOUBLE_TYPE;
229
+ attributeType = AttributeType.DOUBLE_TYPE;
392
230
  break;
393
231
 
394
232
  case 'INT64':
395
233
  case 'UINT64':
396
- attributeType = STRING_TYPE;
234
+ attributeType = AttributeType.STRING_TYPE;
397
235
  break;
398
236
 
399
237
  default:
400
- attributeType = STRING_TYPE;
238
+ attributeType = AttributeType.STRING_TYPE;
401
239
  break;
402
240
  }
403
241
  }