Polyline entities appear momentarily when even though their availability has expired

1. A concise explanation of the problem you're experiencing.

Polyline entities flash for a moment when adding new entities even though their availability should prevent them from showing.
The sandcastle code below will demonstrate the issue clearly. Let it run for 20-30 seconds and you'll notice the flashing. Am I doing something wrong? Should I use primitives instead?

2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.

var viewer = new Cesium.Viewer('cesiumContainer', {
    shouldAnimate : true
});
viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(5,5,4000000),
    orientation: {
        heading: 0,
        pitch: Cesium.Math.toRadians(-90),
        roll: 0
    }
});

var startDate = Cesium.JulianDate.fromIso8601('2018-09-16T00:00:00.000Z');
var endDate = Cesium.JulianDate.fromIso8601('2018-09-16T00:05:00.000Z');

viewer.clock.currentTime = startDate;
viewer.clock.startTime = startDate;
viewer.clock.endTime = endDate;
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;

var pos1 = Cesium.Cartesian3.fromDegrees(0,0,800000);
var pos2 = Cesium.Cartesian3.fromDegrees(10, 10, 0);

var positions = new Cesium.SampledPositionProperty();
positions.setInterpolationOptions({
    interpolationDegrees: 5,
    interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});
positions.addSample(startDate, pos1);
positions.addSample(endDate, pos2);

var ufo = new Cesium.Entity({
    id: 'UFO',
    position: positions,
    path: {
        show: true,
        leadTime: 300,
        trailTime: 300,
        resolution: 1
    },
    point: {
        color: Cesium.Color.YELLOW,
        pixelSize: 9
    },
    label: {
        text: 'UFO',
        pixelOffset: Cesium.Cartesian2.fromArray([-35, -15])
    }
});

var radar = new Cesium.Entity({
    id: 'Radar',
    position: new Cesium.Cartesian3.fromDegrees(10,0,0),
    point: {
        color: Cesium.Color.WHITE,
        pixelSize: 15
    },
    label: {
        text: 'Radar',
        pixelOffset: Cesium.Cartesian2.fromArray([45,20])
    }
});

viewer.entities.add(ufo);
viewer.entities.add(radar);

var RAY_COLOR = new Cesium.Color(0.0, 1.0, 0.0, 0.8);

function radarPing() {
    
    var s = Cesium.JulianDate.clone(viewer.clock.currentTime);
    var e = Cesium.JulianDate.clone(s);
    Cesium.JulianDate.addSeconds(e, 10, e);
    var availability = Cesium.TimeIntervalCollection.fromJulianDateArray({
        julianDates: [s, e]
    });
    
    var radarPos = radar.position.getValue(s);
    var curUfoPos = ufo.position.getValue(s);
    
    var ray = new Cesium.Entity({
        availability: availability,
        polyline: new Cesium.PolylineGraphics({
            positions: [radarPos, curUfoPos],
            followSurface: false,
            width: 1.0,
            material: RAY_COLOR
        })
    });
    viewer.entities.add(ray);
}

var timer = setInterval(radarPing, 1000);

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

I'm receiving real-time data via Server-Sent Events and I want to add polylines representing that data. I also want the data to disappear after some time but retain the ability to use the playback controls to go back in time.
I'm open to suggestions if there is a better way to do this.

4. The Cesium version you're using, your operating system and browser.
v1.49, Windows 10, Firefox and Chrome

Thanks for bringing this up, and for the example code! I took a quick look, this might be a bug. I opened an issue for it on GitHub, so we’ll see if it gets fixed or if there’s a workaround for it.

https://github.com/AnalyticalGraphicsInc/cesium/issues/7048

Feel free to follow that issue - I’ll also update this thread once it’s resolved.

For now, a workaround could be to keep track of the entities yourself and remove them once their availability end time is less than the current time. Here’s a running example of that.

Thank you very much for looking into this.
And thank you for the example code to remove entities. I will use it after a longer delay to avoid performance issues and limit memory use.

However, this workaround still doesn't fully address the issue. If you reverse time, the lines that haven't been removed still flicker. Because of this, I think the only fully functional workaround would be to not use availability at all and implement my own logic to show/hide the line entities. But of course I don't want to do that since time-dynamic visualization is one of Cesium's biggest features! I don't have an urgent need for this so I'd like to figure out why this is happening and resolve the issue rather that implement a workaround.

Now that you have confirmed my code isn't doing something stupid and that this behavior is unexpected, I will investigate further as well. I will update if I find anything.

I have further reproduced the bug without using availability.
By using a CallbackProperty for the polyline's show property, the bug still occurs anytime a line is added and the show property changes.
The bug does not happen if isConstant is true for the CallbackProperty.

The bug also happens if you negate the show property.
ie. If you create a hidden line initially and show it later, it will disappear when new lines are added.

It seems the bug is only apparent if the show property of the new line is different than the existing lines. Then, the show property is reverting back to its initial value.

Example sandcastle code below. You can toggle the show value and try adding lines that are initially shown or hidden.

var viewer = new Cesium.Viewer('cesiumContainer', {
    shouldAnimate : true
});
viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(5,5,4000000),
    orientation: {
        heading: 0,
        pitch: Cesium.Math.toRadians(-90),
        roll: 0
    }
});

var startDate = Cesium.JulianDate.fromIso8601('2018-09-16T00:00:00.000Z');
var endDate = Cesium.JulianDate.fromIso8601('2018-09-16T00:05:00.000Z');

viewer.clock.currentTime = startDate;
viewer.clock.startTime = startDate;
viewer.clock.endTime = endDate;
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;
viewer.clock.multiplier = 3;

var positions = new Cesium.SampledPositionProperty();
positions.setInterpolationOptions({
    interpolationDegrees: 5,
    interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});
positions.addSample(startDate, Cesium.Cartesian3.fromDegrees(0,0,800000));
positions.addSample(endDate, Cesium.Cartesian3.fromDegrees(10, 10, 0));

var groundPos = new Cesium.Cartesian3.fromDegrees(10,0,0);

var lineNum = 0;
var show = true;

function addLine() {
    var creationTime = Cesium.JulianDate.clone(viewer.clock.currentTime);
    
    var pos1 = groundPos.clone();
    var pos2 = positions.getValue(creationTime);
    
    var showProp = new Cesium.CallbackProperty(function(time) {
        return show;
    }, false);
    
    console.log("Adding line " + lineNum++ + " with initial show=" + show);
    var ray = new Cesium.Entity({
        polyline: new Cesium.PolylineGraphics({
            positions: [pos1, pos2],
            show: showProp,
            followSurface: false,
            width: 1.0,
            material: new Cesium.Color(0.0, 1.0, 0.0, 0.8)
        })
    });
    viewer.entities.add(ray);
}

Sandcastle.addToolbarButton('Add Sample', function() {
    addLine();
});
Sandcastle.addToolbarButton('Toggle global show value', function() {
    show = !show;
    console.log("global show=" + show);
});

I have found that if I comment out line #142079 in unminified Cesium.js, the code behaves as expected.

Batch.prototype.update = function(time) {
...
if (defined(originalAttributes.show)) {
    //attributes.show = originalAttributes.show.value; // Line 142079
}

Unfortunately, I don't yet understand the purpose of this code so I don't know if there are any side-effects. I noticed a similar design pattern in the other Geometry Batch classes so I think this bug may affect other geometry types as well.

I hope this information will be useful to the Cesium team so this issue can be resolved soon.

Thank you so much for following up and investigating! I think you’re on the right track, based on Matt’s comment on the issue (https://github.com/AnalyticalGraphicsInc/cesium/issues/7048#issuecomment-422448653).

I think what’s happening is under the hood, when primitives are re-created, it’s supposed to use the last value for “show” that was set. I think it’s related to this fix:

https://github.com/AnalyticalGraphicsInc/cesium/pull/6835

If you look at the commits, it looks like it just might be a matter of swapping the assignment around! I’d try that, and if it works, we’d definitely appreciate a contribution to fix this! Here’s the contributors guide for reference. This should be a pretty straightforward but really important fix.

It looks like this bug is caused by the changes made in PR #6835.
Swapping the assignment back will just cause the bugs fixed by that PR to come back.

It's difficult for me to determine the intent of the code block in question. It looks like it used to exist to update the original values, which seems intuitively correct to me.

But PR #6835 appears to have changed that intent which seems suspicious because now the original values are never updated. Instead, the new logic propagates the initial value to each new entity forever. This does not seem intuitively correct. But maybe I don't understand why the initial value is needed.

I think I will need to revert the changes in #6835 locally and reproduce the issues it intended to solve so I can understand this better.

Pull request created to address this issue.