@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
@@ -1,6 +1,8 @@
1
1
  import Cartesian3 from "../Core/Cartesian3.js";
2
+ import clone from "../Core/clone.js";
2
3
  import defined from "../Core/defined.js";
3
4
  import Matrix3 from "../Core/Matrix3.js";
5
+ import srgbToLinear from "../Core/srgbToLinear.js";
4
6
 
5
7
  /**
6
8
  * This class implements an I3S Geometry. Each I3SGeometry
@@ -267,6 +269,19 @@ I3SGeometry.prototype.getClosestPointIndexOnTriangle = function (px, py, pz) {
267
269
  };
268
270
  };
269
271
 
272
+ function convertColorFactor(factor) {
273
+ const convertedFactor = [];
274
+ const length = factor.length;
275
+ for (let i = 0; i < length; i++) {
276
+ if (i < 3) {
277
+ convertedFactor.push(srgbToLinear(factor[i]));
278
+ } else {
279
+ convertedFactor.push(factor[i]);
280
+ }
281
+ }
282
+ return convertedFactor;
283
+ }
284
+
270
285
  /**
271
286
  * @private
272
287
  */
@@ -276,7 +291,9 @@ I3SGeometry.prototype._generateGltf = function (
276
291
  meshes,
277
292
  buffers,
278
293
  bufferViews,
279
- accessors
294
+ accessors,
295
+ extensions,
296
+ extensionsUsed
280
297
  ) {
281
298
  // Get the material definition
282
299
  let gltfMaterial = {
@@ -344,6 +361,21 @@ I3SGeometry.prototype._generateGltf = function (
344
361
  }).url;
345
362
  }
346
363
  }
364
+
365
+ // Convert color factors from sRGB to linear color space
366
+ if (
367
+ defined(gltfMaterial.pbrMetallicRoughness) &&
368
+ defined(gltfMaterial.pbrMetallicRoughness.baseColorFactor)
369
+ ) {
370
+ gltfMaterial.pbrMetallicRoughness.baseColorFactor = convertColorFactor(
371
+ gltfMaterial.pbrMetallicRoughness.baseColorFactor
372
+ );
373
+ }
374
+ if (defined(gltfMaterial.emissiveFactor)) {
375
+ gltfMaterial.emissiveFactor = convertColorFactor(
376
+ gltfMaterial.emissiveFactor
377
+ );
378
+ }
347
379
  }
348
380
  } else if (defined(this._parent._data.textureData)) {
349
381
  // No material definition, but if there's a texture reference, we can create a simple material using it (version 1.6 support)
@@ -353,6 +385,10 @@ I3SGeometry.prototype._generateGltf = function (
353
385
  }).url;
354
386
  gltfMaterial.pbrMetallicRoughness.baseColorTexture = { index: 0 };
355
387
  }
388
+ if (defined(gltfMaterial.alphaMode)) {
389
+ // I3S specifies alphaMode values in lowercase, but glTF expects values in uppercase
390
+ gltfMaterial.alphaMode = gltfMaterial.alphaMode.toUpperCase();
391
+ }
356
392
 
357
393
  let gltfTextures = [];
358
394
  let gltfImages = [];
@@ -382,6 +418,36 @@ I3SGeometry.prototype._generateGltf = function (
382
418
  ];
383
419
  }
384
420
 
421
+ const gltfMaterials = [];
422
+ const meshesLength = meshes.length;
423
+ for (let meshIndex = 0; meshIndex < meshesLength; meshIndex++) {
424
+ const primitives = meshes[meshIndex].primitives;
425
+ const primitivesLength = primitives.length;
426
+ for (
427
+ let primitiveIndex = 0;
428
+ primitiveIndex < primitivesLength;
429
+ primitiveIndex++
430
+ ) {
431
+ const primitive = primitives[primitiveIndex];
432
+ if (defined(primitive.material)) {
433
+ // Create as many copies of the material as specified in the mesh primitives
434
+ while (primitive.material >= gltfMaterials.length) {
435
+ const material = clone(gltfMaterial, true);
436
+ gltfMaterials.push(material);
437
+ }
438
+ const primitiveMaterial = gltfMaterials[primitive.material];
439
+ if (defined(primitive.extra) && primitive.extra.isTransparent) {
440
+ // If the alpha mode is not specified in the original material but the geometry is transparent, we need to force set BLEND alpha mode. Otherwise the geometry will be rendered opaque.
441
+ if (!defined(primitiveMaterial.alphaMode)) {
442
+ primitiveMaterial.alphaMode = "BLEND";
443
+ }
444
+ } else if (primitiveMaterial.alphaMode === "BLEND") {
445
+ // If the geometry is not transparent, but the alpha mode is set to BLEND in the original material, we need to force set OPAQUE alpha mode. Otherwise the geometry will be rendered transparent.
446
+ primitiveMaterial.alphaMode = "OPAQUE";
447
+ }
448
+ }
449
+ }
450
+ }
385
451
  const gltfData = {
386
452
  scene: 0,
387
453
  scenes: [
@@ -394,13 +460,15 @@ I3SGeometry.prototype._generateGltf = function (
394
460
  buffers: buffers,
395
461
  bufferViews: bufferViews,
396
462
  accessors: accessors,
397
- materials: [gltfMaterial],
463
+ materials: gltfMaterials,
398
464
  textures: gltfTextures,
399
465
  images: gltfImages,
400
466
  samplers: gltfSamplers,
401
467
  asset: {
402
468
  version: "2.0",
403
469
  },
470
+ extensions: extensions,
471
+ extensionsUsed: extensionsUsed,
404
472
  };
405
473
 
406
474
  return gltfData;
@@ -1,9 +1,13 @@
1
+ import Cartesian4 from "../Core/Cartesian4.js";
2
+ import clone from "../Core/clone.js";
3
+ import Color from "../Core/Color.js";
1
4
  import defined from "../Core/defined.js";
2
5
  import Rectangle from "../Core/Rectangle.js";
3
6
  import Resource from "../Core/Resource.js";
4
7
  import RuntimeError from "../Core/RuntimeError.js";
5
8
  import Cesium3DTileset from "./Cesium3DTileset.js";
6
9
  import I3SNode from "./I3SNode.js";
10
+ import I3SSymbology from "./I3SSymbology.js";
7
11
 
8
12
  /**
9
13
  * This class implements an I3S layer. In CesiumJS each I3SLayer creates a Cesium3DTileset.
@@ -14,24 +18,25 @@ import I3SNode from "./I3SNode.js";
14
18
  * @internalConstructor
15
19
  * @privateParam {I3SDataProvider} dataProvider The i3s data provider
16
20
  * @privateParam {object} layerData The layer data that is loaded from the scene layer
17
- * @privateParam {number} index The index of the layer to be reflected
21
+ * @privateParam {I3SDataProvider|I3SSublayer} parent The parent of that layer
18
22
  */
19
- function I3SLayer(dataProvider, layerData, index) {
23
+ function I3SLayer(dataProvider, layerData, parent) {
20
24
  this._dataProvider = dataProvider;
25
+ this._parent = parent;
21
26
 
22
- if (!defined(layerData.href) && defined(index)) {
27
+ if (!defined(layerData.href) && defined(layerData.id)) {
23
28
  // assign a default layer
24
- layerData.href = `layers/${index}`;
29
+ layerData.href = `layers/${layerData.id}`;
25
30
  }
26
31
 
27
- const dataProviderUrl = this._dataProvider.resource.getUrlComponent();
32
+ const parentUrl = this._parent.resource.getUrlComponent();
28
33
 
29
34
  let tilesetUrl = "";
30
- if (dataProviderUrl.match(/layers\/\d/)) {
31
- tilesetUrl = `${dataProviderUrl}`.replace(/\/+$/, "");
35
+ if (parentUrl.match(/layers\/\d/)) {
36
+ tilesetUrl = `${parentUrl}`.replace(/\/+$/, "");
32
37
  } else {
33
38
  // Add '/' to url if needed + `${layerData.href}` if tilesetUrl not already in ../layers/[id] format
34
- tilesetUrl = `${dataProviderUrl}`
39
+ tilesetUrl = `${parentUrl}`
35
40
  .replace(/\/?$/, "/")
36
41
  .concat(`${layerData.href}`);
37
42
  }
@@ -53,6 +58,8 @@ function I3SLayer(dataProvider, layerData, index) {
53
58
  this._extent = undefined;
54
59
  this._tileset = undefined;
55
60
  this._geometryDefinitions = undefined;
61
+ this._filters = [];
62
+ this._symbology = undefined;
56
63
 
57
64
  this._computeGeometryDefinitions(true);
58
65
  this._computeExtent();
@@ -166,7 +173,7 @@ Object.defineProperties(I3SLayer.prototype, {
166
173
  /**
167
174
  * Loads the content, including the root node definition and its children
168
175
  * @param {Cesium3DTileset.ConstructorOptions} [cesium3dTilesetOptions] options for Cesium3dTileset constructor
169
- * @returns {Promise} A promise that is resolved when the layer data is loaded
176
+ * @returns {Promise<void>} A promise that is resolved when the layer data is loaded
170
177
  * @private
171
178
  */
172
179
  I3SLayer.prototype.load = async function (cesium3dTilesetOptions) {
@@ -176,6 +183,9 @@ I3SLayer.prototype.load = async function (cesium3dTilesetOptions) {
176
183
  );
177
184
  }
178
185
 
186
+ if (this._dataProvider.applySymbology) {
187
+ this._symbology = new I3SSymbology(this);
188
+ }
179
189
  await this._dataProvider.loadGeoidData();
180
190
  await this._loadRootNode(cesium3dTilesetOptions);
181
191
  await this._create3DTileset(cesium3dTilesetOptions);
@@ -387,11 +397,20 @@ I3SLayer.prototype._create3DTileset = async function (cesium3dTilesetOptions) {
387
397
  });
388
398
 
389
399
  const tilesetUrl = URL.createObjectURL(tilesetBlob);
400
+ const outlineColor = this._symbology?.defaultSymbology?.edges?.color;
401
+ if (defined(outlineColor) && !defined(cesium3dTilesetOptions?.outlineColor)) {
402
+ cesium3dTilesetOptions = defined(cesium3dTilesetOptions)
403
+ ? clone(cesium3dTilesetOptions)
404
+ : {};
405
+ cesium3dTilesetOptions.outlineColor = Color.fromCartesian4(
406
+ Cartesian4.fromArray(outlineColor)
407
+ );
408
+ }
390
409
  this._tileset = await Cesium3DTileset.fromUrl(
391
410
  tilesetUrl,
392
411
  cesium3dTilesetOptions
393
412
  );
394
- this._tileset.show = this._dataProvider.show;
413
+ this._tileset.show = this._parent.show;
395
414
  this._tileset._isI3STileSet = true;
396
415
  this._tileset.tileUnload.addEventListener(function (tile) {
397
416
  tile._i3sNode._clearGeometryData();
@@ -406,4 +425,30 @@ I3SLayer.prototype._create3DTileset = async function (cesium3dTilesetOptions) {
406
425
  });
407
426
  };
408
427
 
428
+ /**
429
+ * @private
430
+ */
431
+ I3SLayer.prototype._updateVisibility = function () {
432
+ if (defined(this._tileset)) {
433
+ this._tileset.show = this._parent.show;
434
+ }
435
+ };
436
+
437
+ /**
438
+ * Filters the drawn elements of a layer to specific attribute names and values
439
+ * @param {I3SNode.AttributeFilter[]} [filters=[]] The collection of attribute filters
440
+ * @returns {Promise<void>} A promise that is resolved when the filter is applied
441
+ */
442
+ I3SLayer.prototype.filterByAttributes = function (filters) {
443
+ // Filters are applied for each node in the layer when the node model is loaded
444
+ this._filters = defined(filters) ? clone(filters, true) : [];
445
+
446
+ // Forced filtering is required for loaded nodes only
447
+ const rootNode = this._rootNode;
448
+ if (defined(rootNode)) {
449
+ return rootNode._filterFeatures();
450
+ }
451
+ return Promise.resolve();
452
+ };
453
+
409
454
  export default I3SLayer;
@@ -1,4 +1,5 @@
1
1
  import Cartographic from "../Core/Cartographic.js";
2
+ import Check from "../Core/Check.js";
2
3
  import defaultValue from "../Core/defaultValue.js";
3
4
  import defined from "../Core/defined.js";
4
5
  import Ellipsoid from "../Core/Ellipsoid.js";
@@ -15,6 +16,16 @@ import I3SFeature from "./I3SFeature.js";
15
16
  import I3SField from "./I3SField.js";
16
17
  import I3SGeometry from "./I3SGeometry.js";
17
18
 
19
+ /**
20
+ * @typedef {object} I3SNode.AttributeFilter
21
+ *
22
+ * A filter given by an attribute name and values.
23
+ * The 3D feature object should be hidden if its value for the attribute name is not specified in the collection of values.
24
+ *
25
+ * @property {string} name The name of the attribute
26
+ * @property {string[]|number[]} values The collection of values
27
+ */
28
+
18
29
  /**
19
30
  * This class implements an I3S Node. In CesiumJS each I3SNode creates a Cesium3DTile.
20
31
  * <p>
@@ -64,6 +75,7 @@ function I3SNode(parent, ref, isRoot) {
64
75
  this._globalTransform = undefined;
65
76
  this._inverseGlobalTransform = undefined;
66
77
  this._inverseRotationMatrix = undefined;
78
+ this._symbologyData = undefined;
67
79
  }
68
80
 
69
81
  Object.defineProperties(I3SNode.prototype, {
@@ -192,10 +204,7 @@ I3SNode.prototype.load = async function () {
192
204
 
193
205
  // If we don't have a nodepage index load from json
194
206
  if (!defined(this._nodeIndex)) {
195
- const data = await I3SDataProvider.loadJson(
196
- this._resource,
197
- this._dataProvider._traceFetches
198
- );
207
+ const data = await I3SDataProvider.loadJson(this._resource);
199
208
  that._data = data;
200
209
  processData();
201
210
  return;
@@ -217,6 +226,12 @@ I3SNode.prototype.load = async function () {
217
226
  processData();
218
227
  };
219
228
 
229
+ function createAndLoadField(node, storageInfo) {
230
+ const newField = new I3SField(node, storageInfo);
231
+ node._fields[storageInfo.name] = newField;
232
+ return newField.load();
233
+ }
234
+
220
235
  /**
221
236
  * Loads the node fields.
222
237
  * @returns {Promise<void>} A promise that is resolved when the I3S Node fields are loaded
@@ -225,23 +240,50 @@ I3SNode.prototype.loadFields = function () {
225
240
  // Check if we must load fields
226
241
  const fields = this._layer._data.attributeStorageInfo;
227
242
 
228
- const that = this;
229
- function createAndLoadField(fields, index) {
230
- const newField = new I3SField(that, fields[index]);
231
- that._fields[newField._storageInfo.name] = newField;
232
- return newField.load();
233
- }
234
-
235
243
  const promises = [];
236
244
  if (defined(fields)) {
237
245
  for (let i = 0; i < fields.length; i++) {
238
- promises.push(createAndLoadField(fields, i));
246
+ const storageInfo = fields[i];
247
+ const field = this._fields[storageInfo.name];
248
+ if (defined(field)) {
249
+ promises.push(field.load());
250
+ } else {
251
+ promises.push(createAndLoadField(this, storageInfo));
252
+ }
239
253
  }
240
254
  }
241
255
 
242
256
  return Promise.all(promises);
243
257
  };
244
258
 
259
+ /**
260
+ * Loads the node field.
261
+ * @param {string} name The field name
262
+ * @returns {Promise<void>} A promise that is resolved when the I3S Node field is loaded
263
+ */
264
+ I3SNode.prototype.loadField = function (name) {
265
+ //>>includeStart('debug', pragmas.debug);
266
+ Check.defined("name", name);
267
+ //>>includeEnd('debug');
268
+
269
+ const field = this._fields[name];
270
+ if (defined(field)) {
271
+ return field.load();
272
+ }
273
+
274
+ const fields = this._layer._data.attributeStorageInfo;
275
+ if (defined(fields)) {
276
+ for (let i = 0; i < fields.length; i++) {
277
+ const storageInfo = fields[i];
278
+ if (storageInfo.name === name) {
279
+ return createAndLoadField(this, storageInfo);
280
+ }
281
+ }
282
+ }
283
+
284
+ return Promise.resolve();
285
+ };
286
+
245
287
  /**
246
288
  * Returns the fields for a given picked position
247
289
  * @param {Cartesian3} pickedPosition The picked position
@@ -608,6 +650,15 @@ I3SNode.prototype._create3DTileDefinition = function () {
608
650
  return inPlaceTileDefinition;
609
651
  };
610
652
 
653
+ /**
654
+ * @private
655
+ */
656
+ I3SNode.prototype._loadSymbology = async function () {
657
+ if (!defined(this._symbologyData) && defined(this._layer._symbology)) {
658
+ this._symbologyData = await this._layer._symbology._getSymbology(this);
659
+ }
660
+ };
661
+
611
662
  /**
612
663
  * @private
613
664
  */
@@ -646,6 +697,10 @@ I3SNode.prototype._createContentURL = async function () {
646
697
  await Promise.all(dataPromises);
647
698
  // Binary glTF
648
699
  if (defined(this._geometryData) && this._geometryData.length > 0) {
700
+ if (this._dataProvider._applySymbology) {
701
+ await this._loadSymbology();
702
+ }
703
+
649
704
  const url = this._geometryData[0].resource.url;
650
705
  const geometrySchema = this._layer._data.store.defaultGeometrySchema;
651
706
  const geometryData = this._geometryData[0];
@@ -653,7 +708,8 @@ I3SNode.prototype._createContentURL = async function () {
653
708
  url,
654
709
  geometrySchema,
655
710
  geometryData,
656
- this._featureData[0]
711
+ this._featureData[0],
712
+ this._symbologyData
657
713
  );
658
714
  if (!defined(result)) {
659
715
  // Postponed
@@ -666,7 +722,9 @@ I3SNode.prototype._createContentURL = async function () {
666
722
  result.meshData.meshes,
667
723
  result.meshData.buffers,
668
724
  result.meshData.bufferViews,
669
- result.meshData.accessors
725
+ result.meshData.accessors,
726
+ result.meshData.rootExtensions,
727
+ result.meshData.extensionsUsed
670
728
  );
671
729
 
672
730
  this._geometryData[0]._customAttributes = result.meshData._customAttributes;
@@ -679,6 +737,91 @@ I3SNode.prototype._createContentURL = async function () {
679
737
  return URL.createObjectURL(glbDataBlob);
680
738
  };
681
739
 
740
+ async function loadFilters(node) {
741
+ const filters = node._layer._filters;
742
+ const promises = [];
743
+ for (let i = 0; i < filters.length; i++) {
744
+ const promise = node.loadField(filters[i].name);
745
+ promises.push(promise);
746
+ }
747
+ await Promise.all(promises);
748
+ return filters;
749
+ }
750
+
751
+ function checkFeatureValue(featureIndex, field, filter) {
752
+ if (!defined(filter.values) || filter.values.length === 0) {
753
+ return false;
754
+ }
755
+
756
+ const fieldValues = defined(field) ? field.values : [];
757
+ let featureValue;
758
+ if (featureIndex < fieldValues.length) {
759
+ featureValue = fieldValues[featureIndex];
760
+ }
761
+ let matches = false;
762
+ for (let i = 0; i < filter.values.length; i++) {
763
+ if (filter.values[i] === featureValue) {
764
+ matches = true;
765
+ break;
766
+ }
767
+ }
768
+ return matches;
769
+ }
770
+
771
+ async function filterFeatures(node, contentModel) {
772
+ const batchTable = node._tile.content.batchTable;
773
+ if (defined(batchTable) && batchTable.featuresLength > 0) {
774
+ batchTable.setAllShow(true);
775
+
776
+ const filters = await loadFilters(node);
777
+ if (filters.length > 0) {
778
+ for (
779
+ let featureIndex = 0;
780
+ featureIndex < batchTable.featuresLength;
781
+ featureIndex++
782
+ ) {
783
+ for (let filterIndex = 0; filterIndex < filters.length; filterIndex++) {
784
+ const filter = filters[filterIndex];
785
+ if (
786
+ !checkFeatureValue(featureIndex, node._fields[filter.name], filter)
787
+ ) {
788
+ batchTable.setShow(featureIndex, false);
789
+ break;
790
+ }
791
+ }
792
+ }
793
+ }
794
+ }
795
+ contentModel.show = true;
796
+ }
797
+
798
+ /**
799
+ * @private
800
+ */
801
+ I3SNode.prototype._filterFeatures = function () {
802
+ const promises = [];
803
+ // Forced filtering is required for loaded nodes only
804
+ for (let i = 0; i < this._children.length; i++) {
805
+ const promise = this._children[i]._filterFeatures();
806
+ promises.push(promise);
807
+ }
808
+
809
+ // Filters are applied for nodes with geometry data only
810
+ const contentModel = this._tile?.content?._model;
811
+ if (
812
+ defined(this._geometryData) &&
813
+ this._geometryData.length > 0 &&
814
+ defined(contentModel) &&
815
+ contentModel.ready
816
+ ) {
817
+ // The model needs to be hidden till the filters are applied
818
+ contentModel.show = false;
819
+ const promise = filterFeatures(this, contentModel);
820
+ promises.push(promise);
821
+ }
822
+ return Promise.all(promises);
823
+ };
824
+
682
825
  // Reimplement Cesium3DTile.prototype.requestContent so that
683
826
  // We get a chance to load our own gltf from I3S data
684
827
  Cesium3DTile.prototype._hookedRequestContent =
@@ -700,19 +843,33 @@ Cesium3DTile.prototype.requestContent = function () {
700
843
 
701
844
  if (!this._isLoading) {
702
845
  this._isLoading = true;
846
+ const that = this;
703
847
  return this._i3sNode
704
848
  ._createContentURL()
705
849
  .then((url) => {
706
850
  if (!defined(url)) {
707
- this._isLoading = false;
851
+ that._isLoading = false;
708
852
  return;
709
853
  }
710
854
 
711
- this._contentResource = new Resource({ url: url });
712
- return this._hookedRequestContent();
855
+ that._contentResource = new Resource({ url: url });
856
+ return that._hookedRequestContent();
713
857
  })
714
858
  .then((content) => {
715
- this._isLoading = false;
859
+ // Filters are applied for nodes with geometry data only
860
+ const contentModel = content?._model;
861
+ if (
862
+ defined(that._i3sNode._geometryData) &&
863
+ that._i3sNode._geometryData.length > 0 &&
864
+ defined(contentModel)
865
+ ) {
866
+ // The model needs to be hidden till the filters are applied
867
+ contentModel.show = false;
868
+ contentModel.readyEvent.addEventListener(() => {
869
+ filterFeatures(that._i3sNode, contentModel);
870
+ });
871
+ }
872
+ that._isLoading = false;
716
873
  return content;
717
874
  });
718
875
  }
@@ -0,0 +1,94 @@
1
+ import defined from "../Core/defined.js";
2
+ import I3SDataProvider from "./I3SDataProvider.js";
3
+ import Resource from "../Core/Resource.js";
4
+
5
+ /**
6
+ * This class implements an I3S statistics for Building Scene Layer.
7
+ * <p>
8
+ * Do not construct this directly, instead access statistics through {@link I3SDataProvider}.
9
+ * </p>
10
+ * @alias I3SStatistics
11
+ * @internalConstructor
12
+ */
13
+ function I3SStatistics(dataProvider, uri) {
14
+ this._dataProvider = dataProvider;
15
+
16
+ this._resource = new Resource({ url: uri });
17
+ this._resource.setQueryParameters(dataProvider.resource.queryParameters);
18
+ this._resource.appendForwardSlash();
19
+ }
20
+
21
+ Object.defineProperties(I3SStatistics.prototype, {
22
+ /**
23
+ * Gets the resource for the statistics
24
+ * @memberof I3SStatistics.prototype
25
+ * @type {Resource}
26
+ * @readonly
27
+ */
28
+ resource: {
29
+ get: function () {
30
+ return this._resource;
31
+ },
32
+ },
33
+
34
+ /**
35
+ * Gets the I3S data for this object.
36
+ * @memberof I3SStatistics.prototype
37
+ * @type {object}
38
+ * @readonly
39
+ */
40
+ data: {
41
+ get: function () {
42
+ return this._data;
43
+ },
44
+ },
45
+
46
+ /**
47
+ * Gets the collection of attribute names.
48
+ * @memberof I3SStatistics.prototype
49
+ * @type {string[]}
50
+ * @readonly
51
+ */
52
+ names: {
53
+ get: function () {
54
+ const names = [];
55
+ const summary = this._data.summary;
56
+ if (defined(summary)) {
57
+ for (let i = 0; i < summary.length; ++i) {
58
+ names.push(summary[i].fieldName);
59
+ }
60
+ }
61
+ return names;
62
+ },
63
+ },
64
+ });
65
+
66
+ /**
67
+ * Loads the content.
68
+ * @returns {Promise<object>} A promise that is resolved when the data of the I3S statistics is loaded
69
+ * @private
70
+ */
71
+ I3SStatistics.prototype.load = async function () {
72
+ this._data = await I3SDataProvider.loadJson(this._resource);
73
+ return this._data;
74
+ };
75
+
76
+ /**
77
+ * @private
78
+ */
79
+ I3SStatistics.prototype._getValues = function (attributeName) {
80
+ const summary = this._data.summary;
81
+ if (defined(summary)) {
82
+ for (let i = 0; i < summary.length; ++i) {
83
+ const attribute = summary[i];
84
+ if (attribute.fieldName === attributeName) {
85
+ if (defined(attribute.mostFrequentValues)) {
86
+ return [...attribute.mostFrequentValues];
87
+ }
88
+ return [];
89
+ }
90
+ }
91
+ }
92
+ };
93
+
94
+ export default I3SStatistics;