Adding entity.billboard.image with a few thousand entities causes crash

I have an app that displays flights pilots have taken. I generate a GeoJSON file that displays all the airports and routes the pilots have taken. I also replace the billboard with a custom image for airports and waypoints. Everything works great, except when a pilot has something like over 1,000 entities on their map. When this happens, Cesium crashes and returns the generic
cesium RangeError: Invalid array length

``

error message.

My code is pretty basic at this point.

function renderMap(data) {
var promise = Cesium.GeoJsonDataSource.load(data, {
stroke: Cesium.Color.fromBytes(0, 230, 240, 40)
});
promise.then(function(dataSource) {
viewer.dataSources.add(dataSource);
viewer.zoomTo(dataSource);
var entities = dataSource.entities.values;

  for (var i = 0; i < entities.length; i++) {
    var entity = entities[i];
    if (entity.billboard != undefined) {
      if (entity.properties.feature_type._value === "airport") {
        entity.billboard.image = "airport.png";
      } else if (entity.properties.feature_type._value === "waypoint") {
        entity.billboard.image = "waypoint.png";
      }
      entity.billboard.horizontalOrigin = Cesium.HorizontalOrigin.CENTER;
      entity.billboard.verticalOrigin = Cesium.VerticalOrigin.CENTER;
      entity.billboard.eyeOffset = new Cesium.Cartesian3( 0, 0, -100 );
    }
  }
})

}

``

What am I missing here? Is this a bug with larger numbers of entities, or am I adding custom images to entities improperly?

Thanks for the help!

Hi Arel,

I can’t see anything wrong with how you are assigning the billboard images. If you provide the GeoJSON file that could help reproduce this, that would help track down if this a problem with the data or a bug in Cesium.

However, since you are using a lot of billboards and only a few images, I would recommend using a BillboardCollection to manage them. You’ll get better performance because billboards with the same image will share the same texture.

Thanks,

Gabby

Thanks for the response! Here is a gist of a GeoJSON file with well over 1000 entities so you can see the issue.

Switching to a BillboardCollection seems to make sense, but how do you use a BillboardCollection with GeoJSON? I can’t figure it out. I’ve tried doing the following:

var billboards = scene.primitives.add(new Cesium.BillboardCollection());

billboards.add({

image : airportIcon

});

billboards.add({

image : waypointIcon

});

``

then where I loop over the GeoJSON referencing the billboardCollection billboard like this:

if (entity.properties.feature_type._value === “airport”) {

entity.billboard = billboards.get(0);

} else if (entity.properties.feature_type._value === “waypoint”) {

entity.billboard = billboards.get(1);
}

``

Cesium is an awesome library by the way.

Scratch that, the above works! I just had a typo. BillboardCollections works GREAT!! Thanks again for the help!

Spoke too soon. Worked locally, but on production with a large dataset the map loaded, then crashed within a few seconds. Screenshot of the error message is attached.

Hi Arel,

What I had in mind for using a billboard collection with a GeoJson is to iterate through the loaded GeoJson without adding it directly to the scene, like this example. With the billboard collection, billboards which share the same image with automatically take advantage of rendering with indexing.

As for the error, can you run with an uminified version of Cesium? The error will be more descriptive.

Thanks,

Gabby

Thanks! I see what you’re saying. I just updated my implementation. I was confused about how to use GeoJSON and billboard collections together.

I’m still crashing the app with datasets over 3 thousand entities. I’ll run with an uminified version of cesium, and update my sample with a larger dataset and post the error message later this week.

Thanks again for the help.

Glad that helped clear some of this up. There’s been other reports of crashing with a large amount of entities, but it would help to see the final example and the error message so we can narrow down what the problem is. Thanks!

Ok, so I updated the GeoJSON file with over 4,000 flights and experimented a little more. It turns out that adding custom billboards alone isn’t what’s crashing Cesium, adding the lines between the entities with custom billboards is leading to the crash. When I don’t have custom billboards, adding lines between entities doesn’t cause cesium to crash. I updated the sand castle with the new GeoJSON file, and added in how I’m adding lines to the map, which is leading to a crash.

In the sand castle, the error, with stack trace is:

An error occurred while rendering. Rendering has stopped.

DeveloperError: drawingBufferWidth must be greater than zero.
Error
at new DeveloperError (https://cesiumjs.org/Cesium/Source/Core/DeveloperError.js:43:19)
at PerspectiveOffCenterFrustum.getPixelDimensions (https://cesiumjs.org/Cesium/Source/Core/PerspectiveOffCenterFrustum.js:354:19)
at PerspectiveFrustum.getPixelDimensions (https://cesiumjs.org/Cesium/Source/Core/PerspectiveFrustum.js:319:39)
at Camera.getPixelSize (https://cesiumjs.org/Cesium/Source/Scene/Camera.js:2586:38)
at updateBoundingVolume (https://cesiumjs.org/Cesium/Source/Scene/BillboardCollection.js:1261:44)
at BillboardCollection.update (https://cesiumjs.org/Cesium/Source/Scene/BillboardCollection.js:1460:9)
at PrimitiveCollection.update (https://cesiumjs.org/Cesium/Source/Scene/PrimitiveCollection.js:365:27)
at updatePrimitives (https://cesiumjs.org/Cesium/Source/Scene/Scene.js:2596:27)
at executeCommandsInViewport (https://cesiumjs.org/Cesium/Source/Scene/Scene.js:2457:13)
at updateAndExecuteCommands (https://cesiumjs.org/Cesium/Source/Scene/Scene.js:2320:13)

``

And here is how I’m adding the lines between billboards:

Cesium.GeoJsonDataSource.load(‘https://gist.githubusercontent.com/arelenglish/ebacfe043de319b4e72fb5232e208281/raw/004c5a0bf4024fc715f035989e86e0b3d62cd976/test.geojson’, {

stroke: Cesium.Color.fromBytes(0, 230, 240, 40),

markerSize: 0

})

.then(function(data) {

viewer.dataSources.add(data);

viewer.zoomTo(data);

var entities = data.entities.values;

for (var i = 0; i < entities.length; ++i) {

var entity = entities[i];

if (entity.properties.feature_type._value === “airport”) {

billboards.add({

position : entity.position.getValue(viewer.clock.currentTime),

image : ‘…/images/facility.gif’

});

} else if (entity.properties.feature_type._value === “waypoint”) {

billboards.add({

position : entity.position.getValue(viewer.clock.currentTime),

image : ‘…/images/facility.gif’

});

}

}

});

``

I’m still really new to Cesium, and can’t figure out what the error message means. Since adding the lines with custom billboards is leading to the crash, is there a more performant way to add the lines here? Or is the problem something else?

Thanks

Anyone have any update on this?

Hi Arel,

I’m having trouble reproducing the error. If I had to guess, I think the issue is coming from your markerSize being set to 0.

Thanks,

Gabby

Thanks for the response Gabby,

The error is reproduced in this sand castle.

How do I prevent the standard billboard from showing up without setting markerSize to 0? When I remove that line I get this:

That Sandcastle demo runs fine for me, no errors.

Sorry, the markerSize adjustment was off track, ignore that suggestion.

Hmm. Strange. The sandcastle crashes for me after about 30 seconds. Could it be working for you because of your computers memory? I’m running on a MacBook Air with 1.3 GHz processor and 8 GB of memory.

When it crashes, I get this error:

After reloading the page I get a WebGL crash

Nope, not seeing any crashes leaving the app open and panning and zooming around the scene. I’m running 2.8 GHz processor and have 16 GB of memory, so that might be the difference.

I think your best bet is to not use entities at all, (like described in this issue). Don’t add the datasource to the map directly. Instead, iterate through the loaded geojson data and add the billboards directly to the collection. There’s an example in that issue I linked to.

So it turns out you were right that markerSize: 0 was causing the problem. When I switched to just making the markers transparent, everything worked, and the crashes stopped. It seems like there should be a way to just set marker to nil if you don’t want it, but setting it to transparent seems to work well.

I did go down the path of adding the billboards directly to the collection like in the issue you linked, but ended up having the same issue because my billboards were still set to size zero. Took me a while to track down the issue, but glad it’s working now. Thanks for the help!

Got it. I saw the issue #6307 in GitHub that you opened, thanks!