How do I reinitialize the underlying TextureAtlas to prevent Billboard image resource exhaustion

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

The problem I am experiencing is seen in the following image

I am displaying billboards that I update dynamically. I create 4 of these billboards, but I update the image placed on the billboard every 5 seconds.

After a few hours of running the TextureAtlas has increased beyond its configured maximum.

I dont fully understand why this happens since I dont create new entities, I just update the image for each of the four billboard entities. I’d think that cesium is able to do garbage collection on the unused images (thousands of unused images by the time the exhaustion occurs).

Anyways, what is the best way to reset the texture atlas periodically, or better yet, is there a way for me to tell cesium to garbage collect the unused images for the each of the 4 billboards?

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

The billboards are created in this fashion.

``

var datablock_canvas = draw_datablock(processed_data, datablock_info)

//initialize new billboard for the datablock

var datablock_billboard = {}

datablock_billboard.image = datablock_canvas

datablock_billboard.pixelOffset = new Cesium.Cartesian2(offset[0], offset[1])

datablock_billboard.position = pos

datablock_billboard.name = name

datablock_billboard.horizontalOrigin = Cesium.HorizontalOrigin.LEFT

datablock_billboard.verticalOrigin = Cesium.VerticalOrigin.TOP

datablock_billboard.show = true

``

where the actual image is created as follows

export const draw_datablock = (processed_data, datablock_info) => {

const {

width,

height,

num_rows,

num_cols,

row_num_to_pixels,

col_num_to_pixels,

offset

} = processed_data

var canvas = document.createElement(‘canvas’)

canvas.width = width

canvas.height = height

var context2D = canvas.getContext(‘2d’)

var opacity_percentage = datablock_info.background_opacity

var opacity_hex = parseInt(255 * (opacity_percentage/100)).toString(16)

context2D.fillStyle = datablock_info.background_color+opacity_hex

context2D.fillRect(0, 0, width, height)

context2D.strokeStyle = datablock_info.border_color

context2D.lineWidth = 3

context2D.strokeRect(1, 1, width-2, height-2)

context2D.font = ‘14px courier’

//draw fields

for(var zone_number in datablock_info.zones){

const field = datablock_info.zones[zone_number]

const row = Math.floor(zone_number / num_cols)

const col = zone_number % num_cols

var coords = [col_num_to_pixels[col], row_num_to_pixels[row]]

context2D.fillStyle = field.color

const text = field.value || field.value === 0 ? field.value.toString().substring(0, field.width) : “”

	// console.warn('writing', text, 'at', coords[0], coords[1], field.value, field.width)

	context2D.fillText(text, coords[0], coords[1])

}

return canvas

}

``

Every 5 seconds I update the billboard as follows

var datablock_canvas = draw_datablock(processed_data, datablock_info)

//update datablock

datablock_billboard.image = datablock_canvas

``

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

4. The Cesium version you’re using, your operating system and browser.

I dont have a billboard collection… i just have an entity collection.

I know that if I had a billboard collection I could do something like this:

if(billboard_collection.textureAtlas){

        var atlas_dimensions = billboard_collection.textureAtlas.texture.dimensions

if(atlas_dimensions.x > 6000 || atlas_dimensions.y > 6000){

console.log(“Resetting atlas during drag”)

this.viewer.entities.suspendEvents()

var saved_data = [billboards_to_move.datablock, billboards_to_move.leading_line]

billboard_collection.removeAll()

var new_atlas = new Cesium.TextureAtlas({

context: this.viewer.scene.context

})

//overwriting the old atlas DOES actually destroy the old one

//see: https://github.com/AnalyticalGraphicsInc/cesium/blob/13816d679573b2ecaccef39f07ecfcd18a2da43f/Source/Scene/BillboardCollection.js#L368

billboard_collection.textureAtlas = new_atlas

}

        }

``

Perhaps I need to create a billboard collection and place those 4 billboards in it…

This is a longstanding bug (~2014). Cesium doesn’t reuse coordinates in a TextureAtlas, even if you’re conceptually wanting to “overwrite” the previous image you added. See https://github.com/AnalyticalGraphicsInc/cesium/issues/2094 and https://github.com/AnalyticalGraphicsInc/cesium/issues/2319 .