bruce-cesium 7.5.2 → 7.5.3

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.
@@ -3026,6 +3026,7 @@
3026
3026
  }
3027
3027
  let _selectColor = Cesium.Color.fromAlpha(Cesium.Color.YELLOW, 0.5);
3028
3028
  let _highlightColor = Cesium.Color.fromCssColorString("#33b1ff").withAlpha(0.5);
3029
+ const DIMMING_REGISTERS_KEY = "_nextspaceDimmingRegisters";
3029
3030
  const STORE_COLOR_PREFIX = "_storeColor_";
3030
3031
  function getStoreKey(key) {
3031
3032
  return STORE_COLOR_PREFIX + key;
@@ -3182,6 +3183,10 @@
3182
3183
  getColor$1(viewer, "default", graphic);
3183
3184
  }
3184
3185
  let color = (_a = getColor$1(viewer, key, graphic)) !== null && _a !== void 0 ? _a : Cesium.Color.WHITE;
3186
+ // A model that is itself dimmed stays see-through. Only the ones standing out from dimmed surroundings go opaque.
3187
+ if (key != "default" && (opacity == null || opacity >= 1) && exports.CesiumEntityStyler.IsSelectionOpaque(viewer, graphic)) {
3188
+ color = color.withAlpha(1);
3189
+ }
3185
3190
  // If we're selecting and it's highlighted, don't change the color.
3186
3191
  if (key != "select" || getKeyState(graphic, "highlight") == false) {
3187
3192
  let animateMs = key == "highlight" ? ANIMATE_COLOR_HIGHLIGHT_MS : ANIMATE_COLOR_MS;
@@ -3352,6 +3357,50 @@
3352
3357
  return value == null ? false : value;
3353
3358
  }
3354
3359
  (function (CesiumEntityStyler) {
3360
+ /**
3361
+ * Whether a graphic or visual is a 3D model, ie: a tileset feature from a CAD or assembly import, or a model Entity.
3362
+ * @param graphic
3363
+ */
3364
+ function IsModel(graphic) {
3365
+ if (graphic instanceof Cesium.Entity) {
3366
+ return Boolean(graphic.model);
3367
+ }
3368
+ return graphic instanceof Cesium.Cesium3DTileFeature || graphic instanceof Cesium.ModelGraphics;
3369
+ }
3370
+ CesiumEntityStyler.IsModel = IsModel;
3371
+ /**
3372
+ * Whether a graphic is drawn with an opaque selection and highlight because something on its viewer is dimmed.
3373
+ * Only 3D models are. GIS graphics keep the colour's own alpha.
3374
+ * @param viewer
3375
+ * @param graphic
3376
+ */
3377
+ function IsSelectionOpaque(viewer, graphic) {
3378
+ var _a;
3379
+ return Boolean((_a = viewer === null || viewer === void 0 ? void 0 : viewer[DIMMING_REGISTERS_KEY]) === null || _a === void 0 ? void 0 : _a.size) && IsModel(graphic);
3380
+ }
3381
+ CesiumEntityStyler.IsSelectionOpaque = IsSelectionOpaque;
3382
+ /**
3383
+ * Records whether a register dims anything on a viewer, by isolation or by opacity.
3384
+ * @param viewer
3385
+ * @param registerId
3386
+ * @param dimming
3387
+ * @returns Whether the viewer went into or out of dimming, so selected models can be recoloured.
3388
+ */
3389
+ function SetDimming(viewer, registerId, dimming) {
3390
+ let ids = viewer[DIMMING_REGISTERS_KEY];
3391
+ const before = Boolean(ids === null || ids === void 0 ? void 0 : ids.size);
3392
+ if (dimming) {
3393
+ if (!ids) {
3394
+ ids = viewer[DIMMING_REGISTERS_KEY] = new Set();
3395
+ }
3396
+ ids.add(registerId);
3397
+ }
3398
+ else {
3399
+ ids === null || ids === void 0 ? void 0 : ids.delete(registerId);
3400
+ }
3401
+ return before !== Boolean(ids === null || ids === void 0 ? void 0 : ids.size);
3402
+ }
3403
+ CesiumEntityStyler.SetDimming = SetDimming;
3355
3404
  function UpdateColorSetting(key, color) {
3356
3405
  if (key == "highlight") {
3357
3406
  _highlightColor = color.clone();
@@ -9836,6 +9885,8 @@
9836
9885
  // Caches GetIsIsolatedAny(). `null` means "unknown, recompute".
9837
9886
  // Invalidated on any write that could affect isolation.
9838
9887
  this.isolatedAnyCache = null;
9888
+ // Set when isolation or opacity changes, so the next update checks whether anything is still dimmed.
9889
+ this.dimmingDirty = false;
9839
9890
  // Caches GetIsolationOpacity(). `undefined` means "unknown, recompute", `null` means
9840
9891
  // "isolation (if any) is the legacy boolean/full-hide kind, not a numeric dim".
9841
9892
  // Invalidated alongside isolatedAnyCache.
@@ -10104,6 +10155,7 @@
10104
10155
  this.updateQueueInterval = null;
10105
10156
  return;
10106
10157
  }
10158
+ this.syncDimming();
10107
10159
  const batch = this.updateQueue.splice(0, BATCH_SIZE);
10108
10160
  const cache = {};
10109
10161
  for (let i = 0; i < batch.length; i++) {
@@ -10338,6 +10390,9 @@
10338
10390
  this.isolatedAnyCache = null;
10339
10391
  this.isolationOpacityCache = undefined;
10340
10392
  }
10393
+ if (keys.includes("isolated") || keys.includes("opacity")) {
10394
+ this.dimmingDirty = true;
10395
+ }
10341
10396
  let changed = false;
10342
10397
  const eStates = this.states[entityId] || {};
10343
10398
  this.states[entityId] = eStates;
@@ -10769,8 +10824,36 @@
10769
10824
  const { rego } = params;
10770
10825
  markEntity(this, rego, rego.visual, false);
10771
10826
  }
10827
+ /**
10828
+ * Tells the styler whether this register dims anything, by isolation or opacity.
10829
+ */
10830
+ syncDimming() {
10831
+ var _a, _b;
10832
+ if (!this.dimmingDirty) {
10833
+ return;
10834
+ }
10835
+ this.dimmingDirty = false;
10836
+ const dimming = Object.values(this.states).some(states => Object.values(states).some(state => state.isolated || (state.opacity != null && state.opacity < 1)));
10837
+ if (!exports.CesiumEntityStyler.SetDimming(this.viewer, this.id, dimming)) {
10838
+ return;
10839
+ }
10840
+ const entityIds = new Set([...this.GetSelected(), ...this.GetHighlighted()]);
10841
+ for (const entityId of entityIds) {
10842
+ for (const rego of (_a = this.rego[entityId]) !== null && _a !== void 0 ? _a : []) {
10843
+ if (exports.CesiumEntityStyler.IsModel(rego.visual)) {
10844
+ exports.CesiumEntityStyler.Refresh({
10845
+ viewer: this.viewer,
10846
+ entity: rego.visual,
10847
+ requestRender: false
10848
+ });
10849
+ }
10850
+ }
10851
+ }
10852
+ (_b = this.viewer.scene) === null || _b === void 0 ? void 0 : _b.requestRender();
10853
+ }
10772
10854
  Dispose() {
10773
10855
  var _a, _b, _c, _d, _e;
10856
+ exports.CesiumEntityStyler.SetDimming(this.viewer, this.id, false);
10774
10857
  this.ClearLabelHover();
10775
10858
  clearTimeout(this.hoverRingReset);
10776
10859
  this.hoverRingState = {};
@@ -11397,6 +11480,7 @@
11397
11480
  // Mutated `isolated` directly rather than through setStateValues().
11398
11481
  this.isolatedAnyCache = false;
11399
11482
  this.isolationOpacityCache = null;
11483
+ this.dimmingDirty = true;
11400
11484
  }
11401
11485
  if (changed && (params === null || params === void 0 ? void 0 : params.doUpdate) !== false) {
11402
11486
  this.updateAllEntities({
@@ -12133,6 +12217,7 @@
12133
12217
  }
12134
12218
  }
12135
12219
  async updateAllEntities(params) {
12220
+ this.syncDimming();
12136
12221
  const ids = Object.keys(this.rego);
12137
12222
  const interval = setInterval(() => {
12138
12223
  const batch = ids.splice(0, 3000);
@@ -12227,6 +12312,7 @@
12227
12312
  const clearedIds = new Set();
12228
12313
  this.ForEachState((state) => {
12229
12314
  if (!clearedIds.has(state.entityId) && state.opacity != null) {
12315
+ this.dimmingDirty = true;
12230
12316
  this.markLazyExclusion(state.entityId);
12231
12317
  this.queueUpdate({
12232
12318
  entityId: state.entityId,
@@ -18293,8 +18379,6 @@
18293
18379
  console.error(e);
18294
18380
  }
18295
18381
  // Before we start the loop we'll do a single request for the needed Entity Types.
18296
- // This will be aimed at rows that don't specify a Style and if the default fallback-
18297
- //is set to 0 (using the default of the Entity Type).
18298
18382
  const typeMap = new Map();
18299
18383
  const typeIds = styleMapping.map(x => x.StyleID == -1 || Boolean(x.style) ? null : x.EntityTypeID).filter(x => !!x);
18300
18384
  if (typeIds.length) {
@@ -18360,23 +18444,7 @@
18360
18444
  }
18361
18445
  this.styleMappingsLoaded.set(styleMap.EntityTypeID, true);
18362
18446
  if (this.loaded) {
18363
- // If we have a bunch of Entities that were waiting for the style to load,
18364
- // then we can pass them to the gatherer now.
18365
- const relatedIds = this.stylePendingEntityIds.get(styleMap.EntityTypeID);
18366
- if (relatedIds) {
18367
- if (this.getTilesetFeatureNeedsFullData(styleMap.EntityTypeID)) {
18368
- this.entityGatherer.Queue(Array.from(relatedIds));
18369
- }
18370
- else {
18371
- relatedIds.forEach(id => {
18372
- const rego = this.getEntityRego(id);
18373
- if (rego) {
18374
- this.styleTilesetFeature(rego);
18375
- }
18376
- });
18377
- }
18378
- this.stylePendingEntityIds.delete(styleMap.EntityTypeID);
18379
- }
18447
+ this.flushPendingForType(styleMap.EntityTypeID);
18380
18448
  }
18381
18449
  }
18382
18450
  if (this.loadingCounter != counter) {
@@ -18408,6 +18476,67 @@
18408
18476
  this.stylePendingEntityIds.clear();
18409
18477
  }
18410
18478
  }
18479
+ /**
18480
+ * Passes the Entities waiting on an Entity Type's style on to be styled, now that the style is known.
18481
+ * @param entityTypeId
18482
+ */
18483
+ flushPendingForType(entityTypeId) {
18484
+ const relatedIds = this.stylePendingEntityIds.get(entityTypeId);
18485
+ if (!relatedIds) {
18486
+ return;
18487
+ }
18488
+ if (this.getTilesetFeatureNeedsFullData(entityTypeId)) {
18489
+ this.entityGatherer.Queue(Array.from(relatedIds));
18490
+ }
18491
+ else {
18492
+ relatedIds.forEach(id => {
18493
+ const rego = this.getEntityRego(id);
18494
+ if (rego) {
18495
+ this.styleTilesetFeature(rego);
18496
+ }
18497
+ });
18498
+ }
18499
+ this.stylePendingEntityIds.delete(entityTypeId);
18500
+ }
18501
+ hasMappingRow(entityTypeId) {
18502
+ var _a;
18503
+ return Boolean((_a = this.styleMapping) === null || _a === void 0 ? void 0 : _a.some(x => x.EntityTypeID == entityTypeId));
18504
+ }
18505
+ /**
18506
+ * Loads the default style of an Entity Type that the style mapping does not list.
18507
+ * @param entityTypeId
18508
+ */
18509
+ async loadEntityTypeDefaultStyle(entityTypeId) {
18510
+ const counter = this.loadingCounter;
18511
+ const styleMap = { EntityTypeID: entityTypeId, StyleID: 0, style: null };
18512
+ this.styleMapping.push(styleMap);
18513
+ try {
18514
+ const { entityType } = await BModels.EntityType.Get({
18515
+ api: this.api,
18516
+ entityTypeId
18517
+ });
18518
+ const styleId = entityType === null || entityType === void 0 ? void 0 : entityType["DisplaySetting.ID"];
18519
+ if (styleId && styleId != -1) {
18520
+ const { style } = await BModels.Style.Get({
18521
+ api: this.api,
18522
+ styleId
18523
+ });
18524
+ if (style) {
18525
+ styleMap.style = style;
18526
+ styleMap.StyleID = styleId;
18527
+ }
18528
+ }
18529
+ }
18530
+ catch (e) {
18531
+ console.error(e);
18532
+ }
18533
+ // A reload in the meantime resolves the row itself, or replaces the mapping and re-queues everything.
18534
+ if (this.disposed || this.loadingCounter != counter) {
18535
+ return;
18536
+ }
18537
+ this.styleMappingsLoaded.set(entityTypeId, true);
18538
+ this.flushPendingForType(entityTypeId);
18539
+ }
18411
18540
  disposeGatherer() {
18412
18541
  if (this.feedRestyleThrottleTimer) {
18413
18542
  clearTimeout(this.feedRestyleThrottleTimer);
@@ -18446,7 +18575,11 @@
18446
18575
  this.overrideFeatureColor.set(rego.entityId, false);
18447
18576
  }
18448
18577
  const typeId = rego.entityTypeId || "";
18449
- if (this.styleMappingLoaded || this.styleMappingsLoaded.get(typeId)) {
18578
+ // With no fallback style to use instead, a type the mapping does not list falls back to its own default.
18579
+ if (this.styleMappingLoaded && typeId && !this.fallbackStyle && !this.hasMappingRow(typeId)) {
18580
+ this.loadEntityTypeDefaultStyle(typeId);
18581
+ }
18582
+ if (this.styleMappingsLoaded.get(typeId) || (this.styleMappingLoaded && !this.hasMappingRow(typeId))) {
18450
18583
  if (this.getTilesetFeatureNeedsFullData(typeId)) {
18451
18584
  needsDataIds.push(rego.entityId);
18452
18585
  }
@@ -40491,6 +40624,47 @@
40491
40624
  }
40492
40625
  return Cesium.Matrix4.multiplyByPoint(enuFrame, new Cesium.Cartesian3(tx, ty, tz), new Cesium.Cartesian3());
40493
40626
  }
40627
+ // Records created within about this long ago are the ones the oversized GeometryRadius bug could have written.
40628
+ const GEOMETRY_RADIUS_SUSPECT_AGE_MS = 1000 * 60 * 60 * 24 * 183;
40629
+ // Above this a recent record's radius is treated as that bug rather than a real size.
40630
+ const GEOMETRY_RADIUS_SUSPECT_ABOVE = 500;
40631
+ /**
40632
+ * Returns an entity's Bruce.GeometryRadius, or null when there is none or it looks like the oversized-radius bug.
40633
+ * The size cap only applies to records created recently; older ones and ones with no known date are taken as they are.
40634
+ * @param entity
40635
+ */
40636
+ function getTrustedGeometryRadius(entity) {
40637
+ var _a;
40638
+ const radius = EnsureNumber(BModels.Entity.GetValue({
40639
+ entity: entity,
40640
+ path: ["Bruce", "GeometryRadius"]
40641
+ }));
40642
+ if (!(radius > 0)) {
40643
+ return null;
40644
+ }
40645
+ const created = Date.parse((_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.Created);
40646
+ const recent = !isNaN(created) && Date.now() - created < GEOMETRY_RADIUS_SUSPECT_AGE_MS;
40647
+ if (recent && radius >= GEOMETRY_RADIUS_SUSPECT_ABOVE) {
40648
+ return null;
40649
+ }
40650
+ return radius;
40651
+ }
40652
+ /**
40653
+ * Returns the world centre of a model's own bounds, applying the entity's orientation to the offset.
40654
+ * The position is the one GetLocation already resolved, so height references are honoured.
40655
+ * @param viewer
40656
+ * @param part
40657
+ * @param pos3d
40658
+ * @param bounds
40659
+ */
40660
+ function getModelBoundsCenter(viewer, part, pos3d, bounds) {
40661
+ const orientation = GetValue$1(viewer, part.orientation);
40662
+ const rotation = orientation
40663
+ ? Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3())
40664
+ : Cesium.Matrix4.getMatrix3(Cesium.Transforms.eastNorthUpToFixedFrame(pos3d), new Cesium.Matrix3());
40665
+ const offset = Cesium.Matrix3.multiplyByVector(rotation, bounds.center, new Cesium.Cartesian3());
40666
+ return Cesium.Cartesian3.add(pos3d, offset, new Cesium.Cartesian3());
40667
+ }
40494
40668
  // +90° rotation around Z: aligns GLTF Y-up forward with Cesium ENU North.
40495
40669
  const _assemblyAxisShift = new Cesium.Quaternion(0, 0, -Math.SQRT1_2, Math.SQRT1_2);
40496
40670
  (function (EntityUtils) {
@@ -40541,6 +40715,9 @@
40541
40715
  rectangle: null,
40542
40716
  sphere: null
40543
40717
  };
40718
+ const spheres = [];
40719
+ // The tile holding a rendered feature that says nothing of where it is, used only when nothing better turns up.
40720
+ const tileSpheres = [];
40544
40721
  const processPosHeight = async (pos3d, heightRef) => {
40545
40722
  // Raise to minimumAlt if needed.
40546
40723
  if ((!isNaN(minimumAlt) && minimumAlt != null)) {
@@ -40618,7 +40795,7 @@
40618
40795
  * Returns an array of positions from the entity's currently rendered graphics.
40619
40796
  */
40620
40797
  const evaluateRendered = async () => {
40621
- var _a, _b;
40798
+ var _a, _b, _c, _d;
40622
40799
  const rego = visualRegister ? visualRegister.GetRego({
40623
40800
  entityId: sample.entityId,
40624
40801
  menuItemId: sample.menuItemId
@@ -40750,9 +40927,14 @@
40750
40927
  posses.push(pos3d);
40751
40928
  if (part.model) {
40752
40929
  const modelExt = part.model;
40753
- if (modelExt._radius && modelExt._radius > -1) {
40930
+ const bounds = modelExt._bounds;
40931
+ if ((bounds === null || bounds === void 0 ? void 0 : bounds.radius) > 0) {
40932
+ spheres.push(new Cesium.BoundingSphere(getModelBoundsCenter(viewer, part, pos3d, bounds), bounds.radius));
40933
+ }
40934
+ else if (modelExt._radius && modelExt._radius > -1) {
40754
40935
  const sphere = Cesium.BoundingSphere.fromPoints([pos3d]);
40755
40936
  sphere.radius = modelExt._radius;
40937
+ spheres.push(sphere);
40756
40938
  }
40757
40939
  }
40758
40940
  else if (part.ellipse) {
@@ -40771,6 +40953,7 @@
40771
40953
  const radius = Math.max(semiMajorAxis, semiMinorAxis, height);
40772
40954
  if (radius && radius > 0) {
40773
40955
  const sphere = new Cesium.BoundingSphere(pos3d, radius);
40956
+ spheres.push(sphere);
40774
40957
  }
40775
40958
  }
40776
40959
  }
@@ -40789,6 +40972,14 @@
40789
40972
  posses.push(pos3d);
40790
40973
  if (data.radius != null && !isNaN(data.radius)) {
40791
40974
  const sphere = new Cesium.BoundingSphere(pos3d, data.radius);
40975
+ spheres.push(sphere);
40976
+ }
40977
+ }
40978
+ else {
40979
+ // Missing from the typings this library builds against, but there at runtime.
40980
+ const tileSphere = (_d = (_c = part.content) === null || _c === void 0 ? void 0 : _c.tile) === null || _d === void 0 ? void 0 : _d.boundingSphere;
40981
+ if ((tileSphere === null || tileSphere === void 0 ? void 0 : tileSphere.radius) > 0) {
40982
+ tileSpheres.push(Cesium.BoundingSphere.clone(tileSphere));
40792
40983
  }
40793
40984
  }
40794
40985
  }
@@ -40868,7 +41059,7 @@
40868
41059
  }
40869
41060
  const boundaries = BModels.Entity.GetValue({
40870
41061
  entity: entity,
40871
- path: ["Bruce, Boundaries"]
41062
+ path: ["Bruce", "Boundaries"]
40872
41063
  });
40873
41064
  if (boundaries && typeof boundaries == "object") {
40874
41065
  const point = {
@@ -40921,16 +41112,9 @@
40921
41112
  const transformedOffset = Cesium.Matrix3.multiplyByVector(transformHpr, offset, new Cesium.Cartesian3());
40922
41113
  pos3d = Cesium.Matrix4.multiplyByPoint(m1, transformedOffset, new Cesium.Cartesian3());
40923
41114
  pos3d = await processPosHeight(pos3d, Cesium.HeightReference.NONE);
40924
- const geometryRadius = BModels.Entity.GetValue({
40925
- entity: entity,
40926
- path: ["Bruce", "GeometryRadius"]
40927
- });
41115
+ const geometryRadius = getTrustedGeometryRadius(entity);
40928
41116
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
40929
- const sphere = Cesium.BoundingSphere.fromPoints([pos3d]);
40930
- // For now making sure it's less than x amount because we had a bug which made it huge.
40931
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
40932
- sphere.radius = geometryRadius;
40933
- }
41117
+ spheres.push(new Cesium.BoundingSphere(pos3d, geometryRadius));
40934
41118
  }
40935
41119
  return [pos3d];
40936
41120
  }
@@ -40938,16 +41122,9 @@
40938
41122
  if (location) {
40939
41123
  let pos3d = Cesium.Cartesian3.fromDegrees(longitude, latitude, EnsureNumber(location.altitude));
40940
41124
  pos3d = await processPosHeight(pos3d, Cesium.HeightReference.NONE);
40941
- const geometryRadius = BModels.Entity.GetValue({
40942
- entity: entity,
40943
- path: ["Bruce", "GeometryRadius"]
40944
- });
41125
+ const geometryRadius = getTrustedGeometryRadius(entity);
40945
41126
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
40946
- const sphere = Cesium.BoundingSphere.fromPoints([pos3d]);
40947
- // For now making sure it's less than x amount because we had a bug which made it huge.
40948
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
40949
- sphere.radius = geometryRadius;
40950
- }
41127
+ spheres.push(new Cesium.BoundingSphere(pos3d, geometryRadius));
40951
41128
  }
40952
41129
  return [pos3d];
40953
41130
  }
@@ -40970,16 +41147,9 @@
40970
41147
  }
40971
41148
  if (pos3d) {
40972
41149
  pos3d = await processPosHeight(pos3d, Cesium.HeightReference.NONE);
40973
- const geometryRadius = BModels.Entity.GetValue({
40974
- entity: entity,
40975
- path: ["Bruce", "GeometryRadius"]
40976
- });
41150
+ const geometryRadius = getTrustedGeometryRadius(entity);
40977
41151
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
40978
- const sphere = Cesium.BoundingSphere.fromPoints([pos3d]);
40979
- // For now making sure it's less than x amount because we had a bug which made it huge.
40980
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
40981
- sphere.radius = geometryRadius;
40982
- }
41152
+ spheres.push(new Cesium.BoundingSphere(pos3d, geometryRadius));
40983
41153
  }
40984
41154
  return [pos3d];
40985
41155
  }
@@ -40999,16 +41169,9 @@
40999
41169
  if (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x) {
41000
41170
  pos3d = await processPosHeight(pos3d, Cesium.HeightReference.NONE);
41001
41171
  }
41002
- const geometryRadius = BModels.Entity.GetValue({
41003
- entity: entity,
41004
- path: ["Bruce", "GeometryRadius"]
41005
- });
41172
+ const geometryRadius = getTrustedGeometryRadius(entity);
41006
41173
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
41007
- const sphere = Cesium.BoundingSphere.fromPoints([pos3d]);
41008
- // For now making sure it's less than x amount because we had a bug which made it huge.
41009
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
41010
- sphere.radius = geometryRadius;
41011
- }
41174
+ spheres.push(new Cesium.BoundingSphere(pos3d, geometryRadius));
41012
41175
  }
41013
41176
  }
41014
41177
  }
@@ -41243,6 +41406,7 @@
41243
41406
  radius /= 2;
41244
41407
  }
41245
41408
  const sphere = new Cesium.BoundingSphere(data.pos3d, radius);
41409
+ spheres.push(sphere);
41246
41410
  data.sphere = sphere;
41247
41411
  }
41248
41412
  else {
@@ -41252,23 +41416,24 @@
41252
41416
  else if (allPosses.length == 1) {
41253
41417
  data.pos3d = allPosses[0];
41254
41418
  }
41255
- /*
41256
- Was used to clean up bad radius data but now seems to do more harm than good.
41257
- TODO: re-review edge cases.
41258
- if ((data.rectangle && spheres.length > 1) || (!data.rectangle && spheres.length > 0)) {
41259
- const allPointSphere = Cesium.BoundingSphere.fromPoints(allPosses);
41260
- spheres.push(allPointSphere);
41261
- if (data.rectangle) {
41262
- const rectSphere = Cesium.BoundingSphere.fromRectangle3D(data.rectangle);
41263
- spheres.push(rectSphere);
41264
- }
41265
- const combinedSphere = Cesium.BoundingSphere.fromBoundingSpheres(spheres);
41266
- data.sphere = combinedSphere;
41419
+ // The entities' own sizes, so a large piece is framed whole and a small one is not left far away.
41420
+ // The rectangle sphere above only spans the sampled points, which for one entity is its pivot alone.
41421
+ const sizeSpheres = spheres.filter(x => x !== data.sphere && x.radius > 0);
41422
+ if (sizeSpheres.length) {
41423
+ data.sphere = Cesium.BoundingSphere.fromBoundingSpheres(data.sphere ? [data.sphere, ...sizeSpheres] : sizeSpheres);
41424
+ if (allPosses.length <= 1) {
41425
+ data.pos3d = data.sphere.center;
41426
+ }
41267
41427
  }
41268
- */
41269
41428
  if (data.sphere && data.sphere.radius <= 0) {
41270
41429
  data.sphere = null;
41271
41430
  }
41431
+ // An Assembly part's record can come back without a location while the API has yet to resolve its model's
41432
+ // bounds, and its feature carries no position of its own. The tile it is drawn in still says roughly where.
41433
+ if (!data.pos3d && tileSpheres.length) {
41434
+ data.sphere = Cesium.BoundingSphere.fromBoundingSpheres(tileSpheres);
41435
+ data.pos3d = data.sphere.center;
41436
+ }
41272
41437
  return data;
41273
41438
  }
41274
41439
  EntityUtils.GetLocation = GetLocation;
@@ -43827,6 +43992,10 @@
43827
43992
  }
43828
43993
  let radius = modelPrim.boundingSphere.radius;
43829
43994
  let centerOffset = modelPrim.boundingSphere.center;
43995
+ const bounds = {
43996
+ center: centerOffset ? Cesium.Cartesian3.clone(centerOffset) : Cesium.Cartesian3.ZERO.clone(),
43997
+ radius: modelPrim.boundingSphere.radius
43998
+ };
43830
43999
  if (centerOffset) {
43831
44000
  // Add the center offset to the radius because I am not good at math.
43832
44001
  const magnitude = Cesium.Cartesian3.magnitude(centerOffset);
@@ -43838,7 +44007,7 @@
43838
44007
  }
43839
44008
  }
43840
44009
  kill();
43841
- res(radius);
44010
+ res({ radius, bounds });
43842
44011
  };
43843
44012
  let readyEventRemoval = null;
43844
44013
  // Newer Cesium versions have readyEvent. They don't use readyPromise.
@@ -43863,9 +44032,10 @@
43863
44032
  });
43864
44033
  _fileRadiusCache.Set(fileRadiusKey, heightProm);
43865
44034
  }
43866
- heightProm.then((radius) => {
44035
+ heightProm.then((measured) => {
43867
44036
  if (model) {
43868
- model._radius = radius;
44037
+ model._radius = measured ? measured.radius : null;
44038
+ model._bounds = measured ? measured.bounds : null;
43869
44039
  model._radiusLoaded = true;
43870
44040
  if (params.viewer && params.viewer.scene && !params.viewer.isDestroyed()) {
43871
44041
  exports.VisualRegisterCuller.MarkShouldRecheck(params.viewer);
@@ -49649,9 +49819,6 @@ void main() {
49649
49819
  StyleEffective.Combine = Combine;
49650
49820
  /**
49651
49821
  * Returns true if every segment in the filter string appears in the subject effective string.
49652
- * A filter segment matches if the subject contains a segment starting with the same key,
49653
- * and either no value filter is given or the value matches exactly.
49654
- * Passing a partial effective value (e.g. just "f0:gradient") also matches.
49655
49822
  */
49656
49823
  function MatchesFilter(effective, filter) {
49657
49824
  if (!filter) {
@@ -50916,7 +51083,7 @@ void main() {
50916
51083
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
50917
51084
  })(exports.StyleUtils || (exports.StyleUtils = {}));
50918
51085
 
50919
- const VERSION = "7.5.2";
51086
+ const VERSION = "7.5.3";
50920
51087
  /**
50921
51088
  * Updates the environment instance used by bruce-cesium to one specified.
50922
51089
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.