bruce-cesium 7.4.2 → 7.4.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.
@@ -16754,9 +16754,6 @@
16754
16754
  // Last date-time range taken from the clock.
16755
16755
  this.lastDateTimeMin = null;
16756
16756
  this.lastDateTimeMax = null;
16757
- // Entity ID -> last resolved date time.
16758
- // Helps determine if a slow resolved request can still be applied while we wait for the next one.
16759
- this.lastFoundDateTimes = new Map();
16760
16757
  // ID of Entity IDs that need to be requested.
16761
16758
  this.eIdQueue = [];
16762
16759
  // Membership mirror of eIdQueue for quick checks.
@@ -16788,8 +16785,12 @@
16788
16785
  // Unsubscribes the view monitor listener that queues what the camera has moved onto.
16789
16786
  this.monitorRemoval = null;
16790
16787
  // Indicates a tick is active.
16791
- // When true, we won't bother calling onTick again.
16788
+ // When true, a new tick is not started; it is noted in pendingTick and run once this one ends.
16792
16789
  this.runningTick = false;
16790
+ // A tick was asked for while one was running, so another is owed once it finishes.
16791
+ this.pendingTick = false;
16792
+ // The debounce every clock change goes through, kept so a tick owed after a running one does too.
16793
+ this.tickDelay = null;
16793
16794
  // Entity ID -> Entity blob.
16794
16795
  // This is a tool that lets developers set their own JSON blobs instead of requesting data from API.
16795
16796
  this.entityDataOverrides = new Map();
@@ -16853,11 +16854,13 @@
16853
16854
  let tickDelay = new BModels.DelayQueue(() => {
16854
16855
  this.onTick(false);
16855
16856
  }, 250, true);
16857
+ this.tickDelay = tickDelay;
16856
16858
  this.hDisposals.push(() => {
16857
16859
  if (tickDelay) {
16858
16860
  tickDelay.Dispose();
16859
16861
  }
16860
16862
  tickDelay = null;
16863
+ this.tickDelay = null;
16861
16864
  });
16862
16865
  // React to clock changes and request new Entities.
16863
16866
  let prevTime = null;
@@ -16897,7 +16900,6 @@
16897
16900
  this.priorityCount = 0;
16898
16901
  this.lastOrderFocus = null;
16899
16902
  this.allEIds.clear();
16900
- this.lastFoundDateTimes.clear();
16901
16903
  this.everFound.clear();
16902
16904
  this.clearIndex();
16903
16905
  this.lastDateTime = null;
@@ -17259,7 +17261,6 @@
17259
17261
  this.eIdQueued.clear();
17260
17262
  this.priorityCount = 0;
17261
17263
  this.allEIds.clear();
17262
- this.lastFoundDateTimes.clear();
17263
17264
  this.everFound.clear();
17264
17265
  this.clearIndex();
17265
17266
  this.entityDataOverrides.clear();
@@ -17275,7 +17276,13 @@
17275
17276
  }
17276
17277
  }
17277
17278
  onTick(force) {
17278
- if (this.runningTick || this.disposed) {
17279
+ if (this.disposed) {
17280
+ return;
17281
+ }
17282
+ if (this.runningTick) {
17283
+ if (this.historic) {
17284
+ this.pendingTick = true;
17285
+ }
17279
17286
  return;
17280
17287
  }
17281
17288
  const rTime = this.viewer.clock.currentTime.toString();
@@ -17283,10 +17290,16 @@
17283
17290
  return;
17284
17291
  }
17285
17292
  this.lastDateTime = rTime;
17293
+ // Whether the clock has left the moment this tick is reading.
17294
+ const movedOn = () => this.historic && this.viewer.clock.currentTime.toString() !== rTime;
17286
17295
  (async () => {
17287
17296
  this.runningTick = true;
17297
+ this.pendingTick = false;
17288
17298
  this.placeStragglers();
17289
17299
  let rerun = false;
17300
+ let interrupted = false;
17301
+ // Batch's answer is applied while the next batch is being read.
17302
+ const applying = [];
17290
17303
  try {
17291
17304
  const handleResponse = async (requestedBatch, entities) => {
17292
17305
  var _a, _b, _c, _d;
@@ -17350,45 +17363,7 @@
17350
17363
  api: this.api
17351
17364
  })).tags;
17352
17365
  }
17353
- // 0 = rTime is still the current time.
17354
- // 1 = rTime is in the future.
17355
- // -1 = rTime is in the past.
17356
- let changeDir = 0;
17357
- if (this.lastDateTime !== this.viewer.clock.currentTime.toString()) {
17358
- changeDir = this.lastDateTime < this.viewer.clock.currentTime.toString() ? 1 : -1;
17359
- }
17360
- let toEmit;
17361
- if (this.historic) {
17362
- // We can emit Entities if the last resolved time (per Entity) isn't newer than rTime.
17363
- // We compare using the changeDir to determine if we should emit or not.
17364
- toEmit = resolvedEntities.filter((e) => {
17365
- var _a;
17366
- const entityId = ((_a = e === null || e === void 0 ? void 0 : e.Bruce) === null || _a === void 0 ? void 0 : _a.ID) || (e === null || e === void 0 ? void 0 : e.id);
17367
- const lastFoundDateTime = this.lastFoundDateTimes.get(entityId);
17368
- if (lastFoundDateTime) {
17369
- if (changeDir === 1) {
17370
- return lastFoundDateTime <= rTime;
17371
- }
17372
- else if (changeDir === -1) {
17373
- return lastFoundDateTime >= rTime;
17374
- }
17375
- }
17376
- return true;
17377
- });
17378
- // Update the last found date times for the filtered Entities.
17379
- toEmit.forEach((e) => {
17380
- var _a;
17381
- const entityId = ((_a = e === null || e === void 0 ? void 0 : e.Bruce) === null || _a === void 0 ? void 0 : _a.ID) || (e === null || e === void 0 ? void 0 : e.id);
17382
- if (entityId) {
17383
- this.lastFoundDateTimes.set(entityId, rTime);
17384
- }
17385
- });
17386
- }
17387
- else {
17388
- // If we're not historic, we can just emit everything.
17389
- toEmit = resolvedEntities;
17390
- }
17391
- this.emitEntities(toEmit, tags);
17366
+ this.emitEntities(resolvedEntities, tags);
17392
17367
  };
17393
17368
  const QUEUE_BATCH_SIZE = 500;
17394
17369
  const requestedIds = new Set();
@@ -17397,7 +17372,8 @@
17397
17372
  const total = this.eIdQueue.length;
17398
17373
  let done = 0;
17399
17374
  while (this.eIdQueue.length && !this.disposed) {
17400
- if (this.historic && this.lastDateTime !== rTime) {
17375
+ if (movedOn()) {
17376
+ interrupted = true;
17401
17377
  break;
17402
17378
  }
17403
17379
  this.orderQueueByCamera();
@@ -17413,7 +17389,7 @@
17413
17389
  api: this.api,
17414
17390
  maxSearchTimeSec: 60 * 2
17415
17391
  });
17416
- handleResponse(batch, entities);
17392
+ applying.push(handleResponse(batch, entities));
17417
17393
  for (let i = 0; i < batch.length; i++) {
17418
17394
  requestedIds.add(batch[i]);
17419
17395
  }
@@ -17445,7 +17421,8 @@
17445
17421
  // The near ones are resolved first out of whatever the view still reaches.
17446
17422
  allEIds = this.bandIds(allEIds);
17447
17423
  while (allEIds.length && !this.disposed && !this.eIdQueue.length) {
17448
- if (this.historic && this.lastDateTime !== rTime) {
17424
+ if (movedOn()) {
17425
+ interrupted = true;
17449
17426
  break;
17450
17427
  }
17451
17428
  const batch = allEIds.splice(0, QUEUE_BATCH_SIZE);
@@ -17456,7 +17433,7 @@
17456
17433
  api: this.api,
17457
17434
  maxSearchTimeSec: 60 * 2
17458
17435
  });
17459
- handleResponse(batch, entities);
17436
+ applying.push(handleResponse(batch, entities));
17460
17437
  for (let i = 0; i < batch.length; i++) {
17461
17438
  requestedIds.add(batch[i]);
17462
17439
  }
@@ -17471,10 +17448,32 @@
17471
17448
  console.error(e);
17472
17449
  }
17473
17450
  finally {
17451
+ // Only a historic answer can be overtaken by a newer moment, so nothing else waits.
17452
+ if (this.historic && applying.length) {
17453
+ await Promise.all(applying.map((pending) => pending.catch((e) => console.error(e))));
17454
+ }
17474
17455
  this.runningTick = false;
17475
17456
  }
17476
- if (rerun) {
17457
+ // A moment read only in part is forgotten, so coming back to it reads it again in full.
17458
+ if (interrupted && this.lastDateTime === rTime) {
17459
+ this.lastDateTime = null;
17460
+ }
17461
+ if (this.disposed) {
17462
+ return;
17463
+ }
17464
+ // Leftovers at the same moment carry straight on, as they always have.
17465
+ if (rerun && !interrupted) {
17477
17466
  this.onTick(true);
17467
+ return;
17468
+ }
17469
+ if (interrupted || this.pendingTick || movedOn()) {
17470
+ this.pendingTick = false;
17471
+ if (this.tickDelay) {
17472
+ this.tickDelay.Call();
17473
+ }
17474
+ else {
17475
+ this.onTick(false);
17476
+ }
17478
17477
  }
17479
17478
  })();
17480
17479
  }
@@ -49069,7 +49068,7 @@ void main() {
49069
49068
  }
49070
49069
  EntityRenderEngine.GetGraphicShapeId = GetGraphicShapeId;
49071
49070
  async function Render(params) {
49072
- var _a, _b, _c;
49071
+ var _a, _b, _c, _d, _e;
49073
49072
  const groupRenderParams = {
49074
49073
  apiGetter: params.apiGetter,
49075
49074
  viewer: params.viewer,
@@ -49246,10 +49245,20 @@ void main() {
49246
49245
  polygons.push(entity);
49247
49246
  continue;
49248
49247
  }
49248
+ // Present when the gate above chose to reuse this entity's graphic.
49249
+ const existingRoot = cEntities.get(entity.Bruce.ID);
49250
+ const existingParts = new Map();
49251
+ (_d = existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) === null || _d === void 0 ? void 0 : _d.forEach((part) => {
49252
+ if (part._multiPartIndex != null) {
49253
+ existingParts.set(part._multiPartIndex, part);
49254
+ }
49255
+ });
49256
+ const partRendered = new Map();
49257
+ const partIndexes = new Map();
49249
49258
  const pParams = {
49250
49259
  ...groupRenderParams,
49251
49260
  entities: [],
49252
- rendered: cEntities
49261
+ rendered: partRendered
49253
49262
  };
49254
49263
  pParams.entitiesHistoric = params.entitiesHistoric;
49255
49264
  const zoomItem = pParams.zoomItems[entity.Bruce.ID];
@@ -49265,39 +49274,59 @@ void main() {
49265
49274
  };
49266
49275
  pParams.zoomItems[subEntity.Bruce.ID] = zoomItem;
49267
49276
  pParams.entities.push(subEntity);
49268
- }
49269
- const cPoly = await Polygon.RenderGroup(pParams);
49270
- Array.from(cPoly.keys()).forEach((key) => {
49271
- if (cPoly.get(key)) {
49272
- pParams.entities = pParams.entities.filter((e) => e.Bruce.ID != key);
49273
- }
49274
- });
49275
- let rendered = Array.from(cPoly.values());
49276
- const cLines = await Polyline.RenderGroup(pParams);
49277
- Array.from(cLines.keys()).forEach((key) => {
49278
- if (cLines.get(key)) {
49277
+ partIndexes.set(subEntity.Bruce.ID, j);
49278
+ const existingPart = existingParts.get(j);
49279
+ if (existingPart) {
49280
+ // An engine preparing a reused graphic gathers everything connected to it, so a part still
49281
+ // attached to its root would have every other part evicted from the scene.
49282
+ existingPart._parentEntity = null;
49283
+ partRendered.set(subEntity.Bruce.ID, existingPart);
49284
+ }
49285
+ }
49286
+ const rendered = [];
49287
+ const collect = (results) => {
49288
+ results.forEach((cEntity, key) => {
49289
+ if (!cEntity) {
49290
+ return;
49291
+ }
49292
+ cEntity._multiPartIndex = partIndexes.get(key);
49293
+ rendered.push(cEntity);
49279
49294
  pParams.entities = pParams.entities.filter((e) => e.Bruce.ID != key);
49280
- }
49281
- });
49282
- rendered = rendered.concat(Array.from(cLines.values()));
49295
+ });
49296
+ };
49297
+ collect(await Polygon.RenderGroup(pParams));
49298
+ collect(await Polyline.RenderGroup(pParams));
49283
49299
  // We'll only render points when there's no other geometry.
49284
49300
  // Generally speaking when polygons/polylines are drawn, points are only drawn because of invalid data.
49285
49301
  if (!rendered.length) {
49286
- const cPoints = await Point.RenderGroup(pParams);
49287
- rendered = rendered.concat(Array.from(cPoints.values()));
49302
+ collect(await Point.RenderGroup(pParams));
49288
49303
  }
49289
- rendered = rendered.filter(x => x != null);
49290
49304
  if (rendered.length) {
49291
- const rootEntity = new Cesium.Entity({
49292
- id: BModels.ObjectUtils.UId(15)
49293
- });
49294
- rootEntity._siblingGraphics = [];
49305
+ const sameParts = ((_e = existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) === null || _e === void 0 ? void 0 : _e.length) == rendered.length &&
49306
+ rendered.every((part) => existingRoot._siblingGraphics.includes(part));
49307
+ let rootEntity;
49308
+ if (sameParts) {
49309
+ rootEntity = existingRoot;
49310
+ }
49311
+ else {
49312
+ if (existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) {
49313
+ // Retiring the old root removes its parts, and the ones carried over belong to the new root now.
49314
+ existingRoot._siblingGraphics = existingRoot._siblingGraphics.filter((part) => !rendered.includes(part));
49315
+ }
49316
+ rootEntity = new Cesium.Entity({
49317
+ id: BModels.ObjectUtils.UId(15)
49318
+ });
49319
+ }
49320
+ rootEntity._siblingGraphics = rendered;
49295
49321
  rootEntity._renderGroup = GetRenderGroupId(zoomItem);
49296
- rootEntity._siblingGraphics = rootEntity._siblingGraphics.concat(rendered);
49322
+ // The skip gate compares the rego's style against the zoom item's, and the rego takes it from here.
49323
+ rootEntity.styleId = (zoomItem === null || zoomItem === void 0 ? void 0 : zoomItem.StyleID) == -1 ? -1 : (+(zoomItem === null || zoomItem === void 0 ? void 0 : zoomItem.StyleID) || null);
49324
+ rootEntity.styleEffective = rendered[0].styleEffective;
49297
49325
  cEntities.set(entity.Bruce.ID, rootEntity);
49298
- const firstEntity = rendered[0];
49299
- if (firstEntity) {
49300
- rootEntity.position = GetCValue(params.viewer, firstEntity.position);
49326
+ const newPosition = GetCValue(params.viewer, rendered[0].position);
49327
+ const oldPosition = GetCValue(params.viewer, rootEntity.position);
49328
+ if (newPosition && (!oldPosition || !BModels.Cartes.IsEqualCartes3(oldPosition, newPosition))) {
49329
+ rootEntity.position = new Cesium.ConstantPositionProperty(newPosition);
49301
49330
  }
49302
49331
  rendered.forEach((child) => {
49303
49332
  child._parentEntity = rootEntity;
@@ -50231,7 +50260,7 @@ void main() {
50231
50260
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
50232
50261
  })(exports.StyleUtils || (exports.StyleUtils = {}));
50233
50262
 
50234
- const VERSION = "7.4.2";
50263
+ const VERSION = "7.4.3";
50235
50264
  /**
50236
50265
  * Updates the environment instance used by bruce-cesium to one specified.
50237
50266
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.