1. A concise explanation of the problem you're experiencing.
When I replace my custom data source entities, or the entire data source, I get an onTick error ( see below ). What is happening is the hermite spline points are undefined.
My issue with this is I have to modify CesiumJS in order to prevent my inherited code error when reloading new data.
I've looked around and the way we were loading data was not recommended. I've updated the code to suspend events, and rather than remove the data source and add a new one just to populate it, I instead remove all entities and then add the new entities from the new data. Once all the new entities are drawn, I resume events on the data source. However, the issue remains. Whenever I try to load a new data set, I get a render error.
2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.
let cesiumViewer = null;
let arcsDataSource = null;
const conversations = [ {
'src_country':'CA',
'dst_country':'US',
'data':12345
} ];
renderViewer() {
//Render viewer if we haven't already done so
if (! cesiumViewer ) {
cesiumViewer = new Cesium.Viewer(this.cesiumContainer, {
navigationInstructionsInitiallyVisible: false,
timeline : false,
navigationHelpButton: false,
homeButton: false,
animation: false,
geocoder: false,
requestRenderMode: true, //not available in 1.44
baseLayerPicker: false,
/*showRenderLoopErrors: false,*///TODO: Uncomment for production. It'd be nice if errors went to console instead.
projectionPicker: true,
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url : '/tiles/{z}/{x}/{y}.png',
minimumLevel: 3,
maximumLevel:9,
customTags : {
Time: function(imageryProvider, x, y, level) {
return 'Mimir Networks Custom Tag'
}
}
}),
mapProjection : new Cesium.WebMercatorProjection()
//infoBox: false,
});
//Synchronize clock to actual time
this.cesiumViewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK;
//Add data source for arcs
this.arcsDataSource = new Cesium.CustomDataSource('arcs');
this.cesiumViewer.dataSources.add(this.arcsDataSource);
//Add event handlers
const cesiumMapComponent = this;
cesiumViewer.scene.morphStart.addEventListener(function(sceneTransitioner,fromMode, toMode){
console.log( 'morph start');
clearArcs();
});
const props = this.props;
cesiumViewer.scene.morphComplete.addEventListener(function(sceneTransitioner,fromMode, toMode){
renderArcs( props );
});
cesiumViewer.selectedEntityChanged.addEventListener(function(selectedEntity){
//console.log( 'selected entity', selectedEntity );
if ( selectedEntity && selectedEntity.properties ) {
//console.log( selectedEntity )
const entityType = selectedEntity.properties.entityType.getValue();
switch( entityType ){
case 'locality':
const selected_locality = selectedEntity.properties.locality.getValue();
arcsDataSource.entities.values.forEach( entity => {
if( entity
&& entity.polyline
&& entity.polyline.material
&& entity.polyline.material.color ){
/* *
* TODO: make changing polyline colours not
* cause the rendering process to cresh
*/
//const color = cesiumMapComponent.selectConversationColor( entity.properties.arcId.getValue() , cesiumMapComponent )
//console.log( 'setting this color', color, 'replacing this color', entity.polyline.material.color.getValue() )
//entity.polyline.material.color.setValue( color );// = cesiumMapComponent.selectConversationColor( entity.properties.arcId.getValue() , cesiumMapComponent );
}
});
break;
}
}
if (selectedEntity && selectedEntity.properties && selectedEntity.properties.arcId) {
const arcId = selectedEntity.properties.arcId.getValue();
if ( arcId && selectedEntity.id !== arcId) {
const arcEntity = arcsDataSource.entities.getById( arcId );
cesiumViewer.selectedEntity = arcEntity;
}
}
});
}
}
clearArcs() {
//Remove the arcsDataSource entities if the datasource exists exists
//The false argument means don't actually 'destroy' the objects.
if (this.arcsDataSource !== null) {
const entities = arcsDataSource._entityCollection;
console.log( arcsDataSource );
/* *
* events should be suspended for performance, and it may prevent
* render errors....maybe. Resume when all arcs are rendered.
*/
entities.suspendEvents();
entities.removeAll();
}
initArcs();
}
initArcs(){
if( arcsDataSource === null ){
arcsDataSource = new Cesium.CustomDataSource( 'arcs' );
arcsDataSource.errorEvent.addEventListener( e => { console.log( " data source event error. THIS NEVER TRIGGERS", e ) } );
console.log( 'adding arcs data source', arcsDataSource );
cesiumViewer.dataSources.add( arcsDataSource );
}
}
generateArcId( fromLocality, toLocality ){
return fromLocality + '>' + toLocality;
}
renderSplineArc( arcId ){
/* I can provide this code if required. It's 200+ lines of getting a midpoint and creating a hermite spline and drawing billboards which move along the arcs at a variable speed, based on "data" */
}
renderArcs( props ) {
conversations.forEach( conversation => {
const arcId = generateArcId( conversation[ focusField ], conversation[ correlatedField ] )
/* *
* Rerender arcs when switching between 2D and 3D due to the arcs
* not looking proper when projected when switching between
* projections.
*/
renderSplineArc( arcId );
} )
console.log( 'resume events' )
arcsDataSource._entityCollection.resumeEvents();
}
clearArcs();//init called in clear
renderArcs( props );
if ( ! defined( points[ i ] ) return result;
3. Context. Why do you need to do this? We might know a better way to accomplish your goal.
So the user can provide parameters for fetching new data from the server, which goes back years.
4. The Cesium version you're using, your operating system and browser.
CesiumJS 1.44, from npm ( going to upgrade to 1.46.1 to see if issue is resolved ).
===================================================
THE ERROR
AN ERROR OCCURRED WHILE RENDERING. RENDERING HAS STOPPED.