Afternoon Cesium folks,
I have been struggling with a problem in my code that caused this vague “you did something bad” kind of error.
I was using the SampledPositionProperty to draw a path along with some objects in the viewer. I had no problem drawing one Entity, but any more and ku-boom. I feared a race condition or a threading problem and started instrumenting my code for deep debugging. A couple of days later I still had no smoking gun.
To make a long story short, the below code reproduces my error. If you run this in a browser and comment out the second “entityTilted” entity, then hit fast-forward, everything works as expected. Now, uncomment that second entity, refresh your browser and FF again. Splat.
Maybe this is a Cesium bug, I don’t know how you would classify it, the SampledPositionProperty does have Number.NaNs in it.
But if it works for one entity?
<!DOCTYPE html>
<html>
<head>
<title>Satellite.js Example</title>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer" style="width:100%; height:100%; position:absolute; top:0; left:0;"></div>
<script type="module">
// Your access token can be found at: https://cesium.com/ion/tokens.
// This is the default access token from the Sandcastle example and is limited to use on localhost.
// If you're deploying your app to other hosts, you'll need to get your own access token.
Cesium.Ion.defaultAccessToken = '';
let positionAndVelocityArray = [];
// Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
const totalSecs = 86400; // seconds in a day
const timeStep = 120; // steps between propagations
let positionsOverTime = new Cesium.SampledPositionProperty(Cesium.ReferenceFrame.FIXED);
positionsOverTime.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
});
let positionsOverTimeTilted = new Cesium.SampledPositionProperty(Cesium.ReferenceFrame.FIXED);
positionsOverTimeTilted.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
});
const now = viewer.clock.currentTime;
const start = Cesium.JulianDate.addHours(now, -12, new Cesium.JulianDate());
const stop = Cesium.JulianDate.addHours(now, 12, new Cesium.JulianDate());
const earthRadius = 6371.0; // Earth's radius in kilometers
const altitude = 1000 * 1.60934; // Convert miles to kilometers
const totalRadius = earthRadius + altitude; // Total radius in kilometers
let numElem = 0;
for (let i = 0; i < totalSecs; i += timeStep) {
numElem++;
const time = Cesium.JulianDate.addSeconds(start, i, new Cesium.JulianDate());
const jsDate = Cesium.JulianDate.toDate(time);
// Calculate the current latitude in radians
const latitude = (i / totalSecs) * 2 * Math.PI - Math.PI / 2;
// Calculate the position values
let x, y, z;
if (i >= 40 * timeStep && i <= 55 * timeStep) {
x = Number.NaN;
y = Number.NaN;
z = Number.NaN;
} else {
x = 0; // The x value is 0 because the line is on the Z axis
y = 0; // The y value is 0 because the line is on the Z axis
z = totalRadius * Math.sin(latitude);
}
const positionAndVelocity = {
position: [x * 1000, y * 1000, z * 1000], // Convert kilometers to meters
velocity: [0.1,0.7,-0.9],
}
const posECFmeters = new Cesium.Cartesian3(
positionAndVelocity.position[0],
positionAndVelocity.position[1],
positionAndVelocity.position[2]
);
const posECFmetersTilted = Cesium.Matrix3.multiplyByVector(Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(45)), posECFmeters, new Cesium.Cartesian3());
positionAndVelocityArray.push(positionAndVelocity);
positionsOverTime.addSample(time, posECFmeters);
positionsOverTimeTilted.addSample(time, posECFmetersTilted);
}
console.log(`${numElem}: samples loaded.`);
// Print every positionAndVelocity to the console
positionAndVelocityArray.forEach((positionAndVelocity, index) => {
console.log(`positionAndVelocity at index ${index}:`, positionAndVelocity);
});
var entity = viewer.entities.add({
position: positionsOverTime,
path:{
resolution: 10,
width: 10,
trailTime: 50000,
leadTime: 50,
show: true,
}
});
var entityTilted = viewer.entities.add({
position: positionsOverTimeTilted,
path:{
resolution: 10,
width: 10,
trailTime: 50000,
leadTime: 50,
show: true,
}
});
console.log(Cesium.JulianDate.toDate(start).toString());
viewer.clock.startTime = start;
viewer.clock.stopTime = stop;
viewer.clock.currentTime = start;
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
viewer.clock.multiplier = 60;
viewer.clock.shouldAnimate = true;
viewer.timeline.zoomTo(start, stop);
</script>
</body>
</html>