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.
@@ -1,6 +1,6 @@
1
1
  import * as Cesium from 'cesium';
2
- import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ConstantPositionProperty, HeightReference, DistanceDisplayCondition, HorizontalOrigin, VerticalOrigin, Cartesian3, ClassificationType, Math as Math$1, JulianDate, Quaternion, Transforms, HeadingPitchRoll, Matrix4, ArcType, CornerType, ShadowMode, ColorBlendMode, Model, ImageMaterialProperty, Ellipsoid, Cartesian2, SceneTransforms, ShaderSource, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, PolygonHierarchy, PolylineGraphics, Rectangle, FeatureDetection, SceneMode, NearFarScalar, KmlDataSource, Matrix3, GeoJsonDataSource, Cesium3DTileStyle, HeadingPitchRange, Ion, IonResource, Cesium3DTileColorBlendMode, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Cesium3DTileset, Intersect, OrthographicFrustum, EasingFunction, PolygonPipeline, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CesiumInspector, defined, ClockRange, DynamicEnvironmentMapManager, GeometryInstance, EllipsoidGeodesic, sampleTerrainMostDetailed, CustomDataSource, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
- import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Api, Calculator, ClientFile, Entity as Entity$1, EntityTag, EntityType, ObjectUtils, Style, Carto, Geometry as Geometry$1, EntityLod, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, Bounds, BruceEvent, EntityCoords, DataLab, DelayQueue, BruceApi, EntityRelation, AccountConcept, RecordChangeFeed, EntitySource, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType, EntityHistoricData } from 'bruce-models';
2
+ import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ConstantPositionProperty, HeightReference, DistanceDisplayCondition, ShaderSource, Cartesian3, Math as Math$1, Ellipsoid, Transforms, Matrix4, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, ColorBlendMode, HeadingPitchRoll, ShadowMode, ClassificationType, Model, JulianDate, Quaternion, ArcType, CornerType, HorizontalOrigin, VerticalOrigin, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, FeatureDetection, SceneMode, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, Cesium3DTileStyle, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, IonResource, Cesium3DTileset, OrthographicFrustum, EasingFunction, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Intersect, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, PolygonPipeline, CustomDataSource, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, GeometryInstance, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
+ import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, Carto, Geometry as Geometry$1, Api, ClientFileValueMap, Color as Color$1, Bounds, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, RecordChangeFeed, BruceApi, EntityRelation, EntitySource, Camera, ProgramKey, ProjectViewLegacyTile, Account, AccountLimits, Session, UrlUtils, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType, EntityHistoricData } from 'bruce-models';
4
4
 
5
5
  /**
6
6
  * Ensures a number is returned from a given value.
@@ -3028,6 +3028,7 @@ function isAlive(viewer, visual) {
3028
3028
  }
3029
3029
  let _selectColor = Color.fromAlpha(Color.YELLOW, 0.5);
3030
3030
  let _highlightColor = Color.fromCssColorString("#33b1ff").withAlpha(0.5);
3031
+ const DIMMING_REGISTERS_KEY = "_nextspaceDimmingRegisters";
3031
3032
  const STORE_COLOR_PREFIX = "_storeColor_";
3032
3033
  function getStoreKey(key) {
3033
3034
  return STORE_COLOR_PREFIX + key;
@@ -3184,6 +3185,10 @@ function refreshColor(viewer, graphic, opacity) {
3184
3185
  getColor$1(viewer, "default", graphic);
3185
3186
  }
3186
3187
  let color = (_a = getColor$1(viewer, key, graphic)) !== null && _a !== void 0 ? _a : Color.WHITE;
3188
+ // A model that is itself dimmed stays see-through. Only the ones standing out from dimmed surroundings go opaque.
3189
+ if (key != "default" && (opacity == null || opacity >= 1) && CesiumEntityStyler.IsSelectionOpaque(viewer, graphic)) {
3190
+ color = color.withAlpha(1);
3191
+ }
3187
3192
  // If we're selecting and it's highlighted, don't change the color.
3188
3193
  if (key != "select" || getKeyState(graphic, "highlight") == false) {
3189
3194
  let animateMs = key == "highlight" ? ANIMATE_COLOR_HIGHLIGHT_MS : ANIMATE_COLOR_MS;
@@ -3359,6 +3364,50 @@ function getKeyState(graphic, key) {
3359
3364
  */
3360
3365
  var CesiumEntityStyler;
3361
3366
  (function (CesiumEntityStyler) {
3367
+ /**
3368
+ * Whether a graphic or visual is a 3D model, ie: a tileset feature from a CAD or assembly import, or a model Entity.
3369
+ * @param graphic
3370
+ */
3371
+ function IsModel(graphic) {
3372
+ if (graphic instanceof Entity) {
3373
+ return Boolean(graphic.model);
3374
+ }
3375
+ return graphic instanceof Cesium3DTileFeature || graphic instanceof ModelGraphics;
3376
+ }
3377
+ CesiumEntityStyler.IsModel = IsModel;
3378
+ /**
3379
+ * Whether a graphic is drawn with an opaque selection and highlight because something on its viewer is dimmed.
3380
+ * Only 3D models are. GIS graphics keep the colour's own alpha.
3381
+ * @param viewer
3382
+ * @param graphic
3383
+ */
3384
+ function IsSelectionOpaque(viewer, graphic) {
3385
+ var _a;
3386
+ return Boolean((_a = viewer === null || viewer === void 0 ? void 0 : viewer[DIMMING_REGISTERS_KEY]) === null || _a === void 0 ? void 0 : _a.size) && IsModel(graphic);
3387
+ }
3388
+ CesiumEntityStyler.IsSelectionOpaque = IsSelectionOpaque;
3389
+ /**
3390
+ * Records whether a register dims anything on a viewer, by isolation or by opacity.
3391
+ * @param viewer
3392
+ * @param registerId
3393
+ * @param dimming
3394
+ * @returns Whether the viewer went into or out of dimming, so selected models can be recoloured.
3395
+ */
3396
+ function SetDimming(viewer, registerId, dimming) {
3397
+ let ids = viewer[DIMMING_REGISTERS_KEY];
3398
+ const before = Boolean(ids === null || ids === void 0 ? void 0 : ids.size);
3399
+ if (dimming) {
3400
+ if (!ids) {
3401
+ ids = viewer[DIMMING_REGISTERS_KEY] = new Set();
3402
+ }
3403
+ ids.add(registerId);
3404
+ }
3405
+ else {
3406
+ ids === null || ids === void 0 ? void 0 : ids.delete(registerId);
3407
+ }
3408
+ return before !== Boolean(ids === null || ids === void 0 ? void 0 : ids.size);
3409
+ }
3410
+ CesiumEntityStyler.SetDimming = SetDimming;
3362
3411
  function UpdateColorSetting(key, color) {
3363
3412
  if (key == "highlight") {
3364
3413
  _highlightColor = color.clone();
@@ -9858,6 +9907,8 @@ var VisualsRegister;
9858
9907
  // Caches GetIsIsolatedAny(). `null` means "unknown, recompute".
9859
9908
  // Invalidated on any write that could affect isolation.
9860
9909
  this.isolatedAnyCache = null;
9910
+ // Set when isolation or opacity changes, so the next update checks whether anything is still dimmed.
9911
+ this.dimmingDirty = false;
9861
9912
  // Caches GetIsolationOpacity(). `undefined` means "unknown, recompute", `null` means
9862
9913
  // "isolation (if any) is the legacy boolean/full-hide kind, not a numeric dim".
9863
9914
  // Invalidated alongside isolatedAnyCache.
@@ -10126,6 +10177,7 @@ var VisualsRegister;
10126
10177
  this.updateQueueInterval = null;
10127
10178
  return;
10128
10179
  }
10180
+ this.syncDimming();
10129
10181
  const batch = this.updateQueue.splice(0, BATCH_SIZE);
10130
10182
  const cache = {};
10131
10183
  for (let i = 0; i < batch.length; i++) {
@@ -10360,6 +10412,9 @@ var VisualsRegister;
10360
10412
  this.isolatedAnyCache = null;
10361
10413
  this.isolationOpacityCache = undefined;
10362
10414
  }
10415
+ if (keys.includes("isolated") || keys.includes("opacity")) {
10416
+ this.dimmingDirty = true;
10417
+ }
10363
10418
  let changed = false;
10364
10419
  const eStates = this.states[entityId] || {};
10365
10420
  this.states[entityId] = eStates;
@@ -10791,8 +10846,36 @@ var VisualsRegister;
10791
10846
  const { rego } = params;
10792
10847
  markEntity(this, rego, rego.visual, false);
10793
10848
  }
10849
+ /**
10850
+ * Tells the styler whether this register dims anything, by isolation or opacity.
10851
+ */
10852
+ syncDimming() {
10853
+ var _a, _b;
10854
+ if (!this.dimmingDirty) {
10855
+ return;
10856
+ }
10857
+ this.dimmingDirty = false;
10858
+ const dimming = Object.values(this.states).some(states => Object.values(states).some(state => state.isolated || (state.opacity != null && state.opacity < 1)));
10859
+ if (!CesiumEntityStyler.SetDimming(this.viewer, this.id, dimming)) {
10860
+ return;
10861
+ }
10862
+ const entityIds = new Set([...this.GetSelected(), ...this.GetHighlighted()]);
10863
+ for (const entityId of entityIds) {
10864
+ for (const rego of (_a = this.rego[entityId]) !== null && _a !== void 0 ? _a : []) {
10865
+ if (CesiumEntityStyler.IsModel(rego.visual)) {
10866
+ CesiumEntityStyler.Refresh({
10867
+ viewer: this.viewer,
10868
+ entity: rego.visual,
10869
+ requestRender: false
10870
+ });
10871
+ }
10872
+ }
10873
+ }
10874
+ (_b = this.viewer.scene) === null || _b === void 0 ? void 0 : _b.requestRender();
10875
+ }
10794
10876
  Dispose() {
10795
10877
  var _a, _b, _c, _d, _e;
10878
+ CesiumEntityStyler.SetDimming(this.viewer, this.id, false);
10796
10879
  this.ClearLabelHover();
10797
10880
  clearTimeout(this.hoverRingReset);
10798
10881
  this.hoverRingState = {};
@@ -11419,6 +11502,7 @@ var VisualsRegister;
11419
11502
  // Mutated `isolated` directly rather than through setStateValues().
11420
11503
  this.isolatedAnyCache = false;
11421
11504
  this.isolationOpacityCache = null;
11505
+ this.dimmingDirty = true;
11422
11506
  }
11423
11507
  if (changed && (params === null || params === void 0 ? void 0 : params.doUpdate) !== false) {
11424
11508
  this.updateAllEntities({
@@ -12155,6 +12239,7 @@ var VisualsRegister;
12155
12239
  }
12156
12240
  }
12157
12241
  async updateAllEntities(params) {
12242
+ this.syncDimming();
12158
12243
  const ids = Object.keys(this.rego);
12159
12244
  const interval = setInterval(() => {
12160
12245
  const batch = ids.splice(0, 3000);
@@ -12249,6 +12334,7 @@ var VisualsRegister;
12249
12334
  const clearedIds = new Set();
12250
12335
  this.ForEachState((state) => {
12251
12336
  if (!clearedIds.has(state.entityId) && state.opacity != null) {
12337
+ this.dimmingDirty = true;
12252
12338
  this.markLazyExclusion(state.entityId);
12253
12339
  this.queueUpdate({
12254
12340
  entityId: state.entityId,
@@ -18335,8 +18421,6 @@ class TilesetStyler {
18335
18421
  console.error(e);
18336
18422
  }
18337
18423
  // Before we start the loop we'll do a single request for the needed Entity Types.
18338
- // This will be aimed at rows that don't specify a Style and if the default fallback-
18339
- //is set to 0 (using the default of the Entity Type).
18340
18424
  const typeMap = new Map();
18341
18425
  const typeIds = styleMapping.map(x => x.StyleID == -1 || Boolean(x.style) ? null : x.EntityTypeID).filter(x => !!x);
18342
18426
  if (typeIds.length) {
@@ -18402,23 +18486,7 @@ class TilesetStyler {
18402
18486
  }
18403
18487
  this.styleMappingsLoaded.set(styleMap.EntityTypeID, true);
18404
18488
  if (this.loaded) {
18405
- // If we have a bunch of Entities that were waiting for the style to load,
18406
- // then we can pass them to the gatherer now.
18407
- const relatedIds = this.stylePendingEntityIds.get(styleMap.EntityTypeID);
18408
- if (relatedIds) {
18409
- if (this.getTilesetFeatureNeedsFullData(styleMap.EntityTypeID)) {
18410
- this.entityGatherer.Queue(Array.from(relatedIds));
18411
- }
18412
- else {
18413
- relatedIds.forEach(id => {
18414
- const rego = this.getEntityRego(id);
18415
- if (rego) {
18416
- this.styleTilesetFeature(rego);
18417
- }
18418
- });
18419
- }
18420
- this.stylePendingEntityIds.delete(styleMap.EntityTypeID);
18421
- }
18489
+ this.flushPendingForType(styleMap.EntityTypeID);
18422
18490
  }
18423
18491
  }
18424
18492
  if (this.loadingCounter != counter) {
@@ -18450,6 +18518,67 @@ class TilesetStyler {
18450
18518
  this.stylePendingEntityIds.clear();
18451
18519
  }
18452
18520
  }
18521
+ /**
18522
+ * Passes the Entities waiting on an Entity Type's style on to be styled, now that the style is known.
18523
+ * @param entityTypeId
18524
+ */
18525
+ flushPendingForType(entityTypeId) {
18526
+ const relatedIds = this.stylePendingEntityIds.get(entityTypeId);
18527
+ if (!relatedIds) {
18528
+ return;
18529
+ }
18530
+ if (this.getTilesetFeatureNeedsFullData(entityTypeId)) {
18531
+ this.entityGatherer.Queue(Array.from(relatedIds));
18532
+ }
18533
+ else {
18534
+ relatedIds.forEach(id => {
18535
+ const rego = this.getEntityRego(id);
18536
+ if (rego) {
18537
+ this.styleTilesetFeature(rego);
18538
+ }
18539
+ });
18540
+ }
18541
+ this.stylePendingEntityIds.delete(entityTypeId);
18542
+ }
18543
+ hasMappingRow(entityTypeId) {
18544
+ var _a;
18545
+ return Boolean((_a = this.styleMapping) === null || _a === void 0 ? void 0 : _a.some(x => x.EntityTypeID == entityTypeId));
18546
+ }
18547
+ /**
18548
+ * Loads the default style of an Entity Type that the style mapping does not list.
18549
+ * @param entityTypeId
18550
+ */
18551
+ async loadEntityTypeDefaultStyle(entityTypeId) {
18552
+ const counter = this.loadingCounter;
18553
+ const styleMap = { EntityTypeID: entityTypeId, StyleID: 0, style: null };
18554
+ this.styleMapping.push(styleMap);
18555
+ try {
18556
+ const { entityType } = await EntityType.Get({
18557
+ api: this.api,
18558
+ entityTypeId
18559
+ });
18560
+ const styleId = entityType === null || entityType === void 0 ? void 0 : entityType["DisplaySetting.ID"];
18561
+ if (styleId && styleId != -1) {
18562
+ const { style } = await Style.Get({
18563
+ api: this.api,
18564
+ styleId
18565
+ });
18566
+ if (style) {
18567
+ styleMap.style = style;
18568
+ styleMap.StyleID = styleId;
18569
+ }
18570
+ }
18571
+ }
18572
+ catch (e) {
18573
+ console.error(e);
18574
+ }
18575
+ // A reload in the meantime resolves the row itself, or replaces the mapping and re-queues everything.
18576
+ if (this.disposed || this.loadingCounter != counter) {
18577
+ return;
18578
+ }
18579
+ this.styleMappingsLoaded.set(entityTypeId, true);
18580
+ this.flushPendingForType(entityTypeId);
18581
+ }
18453
18582
  disposeGatherer() {
18454
18583
  if (this.feedRestyleThrottleTimer) {
18455
18584
  clearTimeout(this.feedRestyleThrottleTimer);
@@ -18488,7 +18617,11 @@ class TilesetStyler {
18488
18617
  this.overrideFeatureColor.set(rego.entityId, false);
18489
18618
  }
18490
18619
  const typeId = rego.entityTypeId || "";
18491
- if (this.styleMappingLoaded || this.styleMappingsLoaded.get(typeId)) {
18620
+ // With no fallback style to use instead, a type the mapping does not list falls back to its own default.
18621
+ if (this.styleMappingLoaded && typeId && !this.fallbackStyle && !this.hasMappingRow(typeId)) {
18622
+ this.loadEntityTypeDefaultStyle(typeId);
18623
+ }
18624
+ if (this.styleMappingsLoaded.get(typeId) || (this.styleMappingLoaded && !this.hasMappingRow(typeId))) {
18492
18625
  if (this.getTilesetFeatureNeedsFullData(typeId)) {
18493
18626
  needsDataIds.push(rego.entityId);
18494
18627
  }
@@ -40591,6 +40724,47 @@ function calcEntityLocation(entity, modelSpace) {
40591
40724
  }
40592
40725
  return Matrix4.multiplyByPoint(enuFrame, new Cartesian3(tx, ty, tz), new Cartesian3());
40593
40726
  }
40727
+ // Records created within about this long ago are the ones the oversized GeometryRadius bug could have written.
40728
+ const GEOMETRY_RADIUS_SUSPECT_AGE_MS = 1000 * 60 * 60 * 24 * 183;
40729
+ // Above this a recent record's radius is treated as that bug rather than a real size.
40730
+ const GEOMETRY_RADIUS_SUSPECT_ABOVE = 500;
40731
+ /**
40732
+ * Returns an entity's Bruce.GeometryRadius, or null when there is none or it looks like the oversized-radius bug.
40733
+ * The size cap only applies to records created recently; older ones and ones with no known date are taken as they are.
40734
+ * @param entity
40735
+ */
40736
+ function getTrustedGeometryRadius(entity) {
40737
+ var _a;
40738
+ const radius = EnsureNumber(Entity$1.GetValue({
40739
+ entity: entity,
40740
+ path: ["Bruce", "GeometryRadius"]
40741
+ }));
40742
+ if (!(radius > 0)) {
40743
+ return null;
40744
+ }
40745
+ const created = Date.parse((_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.Created);
40746
+ const recent = !isNaN(created) && Date.now() - created < GEOMETRY_RADIUS_SUSPECT_AGE_MS;
40747
+ if (recent && radius >= GEOMETRY_RADIUS_SUSPECT_ABOVE) {
40748
+ return null;
40749
+ }
40750
+ return radius;
40751
+ }
40752
+ /**
40753
+ * Returns the world centre of a model's own bounds, applying the entity's orientation to the offset.
40754
+ * The position is the one GetLocation already resolved, so height references are honoured.
40755
+ * @param viewer
40756
+ * @param part
40757
+ * @param pos3d
40758
+ * @param bounds
40759
+ */
40760
+ function getModelBoundsCenter(viewer, part, pos3d, bounds) {
40761
+ const orientation = GetValue$1(viewer, part.orientation);
40762
+ const rotation = orientation
40763
+ ? Matrix3.fromQuaternion(orientation, new Matrix3())
40764
+ : Matrix4.getMatrix3(Transforms.eastNorthUpToFixedFrame(pos3d), new Matrix3());
40765
+ const offset = Matrix3.multiplyByVector(rotation, bounds.center, new Cartesian3());
40766
+ return Cartesian3.add(pos3d, offset, new Cartesian3());
40767
+ }
40594
40768
  // +90° rotation around Z: aligns GLTF Y-up forward with Cesium ENU North.
40595
40769
  const _assemblyAxisShift = new Quaternion(0, 0, -Math.SQRT1_2, Math.SQRT1_2);
40596
40770
  var EntityUtils;
@@ -40642,6 +40816,9 @@ var EntityUtils;
40642
40816
  rectangle: null,
40643
40817
  sphere: null
40644
40818
  };
40819
+ const spheres = [];
40820
+ // The tile holding a rendered feature that says nothing of where it is, used only when nothing better turns up.
40821
+ const tileSpheres = [];
40645
40822
  const processPosHeight = async (pos3d, heightRef) => {
40646
40823
  // Raise to minimumAlt if needed.
40647
40824
  if ((!isNaN(minimumAlt) && minimumAlt != null)) {
@@ -40719,7 +40896,7 @@ var EntityUtils;
40719
40896
  * Returns an array of positions from the entity's currently rendered graphics.
40720
40897
  */
40721
40898
  const evaluateRendered = async () => {
40722
- var _a, _b;
40899
+ var _a, _b, _c, _d;
40723
40900
  const rego = visualRegister ? visualRegister.GetRego({
40724
40901
  entityId: sample.entityId,
40725
40902
  menuItemId: sample.menuItemId
@@ -40851,9 +41028,14 @@ var EntityUtils;
40851
41028
  posses.push(pos3d);
40852
41029
  if (part.model) {
40853
41030
  const modelExt = part.model;
40854
- if (modelExt._radius && modelExt._radius > -1) {
41031
+ const bounds = modelExt._bounds;
41032
+ if ((bounds === null || bounds === void 0 ? void 0 : bounds.radius) > 0) {
41033
+ spheres.push(new BoundingSphere(getModelBoundsCenter(viewer, part, pos3d, bounds), bounds.radius));
41034
+ }
41035
+ else if (modelExt._radius && modelExt._radius > -1) {
40855
41036
  const sphere = BoundingSphere.fromPoints([pos3d]);
40856
41037
  sphere.radius = modelExt._radius;
41038
+ spheres.push(sphere);
40857
41039
  }
40858
41040
  }
40859
41041
  else if (part.ellipse) {
@@ -40872,6 +41054,7 @@ var EntityUtils;
40872
41054
  const radius = Math.max(semiMajorAxis, semiMinorAxis, height);
40873
41055
  if (radius && radius > 0) {
40874
41056
  const sphere = new BoundingSphere(pos3d, radius);
41057
+ spheres.push(sphere);
40875
41058
  }
40876
41059
  }
40877
41060
  }
@@ -40890,6 +41073,14 @@ var EntityUtils;
40890
41073
  posses.push(pos3d);
40891
41074
  if (data.radius != null && !isNaN(data.radius)) {
40892
41075
  const sphere = new BoundingSphere(pos3d, data.radius);
41076
+ spheres.push(sphere);
41077
+ }
41078
+ }
41079
+ else {
41080
+ // Missing from the typings this library builds against, but there at runtime.
41081
+ const tileSphere = (_d = (_c = part.content) === null || _c === void 0 ? void 0 : _c.tile) === null || _d === void 0 ? void 0 : _d.boundingSphere;
41082
+ if ((tileSphere === null || tileSphere === void 0 ? void 0 : tileSphere.radius) > 0) {
41083
+ tileSpheres.push(BoundingSphere.clone(tileSphere));
40893
41084
  }
40894
41085
  }
40895
41086
  }
@@ -40969,7 +41160,7 @@ var EntityUtils;
40969
41160
  }
40970
41161
  const boundaries = Entity$1.GetValue({
40971
41162
  entity: entity,
40972
- path: ["Bruce, Boundaries"]
41163
+ path: ["Bruce", "Boundaries"]
40973
41164
  });
40974
41165
  if (boundaries && typeof boundaries == "object") {
40975
41166
  const point = {
@@ -41022,16 +41213,9 @@ var EntityUtils;
41022
41213
  const transformedOffset = Matrix3.multiplyByVector(transformHpr, offset, new Cartesian3());
41023
41214
  pos3d = Matrix4.multiplyByPoint(m1, transformedOffset, new Cartesian3());
41024
41215
  pos3d = await processPosHeight(pos3d, HeightReference.NONE);
41025
- const geometryRadius = Entity$1.GetValue({
41026
- entity: entity,
41027
- path: ["Bruce", "GeometryRadius"]
41028
- });
41216
+ const geometryRadius = getTrustedGeometryRadius(entity);
41029
41217
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
41030
- const sphere = BoundingSphere.fromPoints([pos3d]);
41031
- // For now making sure it's less than x amount because we had a bug which made it huge.
41032
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
41033
- sphere.radius = geometryRadius;
41034
- }
41218
+ spheres.push(new BoundingSphere(pos3d, geometryRadius));
41035
41219
  }
41036
41220
  return [pos3d];
41037
41221
  }
@@ -41039,16 +41223,9 @@ var EntityUtils;
41039
41223
  if (location) {
41040
41224
  let pos3d = Cartesian3.fromDegrees(longitude, latitude, EnsureNumber(location.altitude));
41041
41225
  pos3d = await processPosHeight(pos3d, HeightReference.NONE);
41042
- const geometryRadius = Entity$1.GetValue({
41043
- entity: entity,
41044
- path: ["Bruce", "GeometryRadius"]
41045
- });
41226
+ const geometryRadius = getTrustedGeometryRadius(entity);
41046
41227
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
41047
- const sphere = BoundingSphere.fromPoints([pos3d]);
41048
- // For now making sure it's less than x amount because we had a bug which made it huge.
41049
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
41050
- sphere.radius = geometryRadius;
41051
- }
41228
+ spheres.push(new BoundingSphere(pos3d, geometryRadius));
41052
41229
  }
41053
41230
  return [pos3d];
41054
41231
  }
@@ -41071,16 +41248,9 @@ var EntityUtils;
41071
41248
  }
41072
41249
  if (pos3d) {
41073
41250
  pos3d = await processPosHeight(pos3d, HeightReference.NONE);
41074
- const geometryRadius = Entity$1.GetValue({
41075
- entity: entity,
41076
- path: ["Bruce", "GeometryRadius"]
41077
- });
41251
+ const geometryRadius = getTrustedGeometryRadius(entity);
41078
41252
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
41079
- const sphere = BoundingSphere.fromPoints([pos3d]);
41080
- // For now making sure it's less than x amount because we had a bug which made it huge.
41081
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
41082
- sphere.radius = geometryRadius;
41083
- }
41253
+ spheres.push(new BoundingSphere(pos3d, geometryRadius));
41084
41254
  }
41085
41255
  return [pos3d];
41086
41256
  }
@@ -41100,16 +41270,9 @@ var EntityUtils;
41100
41270
  if (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x) {
41101
41271
  pos3d = await processPosHeight(pos3d, HeightReference.NONE);
41102
41272
  }
41103
- const geometryRadius = Entity$1.GetValue({
41104
- entity: entity,
41105
- path: ["Bruce", "GeometryRadius"]
41106
- });
41273
+ const geometryRadius = getTrustedGeometryRadius(entity);
41107
41274
  if (geometryRadius && (pos3d === null || pos3d === void 0 ? void 0 : pos3d.x)) {
41108
- const sphere = BoundingSphere.fromPoints([pos3d]);
41109
- // For now making sure it's less than x amount because we had a bug which made it huge.
41110
- if (geometryRadius && geometryRadius < 500 && geometryRadius > 0.1) {
41111
- sphere.radius = geometryRadius;
41112
- }
41275
+ spheres.push(new BoundingSphere(pos3d, geometryRadius));
41113
41276
  }
41114
41277
  }
41115
41278
  }
@@ -41344,6 +41507,7 @@ var EntityUtils;
41344
41507
  radius /= 2;
41345
41508
  }
41346
41509
  const sphere = new BoundingSphere(data.pos3d, radius);
41510
+ spheres.push(sphere);
41347
41511
  data.sphere = sphere;
41348
41512
  }
41349
41513
  else {
@@ -41353,23 +41517,24 @@ var EntityUtils;
41353
41517
  else if (allPosses.length == 1) {
41354
41518
  data.pos3d = allPosses[0];
41355
41519
  }
41356
- /*
41357
- Was used to clean up bad radius data but now seems to do more harm than good.
41358
- TODO: re-review edge cases.
41359
- if ((data.rectangle && spheres.length > 1) || (!data.rectangle && spheres.length > 0)) {
41360
- const allPointSphere = Cesium.BoundingSphere.fromPoints(allPosses);
41361
- spheres.push(allPointSphere);
41362
- if (data.rectangle) {
41363
- const rectSphere = Cesium.BoundingSphere.fromRectangle3D(data.rectangle);
41364
- spheres.push(rectSphere);
41365
- }
41366
- const combinedSphere = Cesium.BoundingSphere.fromBoundingSpheres(spheres);
41367
- data.sphere = combinedSphere;
41520
+ // The entities' own sizes, so a large piece is framed whole and a small one is not left far away.
41521
+ // The rectangle sphere above only spans the sampled points, which for one entity is its pivot alone.
41522
+ const sizeSpheres = spheres.filter(x => x !== data.sphere && x.radius > 0);
41523
+ if (sizeSpheres.length) {
41524
+ data.sphere = BoundingSphere.fromBoundingSpheres(data.sphere ? [data.sphere, ...sizeSpheres] : sizeSpheres);
41525
+ if (allPosses.length <= 1) {
41526
+ data.pos3d = data.sphere.center;
41527
+ }
41368
41528
  }
41369
- */
41370
41529
  if (data.sphere && data.sphere.radius <= 0) {
41371
41530
  data.sphere = null;
41372
41531
  }
41532
+ // An Assembly part's record can come back without a location while the API has yet to resolve its model's
41533
+ // bounds, and its feature carries no position of its own. The tile it is drawn in still says roughly where.
41534
+ if (!data.pos3d && tileSpheres.length) {
41535
+ data.sphere = BoundingSphere.fromBoundingSpheres(tileSpheres);
41536
+ data.pos3d = data.sphere.center;
41537
+ }
41373
41538
  return data;
41374
41539
  }
41375
41540
  EntityUtils.GetLocation = GetLocation;
@@ -43937,6 +44102,10 @@ var EntityRenderEngineModel3d;
43937
44102
  }
43938
44103
  let radius = modelPrim.boundingSphere.radius;
43939
44104
  let centerOffset = modelPrim.boundingSphere.center;
44105
+ const bounds = {
44106
+ center: centerOffset ? Cartesian3.clone(centerOffset) : Cartesian3.ZERO.clone(),
44107
+ radius: modelPrim.boundingSphere.radius
44108
+ };
43940
44109
  if (centerOffset) {
43941
44110
  // Add the center offset to the radius because I am not good at math.
43942
44111
  const magnitude = Cartesian3.magnitude(centerOffset);
@@ -43948,7 +44117,7 @@ var EntityRenderEngineModel3d;
43948
44117
  }
43949
44118
  }
43950
44119
  kill();
43951
- res(radius);
44120
+ res({ radius, bounds });
43952
44121
  };
43953
44122
  let readyEventRemoval = null;
43954
44123
  // Newer Cesium versions have readyEvent. They don't use readyPromise.
@@ -43973,9 +44142,10 @@ var EntityRenderEngineModel3d;
43973
44142
  });
43974
44143
  _fileRadiusCache.Set(fileRadiusKey, heightProm);
43975
44144
  }
43976
- heightProm.then((radius) => {
44145
+ heightProm.then((measured) => {
43977
44146
  if (model) {
43978
- model._radius = radius;
44147
+ model._radius = measured ? measured.radius : null;
44148
+ model._bounds = measured ? measured.bounds : null;
43979
44149
  model._radiusLoaded = true;
43980
44150
  if (params.viewer && params.viewer.scene && !params.viewer.isDestroyed()) {
43981
44151
  VisualRegisterCuller.MarkShouldRecheck(params.viewer);
@@ -49785,9 +49955,6 @@ var StyleEffective;
49785
49955
  StyleEffective.Combine = Combine;
49786
49956
  /**
49787
49957
  * Returns true if every segment in the filter string appears in the subject effective string.
49788
- * A filter segment matches if the subject contains a segment starting with the same key,
49789
- * and either no value filter is given or the value matches exactly.
49790
- * Passing a partial effective value (e.g. just "f0:gradient") also matches.
49791
49958
  */
49792
49959
  function MatchesFilter(effective, filter) {
49793
49960
  if (!filter) {
@@ -51056,7 +51223,7 @@ var StyleUtils;
51056
51223
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
51057
51224
  })(StyleUtils || (StyleUtils = {}));
51058
51225
 
51059
- const VERSION = "7.5.2";
51226
+ const VERSION = "7.5.3";
51060
51227
  /**
51061
51228
  * Updates the environment instance used by bruce-cesium to one specified.
51062
51229
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.