bruce-cesium 5.9.7 → 5.9.8

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, ProjectViewTile, Carto, Geometry, MathUtils, LRUCache, Api, Calculator, ClientFile, EntityTag, EntityType, ObjectUtils, Style, 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';
1
+ import { BruceEvent, Cartes, Entity as Entity$1, ProjectViewTile, Carto, Geometry, MathUtils, LRUCache, Api, Calculator, ClientFile, EntityTag, EntityType, ObjectUtils, Style, DelayQueue, EntityLod, Bounds, ZoomControl, EntityRelationType, ENVIRONMENT, EntityHistoricData, Tileset, EntityCoords, DataLab, EntitySource, MenuItem, EntityRelation, ProgramKey, ProjectView, ProjectViewBookmark, ProjectViewLegacyTile, Camera, Session, EntityAttachment, EntityAttachmentType, EntityAttribute, AbstractApi } 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, HorizontalOrigin, VerticalOrigin, ColorBlendMode, HeadingPitchRoll, Transforms, Model, PolygonHierarchy, PolylineGraphics, ColorMaterialProperty, Primitive, Cesium3DTileFeature, SceneMode, GeoJsonDataSource, Cesium3DTileStyle, HeadingPitchRange, Cesium3DTileColorBlendMode, Ion, KmlDataSource, Quaternion, Matrix3, Matrix4, OrthographicFrustum, EasingFunction, NearFarScalar, SceneTransforms, Cesium3DTileset, IonResource, EllipsoidTerrainProvider, CesiumInspector, defined, ClockRange, EllipsoidGeodesic, sampleTerrainMostDetailed, PolygonPipeline, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, ScreenSpaceEventHandler, ScreenSpaceEventType, BoundingSphere, GeometryInstance, CzmlDataSource, Intersect, Fullscreen } from 'cesium';
3
+ import { Cartographic, Cartesian2, Math as Math$1, Cartesian3, CallbackProperty, Color, HeightReference, Rectangle, Entity, DistanceDisplayCondition, ClassificationType, ArcType, CornerType, ShadowMode, ConstantProperty, ConstantPositionProperty, JulianDate, HorizontalOrigin, VerticalOrigin, PolygonHierarchy, PolylineGraphics, ColorMaterialProperty, ColorBlendMode, HeadingPitchRoll, Transforms, Model, Primitive, Cesium3DTileFeature, SceneMode, GeoJsonDataSource, HeadingPitchRange, Ion, Cesium3DTileStyle, Cesium3DTileColorBlendMode, KmlDataSource, Quaternion, Matrix3, Matrix4, SceneTransforms, EllipsoidTerrainProvider, CesiumInspector, OrthographicFrustum, defined, ClockRange, EllipsoidGeodesic, sampleTerrainMostDetailed, Cesium3DTileset, PolygonPipeline, IonResource, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, EasingFunction, NearFarScalar, ScreenSpaceEventHandler, ScreenSpaceEventType, BoundingSphere, GeometryInstance, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CzmlDataSource, Intersect, Fullscreen } from 'cesium';
4
4
 
5
5
  const TIME_LAG = 300;
6
6
  const POSITION_CHECK_TIMER = 950;
@@ -1144,19 +1144,18 @@ var CesiumAnimatedProperty;
1144
1144
  */
1145
1145
  class AnimatePositionSeries {
1146
1146
  constructor(params) {
1147
- // Animation state.
1148
- this.currentAnimatedPos = null;
1149
- this.actualTargetPos = null;
1150
- this.animationStartPos = null;
1151
- this.animationStartTime = null;
1152
- this.animationDuration = 350;
1153
- // Cached data for performance.
1147
+ this.currentPos = null;
1148
+ this.currentVelocity = new Cartesian3(0, 0, 0);
1149
+ this.smoothingFactor = 0.5;
1150
+ this.positionHistory = [];
1151
+ this.maxHistorySize = 10;
1152
+ this.averageSpeed = 0;
1153
+ this.averageTimeInterval = 0;
1154
+ this.lastUpdateTime = null;
1154
1155
  this.lastDesiredPosIndex = -1;
1155
1156
  this.lastDesiredNextIndex = -1;
1156
- // Series data for rendering path
1157
1157
  this.lastCalcSeriesPos3d = [];
1158
1158
  this.lastCalcSeriesTime = null;
1159
- // Orientation cache.
1160
1159
  this.lastCalcOrient = null;
1161
1160
  this.lastCalcOrientTime = null;
1162
1161
  this.viewer = params.viewer;
@@ -1165,25 +1164,23 @@ var CesiumAnimatedProperty;
1165
1164
  this.roll = params.roll || 0;
1166
1165
  this.processHeadings();
1167
1166
  this.sortPositions();
1168
- // Initialize animation from starting position if provided.
1169
- if (params.animateFromPos3d) {
1170
- this.animationStartPos = params.animateFromPos3d;
1171
- const currentTime = Date.now();
1172
- const providedTime = params.animateFromPos3dTimeStart || 0;
1173
- // Check if the provided timestamp is stale.
1174
- if (!providedTime || (currentTime - providedTime) >= this.animationDuration) {
1175
- this.animationStartTime = currentTime;
1176
- }
1177
- else {
1178
- this.animationStartTime = providedTime;
1179
- }
1180
- }
1181
1167
  }
1182
1168
  AddPosition(pos) {
1183
1169
  if (!pos || !pos.pos3d || !pos.dateTime) {
1184
1170
  console.warn("Invalid position provided to AnimatePositionSeries.");
1185
1171
  return;
1186
1172
  }
1173
+ const now = Date.now();
1174
+ const posTime = pos.dateTime.getTime();
1175
+ this.positionHistory.push({
1176
+ pos: pos.pos3d.clone(),
1177
+ time: posTime,
1178
+ realTime: now
1179
+ });
1180
+ if (this.positionHistory.length > this.maxHistorySize) {
1181
+ this.positionHistory.shift();
1182
+ }
1183
+ this.analyzeMovementPatterns();
1187
1184
  this.positions.push(pos);
1188
1185
  this.processHeadings();
1189
1186
  this.sortPositions();
@@ -1194,12 +1191,70 @@ var CesiumAnimatedProperty;
1194
1191
  this.roll = roll;
1195
1192
  this.invalidateCache();
1196
1193
  }
1197
- GetAnimateFromDateTime() {
1198
- return this.animationStartTime;
1199
- }
1200
1194
  GetPositions() {
1201
1195
  return this.positions;
1202
1196
  }
1197
+ analyzeMovementPatterns() {
1198
+ if (this.positionHistory.length < 2) {
1199
+ return;
1200
+ }
1201
+ let totalDistance = 0;
1202
+ let totalTimeSpan = 0;
1203
+ let totalRealTimeSpan = 0;
1204
+ let validSegments = 0;
1205
+ for (let i = 1; i < this.positionHistory.length; i++) {
1206
+ const prev = this.positionHistory[i - 1];
1207
+ const curr = this.positionHistory[i];
1208
+ const distance = Cartesian3.distance(prev.pos, curr.pos);
1209
+ const timeSpan = Math.abs(curr.time - prev.time) / 1000.0;
1210
+ const realTimeSpan = Math.abs(curr.realTime - prev.realTime) / 1000.0;
1211
+ if (distance > 0.1 && timeSpan > 0.01) {
1212
+ totalDistance += distance;
1213
+ totalTimeSpan += timeSpan;
1214
+ totalRealTimeSpan += realTimeSpan;
1215
+ validSegments++;
1216
+ }
1217
+ }
1218
+ if (validSegments > 0) {
1219
+ this.averageSpeed = totalDistance / totalTimeSpan;
1220
+ this.averageTimeInterval = totalRealTimeSpan / validSegments;
1221
+ this.averageSpeed = Math.max(0.1, Math.min(this.averageSpeed, 1000));
1222
+ this.averageTimeInterval = Math.max(0.01, Math.min(this.averageTimeInterval, 10));
1223
+ }
1224
+ }
1225
+ calculateExpectedPosition(viewerTimeMs) {
1226
+ const desired = this.calculateDesiredPosition(viewerTimeMs);
1227
+ if (!desired.position) {
1228
+ return { position: null, timeDelta: 0 };
1229
+ }
1230
+ let timeDelta = 0;
1231
+ if (this.positionHistory.length >= 2) {
1232
+ // Calculate how far behind we are based on viewer time vs real time.
1233
+ const now = Date.now();
1234
+ const timeDiffFromNow = (viewerTimeMs - now) / 1000.0;
1235
+ // Negative means we're behind, positive means ahead.
1236
+ timeDelta = timeDiffFromNow;
1237
+ }
1238
+ return { position: desired.position, timeDelta };
1239
+ }
1240
+ calculateAutonomousSpeed(distanceToTarget, timeDelta) {
1241
+ let baseSpeed = this.averageSpeed || 50;
1242
+ let speedMultiplier = 1.0;
1243
+ // Calculate speed multiplier based on distance and time lag.
1244
+ if (distanceToTarget > 50) {
1245
+ speedMultiplier *= Math.min(100.0, distanceToTarget / 10.0);
1246
+ }
1247
+ else if (distanceToTarget > 10) {
1248
+ const distanceMultiplier = Math.min(20.0, 1.0 + (distanceToTarget / 5.0));
1249
+ speedMultiplier *= distanceMultiplier;
1250
+ }
1251
+ else if (Math.abs(timeDelta) > 0.1) {
1252
+ const timeLagMultiplier = Math.max(0.1, 1.0 - (timeDelta * 5.0));
1253
+ speedMultiplier *= Math.min(50.0, timeLagMultiplier);
1254
+ }
1255
+ // Minimum 10% speed.
1256
+ return Math.max(baseSpeed * 0.1, baseSpeed * speedMultiplier);
1257
+ }
1203
1258
  sortPositions() {
1204
1259
  if (this.positions.length > 0) {
1205
1260
  this.positions.sort((a, b) => a.dateTime.getTime() - b.dateTime.getTime());
@@ -1209,10 +1264,6 @@ var CesiumAnimatedProperty;
1209
1264
  this.lastCalcSeriesTime = null;
1210
1265
  this.lastCalcOrientTime = null;
1211
1266
  }
1212
- /**
1213
- * Pre-process headings in the series.
1214
- * If all are null or 0, then we assume all are null.
1215
- */
1216
1267
  processHeadings() {
1217
1268
  if (!this.positions || this.positions.length === 0) {
1218
1269
  return;
@@ -1234,15 +1285,10 @@ var CesiumAnimatedProperty;
1234
1285
  easeInOutQuad(t) {
1235
1286
  return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
1236
1287
  }
1237
- /**
1238
- * Calculate the desired position based on current time without any animation smoothing.
1239
- */
1240
1288
  calculateDesiredPosition(timeMs) {
1241
- // No positions available.
1242
1289
  if (!this.positions || this.positions.length === 0) {
1243
1290
  return { position: null, lastIndex: -1, nextIndex: -1 };
1244
1291
  }
1245
- // Only one position..
1246
1292
  if (this.positions.length === 1) {
1247
1293
  return {
1248
1294
  position: this.positions[0].pos3d || null,
@@ -1250,7 +1296,6 @@ var CesiumAnimatedProperty;
1250
1296
  nextIndex: 0
1251
1297
  };
1252
1298
  }
1253
- // Before first position - use first two positions for orientation.
1254
1299
  if (timeMs <= this.positions[0].dateTime.getTime()) {
1255
1300
  return {
1256
1301
  position: this.positions[0].pos3d || null,
@@ -1258,7 +1303,6 @@ var CesiumAnimatedProperty;
1258
1303
  nextIndex: Math.min(1, this.positions.length - 1)
1259
1304
  };
1260
1305
  }
1261
- // After last position - use last two positions for orientation.
1262
1306
  const lastIdx = this.positions.length - 1;
1263
1307
  if (timeMs >= this.positions[lastIdx].dateTime.getTime()) {
1264
1308
  return {
@@ -1267,12 +1311,10 @@ var CesiumAnimatedProperty;
1267
1311
  nextIndex: lastIdx
1268
1312
  };
1269
1313
  }
1270
- // Find positions to interpolate between.
1271
1314
  for (let i = 0; i < this.positions.length - 1; i++) {
1272
1315
  const current = this.positions[i];
1273
1316
  const next = this.positions[i + 1];
1274
1317
  if (timeMs >= current.dateTime.getTime() && timeMs < next.dateTime.getTime()) {
1275
- // Exact match on current position - still use current and next for orientation.
1276
1318
  if (timeMs === current.dateTime.getTime()) {
1277
1319
  return {
1278
1320
  position: current.pos3d || null,
@@ -1280,7 +1322,6 @@ var CesiumAnimatedProperty;
1280
1322
  nextIndex: i + 1
1281
1323
  };
1282
1324
  }
1283
- // Interpolate between current and next.
1284
1325
  if (!current.pos3d || !next.pos3d) {
1285
1326
  return {
1286
1327
  position: current.pos3d || next.pos3d || null,
@@ -1307,16 +1348,12 @@ var CesiumAnimatedProperty;
1307
1348
  }
1308
1349
  }
1309
1350
  }
1310
- // Fallback to last position with previous position for orientation.
1311
1351
  return {
1312
1352
  position: this.positions[lastIdx].pos3d || null,
1313
1353
  lastIndex: Math.max(0, lastIdx - 1),
1314
1354
  nextIndex: lastIdx
1315
1355
  };
1316
1356
  }
1317
- /**
1318
- * Main method to get the current position based on time.
1319
- */
1320
1357
  GetValue() {
1321
1358
  let viewerTime = this.viewer.scene.lastRenderTime;
1322
1359
  if (!viewerTime) {
@@ -1324,88 +1361,46 @@ var CesiumAnimatedProperty;
1324
1361
  }
1325
1362
  const viewerTimeMs = JulianDate.toDate(viewerTime).getTime();
1326
1363
  const currentRealTimeMs = Date.now();
1327
- // Calculate the desired position based on time.
1328
- const desired = this.calculateDesiredPosition(viewerTimeMs);
1329
- if (!desired.position) {
1330
- this.currentAnimatedPos = null;
1331
- this.actualTargetPos = null;
1364
+ const expected = this.calculateExpectedPosition(viewerTimeMs);
1365
+ if (!expected.position) {
1366
+ this.currentPos = null;
1367
+ this.currentVelocity = new Cartesian3(0, 0, 0);
1332
1368
  return new Cartesian3();
1333
1369
  }
1370
+ const desired = this.calculateDesiredPosition(viewerTimeMs);
1334
1371
  this.lastDesiredPosIndex = desired.lastIndex;
1335
1372
  this.lastDesiredNextIndex = desired.nextIndex;
1336
- // Determine the desired position without interpolation.
1337
- let discreteTarget;
1338
- if (desired.lastIndex === desired.nextIndex) {
1339
- discreteTarget = this.positions[desired.lastIndex].pos3d;
1340
- }
1341
- // Use the next position as the target.
1342
- else {
1343
- discreteTarget = this.positions[desired.nextIndex].pos3d;
1344
- }
1345
- // Check if we have a new actual target
1346
- const actualTargetChanged = !this.actualTargetPos || !Cartesian3.equals(this.actualTargetPos, discreteTarget);
1347
- // First time or no previous position - start here.
1348
- if (!this.currentAnimatedPos) {
1349
- if (this.animationStartPos) {
1350
- this.actualTargetPos = discreteTarget;
1351
- const progress = this.getAnimationProgress(currentRealTimeMs, this.animationStartTime);
1352
- // Animation from start position complete.
1353
- if (progress >= 1.0) {
1354
- this.currentAnimatedPos = desired.position;
1355
- this.animationStartPos = null;
1356
- this.animationStartTime = null;
1357
- return desired.position;
1358
- }
1359
- // Still animating from initial position.
1360
- else {
1361
- const easedProgress = this.easeInOutQuad(progress);
1362
- this.currentAnimatedPos = Cartesian3.lerp(this.animationStartPos, desired.position, easedProgress, new Cartesian3());
1363
- return this.currentAnimatedPos;
1364
- }
1365
- }
1366
- // No initial animation needed.
1367
- else {
1368
- this.currentAnimatedPos = desired.position;
1369
- this.actualTargetPos = discreteTarget;
1370
- return desired.position;
1371
- }
1372
- }
1373
- // Target changed.
1374
- if (actualTargetChanged) {
1375
- this.animationStartPos = this.currentAnimatedPos;
1376
- this.animationStartTime = currentRealTimeMs;
1377
- this.actualTargetPos = discreteTarget;
1378
- }
1379
- // Continue or start animation to target if we have an active animation.
1380
- if (this.animationStartPos && this.animationStartTime) {
1381
- const progress = this.getAnimationProgress(currentRealTimeMs, this.animationStartTime);
1382
- // Animation complete.
1383
- if (progress >= 1.0) {
1384
- this.currentAnimatedPos = desired.position;
1385
- this.animationStartPos = null;
1386
- this.animationStartTime = null;
1387
- return desired.position;
1388
- }
1389
- // Continue animation to interpolated position.
1390
- else {
1391
- const easedProgress = this.easeInOutQuad(progress);
1392
- this.currentAnimatedPos = Cartesian3.lerp(this.animationStartPos, desired.position, easedProgress, new Cartesian3());
1393
- return this.currentAnimatedPos;
1394
- }
1395
- }
1396
- // No active animation - follow interpolated path directly.
1397
- this.currentAnimatedPos = desired.position;
1398
- return desired.position;
1373
+ if (!this.currentPos) {
1374
+ this.currentPos = expected.position.clone();
1375
+ this.currentVelocity = new Cartesian3(0, 0, 0);
1376
+ this.lastUpdateTime = currentRealTimeMs;
1377
+ return this.currentPos;
1378
+ }
1379
+ const deltaTime = this.lastUpdateTime ? (currentRealTimeMs - this.lastUpdateTime) / 1000.0 : 0.016;
1380
+ this.lastUpdateTime = currentRealTimeMs;
1381
+ const clampedDeltaTime = Math.min(deltaTime, 0.1);
1382
+ const targetDistance = Cartesian3.distance(this.currentPos, expected.position);
1383
+ if (targetDistance < 0.5) {
1384
+ this.currentPos = expected.position.clone();
1385
+ this.currentVelocity = new Cartesian3(0, 0, 0);
1386
+ return this.currentPos;
1387
+ }
1388
+ // Check if we're really far behind and need to teleport.
1389
+ if (targetDistance > 500) {
1390
+ this.currentPos = expected.position.clone();
1391
+ this.currentVelocity = new Cartesian3(0, 0, 0);
1392
+ return this.currentPos;
1393
+ }
1394
+ const direction = Cartesian3.subtract(expected.position, this.currentPos, new Cartesian3());
1395
+ Cartesian3.normalize(direction, direction);
1396
+ const targetSpeed = this.calculateAutonomousSpeed(targetDistance, expected.timeDelta);
1397
+ const targetVelocity = Cartesian3.multiplyByScalar(direction, targetSpeed, new Cartesian3());
1398
+ this.currentVelocity = Cartesian3.lerp(this.currentVelocity, targetVelocity, this.smoothingFactor, new Cartesian3());
1399
+ const velocityDelta = Cartesian3.multiplyByScalar(this.currentVelocity, clampedDeltaTime, new Cartesian3());
1400
+ this.currentPos = Cartesian3.add(this.currentPos, velocityDelta, new Cartesian3());
1401
+ return this.currentPos;
1399
1402
  }
1400
- getAnimationProgress(currentTime, startTime) {
1401
- const elapsed = currentTime - startTime;
1402
- return Math.min(elapsed / this.animationDuration, 1.0);
1403
- }
1404
- /**
1405
- * Returns a series of positions to use for rendering the path.
1406
- */
1407
1403
  GetSeries() {
1408
- // Update at 30 fps.
1409
1404
  let doUpdate = this.lastCalcSeriesTime == null;
1410
1405
  if (!doUpdate && this.lastCalcSeriesTime && (new Date().getTime() - this.lastCalcSeriesTime) > 1000 / 30) {
1411
1406
  doUpdate = true;
@@ -1413,33 +1408,27 @@ var CesiumAnimatedProperty;
1413
1408
  if (!doUpdate) {
1414
1409
  return this.lastCalcSeriesPos3d;
1415
1410
  }
1416
- // Ensure position indices are up-to-date.
1417
1411
  this.GetValue();
1418
1412
  let now = this.viewer.scene.lastRenderTime;
1419
1413
  if (!now) {
1420
1414
  now = this.viewer.clock.currentTime;
1421
1415
  }
1422
1416
  const nowDate = JulianDate.toDate(now);
1423
- // Get total duration.
1424
1417
  if (!this.positions || this.positions.length < 2) {
1425
1418
  this.lastCalcSeriesTime = nowDate.getTime();
1426
1419
  this.lastCalcSeriesPos3d = [];
1427
1420
  return [];
1428
1421
  }
1429
1422
  const totalDuration = this.positions[this.positions.length - 1].dateTime.getTime() - this.positions[0].dateTime.getTime();
1430
- // Percentage of the polyline to be visible before and after each point.
1431
- const visibilityPercentage = 0.05; // 5%
1423
+ const visibilityPercentage = 0.05;
1432
1424
  const visibilityDuration = totalDuration * visibilityPercentage;
1433
- // Gather positions that fall within the visibility duration.
1434
1425
  const newPosses = [];
1435
1426
  for (let i = 0; i < this.positions.length; i++) {
1436
1427
  const pos = this.positions[i];
1437
1428
  if (!pos.pos3d) {
1438
1429
  continue;
1439
1430
  }
1440
- let add = nowDate >= new Date(pos.dateTime.getTime() - visibilityDuration / 2) &&
1441
- nowDate <= new Date(pos.dateTime.getTime() + visibilityDuration / 2);
1442
- // Also include the segment we're currently traversing.
1431
+ let add = nowDate >= new Date(pos.dateTime.getTime() - visibilityDuration / 2) && nowDate <= new Date(pos.dateTime.getTime() + visibilityDuration / 2);
1443
1432
  if (!add && this.lastDesiredPosIndex > -1 && this.lastDesiredNextIndex > -1) {
1444
1433
  add = i >= this.lastDesiredPosIndex && i <= this.lastDesiredNextIndex;
1445
1434
  }
@@ -1451,11 +1440,7 @@ var CesiumAnimatedProperty;
1451
1440
  this.lastCalcSeriesPos3d = newPosses;
1452
1441
  return newPosses;
1453
1442
  }
1454
- /**
1455
- * Returns the orientation based on current position and heading.
1456
- */
1457
1443
  GetOrient() {
1458
- // Update at 30 fps.
1459
1444
  let doUpdate = this.lastCalcOrientTime == null;
1460
1445
  if (!doUpdate && this.lastCalcOrientTime && (new Date().getTime() - this.lastCalcOrientTime) > 1000 / 30) {
1461
1446
  doUpdate = true;
@@ -1463,26 +1448,34 @@ var CesiumAnimatedProperty;
1463
1448
  if (!doUpdate && this.lastCalcOrient) {
1464
1449
  return this.lastCalcOrient;
1465
1450
  }
1466
- // Default quaternion to return if we can't calculate.
1467
1451
  const defaultQuaternion = new Quaternion();
1468
1452
  if (!this.positions || this.positions.length === 0) {
1469
1453
  return defaultQuaternion;
1470
1454
  }
1471
- // Ensure position is up-to-date.
1472
1455
  const currentPosition = this.GetValue();
1473
1456
  if (!currentPosition) {
1474
1457
  return defaultQuaternion;
1475
1458
  }
1476
- let now = this.viewer.scene.lastRenderTime;
1477
- if (!now) {
1478
- now = this.viewer.clock.currentTime;
1479
- }
1480
- const nowTime = JulianDate.toDate(now).getTime();
1481
1459
  try {
1482
- // Get current position indices.
1460
+ const velocityMagnitude = Cartesian3.magnitude(this.currentVelocity);
1461
+ const minimumSpeedForVelocityOrientation = Math.max(1.0, this.averageSpeed * 0.1);
1462
+ if (velocityMagnitude > minimumSpeedForVelocityOrientation) {
1463
+ const normalizedVelocity = Cartesian3.normalize(this.currentVelocity, new Cartesian3());
1464
+ const rotationMatrix = Transforms.rotationMatrixFromPositionVelocity(currentPosition, normalizedVelocity);
1465
+ const quaternion = Quaternion.fromRotationMatrix(rotationMatrix);
1466
+ const hpr = new HeadingPitchRoll(0, Math$1.toRadians(this.pitch), Math$1.toRadians(this.roll));
1467
+ const pitchRollQuaternion = Quaternion.fromHeadingPitchRoll(hpr);
1468
+ this.lastCalcOrient = Quaternion.multiply(quaternion, pitchRollQuaternion, new Quaternion());
1469
+ this.lastCalcOrientTime = Date.now();
1470
+ return this.lastCalcOrient;
1471
+ }
1472
+ let now = this.viewer.scene.lastRenderTime;
1473
+ if (!now) {
1474
+ now = this.viewer.clock.currentTime;
1475
+ }
1476
+ const nowTime = JulianDate.toDate(now).getTime();
1483
1477
  const lastIndex = this.lastDesiredPosIndex;
1484
1478
  const nextIndex = this.lastDesiredNextIndex;
1485
- // Invalid indices.
1486
1479
  if (lastIndex < 0 || nextIndex < 0 ||
1487
1480
  lastIndex >= this.positions.length || nextIndex >= this.positions.length) {
1488
1481
  return this.lastCalcOrient || defaultQuaternion;
@@ -1492,74 +1485,53 @@ var CesiumAnimatedProperty;
1492
1485
  if (!lastPos || !nextPos) {
1493
1486
  return this.lastCalcOrient || defaultQuaternion;
1494
1487
  }
1495
- // Single position case - use its heading if available.
1496
1488
  if (lastIndex === nextIndex) {
1497
1489
  if (lastPos.heading !== null) {
1498
1490
  this.lastCalcOrient = Transforms.headingPitchRollQuaternion(currentPosition, new HeadingPitchRoll(Math$1.toRadians(lastPos.heading), Math$1.toRadians(this.pitch), Math$1.toRadians(this.roll)));
1499
1491
  this.lastCalcOrientTime = Date.now();
1500
1492
  return this.lastCalcOrient;
1501
1493
  }
1502
- // No heading data and single position, return previous or default.
1503
1494
  return this.lastCalcOrient || defaultQuaternion;
1504
1495
  }
1505
- // Two different positions - we can calculate orientation.
1506
- // Use explicit heading values if available.
1507
1496
  if (lastPos.heading !== null && nextPos.heading !== null) {
1508
- // Calculate interpolated heading.
1509
1497
  let deltaHeading = nextPos.heading - lastPos.heading;
1510
- // Handle wrap-around between 359° and 0°.
1511
1498
  if (deltaHeading > 180) {
1512
1499
  deltaHeading -= 360;
1513
1500
  }
1514
1501
  else if (deltaHeading < -180) {
1515
1502
  deltaHeading += 360;
1516
1503
  }
1517
- // Calculate interpolation factor.
1518
1504
  let factor = 0;
1519
1505
  if (lastPos.dateTime.getTime() !== nextPos.dateTime.getTime()) {
1520
- factor = (nowTime - lastPos.dateTime.getTime()) /
1521
- (nextPos.dateTime.getTime() - lastPos.dateTime.getTime());
1506
+ factor = (nowTime - lastPos.dateTime.getTime()) / (nextPos.dateTime.getTime() - lastPos.dateTime.getTime());
1522
1507
  factor = Math.max(0, Math.min(1, factor));
1523
1508
  }
1524
- // Apply easing for smoother rotation.
1525
1509
  factor = this.easeInOutQuad(factor);
1526
- // Calculate final heading.
1527
1510
  let interpolatedHeading = lastPos.heading + factor * deltaHeading;
1528
1511
  interpolatedHeading = (interpolatedHeading + 360) % 360;
1529
- // Create quaternion from heading, pitch, roll.
1530
1512
  this.lastCalcOrient = Transforms.headingPitchRollQuaternion(currentPosition, new HeadingPitchRoll(Math$1.toRadians(interpolatedHeading), Math$1.toRadians(this.pitch), Math$1.toRadians(this.roll)));
1531
1513
  }
1532
- // Calculate heading from position changes if heading data not available.
1533
1514
  else {
1534
1515
  if (!lastPos.pos3d || !nextPos.pos3d) {
1535
1516
  return this.lastCalcOrient || defaultQuaternion;
1536
1517
  }
1537
- // Flatten positions to avoid altitude-related heading changes.
1538
1518
  const adjustedPointPrev = Cartographic.fromCartesian(lastPos.pos3d);
1539
1519
  const adjustedPos3dPrev = Cartesian3.fromRadians(adjustedPointPrev.longitude, adjustedPointPrev.latitude, 0);
1540
1520
  const adjustedPointNext = Cartographic.fromCartesian(nextPos.pos3d);
1541
1521
  const adjustedPos3dNext = Cartesian3.fromRadians(adjustedPointNext.longitude, adjustedPointNext.latitude, 0);
1542
- // Skip if positions are too close (less than 5cm).
1543
1522
  const distance = Cartesian3.distance(adjustedPos3dPrev, adjustedPos3dNext);
1544
1523
  if (distance < 0.05) {
1545
1524
  return this.lastCalcOrient || defaultQuaternion;
1546
1525
  }
1547
- // Calculate direction vector.
1548
1526
  const direction = Cartesian3.subtract(adjustedPos3dNext, adjustedPos3dPrev, new Cartesian3());
1549
- // Skip if no movement.
1550
1527
  if (direction.x === 0 && direction.y === 0 && direction.z === 0) {
1551
1528
  return this.lastCalcOrient || defaultQuaternion;
1552
1529
  }
1553
- // Normalize the direction vector.
1554
1530
  Cartesian3.normalize(direction, direction);
1555
- // Calculate rotation based on movement direction.
1556
1531
  const rotationMatrix = Transforms.rotationMatrixFromPositionVelocity(currentPosition, direction);
1557
- // Convert to quaternion.
1558
1532
  const quaternion = Quaternion.fromRotationMatrix(rotationMatrix);
1559
- // Add pitch and roll adjustments.
1560
1533
  const hpr = new HeadingPitchRoll(0, Math$1.toRadians(this.pitch), Math$1.toRadians(this.roll));
1561
1534
  const pitchRollQuaternion = Quaternion.fromHeadingPitchRoll(hpr);
1562
- // Combine quaternions.
1563
1535
  this.lastCalcOrient = Quaternion.multiply(quaternion, pitchRollQuaternion, new Quaternion());
1564
1536
  }
1565
1537
  }
@@ -1570,6 +1542,52 @@ var CesiumAnimatedProperty;
1570
1542
  this.lastCalcOrientTime = Date.now();
1571
1543
  return this.lastCalcOrient;
1572
1544
  }
1545
+ GetCurrentVelocity() {
1546
+ return this.currentVelocity ? this.currentVelocity.clone() : new Cartesian3(0, 0, 0);
1547
+ }
1548
+ SupplementSeries(newSeries) {
1549
+ if (!newSeries || newSeries.length === 0) {
1550
+ return;
1551
+ }
1552
+ for (const pos of newSeries) {
1553
+ if (!pos || !pos.pos3d || !pos.dateTime) {
1554
+ continue;
1555
+ }
1556
+ const existingIndex = this.positions.findIndex(p => p.dateTime.getTime() === pos.dateTime.getTime());
1557
+ if (existingIndex >= 0) {
1558
+ this.positions[existingIndex] = pos;
1559
+ }
1560
+ else {
1561
+ this.AddPosition(pos);
1562
+ }
1563
+ }
1564
+ }
1565
+ UpdatePositionForDateTime(pos3d, dateTime, heading) {
1566
+ if (!pos3d || !dateTime) {
1567
+ return;
1568
+ }
1569
+ const existingIndex = this.positions.findIndex(p => p.dateTime.getTime() === dateTime.getTime());
1570
+ const newPos = {
1571
+ pos3d: pos3d,
1572
+ dateTime: dateTime,
1573
+ heading: heading !== undefined ? heading : null
1574
+ };
1575
+ if (existingIndex >= 0) {
1576
+ this.positions[existingIndex] = newPos;
1577
+ this.processHeadings();
1578
+ this.sortPositions();
1579
+ this.invalidateCache();
1580
+ }
1581
+ else {
1582
+ this.AddPosition(newPos);
1583
+ }
1584
+ }
1585
+ HasPositionForDateTime(dateTime) {
1586
+ return this.positions.some(p => p.dateTime.getTime() === dateTime.getTime());
1587
+ }
1588
+ GetPositionCount() {
1589
+ return this.positions.length;
1590
+ }
1573
1591
  }
1574
1592
  CesiumAnimatedProperty.AnimatePositionSeries = AnimatePositionSeries;
1575
1593
  function GetSeriesPossesForHistoricEntity(viewer, dataHeightRef, heightRef, historic) {
@@ -5452,7 +5470,7 @@ var EntityRenderEnginePoint;
5452
5470
  * @returns
5453
5471
  */
5454
5472
  async function Render(params) {
5455
- var _a, _b, _c, _d;
5473
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
5456
5474
  const entity = params.entity;
5457
5475
  if (!params.entityHistoric) {
5458
5476
  params.entityHistoric = [];
@@ -5653,39 +5671,69 @@ var EntityRenderEnginePoint;
5653
5671
  // Unset width/height.
5654
5672
  cEntity.billboard.width = undefined;
5655
5673
  cEntity.billboard.height = undefined;
5674
+ const pos3d = EntityUtils.GetPos({
5675
+ viewer: params.viewer,
5676
+ entity,
5677
+ recordHeightRef: heightRef,
5678
+ returnHeightRef: heightRef,
5679
+ allowRendered: false
5680
+ });
5656
5681
  const prevPos3d = GetCValue(params.viewer, cEntity.position);
5657
- let prevStartTime = null;
5658
5682
  if (cEntity.position && cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"]) {
5659
- prevStartTime = cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"].GetAnimateFromDateTime();
5660
- }
5661
- // If we have a series of time-based positions then we'll animate as time changes.
5662
- const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
5663
- if (series.length > 1) {
5664
- animatePosition = new CesiumAnimatedProperty.AnimatePositionSeries({
5665
- posses: series,
5666
- viewer: params.viewer,
5667
- animateFromPos3d: prevPos3d,
5668
- animateFromPos3dTimeStart: prevStartTime
5669
- });
5670
- cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
5671
- cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
5683
+ animatePosition = cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"];
5684
+ const animateSeries = animatePosition;
5685
+ const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
5686
+ if (series.length) {
5687
+ animateSeries.SupplementSeries(series);
5688
+ }
5689
+ const dateTimeStr = (_d = (_c = entity.Bruce.Outline) === null || _c === void 0 ? void 0 : _c.find(x => !!x.DateTime)) === null || _d === void 0 ? void 0 : _d.DateTime;
5690
+ const dateTime = dateTimeStr ? new Date(dateTimeStr) : null;
5691
+ if (dateTime) {
5692
+ animateSeries.UpdatePositionForDateTime(pos3d, dateTime);
5693
+ }
5694
+ // We don't have a date-stamped incoming position.
5695
+ if (!dateTime && !series.length) {
5696
+ animatePosition = null;
5697
+ }
5672
5698
  }
5673
- else {
5674
- const pos3d = EntityUtils.GetPos({
5675
- viewer: params.viewer,
5676
- entity,
5677
- recordHeightRef: heightRef,
5678
- returnHeightRef: heightRef,
5679
- allowRendered: false
5680
- });
5681
- if (!prevPos3d || !Cartesian3.equals(prevPos3d, pos3d)) {
5682
- animatePosition = new CesiumAnimatedProperty.AnimatePosition({
5683
- durationMs: 200,
5684
- targetPos3d: pos3d,
5685
- viewer: params.viewer,
5686
- startPos3d: prevPos3d
5699
+ if (!animatePosition) {
5700
+ // If we've loaded a set of series positions then we'll animate through them.
5701
+ const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
5702
+ if (series.length > 1) {
5703
+ animatePosition = new CesiumAnimatedProperty.AnimatePositionSeries({
5704
+ posses: series,
5705
+ viewer: params.viewer
5687
5706
  });
5688
5707
  cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
5708
+ cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
5709
+ }
5710
+ else {
5711
+ const dateTimeStr = (_f = (_e = entity.Bruce.Outline) === null || _e === void 0 ? void 0 : _e.find(x => !!x.DateTime)) === null || _f === void 0 ? void 0 : _f.DateTime;
5712
+ const dateTime = dateTimeStr ? new Date(dateTimeStr) : null;
5713
+ const posChanged = !prevPos3d || !Cartesian3.equals(prevPos3d, pos3d);
5714
+ if (posChanged) {
5715
+ let posses = [];
5716
+ const isLive = ViewUtils.GetTimeDetails({ viewer: params.viewer }).isLive;
5717
+ if (prevPos3d && isLive) {
5718
+ posses.push({
5719
+ pos3d: prevPos3d,
5720
+ // Guess so that we can determine a direction of movement right away :)
5721
+ dateTime: new Date(dateTime.getTime() - 1000),
5722
+ heading: null
5723
+ });
5724
+ }
5725
+ posses.push({
5726
+ pos3d: pos3d,
5727
+ dateTime: dateTime,
5728
+ heading: null
5729
+ });
5730
+ animatePosition = new CesiumAnimatedProperty.AnimatePositionSeries({
5731
+ posses: posses,
5732
+ viewer: params.viewer
5733
+ });
5734
+ cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
5735
+ cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
5736
+ }
5689
5737
  }
5690
5738
  }
5691
5739
  // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
@@ -5984,39 +6032,52 @@ var EntityRenderEnginePoint;
5984
6032
  cEntity.billboard.heightReference = new ConstantProperty(heightRef);
5985
6033
  cEntity.billboard.distanceDisplayCondition = new ConstantProperty(EntityRenderEngine.GetDisplayCondition(params.minDistance, params.maxDistance));
5986
6034
  cEntity.billboard.disableDepthTestDistance = new ConstantProperty(disableDepthTest ? Number.POSITIVE_INFINITY : undefined);
6035
+ const pos3d = EntityUtils.GetPos({
6036
+ viewer: params.viewer,
6037
+ entity,
6038
+ recordHeightRef: heightRef,
6039
+ returnHeightRef: heightRef,
6040
+ allowRendered: false
6041
+ });
5987
6042
  const prevPos3d = GetCValue(params.viewer, cEntity.position);
5988
- let prevStartTime = null;
5989
6043
  if (cEntity.position && cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"]) {
5990
- prevStartTime = cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"].GetAnimateFromDateTime();
5991
- }
5992
- // If we have a series of time-based positions then we'll animate as time changes.
5993
- const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
5994
- if (series.length > 1) {
5995
- animatePosition = new CesiumAnimatedProperty.AnimatePositionSeries({
5996
- posses: series,
5997
- viewer: params.viewer,
5998
- animateFromPos3d: prevPos3d,
5999
- animateFromPos3dTimeStart: prevStartTime
6000
- });
6001
- cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
6002
- cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
6003
- }
6004
- else {
6005
- const pos3d = EntityUtils.GetPos({
6006
- viewer: params.viewer,
6007
- entity,
6008
- recordHeightRef: heightRef,
6009
- returnHeightRef: heightRef,
6010
- allowRendered: false
6011
- });
6012
- if (!prevPos3d || !Cartesian3.equals(prevPos3d, pos3d)) {
6013
- animatePosition = new CesiumAnimatedProperty.AnimatePosition({
6014
- durationMs: 200,
6015
- targetPos3d: pos3d,
6016
- viewer: params.viewer,
6017
- startPos3d: prevPos3d
6044
+ animatePosition = cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"];
6045
+ const animateSeries = animatePosition;
6046
+ const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
6047
+ if (series.length) {
6048
+ animateSeries.SupplementSeries(series);
6049
+ }
6050
+ const dateTimeStr = (_h = (_g = entity.Bruce.Outline) === null || _g === void 0 ? void 0 : _g.find(x => !!x.DateTime)) === null || _h === void 0 ? void 0 : _h.DateTime;
6051
+ const dateTime = dateTimeStr ? new Date(dateTimeStr) : null;
6052
+ if (dateTime) {
6053
+ animateSeries.UpdatePositionForDateTime(pos3d, dateTime);
6054
+ }
6055
+ // We don't have a date-stamped incoming position.
6056
+ if (!dateTime && !series.length) {
6057
+ animatePosition = null;
6058
+ }
6059
+ }
6060
+ if (!animatePosition) {
6061
+ // If we have a series of time-based positions then we'll animate as time changes.
6062
+ const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
6063
+ if (series.length > 1) {
6064
+ animatePosition = new CesiumAnimatedProperty.AnimatePositionSeries({
6065
+ posses: series,
6066
+ viewer: params.viewer
6018
6067
  });
6019
6068
  cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
6069
+ cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
6070
+ }
6071
+ else {
6072
+ if (!prevPos3d || !Cartesian3.equals(prevPos3d, pos3d)) {
6073
+ animatePosition = new CesiumAnimatedProperty.AnimatePosition({
6074
+ durationMs: 200,
6075
+ targetPos3d: pos3d,
6076
+ viewer: params.viewer,
6077
+ startPos3d: prevPos3d
6078
+ });
6079
+ cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
6080
+ }
6020
6081
  }
6021
6082
  }
6022
6083
  // We'll use "SetDefaultColor" to updating the internal reference and to allow for an animation.
@@ -6035,7 +6096,7 @@ var EntityRenderEnginePoint;
6035
6096
  // Generate a polyline 'track' for the historic data.
6036
6097
  // We do this for historic data that exists and is moving.
6037
6098
  if (shouldShowTrack && animatePosition && animatePosition instanceof CesiumAnimatedProperty.AnimatePositionSeries && animatePosition.GetSeries) {
6038
- const lStyle = (_d = (_c = params.fullStyle) === null || _c === void 0 ? void 0 : _c.polylineStyle) !== null && _d !== void 0 ? _d : {};
6099
+ const lStyle = (_k = (_j = params.fullStyle) === null || _j === void 0 ? void 0 : _j.polylineStyle) !== null && _k !== void 0 ? _k : {};
6039
6100
  const bColor = lStyle.lineColor ? Calculator.GetColor(lStyle.lineColor, entity, params.tags) : null;
6040
6101
  const cColor = bColor ? ColorToCColor(bColor) : Color.fromCssColorString("rgba(255, 193, 7, 0.8)");
6041
6102
  let width = lStyle.lineWidth ? EnsureNumber(Calculator.GetNumber(lStyle.lineWidth, entity, params.tags)) : 2;
@@ -7055,7 +7116,7 @@ var EntityRenderEngineModel3d;
7055
7116
  * @returns
7056
7117
  */
7057
7118
  function Render(params) {
7058
- var _a, _b, _c, _d;
7119
+ var _a, _b, _c, _d, _e, _f;
7059
7120
  const entity = params.entity;
7060
7121
  if (!params.entityHistoric) {
7061
7122
  params.entityHistoric = [];
@@ -7247,40 +7308,41 @@ var EntityRenderEngineModel3d;
7247
7308
  cEntity.model.colorBlendAmount = new ConstantProperty(blendAmount);
7248
7309
  cEntity.model.colorBlendMode = new ConstantProperty(blendMode);
7249
7310
  cEntity.model.distanceDisplayCondition = new ConstantProperty(EntityRenderEngine.GetDisplayCondition(params.minDistance, params.maxDistance));
7250
- let prevStartTime = null;
7251
7311
  if (cEntity.position && cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"]) {
7252
- prevStartTime = cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"].GetAnimateFromDateTime();
7253
- }
7254
- // If we've loaded a set of series positions then we'll animate through them.
7255
- const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
7256
- if (series.length > 1) {
7257
- animatePosition = new CesiumAnimatedProperty.AnimatePositionSeries({
7258
- posses: series,
7259
- viewer: params.viewer,
7260
- pitch: pitch,
7261
- roll: roll,
7262
- animateFromPos3d: prevPos3d,
7263
- animateFromPos3dTimeStart: prevStartTime
7264
- });
7265
- cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
7266
- cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
7267
- }
7268
- else {
7312
+ animatePosition = cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"];
7313
+ const animateSeries = animatePosition;
7314
+ const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
7315
+ if (series.length) {
7316
+ animateSeries.SupplementSeries(series);
7317
+ }
7269
7318
  const dateTimeStr = (_b = (_a = entity.Bruce.Outline) === null || _a === void 0 ? void 0 : _a.find(x => !!x.DateTime)) === null || _b === void 0 ? void 0 : _b.DateTime;
7270
7319
  const dateTime = dateTimeStr ? new Date(dateTimeStr) : null;
7271
- const posChanged = !prevPos3d || !Cartesian3.equals(prevPos3d, pos3d);
7272
- if (posChanged) {
7273
- if (cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"]) {
7274
- const prevAnimatePosition = cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"];
7275
- animatePosition = prevAnimatePosition;
7276
- animatePosition.AddPosition({
7277
- pos3d: pos3d,
7278
- dateTime: dateTime,
7279
- heading: !EnsureNumber(transform === null || transform === void 0 ? void 0 : transform.heading) ? null : heading
7280
- });
7281
- animatePosition.UpdatePitchRoll(pitch, roll);
7282
- }
7283
- else {
7320
+ if (dateTime) {
7321
+ animateSeries.UpdatePositionForDateTime(pos3d, dateTime, !EnsureNumber(transform === null || transform === void 0 ? void 0 : transform.heading) ? null : heading);
7322
+ }
7323
+ // We don't have a date-stamped incoming position.
7324
+ if (!dateTime && !series.length) {
7325
+ animatePosition = null;
7326
+ }
7327
+ }
7328
+ if (!animatePosition) {
7329
+ // If we've loaded a set of series positions then we'll animate through them.
7330
+ const series = CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(params.viewer, heightRef, heightRef, params.entityHistoric);
7331
+ if (series.length > 1) {
7332
+ animatePosition = new CesiumAnimatedProperty.AnimatePositionSeries({
7333
+ posses: series,
7334
+ viewer: params.viewer,
7335
+ pitch: pitch,
7336
+ roll: roll
7337
+ });
7338
+ cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
7339
+ cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
7340
+ }
7341
+ else {
7342
+ const dateTimeStr = (_d = (_c = entity.Bruce.Outline) === null || _c === void 0 ? void 0 : _c.find(x => !!x.DateTime)) === null || _d === void 0 ? void 0 : _d.DateTime;
7343
+ const dateTime = dateTimeStr ? new Date(dateTimeStr) : null;
7344
+ const posChanged = !prevPos3d || !Cartesian3.equals(prevPos3d, pos3d);
7345
+ if (posChanged) {
7284
7346
  let posses = [];
7285
7347
  const isLive = ViewUtils.GetTimeDetails({ viewer: params.viewer }).isLive;
7286
7348
  if (prevPos3d && isLive) {
@@ -7300,9 +7362,7 @@ var EntityRenderEngineModel3d;
7300
7362
  posses: posses,
7301
7363
  viewer: params.viewer,
7302
7364
  pitch: pitch,
7303
- roll: roll,
7304
- animateFromPos3d: prevPos3d && !isLive ? prevPos3d : null,
7305
- animateFromPos3dTimeStart: null
7365
+ roll: roll
7306
7366
  });
7307
7367
  cEntity.position = new CallbackProperty(() => animatePosition.GetValue(), false);
7308
7368
  cEntity.position["CesiumAnimatedProperty.AnimatePositionSeries"] = animatePosition;
@@ -7455,7 +7515,7 @@ var EntityRenderEngineModel3d;
7455
7515
  // Generate a polyline 'track' for the historic data.
7456
7516
  // We do this for historic data that exists and is moving.
7457
7517
  if (shouldShowTrack && animatePosition && animatePosition instanceof CesiumAnimatedProperty.AnimatePositionSeries && animatePosition.GetSeries) {
7458
- const lStyle = (_d = (_c = params.fullStyle) === null || _c === void 0 ? void 0 : _c.polylineStyle) !== null && _d !== void 0 ? _d : {};
7518
+ const lStyle = (_f = (_e = params.fullStyle) === null || _e === void 0 ? void 0 : _e.polylineStyle) !== null && _f !== void 0 ? _f : {};
7459
7519
  const bColor = lStyle.lineColor ? Calculator.GetColor(lStyle.lineColor, entity, params.tags) : null;
7460
7520
  const cColor = bColor ? ColorToCColor(bColor) : Color.fromCssColorString("rgba(255, 193, 7, 0.8)");
7461
7521
  let width = lStyle.lineWidth ? EnsureNumber(Calculator.GetNumber(lStyle.lineWidth, entity, params.tags)) : 2;
@@ -33249,7 +33309,7 @@ class WidgetViewBar extends Widget.AWidget {
33249
33309
  }
33250
33310
  }
33251
33311
 
33252
- const VERSION = "5.9.7";
33312
+ const VERSION = "5.9.8";
33253
33313
 
33254
33314
  export { VERSION, CesiumViewMonitor, ViewerUtils, ViewerEventTracker, MenuItemManager, isOutlineChanged, EntityRenderEngine, EntityRenderEnginePoint, EntityRenderEnginePolyline, EntityRenderEnginePolygon, EntityRenderEngineModel3d, MenuItemCreator, VisualsRegister, RenderManager, EntitiesIdsRenderManager, DataLabRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, TilesetCadRenderManager, TilesetArbRenderManager, TilesetEntitiesRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TilesetGooglePhotosRenderManager, DataSourceStaticKmlManager, GoogleSearchRenderManager, AssemblyRenderManager, RelationsRenderManager, SharedGetters, CesiumParabola, EntityLabel, ViewRenderEngine, TileRenderEngine, TilesetRenderEngine, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, DEFAULT_LIVE_PADDING_SECONDS, 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 };
33255
33315
  //# sourceMappingURL=bruce-cesium.es5.js.map