bruce-cesium 5.4.0 → 5.4.1

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
- import { BruceEvent, Cartes, Entity as Entity$1, Carto, Geometry, MathUtils, LRUCache, Api, Calculator, ClientFile, EntityTag, EntityType, ObjectUtils, Style, ProjectViewTile, DelayQueue, EntityLod, Bounds, ZoomControl, EntityRelationType, ENVIRONMENT, EntityHistoricData, Tileset, EntityCoords, DataLab, EntitySource, MenuItem, EntityRelation, ProgramKey, ProjectView, ProjectViewBookmark, ProjectViewLegacyTile, Camera, EntityAttachment, EntityAttachmentType, EntityAttribute, AbstractApi, Session } from 'bruce-models';
1
+ import { BruceEvent, Cartes, Entity as Entity$1, Carto, Geometry, MathUtils, LRUCache, Api, Calculator, ClientFile, EntityTag, EntityType, ObjectUtils, Style, ProjectViewTile, DelayQueue, EntityLod, Bounds, ZoomControl, EntityRelationType, ENVIRONMENT, EntityHistoricData, Tileset, EntityCoords, DataLab, EntitySource, MenuItem, EntityRelation, ProgramKey, ProjectView, ProjectViewBookmark, Camera, ProjectViewLegacyTile, EntityAttachment, EntityAttachmentType, EntityAttribute, AbstractApi, Session } from 'bruce-models';
2
2
  import * as Cesium from 'cesium';
3
- import { Cartographic, Cartesian2, Math as Math$1, Cartesian3, CallbackProperty, Color, HeightReference, Rectangle, JulianDate, Entity, DistanceDisplayCondition, ClassificationType, ArcType, CornerType, ShadowMode, ConstantProperty, ConstantPositionProperty, PolygonHierarchy, PolylineGraphics, ColorMaterialProperty, ColorBlendMode, HeadingPitchRoll, Transforms, Model, HorizontalOrigin, VerticalOrigin, SceneMode, GeoJsonDataSource, Primitive, Cesium3DTileFeature, Cesium3DTileStyle, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, KmlDataSource, SceneTransforms, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, CesiumInspector, OrthographicFrustum, defined, ClockRange, EasingFunction, NearFarScalar, EllipsoidGeodesic, sampleTerrainMostDetailed, Cesium3DTileset, PolygonPipeline, Matrix4, Matrix3, IonResource, BoundingSphere, GeometryInstance, Quaternion, ScreenSpaceEventHandler, ScreenSpaceEventType, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CzmlDataSource, Intersect, Fullscreen } from 'cesium';
3
+ import { Cartographic, Cartesian2, Math as Math$1, Cartesian3, CallbackProperty, Color, HeightReference, Rectangle, JulianDate, Entity, DistanceDisplayCondition, HorizontalOrigin, VerticalOrigin, ConstantProperty, ClassificationType, ConstantPositionProperty, ArcType, CornerType, ShadowMode, PolygonHierarchy, PolylineGraphics, ColorMaterialProperty, ColorBlendMode, HeadingPitchRoll, Transforms, Model, SceneMode, Primitive, Cesium3DTileFeature, GeoJsonDataSource, Cesium3DTileStyle, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, KmlDataSource, SceneTransforms, OrthographicFrustum, EasingFunction, NearFarScalar, EllipsoidTerrainProvider, CesiumInspector, defined, ClockRange, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, EllipsoidGeodesic, sampleTerrainMostDetailed, Cesium3DTileset, Matrix4, Matrix3, IonResource, PolygonPipeline, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, BoundingSphere, GeometryInstance, Quaternion, ScreenSpaceEventHandler, ScreenSpaceEventType, CzmlDataSource, Intersect, Fullscreen } from 'cesium';
4
4
 
5
5
  const TIME_LAG = 300;
6
6
  const POSITION_CHECK_TIMER = 950;
@@ -1368,6 +1368,9 @@ var CesiumAnimatedProperty;
1368
1368
  }
1369
1369
  CesiumAnimatedProperty.AnimatePositionSeries = AnimatePositionSeries;
1370
1370
  function GetSeriesPossesForHistoricEntity(viewer, heightRef, historic) {
1371
+ if (!historic || !historic.length) {
1372
+ return [];
1373
+ }
1371
1374
  const series = [];
1372
1375
  for (let i = 0; i < historic.length; i++) {
1373
1376
  const item = historic[i];
@@ -1406,25 +1409,6 @@ var CesiumAnimatedProperty;
1406
1409
  return series;
1407
1410
  }
1408
1411
  CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity = GetSeriesPossesForHistoricEntity;
1409
- /**
1410
- * Animates a tileset position and heading from a series of positions over time.
1411
- * Unlike other animation functions that directly modify the tileset,
1412
- * this provides a callback with calculated values for the caller to apply.
1413
- *
1414
- * Example:
1415
- * ```
1416
- * const dispose = CesiumAnimatedProperty.AnimateTPositionSeries({
1417
- * viewer: viewer,
1418
- * posses: positionSeries,
1419
- * onUpdate: (position, heading) => {}
1420
- * });
1421
- *
1422
- * // To dispose:
1423
- * dispose();
1424
- * ```
1425
- * @param params Animation parameters
1426
- * @returns Function to stop the animation
1427
- */
1428
1412
  class AnimateTPositionSeries {
1429
1413
  constructor(params) {
1430
1414
  // Cache for calculated values.
@@ -1432,23 +1416,74 @@ var CesiumAnimatedProperty;
1432
1416
  this.lastCalcPos3d = null;
1433
1417
  this.lastCalcHeading = null;
1434
1418
  this.removal = null;
1419
+ // Track the timeline range for which we have data.
1420
+ this.minDate = null;
1421
+ this.maxDate = null;
1422
+ // Map of positions by timestamp for quick lookup and deduplication.
1423
+ this.positionsMap = new Map();
1435
1424
  this.viewer = params.viewer;
1436
1425
  this.onUpdate = params.onUpdate;
1437
1426
  this.onDone = params.onDone;
1438
- // No positions to animate.
1439
- if (!params.posses || params.posses.length === 0) {
1440
- return;
1427
+ this.onRangeChangeCallback = params.onRangeChange;
1428
+ // Initialize the positions map
1429
+ this.positionsMap = new Map();
1430
+ // Add initial positions
1431
+ if (params.posses && params.posses.length > 0) {
1432
+ this.addPositions(params.posses);
1441
1433
  }
1442
- // Order positions by date.
1443
- const orderedPosses = [...params.posses].sort((a, b) => {
1444
- return a.dateTime.getTime() - b.dateTime.getTime();
1445
- });
1446
- // Process headings - if all are null or 0, assume all are null.
1447
- this.positions = this.processHeadings([...orderedPosses]);
1448
1434
  // Set up the animation loop.
1449
1435
  this.removal = this.viewer.scene.postUpdate.addEventListener(() => this.update());
1450
1436
  this.update();
1451
1437
  }
1438
+ /**
1439
+ * Add new positions to the animation.
1440
+ * Will deduplicate positions with the same timestamp and sort them.
1441
+ * @param newPositions Positions to add
1442
+ */
1443
+ addPositions(newPositions) {
1444
+ if (!newPositions || newPositions.length === 0) {
1445
+ return;
1446
+ }
1447
+ // Add new positions to our map, overwriting any existing positions with the same timestamp
1448
+ for (const pos of newPositions) {
1449
+ const key = pos.dateTime.toISOString();
1450
+ this.positionsMap.set(key, pos);
1451
+ }
1452
+ // Rebuild our sorted array from the map
1453
+ this.positions = Array.from(this.positionsMap.values()).sort((a, b) => {
1454
+ return a.dateTime.getTime() - b.dateTime.getTime();
1455
+ });
1456
+ // Process headings
1457
+ this.positions = this.processHeadings([...this.positions]);
1458
+ // Update our min/max dates
1459
+ if (this.positions.length > 0) {
1460
+ const first = this.positions[0];
1461
+ const last = this.positions[this.positions.length - 1];
1462
+ if (!this.minDate || first.dateTime < this.minDate) {
1463
+ this.minDate = first.dateTime;
1464
+ }
1465
+ if (!this.maxDate || last.dateTime > this.maxDate) {
1466
+ this.maxDate = last.dateTime;
1467
+ }
1468
+ }
1469
+ }
1470
+ /**
1471
+ * Get the current date range covered by our positions.
1472
+ */
1473
+ getDateRange() {
1474
+ return {
1475
+ minDate: this.minDate,
1476
+ maxDate: this.maxDate
1477
+ };
1478
+ }
1479
+ /**
1480
+ * Trigger the onRangeChange callback to request more data.
1481
+ */
1482
+ onRangeChange() {
1483
+ if (this.onRangeChangeCallback) {
1484
+ this.onRangeChangeCallback();
1485
+ }
1486
+ }
1452
1487
  /**
1453
1488
  * Stop the animation and call the onDone callback if provided.
1454
1489
  */
@@ -1462,9 +1497,12 @@ var CesiumAnimatedProperty;
1462
1497
  }
1463
1498
  }
1464
1499
  /**
1465
- * Update function called on each frame.
1500
+ * Update function called on each render frame.
1466
1501
  */
1467
1502
  update() {
1503
+ if (!this.positions || this.positions.length === 0) {
1504
+ return;
1505
+ }
1468
1506
  let now = this.viewer.scene.lastRenderTime;
1469
1507
  if (!now) {
1470
1508
  now = this.viewer.clock.currentTime;
@@ -1506,11 +1544,19 @@ var CesiumAnimatedProperty;
1506
1544
  return posses;
1507
1545
  }
1508
1546
  /**
1509
- * Calculate the position at the given time
1547
+ * Calculate the position at the given time.
1510
1548
  */
1511
1549
  calculatePosition(currentTimeMs) {
1512
1550
  const posses = this.positions;
1513
- // See if we're before the first position
1551
+ // No positions to interpolate
1552
+ if (!posses || posses.length === 0) {
1553
+ return {
1554
+ pos3d: new Cartesian3(),
1555
+ indexLast: -1,
1556
+ indexNext: -1
1557
+ };
1558
+ }
1559
+ // See if we're before the first position.
1514
1560
  if (currentTimeMs <= posses[0].dateTime.getTime()) {
1515
1561
  return {
1516
1562
  pos3d: posses[0].pos3d,
@@ -1518,7 +1564,7 @@ var CesiumAnimatedProperty;
1518
1564
  indexNext: 0
1519
1565
  };
1520
1566
  }
1521
- // See if we're after the last position
1567
+ // See if we're after the last position.
1522
1568
  if (currentTimeMs >= posses[posses.length - 1].dateTime.getTime()) {
1523
1569
  const lastIndex = posses.length - 1;
1524
1570
  return {
@@ -1527,35 +1573,41 @@ var CesiumAnimatedProperty;
1527
1573
  indexNext: lastIndex
1528
1574
  };
1529
1575
  }
1530
- // Find the current position
1576
+ // Binary search to find the closest position.
1577
+ let start = 0;
1578
+ let end = posses.length - 1;
1531
1579
  let lastIndex = 0;
1532
- for (let i = 1; i < posses.length; i++) {
1533
- let pos = posses[i];
1534
- if (currentTimeMs >= pos.dateTime.getTime()) {
1535
- lastIndex = i;
1580
+ while (start <= end) {
1581
+ const mid = Math.floor((start + end) / 2);
1582
+ const midTime = posses[mid].dateTime.getTime();
1583
+ if (midTime <= currentTimeMs) {
1584
+ lastIndex = mid;
1585
+ start = mid + 1;
1536
1586
  }
1537
1587
  else {
1538
- break;
1588
+ end = mid - 1;
1539
1589
  }
1540
1590
  }
1541
1591
  const last = posses[lastIndex];
1542
- const next = posses[lastIndex + 1];
1543
- // If no next position, use the last one
1544
- if (!next) {
1592
+ const nextIndex = Math.min(lastIndex + 1, posses.length - 1);
1593
+ const next = posses[nextIndex];
1594
+ // If we found an exact match or there's no next position.
1595
+ if (currentTimeMs === last.dateTime.getTime() || lastIndex === nextIndex) {
1545
1596
  return {
1546
1597
  pos3d: last.pos3d,
1547
1598
  indexLast: lastIndex,
1548
1599
  indexNext: lastIndex
1549
1600
  };
1550
1601
  }
1551
- // Interpolate the position
1552
- const progress = (currentTimeMs - last.dateTime.getTime()) /
1553
- (next.dateTime.getTime() - last.dateTime.getTime());
1602
+ // Interpolate between the two closest positions.
1603
+ const lastTime = last.dateTime.getTime();
1604
+ const nextTime = next.dateTime.getTime();
1605
+ const progress = (currentTimeMs - lastTime) / (nextTime - lastTime);
1554
1606
  const interpolatedPos = Cartesian3.lerp(last.pos3d, next.pos3d, progress, new Cartesian3());
1555
1607
  return {
1556
1608
  pos3d: interpolatedPos,
1557
1609
  indexLast: lastIndex,
1558
- indexNext: lastIndex + 1
1610
+ indexNext: nextIndex
1559
1611
  };
1560
1612
  }
1561
1613
  /**
@@ -5238,6 +5290,12 @@ async function getStyle(api, entity, styleId) {
5238
5290
 
5239
5291
  const CESIUM_INSPECTOR_KEY = "_nextspace_inspector";
5240
5292
  const CESIUM_TIMELINE_KEY = "_nextspace_timeline";
5293
+ const CESIUM_TIMELINE_LIVE_KEY = "_nextspace_timeline_live";
5294
+ const CESIUM_TIMELINE_LIVE_PADDING_FORWARD_KEY = "_nextspace_timeline_live_padding_forward";
5295
+ const CESIUM_TIMELINE_LIVE_PADDING_BACKWARD_KEY = "_nextspace_timeline_live_padding_backward";
5296
+ const CESIUM_TIMELINE_INTERVAL_KEY = "_nextspace_timeline_interval";
5297
+ const DEFAULT_LIVE_PADDING_FORWARD_SECONDS = 5 * 60;
5298
+ const DEFAULT_LIVE_PADDING_BACKWARD_SECONDS = 25 * 60;
5241
5299
  var ViewUtils;
5242
5300
  (function (ViewUtils) {
5243
5301
  function GatherLegacyMapTiles(params) {
@@ -5460,7 +5518,10 @@ var ViewUtils;
5460
5518
  currentTimeIso: clock.currentTime.toString(),
5461
5519
  stopTime: clock.stopTime,
5462
5520
  stopTimeIso: clock.stopTime.toString(),
5463
- areCesiumValues: clock[CESIUM_TIMELINE_KEY] != true
5521
+ areCesiumValues: clock[CESIUM_TIMELINE_KEY] != true,
5522
+ isLive: clock[CESIUM_TIMELINE_LIVE_KEY] == true,
5523
+ livePaddingForwardSeconds: clock[CESIUM_TIMELINE_LIVE_PADDING_FORWARD_KEY] || DEFAULT_LIVE_PADDING_FORWARD_SECONDS,
5524
+ livePaddingBackwardSeconds: clock[CESIUM_TIMELINE_LIVE_PADDING_BACKWARD_KEY] || DEFAULT_LIVE_PADDING_BACKWARD_SECONDS
5464
5525
  };
5465
5526
  }
5466
5527
  ViewUtils.GetTimeDetails = GetTimeDetails;
@@ -5518,8 +5579,59 @@ var ViewUtils;
5518
5579
  }
5519
5580
  viewer.scene.requestRender();
5520
5581
  clock[CESIUM_TIMELINE_KEY] = true;
5582
+ clock[CESIUM_TIMELINE_LIVE_KEY] = params.isLive == true;
5583
+ clock[CESIUM_TIMELINE_LIVE_PADDING_FORWARD_KEY] = params.livePaddingSeconds || DEFAULT_LIVE_PADDING_FORWARD_SECONDS;
5584
+ clock[CESIUM_TIMELINE_LIVE_PADDING_BACKWARD_KEY] = params.livePaddingSeconds || DEFAULT_LIVE_PADDING_BACKWARD_SECONDS;
5585
+ if (params.isLive) {
5586
+ startLive(viewer);
5587
+ }
5588
+ else {
5589
+ stopLive(viewer);
5590
+ }
5521
5591
  }
5522
5592
  ViewUtils.SetTimeDetails = SetTimeDetails;
5593
+ function startLive(viewer) {
5594
+ if (viewer[CESIUM_TIMELINE_INTERVAL_KEY]) {
5595
+ // Already live.
5596
+ return;
5597
+ }
5598
+ const doUpdate = () => {
5599
+ if (!viewer || viewer.isDestroyed() || !viewer.scene) {
5600
+ stopLive(viewer);
5601
+ return;
5602
+ }
5603
+ // Get the current settings.
5604
+ const tDetails = GetTimeDetails({ viewer });
5605
+ const clock = viewer.clock;
5606
+ if (clock) {
5607
+ clock.shouldAnimate = true;
5608
+ clock.multiplier = 1;
5609
+ clock.currentTime = JulianDate.now();
5610
+ clock.startTime = JulianDate.addSeconds(clock.currentTime, -tDetails.livePaddingBackwardSeconds, new JulianDate());
5611
+ clock.stopTime = JulianDate.addSeconds(clock.currentTime, tDetails.livePaddingForwardSeconds, new JulianDate());
5612
+ clock.clockRange = ClockRange.UNBOUNDED;
5613
+ }
5614
+ };
5615
+ // We'll start an interval that occasionally updates the Cesium clock to stay in the desired settings.
5616
+ // Since it moves live (1 second per second), we don't have to worry about the ranges being out of date quickly.
5617
+ viewer[CESIUM_TIMELINE_INTERVAL_KEY] = setInterval(() => {
5618
+ doUpdate();
5619
+ }, 800);
5620
+ viewer[CESIUM_TIMELINE_LIVE_KEY] = true;
5621
+ // Initial update.
5622
+ doUpdate();
5623
+ }
5624
+ function stopLive(viewer) {
5625
+ if (!viewer) {
5626
+ return;
5627
+ }
5628
+ let interval = viewer[CESIUM_TIMELINE_INTERVAL_KEY];
5629
+ if (interval) {
5630
+ clearInterval(interval);
5631
+ viewer[CESIUM_TIMELINE_INTERVAL_KEY] = null;
5632
+ }
5633
+ viewer[CESIUM_TIMELINE_LIVE_KEY] = false;
5634
+ }
5523
5635
  })(ViewUtils || (ViewUtils = {}));
5524
5636
 
5525
5637
  const MODEL_MIN_RADIUS = 10;
@@ -17159,7 +17271,7 @@ var TilesetCadRenderManager;
17159
17271
  this.viewerDateTimeChangeRemoval = null;
17160
17272
  // Series of points to help interpolate movement when the timeline changes.
17161
17273
  this.historicPosses = [];
17162
- this.historicPossesLoading = false;
17274
+ this.historicAnimation = null;
17163
17275
  this.historicPossesLoadingProm = null;
17164
17276
  const { viewer, register: visualsManager, getters, item } = params;
17165
17277
  this.viewer = viewer;
@@ -17616,7 +17728,7 @@ var TilesetCadRenderManager;
17616
17728
  /**
17617
17729
  * Monitors the Cesium Viewer and updates the root Entity based on the scene time changing.
17618
17730
  * If the root Entity is historic, this can allow for movement of the assembly as a whole.
17619
- * @parma tileset
17731
+ * @param tileset
17620
17732
  */
17621
17733
  viewerDateTimeSub(tileset) {
17622
17734
  var _a, _b;
@@ -17630,60 +17742,172 @@ var TilesetCadRenderManager;
17630
17742
  const api = this.getters.GetBruceApi({
17631
17743
  accountId: accountId
17632
17744
  });
17633
- // Returns a series of positions to use for position interpolation based on time.
17634
- // If the timeline range is different to the previous query, we'll re-request the data.
17635
- const getSeriesPosses = async () => {
17745
+ // 'start-stop' time string that maps to a pending request.
17746
+ // Helps us avoid repeated requests that are the same.
17747
+ const pendingRequests = new Map();
17748
+ /**
17749
+ * Returns a list of historic positions for a given time range.
17750
+ * @param startStr
17751
+ * @param stopStr
17752
+ * @returns
17753
+ */
17754
+ const getPossesForRange = async (startStr, stopStr) => {
17755
+ const requestKey = `${startStr}-${stopStr}`;
17756
+ if (pendingRequests.has(requestKey)) {
17757
+ return pendingRequests.get(requestKey);
17758
+ }
17759
+ const requestPromise = new Promise(async (res) => {
17760
+ try {
17761
+ const historicData = await EntityHistoricData.GetList({
17762
+ attrKey: null,
17763
+ dateTimeFrom: startStr,
17764
+ dateTimeTo: stopStr,
17765
+ entityIds: [this.rootId],
17766
+ api: api
17767
+ });
17768
+ const posses = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(this.viewer, HeightReference.NONE, historicData.recordsByIds[this.rootId]);
17769
+ res(posses);
17770
+ }
17771
+ catch (e) {
17772
+ console.error(e);
17773
+ res([]);
17774
+ }
17775
+ finally {
17776
+ pendingRequests.delete(requestKey);
17777
+ }
17778
+ });
17779
+ pendingRequests.set(requestKey, requestPromise);
17780
+ return requestPromise;
17781
+ };
17782
+ /**
17783
+ * Checks if the current timeline range is not fully loaded and requests the difference.
17784
+ * This will call getPossesForRange() if it needs more data.
17785
+ * @returns
17786
+ */
17787
+ const checkTimelineRange = async () => {
17636
17788
  const minDateTime = this.viewer.clock.startTime.toString();
17637
17789
  const maxDateTime = this.viewer.clock.stopTime.toString();
17638
- if (this.historicPossesMinDateTime == minDateTime &&
17639
- this.historicPossesMaxDateTime == maxDateTime) {
17640
- if (this.historicPossesLoading) {
17641
- if (!await this.historicPossesLoadingProm) {
17642
- return false;
17643
- }
17644
- }
17645
- return this.historicPosses;
17790
+ // See if the current range is within the range we already have.
17791
+ if (this.historicPosses.length > 0 &&
17792
+ this.historicPossesMinDateTime &&
17793
+ this.historicPossesMaxDateTime &&
17794
+ minDateTime >= this.historicPossesMinDateTime &&
17795
+ maxDateTime <= this.historicPossesMaxDateTime) {
17796
+ return;
17646
17797
  }
17647
- this.historicPossesMinDateTime = minDateTime;
17648
- this.historicPossesMaxDateTime = maxDateTime;
17649
- this.historicPossesLoading = true;
17650
- this.historicPossesLoadingProm = new Promise(async (res) => {
17651
- // We'll add/remove 1 second to ensure we cover all records.
17798
+ // See if the requested range is before or after the range we have.
17799
+ const fetchBefore = !this.historicPossesMinDateTime || minDateTime < this.historicPossesMinDateTime;
17800
+ const fetchAfter = !this.historicPossesMaxDateTime || maxDateTime > this.historicPossesMaxDateTime;
17801
+ if (!fetchBefore && !fetchAfter) {
17802
+ // Already have the data we need.
17803
+ return;
17804
+ }
17805
+ // No known range so we need to fetch the whole thing.
17806
+ if (!this.historicPossesMinDateTime || !this.historicPossesMaxDateTime) {
17652
17807
  const startTmp = JulianDate.toDate(this.viewer.clock.startTime);
17653
17808
  const stopTmp = JulianDate.toDate(this.viewer.clock.stopTime);
17654
17809
  const startStr = new Date(startTmp.getTime() - 1000).toISOString();
17655
17810
  const stopStr = new Date(stopTmp.getTime() + 1000).toISOString();
17656
- const historicData = await EntityHistoricData.GetList({
17657
- attrKey: null,
17658
- dateTimeFrom: startStr,
17659
- dateTimeTo: stopStr,
17660
- entityIds: [this.rootId],
17661
- api: api
17662
- });
17663
- const posses = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(this.viewer, HeightReference.NONE, historicData.recordsByIds[this.rootId]);
17664
- if (this.historicPossesMinDateTime == minDateTime &&
17665
- this.historicPossesMaxDateTime == maxDateTime) {
17666
- this.historicPosses = posses;
17811
+ const newPositions = await getPossesForRange(startStr, stopStr);
17812
+ if (this.disposed) {
17813
+ return;
17814
+ }
17815
+ if (this.historicAnimation && this.historicAnimation.addPositions) {
17816
+ this.historicAnimation.addPositions(newPositions);
17817
+ }
17818
+ this.historicPossesMinDateTime = minDateTime;
17819
+ this.historicPossesMaxDateTime = maxDateTime;
17820
+ }
17821
+ else {
17822
+ // The data we want is before the range we've currently loaded.
17823
+ if (fetchBefore) {
17824
+ // Calculate the missing difference and request it.
17825
+ const startTmp = JulianDate.toDate(this.viewer.clock.startTime);
17826
+ const stopTmp = new Date(this.historicPossesMinDateTime);
17827
+ const startStr = new Date(startTmp.getTime() - 1000).toISOString();
17828
+ const stopStr = stopTmp.toISOString();
17829
+ getPossesForRange(startStr, stopStr).then(newPositions => {
17830
+ if (this.disposed) {
17831
+ return;
17832
+ }
17833
+ this.historicPossesMinDateTime = minDateTime;
17834
+ if (this.historicAnimation && this.historicAnimation.addPositions) {
17835
+ this.historicAnimation.addPositions(newPositions);
17836
+ }
17837
+ });
17838
+ }
17839
+ // The data we want is after the range we've currently loaded.
17840
+ if (fetchAfter) {
17841
+ // Calculate the missing difference and request it.
17842
+ const startTmp = new Date(this.historicPossesMaxDateTime);
17843
+ const stopTmp = JulianDate.toDate(this.viewer.clock.stopTime);
17844
+ const startStr = startTmp.toISOString();
17845
+ const stopStr = new Date(stopTmp.getTime() + 1000).toISOString();
17846
+ getPossesForRange(startStr, stopStr).then(newPositions => {
17847
+ if (this.disposed) {
17848
+ return;
17849
+ }
17850
+ this.historicPossesMaxDateTime = maxDateTime;
17851
+ if (this.historicAnimation && this.historicAnimation.addPositions) {
17852
+ this.historicAnimation.addPositions(newPositions);
17853
+ }
17854
+ });
17855
+ }
17856
+ }
17857
+ };
17858
+ /**
17859
+ * Requests the initial set of historic positions for the timeline range.
17860
+ * This is called when the tileset is loaded and the timeline range is set.
17861
+ * @returns
17862
+ */
17863
+ const getInitialPosses = async () => {
17864
+ const minDateTime = this.viewer.clock.startTime.toString();
17865
+ const maxDateTime = this.viewer.clock.stopTime.toString();
17866
+ this.historicPossesLoadingProm = new Promise(async (res) => {
17867
+ try {
17868
+ if (this.disposed) {
17869
+ res(false);
17870
+ return;
17871
+ }
17872
+ const startTmp = JulianDate.toDate(this.viewer.clock.startTime);
17873
+ const stopTmp = JulianDate.toDate(this.viewer.clock.stopTime);
17874
+ const startStr = new Date(startTmp.getTime() - 1000).toISOString();
17875
+ const stopStr = new Date(stopTmp.getTime() + 1000).toISOString();
17876
+ const positions = await getPossesForRange(startStr, stopStr);
17877
+ if (this.disposed) {
17878
+ res(false);
17879
+ return;
17880
+ }
17881
+ this.historicPosses = positions;
17667
17882
  this.historicPossesMinDateTime = minDateTime;
17668
17883
  this.historicPossesMaxDateTime = maxDateTime;
17669
- this.historicPossesLoading = false;
17670
- res(posses);
17884
+ res(positions);
17885
+ }
17886
+ catch (e) {
17887
+ console.error(e);
17888
+ res(false);
17671
17889
  }
17672
- res(false);
17673
17890
  });
17674
17891
  return await this.historicPossesLoadingProm;
17675
17892
  };
17676
- getSeriesPosses().then((posses) => {
17893
+ // Last known timeline range. Helps us detect changes.
17894
+ let lastStartTime = this.viewer.clock.startTime.toString();
17895
+ let lastStopTime = this.viewer.clock.stopTime.toString();
17896
+ let clockTickRemoval;
17897
+ getInitialPosses().then((posses) => {
17677
17898
  if (this.disposed || posses === false) {
17678
17899
  return;
17679
17900
  }
17680
- let animation = new CesiumAnimatedProperty.AnimateTPositionSeries({
17901
+ // Generate animation utility for the initial set of positions.
17902
+ this.historicAnimation = new CesiumAnimatedProperty.AnimateTPositionSeries({
17681
17903
  viewer: this.viewer,
17682
17904
  posses: posses,
17683
17905
  onUpdate: (pos3d, heading) => {
17684
17906
  if (this.disposed) {
17685
17907
  return;
17686
17908
  }
17909
+ // Jank code that hacks the position to be different.
17910
+ // This can mess up our panels so we'll need to disable editing until a better system is in place.
17687
17911
  const location = Cartographic.fromCartesian(pos3d);
17688
17912
  const lat = Math$1.toDegrees(location.latitude);
17689
17913
  const lon = Math$1.toDegrees(location.longitude);
@@ -17710,12 +17934,35 @@ var TilesetCadRenderManager;
17710
17934
  }
17711
17935
  };
17712
17936
  this.applyCoords(tileset, coords);
17937
+ },
17938
+ onRangeChange: () => {
17939
+ checkTimelineRange();
17940
+ },
17941
+ onDone: () => {
17942
+ if (this.viewerDateTimeChangeRemoval) {
17943
+ this.viewerDateTimeChangeRemoval();
17944
+ this.viewerDateTimeChangeRemoval = null;
17945
+ }
17946
+ }
17947
+ });
17948
+ // When the clock changes we'll see if the range is different and queue a request for the difference.
17949
+ clockTickRemoval = this.viewer.clock.onTick.addEventListener(() => {
17950
+ const startTime = this.viewer.clock.startTime.toString();
17951
+ const stopTime = this.viewer.clock.stopTime.toString();
17952
+ if (startTime !== lastStartTime || stopTime !== lastStopTime) {
17953
+ lastStartTime = startTime;
17954
+ lastStopTime = stopTime;
17955
+ this.historicAnimation.onRangeChange();
17713
17956
  }
17714
17957
  });
17715
17958
  this.viewerDateTimeChangeRemoval = () => {
17716
- if (animation) {
17717
- animation.stop();
17718
- animation = null;
17959
+ if (this.historicAnimation) {
17960
+ this.historicAnimation.stop();
17961
+ this.historicAnimation = null;
17962
+ }
17963
+ if (clockTickRemoval) {
17964
+ clockTickRemoval();
17965
+ clockTickRemoval = null;
17719
17966
  }
17720
17967
  };
17721
17968
  });
@@ -24676,7 +24923,8 @@ async function renderNavigator(iteration, params, bookmark, view, getters) {
24676
24923
  end: null,
24677
24924
  playing: false,
24678
24925
  speed: 1,
24679
- start: null
24926
+ start: null,
24927
+ live: false
24680
24928
  };
24681
24929
  }
24682
24930
  ViewUtils.SetTimeDetails({
@@ -24685,7 +24933,8 @@ async function renderNavigator(iteration, params, bookmark, view, getters) {
24685
24933
  currentTimeIso: dateTime,
24686
24934
  startTimeIso: timeline.start,
24687
24935
  stopTimeIso: timeline.end,
24688
- isAnimating: timeline.playing
24936
+ isAnimating: timeline.playing,
24937
+ isLive: timeline.live
24689
24938
  });
24690
24939
  // Newer version that has states per Entity ID + Menu Item ID.
24691
24940
  let states = bSettings === null || bSettings === void 0 ? void 0 : bSettings.states;
@@ -30501,7 +30750,7 @@ class WidgetViewBar extends Widget.AWidget {
30501
30750
  }
30502
30751
  }
30503
30752
 
30504
- const VERSION = "5.4.0";
30753
+ const VERSION = "5.4.1";
30505
30754
 
30506
- export { VERSION, CesiumViewMonitor, ViewerUtils, ViewerEventTracker, MenuItemManager, isHistoricMetadataChanged, EntityRenderEngine, EntityRenderEnginePoint, EntityRenderEnginePolyline, EntityRenderEnginePolygon, EntityRenderEngineModel3d, MenuItemCreator, VisualsRegister, RenderManager, EntitiesIdsRenderManager, DataLabRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, TilesetCadRenderManager, TilesetArbRenderManager, TilesetEntitiesRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TilesetGooglePhotosRenderManager, DataSourceStaticKmlManager, GoogleSearchRenderManager, RelationsRenderManager, SharedGetters, CesiumParabola, EntityLabel, ViewRenderEngine, TileRenderEngine, TilesetRenderEngine, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, ViewUtils, DrawingUtils, MeasureUtils, EntityUtils, CesiumEntityStyler, CesiumAnimatedProperty, CesiumAnimatedInOut, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar, WidgetControlViewBar, WidgetControlViewBarSearch, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks };
30755
+ export { VERSION, CesiumViewMonitor, ViewerUtils, ViewerEventTracker, MenuItemManager, isHistoricMetadataChanged, EntityRenderEngine, EntityRenderEnginePoint, EntityRenderEnginePolyline, EntityRenderEnginePolygon, EntityRenderEngineModel3d, MenuItemCreator, VisualsRegister, RenderManager, EntitiesIdsRenderManager, DataLabRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, TilesetCadRenderManager, TilesetArbRenderManager, TilesetEntitiesRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TilesetGooglePhotosRenderManager, DataSourceStaticKmlManager, GoogleSearchRenderManager, RelationsRenderManager, SharedGetters, CesiumParabola, EntityLabel, ViewRenderEngine, TileRenderEngine, TilesetRenderEngine, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_FORWARD_KEY, CESIUM_TIMELINE_LIVE_PADDING_BACKWARD_KEY, CESIUM_TIMELINE_INTERVAL_KEY, ViewUtils, DrawingUtils, MeasureUtils, EntityUtils, CesiumEntityStyler, CesiumAnimatedProperty, CesiumAnimatedInOut, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar, WidgetControlViewBar, WidgetControlViewBarSearch, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks };
30507
30756
  //# sourceMappingURL=bruce-cesium.es5.js.map