@cesium/engine 7.0.0 → 8.0.0

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 (172) hide show
  1. package/Build/Workers/{chunk-MY3VNFGQ.js → chunk-23UFSGND.js} +7 -7
  2. package/Build/Workers/{chunk-IQBYFRVW.js → chunk-2A75IWRS.js} +7 -7
  3. package/Build/Workers/{chunk-VRGFV2UO.js → chunk-2FRVPMCS.js} +10 -10
  4. package/Build/Workers/{chunk-46UD5ABS.js → chunk-2FWRMUTY.js} +4 -4
  5. package/Build/Workers/{chunk-DTAIXKTO.js → chunk-2UPKWTMJ.js} +6 -6
  6. package/Build/Workers/{chunk-6VJVYK2V.js → chunk-34FXV7D7.js} +2 -2
  7. package/Build/Workers/{chunk-ODW7WYM4.js → chunk-3VAZEH7M.js} +2 -2
  8. package/Build/Workers/{chunk-U2VCRRQW.js → chunk-4DO5W5XZ.js} +6 -6
  9. package/Build/Workers/{chunk-VK3EJHWI.js → chunk-4H7PY4U5.js} +2 -2
  10. package/Build/Workers/{chunk-RV7ZYPFT.js → chunk-5QULIR53.js} +4 -4
  11. package/Build/Workers/{chunk-JY5YEZFA.js → chunk-7TC63SJW.js} +8 -8
  12. package/Build/Workers/{chunk-JJ4VBOQ3.js → chunk-7ZFGPDJA.js} +4 -4
  13. package/Build/Workers/{chunk-FP6GYBFX.js → chunk-A5DWLWCY.js} +10 -10
  14. package/Build/Workers/{chunk-5M3U6ZMA.js → chunk-BBWDMCVU.js} +1 -1
  15. package/Build/Workers/{chunk-WZU2YLWG.js → chunk-BG4UCVXN.js} +3 -3
  16. package/Build/Workers/{chunk-5WQ523AW.js → chunk-BIKA3NRA.js} +5 -5
  17. package/Build/Workers/{chunk-PTQQUQC3.js → chunk-BROJAZRZ.js} +13 -13
  18. package/Build/Workers/{chunk-YUCVWAY6.js → chunk-DDUQAJ4P.js} +7 -7
  19. package/Build/Workers/{chunk-2HJWSU7B.js → chunk-EERJKOAF.js} +4 -4
  20. package/Build/Workers/{chunk-LZGHD6NY.js → chunk-EG6PTBY2.js} +15 -15
  21. package/Build/Workers/{chunk-IX2JCCNM.js → chunk-EHWHNOEX.js} +1 -1
  22. package/Build/Workers/{chunk-NKPBIX7F.js → chunk-F3YA3Y2Z.js} +1 -1
  23. package/Build/Workers/{chunk-L2ZN645J.js → chunk-F4HFJMGM.js} +6 -6
  24. package/Build/Workers/{chunk-F6SE42BK.js → chunk-FJKNFAKQ.js} +15 -472
  25. package/Build/Workers/{chunk-PNBGBETF.js → chunk-FNIRWHJB.js} +10 -10
  26. package/Build/Workers/{chunk-RAEV7K66.js → chunk-FZRIVR7Y.js} +5 -5
  27. package/Build/Workers/{chunk-AIPU2VSX.js → chunk-G43QFN4Q.js} +6 -6
  28. package/Build/Workers/{chunk-ZUA2UUNV.js → chunk-GATZHF3K.js} +2 -2
  29. package/Build/Workers/{chunk-ZK5JOS3D.js → chunk-GRC2ZTAF.js} +14 -14
  30. package/Build/Workers/{chunk-5YLJ77FF.js → chunk-HU6N6EXB.js} +10 -10
  31. package/Build/Workers/{chunk-4EBHOMFX.js → chunk-I46ZRR5W.js} +17 -17
  32. package/Build/Workers/{chunk-LZ7JIV3K.js → chunk-JURN7NPV.js} +17 -17
  33. package/Build/Workers/{chunk-JCNXK6EL.js → chunk-KKCR2YOP.js} +11 -11
  34. package/Build/Workers/{chunk-S6SKF6DT.js → chunk-LPR3YNP2.js} +5 -5
  35. package/Build/Workers/{chunk-UDO6BFSF.js → chunk-M7ERACJJ.js} +13 -13
  36. package/Build/Workers/{chunk-BZP4T2JJ.js → chunk-MDWEGWPA.js} +10 -10
  37. package/Build/Workers/{chunk-72SANQJV.js → chunk-OGXZVPPM.js} +9 -5
  38. package/Build/Workers/{chunk-AR5DNBJ4.js → chunk-PGSJK77E.js} +6 -6
  39. package/Build/Workers/{chunk-GEJTYLCO.js → chunk-PPH7OFP3.js} +5 -5
  40. package/Build/Workers/{chunk-OVLG3FRS.js → chunk-SH5USDPI.js} +6 -6
  41. package/Build/Workers/{chunk-6HZQPRUS.js → chunk-SOWMRMWA.js} +1 -1
  42. package/Build/Workers/{chunk-JXDC723O.js → chunk-STW2DGFI.js} +2 -2
  43. package/Build/Workers/{chunk-5HDYHG3F.js → chunk-T3XIFPYR.js} +13 -13
  44. package/Build/Workers/chunk-TTUZP4BO.js +501 -0
  45. package/Build/Workers/{chunk-7XEAYGZK.js → chunk-UEXTBDBE.js} +10 -10
  46. package/Build/Workers/{chunk-GV56Q4LU.js → chunk-VOXYEYJT.js} +11 -11
  47. package/Build/Workers/{chunk-NY3K4IM3.js → chunk-X4356LRH.js} +12 -12
  48. package/Build/Workers/{chunk-S4MAZ3SS.js → chunk-XGI5BXZY.js} +2 -2
  49. package/Build/Workers/{chunk-UAEW6HKG.js → chunk-Y2ME2IJV.js} +13 -13
  50. package/Build/Workers/{chunk-XWXM2O2R.js → chunk-Y5UQJLYE.js} +6 -6
  51. package/Build/Workers/{chunk-QZAD5O7I.js → chunk-YJEBABKH.js} +7 -7
  52. package/Build/Workers/{chunk-UGK3FCDY.js → chunk-YWTJ2B4B.js} +1 -1
  53. package/Build/Workers/{chunk-R5X4OQT4.js → chunk-Z3TIFFGF.js} +7 -7
  54. package/Build/Workers/{chunk-WBQCVXR3.js → chunk-ZT7KWISZ.js} +4 -4
  55. package/Build/Workers/combineGeometry.js +24 -23
  56. package/Build/Workers/createBoxGeometry.js +18 -17
  57. package/Build/Workers/createBoxOutlineGeometry.js +16 -15
  58. package/Build/Workers/createCircleGeometry.js +26 -25
  59. package/Build/Workers/createCircleOutlineGeometry.js +19 -18
  60. package/Build/Workers/createCoplanarPolygonGeometry.js +33 -32
  61. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -30
  62. package/Build/Workers/createCorridorGeometry.js +29 -28
  63. package/Build/Workers/createCorridorOutlineGeometry.js +28 -27
  64. package/Build/Workers/createCylinderGeometry.js +20 -19
  65. package/Build/Workers/createCylinderOutlineGeometry.js +18 -17
  66. package/Build/Workers/createEllipseGeometry.js +26 -25
  67. package/Build/Workers/createEllipseOutlineGeometry.js +19 -18
  68. package/Build/Workers/createEllipsoidGeometry.js +19 -18
  69. package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -17
  70. package/Build/Workers/createFrustumGeometry.js +18 -17
  71. package/Build/Workers/createFrustumOutlineGeometry.js +18 -17
  72. package/Build/Workers/createGeometry.js +54 -33
  73. package/Build/Workers/createGroundPolylineGeometry.js +22 -21
  74. package/Build/Workers/createPlaneGeometry.js +16 -15
  75. package/Build/Workers/createPlaneOutlineGeometry.js +15 -14
  76. package/Build/Workers/createPolygonGeometry.js +32 -31
  77. package/Build/Workers/createPolygonOutlineGeometry.js +30 -29
  78. package/Build/Workers/createPolylineGeometry.js +25 -24
  79. package/Build/Workers/createPolylineVolumeGeometry.js +31 -30
  80. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -26
  81. package/Build/Workers/createRectangleGeometry.js +27 -26
  82. package/Build/Workers/createRectangleOutlineGeometry.js +20 -19
  83. package/Build/Workers/createSimplePolylineGeometry.js +23 -22
  84. package/Build/Workers/createSphereGeometry.js +19 -18
  85. package/Build/Workers/createSphereOutlineGeometry.js +18 -17
  86. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  87. package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
  88. package/Build/Workers/createVectorTileGeometries.js +24 -23
  89. package/Build/Workers/createVectorTilePoints.js +12 -12
  90. package/Build/Workers/createVectorTilePolygons.js +22 -21
  91. package/Build/Workers/createVectorTilePolylines.js +14 -14
  92. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +22 -21
  93. package/Build/Workers/createVerticesFromHeightmap.js +22 -21
  94. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +19 -18
  95. package/Build/Workers/createWallGeometry.js +24 -23
  96. package/Build/Workers/createWallOutlineGeometry.js +23 -22
  97. package/Build/Workers/decodeDraco.js +11 -11
  98. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  99. package/Build/Workers/decodeI3S.js +601 -92
  100. package/Build/Workers/transcodeKTX2.js +7 -7
  101. package/Build/Workers/transferTypedArrayTest.js +1 -1
  102. package/Build/Workers/upsampleQuantizedTerrainMesh.js +22 -21
  103. package/Source/Core/Ellipsoid.js +6 -0
  104. package/Source/Core/IntersectionTests.js +6 -3
  105. package/Source/Core/Ion.js +1 -1
  106. package/Source/Core/PixelFormat.js +5 -0
  107. package/Source/Core/Transforms.js +3 -0
  108. package/Source/Core/srgbToLinear.js +32 -0
  109. package/Source/DataSources/CzmlDataSource.js +51 -23
  110. package/Source/DataSources/DataSourceDisplay.js +27 -0
  111. package/Source/DataSources/Entity.js +20 -2
  112. package/Source/DataSources/GeometryUpdaterSet.js +114 -0
  113. package/Source/DataSources/GeometryVisualizer.js +19 -83
  114. package/Source/Renderer/Context.js +10 -0
  115. package/Source/Renderer/ContextLimits.js +2 -0
  116. package/Source/Renderer/demodernizeShader.js +4 -1
  117. package/Source/Scene/ArcGisMapService.js +1 -1
  118. package/Source/Scene/Axis.js +12 -7
  119. package/Source/Scene/Camera.js +46 -4
  120. package/Source/Scene/Cesium3DTileset.js +44 -6
  121. package/Source/Scene/Cesium3DTilesetBaseTraversal.js +2 -4
  122. package/Source/Scene/FrameState.js +5 -0
  123. package/Source/Scene/GlobeTranslucencyState.js +1 -1
  124. package/Source/Scene/GltfPipeline/updateVersion.js +69 -68
  125. package/Source/Scene/I3SDataProvider.js +270 -53
  126. package/Source/Scene/I3SDecoder.js +8 -1
  127. package/Source/Scene/I3SFeature.js +2 -5
  128. package/Source/Scene/I3SField.js +136 -31
  129. package/Source/Scene/I3SGeometry.js +70 -2
  130. package/Source/Scene/I3SLayer.js +55 -10
  131. package/Source/Scene/I3SNode.js +175 -18
  132. package/Source/Scene/I3SStatistics.js +94 -0
  133. package/Source/Scene/I3SSublayer.js +176 -0
  134. package/Source/Scene/I3SSymbology.js +337 -0
  135. package/Source/Scene/KeyframeNode.js +1 -1
  136. package/Source/Scene/Model/pickModel.js +25 -7
  137. package/Source/Scene/PickFramebuffer.js +37 -2
  138. package/Source/Scene/Picking.js +113 -39
  139. package/Source/Scene/Primitive.js +6 -2
  140. package/Source/Scene/Scene.js +126 -42
  141. package/Source/Scene/ScreenSpaceCameraController.js +21 -7
  142. package/Source/Scene/SensorVolumePortionToDisplay.js +69 -0
  143. package/Source/Scene/SpatialNode.js +12 -19
  144. package/Source/Scene/StructuralMetadata.js +1 -1
  145. package/Source/Scene/VoxelBoxShape.js +76 -0
  146. package/Source/Scene/VoxelCell.js +273 -0
  147. package/Source/Scene/VoxelCylinderShape.js +114 -43
  148. package/Source/Scene/VoxelEllipsoidShape.js +158 -116
  149. package/Source/Scene/VoxelPrimitive.js +3 -1
  150. package/Source/Scene/VoxelRenderResources.js +3 -0
  151. package/Source/Scene/VoxelShape.js +13 -0
  152. package/Source/Scene/VoxelTraversal.js +76 -54
  153. package/Source/Scene/buildVoxelDrawCommands.js +23 -0
  154. package/Source/Scene/createGooglePhotorealistic3DTileset.js +1 -0
  155. package/Source/Scene/processVoxelProperties.js +2 -0
  156. package/Source/Shaders/Voxels/IntersectCylinder.glsl +14 -111
  157. package/Source/Shaders/Voxels/IntersectCylinder.js +14 -111
  158. package/Source/Shaders/Voxels/IntersectEllipsoid.glsl +32 -113
  159. package/Source/Shaders/Voxels/IntersectEllipsoid.js +32 -113
  160. package/Source/Shaders/Voxels/IntersectLongitude.glsl +102 -0
  161. package/Source/Shaders/Voxels/IntersectLongitude.js +104 -0
  162. package/Source/Shaders/Voxels/VoxelFS.glsl +39 -1
  163. package/Source/Shaders/Voxels/VoxelFS.js +39 -1
  164. package/Source/Shaders/Voxels/convertUvToCylinder.glsl +19 -37
  165. package/Source/Shaders/Voxels/convertUvToCylinder.js +19 -37
  166. package/Source/Shaders/Voxels/convertUvToEllipsoid.glsl +24 -44
  167. package/Source/Shaders/Voxels/convertUvToEllipsoid.js +24 -44
  168. package/Source/Workers/createGeometry.js +40 -11
  169. package/Source/Workers/decodeI3S.js +720 -94
  170. package/index.d.ts +296 -11
  171. package/index.js +102 -94
  172. package/package.json +1 -1
@@ -57,6 +57,8 @@ import Resource from "../Core/Resource.js";
57
57
  import RuntimeError from "../Core/RuntimeError.js";
58
58
  import WebMercatorProjection from "../Core/WebMercatorProjection.js";
59
59
  import I3SLayer from "./I3SLayer.js";
60
+ import I3SStatistics from "./I3SStatistics.js";
61
+ import I3SSublayer from "./I3SSublayer.js";
60
62
  import Lerc from "lerc";
61
63
  import Rectangle from "../Core/Rectangle.js";
62
64
 
@@ -68,8 +70,30 @@ import Rectangle from "../Core/Rectangle.js";
68
70
  * @property {string} [name] The name of the I3S dataset.
69
71
  * @property {boolean} [show=true] Determines if the dataset will be shown.
70
72
  * @property {ArcGISTiledElevationTerrainProvider|Promise<ArcGISTiledElevationTerrainProvider>} [geoidTiledTerrainProvider] Tiled elevation provider describing an Earth Gravitational Model. If defined, geometry will be shifted based on the offsets given by this provider. Required to position I3S data sets with gravity-related height at the correct location.
71
- * @property {boolean} [traceFetches=false] Debug option. When true, log a message whenever an I3S tile is fetched.
72
73
  * @property {Cesium3DTileset.ConstructorOptions} [cesium3dTilesetOptions] Object containing options to pass to an internally created {@link Cesium3DTileset}. See {@link Cesium3DTileset} for list of valid properties. All options can be used with the exception of <code>url</code> and <code>show</code> which are overridden by values from I3SDataProvider.
74
+ * @property {boolean} [showFeatures=false] Determines if the features will be shown.
75
+ * @property {boolean} [adjustMaterialAlphaMode=false] The option to adjust the alpha mode of the material based on the transparency of the vertex color. When <code>true</code>, the alpha mode of the material (if not defined) will be set to BLEND for geometry with any transparency in the color vertex attribute.
76
+ * @property {boolean} [applySymbology=false] Determines if the I3S symbology will be parsed and applied for the layers.
77
+ * @property {boolean} [calculateNormals=false] Determines if the flat normals will be generated for I3S geometry without normals.
78
+ *
79
+ * @example
80
+ * // Increase LOD by reducing SSE
81
+ * const cesium3dTilesetOptions = {
82
+ * maximumScreenSpaceError: 1,
83
+ * };
84
+ * const i3sOptions = {
85
+ * cesium3dTilesetOptions: cesium3dTilesetOptions,
86
+ * };
87
+ *
88
+ * @example
89
+ * // Set a custom outline color to replace the color defined in I3S symbology
90
+ * const cesium3dTilesetOptions = {
91
+ * outlineColor: Cesium.Color.BLUE,
92
+ * };
93
+ * const i3sOptions = {
94
+ * cesium3dTilesetOptions: cesium3dTilesetOptions,
95
+ * applySymbology: true,
96
+ * };
73
97
  */
74
98
 
75
99
  /**
@@ -122,7 +146,13 @@ function I3SDataProvider(options) {
122
146
  this._name = options.name;
123
147
  this._show = defaultValue(options.show, true);
124
148
  this._geoidTiledTerrainProvider = options.geoidTiledTerrainProvider;
125
- this._traceFetches = defaultValue(options.traceFetches, false);
149
+ this._showFeatures = defaultValue(options.showFeatures, false);
150
+ this._adjustMaterialAlphaMode = defaultValue(
151
+ options.adjustMaterialAlphaMode,
152
+ false
153
+ );
154
+ this._applySymbology = defaultValue(options.applySymbology, false);
155
+ this._calculateNormals = defaultValue(options.calculateNormals, false);
126
156
 
127
157
  this._cesium3dTilesetOptions = defaultValue(
128
158
  options.cesium3dTilesetOptions,
@@ -130,12 +160,15 @@ function I3SDataProvider(options) {
130
160
  );
131
161
 
132
162
  this._layers = [];
163
+ this._sublayers = [];
133
164
  this._data = undefined;
134
165
  this._extent = undefined;
135
166
  this._geoidDataPromise = undefined;
136
167
  this._geoidDataList = undefined;
137
168
  this._decoderTaskProcessor = undefined;
138
169
  this._taskProcessorReadyPromise = undefined;
170
+ this._attributeStatistics = [];
171
+ this._layersExtent = [];
139
172
  }
140
173
 
141
174
  Object.defineProperties(I3SDataProvider.prototype, {
@@ -165,33 +198,15 @@ Object.defineProperties(I3SDataProvider.prototype, {
165
198
  Check.defined("value", value);
166
199
  //>>includeEnd('debug');
167
200
 
168
- this._show = value;
169
- for (let i = 0; i < this._layers.length; i++) {
170
- if (defined(this._layers[i]._tileset)) {
171
- this._layers[i]._tileset.show = this._show;
201
+ if (this._show !== value) {
202
+ this._show = value;
203
+ for (let i = 0; i < this._layers.length; i++) {
204
+ this._layers[i]._updateVisibility();
172
205
  }
173
206
  }
174
207
  },
175
208
  },
176
209
 
177
- /**
178
- * Gets or sets debugging and tracing of I3S fetches.
179
- * @memberof I3SDataProvider.prototype
180
- * @type {boolean}
181
- */
182
- traceFetches: {
183
- get: function () {
184
- return this._traceFetches;
185
- },
186
- set: function (value) {
187
- //>>includeStart('debug', pragmas.debug);
188
- Check.defined("value", value);
189
- //>>includeEnd('debug');
190
-
191
- this._traceFetches = value;
192
- },
193
- },
194
-
195
210
  /**
196
211
  * The terrain provider referencing the GEOID service to be used for orthometric to ellipsoidal conversion.
197
212
  * @memberof I3SDataProvider.prototype
@@ -216,6 +231,18 @@ Object.defineProperties(I3SDataProvider.prototype, {
216
231
  },
217
232
  },
218
233
 
234
+ /**
235
+ * Gets the collection of building sublayers.
236
+ * @memberof I3SDataProvider.prototype
237
+ * @type {I3SSublayer[]}
238
+ * @readonly
239
+ */
240
+ sublayers: {
241
+ get: function () {
242
+ return this._sublayers;
243
+ },
244
+ },
245
+
219
246
  /**
220
247
  * Gets the I3S data for this object.
221
248
  * @memberof I3SDataProvider.prototype
@@ -251,6 +278,54 @@ Object.defineProperties(I3SDataProvider.prototype, {
251
278
  return this._resource;
252
279
  },
253
280
  },
281
+
282
+ /**
283
+ * Determines if the features will be shown.
284
+ * @memberof I3SDataProvider.prototype
285
+ * @type {boolean}
286
+ * @readonly
287
+ */
288
+ showFeatures: {
289
+ get: function () {
290
+ return this._showFeatures;
291
+ },
292
+ },
293
+
294
+ /**
295
+ * Determines if the alpha mode of the material will be adjusted depending on the color vertex attribute.
296
+ * @memberof I3SDataProvider.prototype
297
+ * @type {boolean}
298
+ * @readonly
299
+ */
300
+ adjustMaterialAlphaMode: {
301
+ get: function () {
302
+ return this._adjustMaterialAlphaMode;
303
+ },
304
+ },
305
+
306
+ /**
307
+ * Determines if the I3S symbology will be parsed and applied for the layers.
308
+ * @memberof I3SDataProvider.prototype
309
+ * @type {boolean}
310
+ * @readonly
311
+ */
312
+ applySymbology: {
313
+ get: function () {
314
+ return this._applySymbology;
315
+ },
316
+ },
317
+
318
+ /**
319
+ * Determines if the flat normals will be generated for I3S geometry without normals.
320
+ * @memberof I3SDataProvider.prototype
321
+ * @type {boolean}
322
+ * @readonly
323
+ */
324
+ calculateNormals: {
325
+ get: function () {
326
+ return this._calculateNormals;
327
+ },
328
+ },
254
329
  });
255
330
 
256
331
  /**
@@ -335,6 +410,101 @@ I3SDataProvider.prototype.updateForPass = function (frameState, passState) {
335
410
  }
336
411
  };
337
412
 
413
+ function buildLayerUrl(provider, layerId) {
414
+ const dataProviderUrl = provider.resource.getUrlComponent();
415
+
416
+ let layerUrl = "";
417
+ if (dataProviderUrl.match(/layers\/\d/)) {
418
+ layerUrl = `${dataProviderUrl}`.replace(/\/+$/, "");
419
+ } else {
420
+ // Add '/' to url if needed + `$layers/${layerId}/` if tilesetUrl not already in ../layers/[id] format
421
+ layerUrl = `${dataProviderUrl}`
422
+ .replace(/\/?$/, "/")
423
+ .concat(`layers/${layerId}`);
424
+ }
425
+ return layerUrl;
426
+ }
427
+
428
+ async function addLayers(provider, data, options) {
429
+ if (data.layerType === "Building") {
430
+ if (!defined(options.showFeatures)) {
431
+ // The Building Scene Layer requires features to be shown to support filtering
432
+ provider._showFeatures = true;
433
+ }
434
+ if (!defined(options.adjustMaterialAlphaMode)) {
435
+ // The Building Scene Layer enables transparency by default
436
+ provider._adjustMaterialAlphaMode = true;
437
+ }
438
+ if (!defined(options.applySymbology)) {
439
+ // The Building Scene Layer applies symbology by default
440
+ provider._applySymbology = true;
441
+ }
442
+ if (!defined(options.calculateNormals)) {
443
+ // The Building Scene Layer calculates flat normals by default
444
+ provider._calculateNormals = true;
445
+ }
446
+
447
+ const buildingLayerUrl = buildLayerUrl(provider, data.id);
448
+ if (defined(data.sublayers)) {
449
+ const promises = [];
450
+ for (let i = 0; i < data.sublayers.length; i++) {
451
+ const promise = I3SSublayer._fromData(
452
+ provider,
453
+ buildingLayerUrl,
454
+ data.sublayers[i],
455
+ provider
456
+ );
457
+ promises.push(promise);
458
+ }
459
+ const sublayers = await Promise.all(promises);
460
+ for (let i = 0; i < sublayers.length; i++) {
461
+ const sublayer = sublayers[i];
462
+ provider._sublayers.push(sublayer);
463
+ provider._layers.push(...sublayer._i3sLayers);
464
+ }
465
+ }
466
+
467
+ if (defined(data.statisticsHRef)) {
468
+ const uri = buildingLayerUrl.concat(`/${data.statisticsHRef}`);
469
+ const statistics = new I3SStatistics(provider, uri);
470
+ await statistics.load();
471
+ provider._attributeStatistics.push(statistics);
472
+ }
473
+
474
+ if (defined(data.fullExtent)) {
475
+ const extent = Rectangle.fromDegrees(
476
+ data.fullExtent.xmin,
477
+ data.fullExtent.ymin,
478
+ data.fullExtent.xmax,
479
+ data.fullExtent.ymax
480
+ );
481
+ provider._layersExtent.push(extent);
482
+ }
483
+ } else if (
484
+ data.layerType === "3DObject" ||
485
+ data.layerType === "IntegratedMesh"
486
+ ) {
487
+ if (
488
+ !defined(options.calculateNormals) &&
489
+ !defined(data.textureSetDefinitions)
490
+ ) {
491
+ // I3S Layers without textures should calculate flat normals by default
492
+ provider._calculateNormals = true;
493
+ }
494
+
495
+ const newLayer = new I3SLayer(provider, data, provider);
496
+ provider._layers.push(newLayer);
497
+ if (defined(newLayer._extent)) {
498
+ provider._layersExtent.push(newLayer._extent);
499
+ }
500
+ } else {
501
+ // Filter other scene layer types out
502
+ console.log(
503
+ `${data.layerType} layer ${data.name} is skipped as not supported.`
504
+ );
505
+ }
506
+ }
507
+
338
508
  /**
339
509
  * Creates an I3SDataProvider. Currently supported I3S versions are 1.6 and
340
510
  * 1.7/1.8 (OGC I3S 1.2).
@@ -375,6 +545,8 @@ I3SDataProvider.fromUrl = async function (url, options) {
375
545
  options = defaultValue(options, defaultValue.EMPTY_OBJECT);
376
546
 
377
547
  const resource = Resource.createIfNeeded(url);
548
+ // Set a query parameter for json to avoid failure on html pages
549
+ resource.setQueryParameters({ f: "pjson" }, true);
378
550
  const data = await I3SDataProvider.loadJson(resource);
379
551
 
380
552
  const provider = new I3SDataProvider(options);
@@ -383,17 +555,14 @@ I3SDataProvider.fromUrl = async function (url, options) {
383
555
 
384
556
  // Success
385
557
  if (defined(data.layers)) {
558
+ const promises = [];
386
559
  for (let layerIndex = 0; layerIndex < data.layers.length; layerIndex++) {
387
- const newLayer = new I3SLayer(
388
- provider,
389
- data.layers[layerIndex],
390
- layerIndex
391
- );
392
- provider._layers.push(newLayer);
560
+ const promise = addLayers(provider, data.layers[layerIndex], options);
561
+ promises.push(promise);
393
562
  }
563
+ await Promise.all(promises);
394
564
  } else {
395
- const newLayer = new I3SLayer(provider, data, data.id);
396
- provider._layers.push(newLayer);
565
+ await addLayers(provider, data, options);
397
566
  }
398
567
 
399
568
  provider._computeExtent();
@@ -421,14 +590,9 @@ I3SDataProvider._fetchJson = function (resource) {
421
590
  * @private
422
591
  *
423
592
  * @param {Resource} resource The JSON resource to request
424
- * @param {boolean} [trace=false] Log the resource
425
593
  * @returns {Promise<object>} The fetched data
426
594
  */
427
- I3SDataProvider.loadJson = async function (resource, trace) {
428
- if (trace) {
429
- console.log("I3S FETCH:", resource.url);
430
- }
431
-
595
+ I3SDataProvider.loadJson = async function (resource) {
432
596
  const data = await I3SDataProvider._fetchJson(resource);
433
597
  if (defined(data.error)) {
434
598
  console.error("Failed to fetch I3S ", resource.url);
@@ -450,11 +614,20 @@ I3SDataProvider.loadJson = async function (resource, trace) {
450
614
  /**
451
615
  * @private
452
616
  */
453
- I3SDataProvider.prototype._loadBinary = function (resource) {
454
- if (this._traceFetches) {
455
- console.log("I3S FETCH:", resource.url);
617
+ I3SDataProvider.prototype._loadBinary = async function (resource) {
618
+ const buffer = await resource.fetchArrayBuffer();
619
+ if (buffer.byteLength > 0) {
620
+ // Check if we have a JSON response with 404
621
+ const array = new Uint8Array(buffer);
622
+ if (array[0] === "{".charCodeAt(0)) {
623
+ const textContent = new TextDecoder();
624
+ const str = textContent.decode(buffer);
625
+ if (str.includes("404")) {
626
+ throw new RuntimeError(`Failed to load binary: ${resource.url}`);
627
+ }
628
+ }
456
629
  }
457
- return resource.fetchArrayBuffer();
630
+ return buffer;
458
631
  };
459
632
 
460
633
  /**
@@ -593,9 +766,6 @@ async function loadGeoidData(provider) {
593
766
  const geoidTerrainProvider = provider._geoidTiledTerrainProvider;
594
767
 
595
768
  if (!defined(geoidTerrainProvider)) {
596
- console.log(
597
- "No Geoid Terrain service provided - no geoid conversion will be performed."
598
- );
599
769
  return;
600
770
  }
601
771
 
@@ -631,18 +801,65 @@ I3SDataProvider.prototype._computeExtent = function () {
631
801
  let rectangle;
632
802
 
633
803
  // Compute the extent from all layers
634
- for (let layerIndex = 0; layerIndex < this._layers.length; layerIndex++) {
635
- if (defined(this._layers[layerIndex]._extent)) {
636
- const layerExtent = this._layers[layerIndex]._extent;
637
- if (!defined(rectangle)) {
638
- rectangle = Rectangle.clone(layerExtent);
639
- } else {
640
- Rectangle.union(rectangle, layerExtent, rectangle);
641
- }
804
+ for (
805
+ let layerIndex = 0;
806
+ layerIndex < this._layersExtent.length;
807
+ layerIndex++
808
+ ) {
809
+ const layerExtent = this._layersExtent[layerIndex];
810
+ if (!defined(rectangle)) {
811
+ rectangle = Rectangle.clone(layerExtent);
812
+ } else {
813
+ Rectangle.union(rectangle, layerExtent, rectangle);
642
814
  }
643
815
  }
644
816
 
645
817
  this._extent = rectangle;
646
818
  };
647
819
 
820
+ /**
821
+ * Returns the collection of names for all available attributes
822
+ * @returns {string[]} The collection of attribute names
823
+ */
824
+ I3SDataProvider.prototype.getAttributeNames = function () {
825
+ const attributes = [];
826
+ for (let i = 0; i < this._attributeStatistics.length; ++i) {
827
+ attributes.push(...this._attributeStatistics[i].names);
828
+ }
829
+ return attributes;
830
+ };
831
+
832
+ /**
833
+ * Returns the collection of values for the attribute with the given name
834
+ * @param {string} name The attribute name
835
+ * @returns {string[]} The collection of attribute values
836
+ */
837
+ I3SDataProvider.prototype.getAttributeValues = function (name) {
838
+ //>>includeStart('debug', pragmas.debug);
839
+ Check.defined("name", name);
840
+ //>>includeEnd('debug');
841
+
842
+ for (let i = 0; i < this._attributeStatistics.length; ++i) {
843
+ const values = this._attributeStatistics[i]._getValues(name);
844
+ if (defined(values)) {
845
+ return values;
846
+ }
847
+ }
848
+ return [];
849
+ };
850
+
851
+ /**
852
+ * Filters the drawn elements of a scene to specific attribute names and values
853
+ * @param {I3SNode.AttributeFilter[]} [filters=[]] The collection of attribute filters
854
+ * @returns {Promise<void>} A promise that is resolved when the filter is applied
855
+ */
856
+ I3SDataProvider.prototype.filterByAttributes = function (filters) {
857
+ const promises = [];
858
+ for (let i = 0; i < this._layers.length; i++) {
859
+ const promise = this._layers[i].filterByAttributes(filters);
860
+ promises.push(promise);
861
+ }
862
+ return Promise.all(promises);
863
+ };
864
+
648
865
  export default I3SDataProvider;
@@ -45,6 +45,7 @@ async function initializeDecoder() {
45
45
  * @param {Object} defaultGeometrySchema Schema to use during decoding
46
46
  * @param {I3SGeometry} geometryData The draco encoded geometry data
47
47
  * @param {Array} [featureData] The draco encoded feature data
48
+ * @param {Object} [symbologyData] The rendering symbology to apply
48
49
  * @returns Promise<undefined|object> Returns a promise which resolves to the glTF result, or undefined if the task cannot be scheduled this frame.
49
50
  *
50
51
  * @exception {RuntimeError} I3S decoder could not be initialized.
@@ -53,7 +54,8 @@ I3SDecoder.decode = async function (
53
54
  url,
54
55
  defaultGeometrySchema,
55
56
  geometryData,
56
- featureData
57
+ featureData,
58
+ symbologyData
57
59
  ) {
58
60
  //>>includeStart('debug', pragmas.debug);
59
61
  Check.typeOf.string("url", url);
@@ -118,6 +120,11 @@ I3SDecoder.decode = async function (
118
120
  cartographicCenter: cartographicCenter,
119
121
  cartesianCenter: cartesianCenter,
120
122
  parentRotation: parentRotation,
123
+ enableFeatures: geometryData._dataProvider.showFeatures,
124
+ splitGeometryByColorTransparency:
125
+ geometryData._dataProvider.adjustMaterialAlphaMode,
126
+ symbologyData: symbologyData,
127
+ calculateNormals: geometryData._dataProvider.calculateNormals,
121
128
  };
122
129
 
123
130
  return taskProcessor.scheduleTask(payload);
@@ -50,14 +50,11 @@ Object.defineProperties(I3SFeature.prototype, {
50
50
 
51
51
  /**
52
52
  * Loads the content.
53
- * @returns {Promise} A promise that is resolved when the data of the I3S feature is loaded
53
+ * @returns {Promise<object>} A promise that is resolved when the data of the I3S feature is loaded
54
54
  * @private
55
55
  */
56
56
  I3SFeature.prototype.load = async function () {
57
- this._data = await I3SDataProvider.loadJson(
58
- this._resource,
59
- this._dataProvider._traceFetches
60
- );
57
+ this._data = await I3SDataProvider.loadJson(this._resource);
61
58
  return this._data;
62
59
  };
63
60
 
@@ -1,4 +1,5 @@
1
1
  import defined from "../Core/defined.js";
2
+ import RuntimeError from "../Core/RuntimeError.js";
2
3
 
3
4
  /**
4
5
  * This class implements an I3S Field which is custom data attached
@@ -12,6 +13,7 @@ function I3SField(parent, storageInfo) {
12
13
  this._storageInfo = storageInfo;
13
14
  this._parent = parent;
14
15
  this._dataProvider = parent._dataProvider;
16
+ this._loadPromise = undefined;
15
17
  const uri = `attributes/${storageInfo.key}/0`;
16
18
 
17
19
  if (defined(this._parent._nodeIndex)) {
@@ -54,9 +56,16 @@ Object.defineProperties(I3SField.prototype, {
54
56
  */
55
57
  values: {
56
58
  get: function () {
57
- return defined(this._values) && defined(this._values.attributeValues)
58
- ? this._values.attributeValues
59
- : [];
59
+ if (defined(this._values)) {
60
+ // attribute data can be stored either as values or as object identifiers
61
+ if (defined(this._values.attributeValues)) {
62
+ return this._values.attributeValues;
63
+ }
64
+ if (defined(this._values.objectIds)) {
65
+ return this._values.objectIds;
66
+ }
67
+ }
68
+ return [];
60
69
  },
61
70
  },
62
71
  /**
@@ -92,40 +101,37 @@ function getNumericTypeSize(type) {
92
101
  return 0;
93
102
  }
94
103
 
104
+ function getValueTypeSize(type) {
105
+ if (type === "String") {
106
+ return 1;
107
+ }
108
+ return getNumericTypeSize(type);
109
+ }
110
+
111
+ async function load(field) {
112
+ const data = await field._dataProvider._loadBinary(field._resource);
113
+ const dataView = new DataView(data);
114
+ field._data = data;
115
+ field._validateHeader(dataView);
116
+ const headerSize = field._parseHeader(dataView);
117
+ const offset = field._getBodyOffset(headerSize);
118
+ field._validateBody(dataView, offset);
119
+ field._parseBody(dataView, offset);
120
+ }
121
+
95
122
  /**
96
123
  * Loads the content.
97
124
  * @returns {Promise<void>} A promise that is resolved when the field data is loaded
98
125
  */
99
126
  I3SField.prototype.load = function () {
100
- const that = this;
101
- return this._dataProvider._loadBinary(this._resource).then(function (data) {
102
- // Check if we have a 404
103
- const dataView = new DataView(data);
104
- let success = true;
105
- if (dataView.getUint8(0) === "{".charCodeAt(0)) {
106
- const textContent = new TextDecoder();
107
- const str = textContent.decode(data);
108
- if (str.includes("404")) {
109
- success = false;
110
- console.error(`Failed to load: ${that.resource.url}`);
111
- }
112
- }
113
-
114
- if (success) {
115
- that._data = data;
116
- let offset = that._parseHeader(dataView);
117
-
118
- const valueSize = getNumericTypeSize(
119
- that._storageInfo.attributeValues.valueType
120
- );
121
- if (valueSize > 0) {
122
- // Values will be padded to align the addresses with the data size
123
- offset = Math.ceil(offset / valueSize) * valueSize;
124
- }
127
+ if (defined(this._loadPromise)) {
128
+ return this._loadPromise;
129
+ }
125
130
 
126
- that._parseBody(dataView, offset);
127
- }
131
+ this._loadPromise = load(this).catch(function (error) {
132
+ console.error(error);
128
133
  });
134
+ return this._loadPromise;
129
135
  };
130
136
 
131
137
  /**
@@ -217,7 +223,9 @@ I3SField.prototype._parseBody = function (dataView, offset) {
217
223
  itemIndex < this._storageInfo.ordering.length;
218
224
  itemIndex++
219
225
  ) {
220
- const item = this._storageInfo.ordering[itemIndex];
226
+ const orderingValue = this._storageInfo.ordering[itemIndex];
227
+ // all strings in the ordering array correspond to the property name, except ObjectIds
228
+ const item = orderingValue === "ObjectIds" ? "objectIds" : orderingValue;
221
229
  const desc = this._storageInfo[item];
222
230
  if (defined(desc)) {
223
231
  this._values[item] = [];
@@ -252,4 +260,101 @@ I3SField.prototype._parseBody = function (dataView, offset) {
252
260
  }
253
261
  };
254
262
 
263
+ /**
264
+ * @private
265
+ */
266
+ I3SField.prototype._getBodyOffset = function (headerSize) {
267
+ let valueSize = 0;
268
+ if (defined(this._storageInfo.attributeValues)) {
269
+ valueSize = getNumericTypeSize(this._storageInfo.attributeValues.valueType);
270
+ } else if (defined(this._storageInfo.objectIds)) {
271
+ valueSize = getNumericTypeSize(this._storageInfo.objectIds.valueType);
272
+ }
273
+ if (valueSize > 0) {
274
+ // Values will be padded to align the addresses with the data size
275
+ return Math.ceil(headerSize / valueSize) * valueSize;
276
+ }
277
+ return headerSize;
278
+ };
279
+
280
+ /**
281
+ * @private
282
+ */
283
+ I3SField.prototype._validateHeader = function (dataView) {
284
+ let headerSize = 0;
285
+ for (
286
+ let itemIndex = 0;
287
+ itemIndex < this._storageInfo.header.length;
288
+ itemIndex++
289
+ ) {
290
+ const item = this._storageInfo.header[itemIndex];
291
+ headerSize += getValueTypeSize(item.valueType);
292
+ }
293
+ if (dataView.byteLength < headerSize) {
294
+ throw new RuntimeError(
295
+ `Invalid attribute buffer size (field: ${this.name}, header: ${headerSize}, actual: ${dataView.byteLength})`
296
+ );
297
+ }
298
+ };
299
+
300
+ /**
301
+ * @private
302
+ */
303
+ I3SField.prototype._validateBody = function (dataView, offset) {
304
+ if (!defined(this._header.count)) {
305
+ throw new RuntimeError(
306
+ `Invalid attribute buffer (field: ${this.name}, count is missing)`
307
+ );
308
+ }
309
+ let attributeByteCountsOffset;
310
+ for (
311
+ let itemIndex = 0;
312
+ itemIndex < this._storageInfo.ordering.length &&
313
+ offset < dataView.byteLength;
314
+ itemIndex++
315
+ ) {
316
+ const orderingValue = this._storageInfo.ordering[itemIndex];
317
+ // all strings in the ordering array correspond to the property name, except ObjectIds
318
+ const item = orderingValue === "ObjectIds" ? "objectIds" : orderingValue;
319
+ const desc = this._storageInfo[item];
320
+ if (defined(desc)) {
321
+ if (desc.valueType !== "String") {
322
+ if (item === "attributeByteCounts") {
323
+ attributeByteCountsOffset = offset;
324
+ }
325
+ const valueSize = getNumericTypeSize(desc.valueType);
326
+ offset += valueSize * this._header.count;
327
+ } else {
328
+ if (!defined(attributeByteCountsOffset)) {
329
+ throw new RuntimeError(
330
+ `Invalid attribute buffer (field: ${this.name}, attributeByteCounts is missing)`
331
+ );
332
+ }
333
+ for (
334
+ let index = 0;
335
+ index < this._header.count && offset < dataView.byteLength;
336
+ ++index
337
+ ) {
338
+ const parsedValue = this._parseValue(
339
+ dataView,
340
+ this._storageInfo.attributeByteCounts.valueType,
341
+ attributeByteCountsOffset
342
+ );
343
+ offset += parsedValue.value;
344
+ attributeByteCountsOffset = parsedValue.offset;
345
+ }
346
+ }
347
+ } else {
348
+ throw new RuntimeError(
349
+ `Invalid attribute buffer (field: ${this.name}, ${item} is missing)`
350
+ );
351
+ }
352
+ }
353
+ if (dataView.byteLength < offset) {
354
+ throw new RuntimeError(
355
+ `Invalid attribute buffer size (field: ${this.name}, expected: ${offset}, actual: ${dataView.byteLength})`
356
+ );
357
+ }
358
+ };
359
+
255
360
  export default I3SField;