Initial polyline render sometimes takes many seconds

We have a very simple line drawing tool that draws a polyline entity that can be edited by the user (points can be dragged after the line is drawn).

The first time a line is drawn sometimes takes many seconds for the line to appear. Any subsequent changes to the line are drawn very quickly.

I did find this topic: slow initial rendering of polyline / polygon

I’m wondering if there have been any changes that provide another or better method of eliminating this initial draw delay?

Here’s a link to a simple Sandcastle example that demonstrates the delay.

EDIT:
When Sandcastle loads there’s a panel on the left side. Check the “Enable drawing” checkbox (or right-click on the canvas) to enable drawing. Left-click on the globe to draw several points. Then either uncheck the “Enable drawing” checkbox or right-click on the canvas to have the shape rendered.

The first time you disable the drawing mode and render the polyline is when the pause takes place.

I’d really love to hear from one of the Cesium team about this. The initial draw delay is pretty extreme, and so far I can’t figure out a way to prevent it…

Here are some pointers for the slow rendering:

  • Setting clampToGround to true will slow the drawing down, since ground polylines are expensive to compute especially if you are not using a computer that has a graphics card for hardware acceleration. Setting clampToGround to false should help with performance.
  • What Omar said about web workers in the thread that you linked is still relevant.
  • CallbackProperty will force the line to draw synchronously, but it also makes it re-render every frame, which is probably not something you want if the user has finished drawing the polylines. This is a drawback of the Entity API and there isn’t a way to force the line to only draw synchronously once. Have you considered using the Primitive API instead?

Hi dzung, thanks for the reply.

Can you point me to a simple example of an approach to using the Primitive API for drawing points and polylines that would work well for this situation?

Thanks.

I think it would help if there was a way to initialize the web workers required for drawing either onload or programmatically…basically any time before the user finishes a polyline or polygon drawing.

The Primitive API draws faster but then you lose many of the ease-of-use benefits of the Entity API.

I didn’t realize CallbackProperty is a potential workaround for this. That sounds like a good idea and we will try it for our scenario even though none of our geometries will be moving. If it draws in 0.5seconds instead of 10seconds, that sounds like a win.

If that’s problematic we’ll probably just draw a tiny polygon and a tiny line somewhere then immediately delete it when the app initializes to force load all that stuff.

@ashley-mort

Welcome to the community! :rocket: :fireworks:

CallbackProperty seems like a robust workaround for this application. Try it out and let me know if you run into any shortcomings!

Out of curiosity, what kind of an application are you developing with CesiumJS?

-Sam

Would love to hear if you come up with a reasonable solution. There seems to be more at play here. We’ve added a function to draw entities when the application loads, but this hasn’t addressed the issue. However, it dawns on me that we attempted drawing the entities on the other side of the globe and maybe this was a problem. Maybe nothing happens if the entities are outside the visible scene.

1 Like

For right now I just drew tiny a polyline and polygon about the size of a building whenever our app starts. The user won’t even notice it (it is technically onscreen…not sure if that matters). Then I do a setTimeout for ~20seconds then remove that polyline and polygon. I wish there was an event for when an Entity is fully rendered but I didn’t find one.

I’ll try the CallbackProperty later but I’m worried that require a bigger change to our codebase.

Sam, we have a variety of Cesium projects. I’ve been around since like version b6 but have been on & off regarding Cesium specific work these past few years. 90% of my experience is with the Primitive API.

Your sample app- modified

1 Like

@ashley-mort

I apologize for the confusion. The community forum indicated that this was the first time you posted, so I assumed that you were new to the community.

Let me know if you have any luck with the CallbackProperty.

-Sam

CallbackProperty didn’t help. It still ends up loading a ton of cesiumWorkerBootstrapper.js classes (ex: Ray.js 10 times).

It doesn’t matter if my hierarchy is a CallbackProperty or not. It also doesn’t seem to matter if I pre-draw a sample polygon somewhere else or not (still loads a ton of classes when we display our query results of ~10 polygons). For example, I’ll see files like Ray.js load 5+ times in my Network tab while my results are being rendered.

Here is exactly what we’re doing. Why does the setTimeout’d polygon trigger a loading of more Cesium .js resources?

Example app of our problem

Edit:
This seems to work. We will make this change virtually everywhere and see how it goes.

let constant = false;
let result = viewer.entities.add({
    name: "Actual Data",
    polygon: {
        hierarchy: new Cesium.CallbackProperty(function() {
            return new Cesium.PolygonHierarchy(positions);
        }, constant),
        material: Cesium.Color.BLUE.withAlpha(0.0),
        height: 0,
        outline: true,
        outlinWidth: 1,
        outlineColor: Cesium.Color.RED,
    }
  });

@ashley-mort

Thank you for adding some clarifying details and posting an update. I looked over your edit - and your revisions seem robust. Please let me know if you encounter any issues when applying this change to other parts of your codebase.

-Sam

Now we have a requirement for ArcType.RHUMB which has very bad rendering performance in a Cesium.CallbackProperty. It’s always an adventure :slight_smile:

Example

1 Like

@ashley-mort

Thank you for sharing this update with me! I agree - software development is always a journey.

-Sam

c137.js seems like one solution. It has all the webworkers loaded up front so there’s no delay displaying Entities: GitHub - DigitalArsenal/c137.js: A CesiumJS Distribution

<html>
  <head>
    <title>Cesium</title>
  </head>
  <body>
    <div id="cesiumContainer"></div>
    <script type="module">
        import {
            createWorldTerrain,
            Ion,
            Viewer,
            Cartesian3,
            Color
        } from "./node_modules/c137.js/dist/c137.mjs";
        
        //Needed this for layer picker (Bing, etc) to work
        Ion.defaultAccessToken = "MY_TOKEN";
        
        //Needed this or I get a fatal error at startup.
        window.CESIUM_BASE_URL = window.location.href;
        
        let viewer = new Viewer("cesiumContainer", {
            terrainProvider: createWorldTerrain(),
        });
        
        setTimeout(function() {
            let positions = Cartesian3.fromDegreesArray([
                -117.20019897522269,
                32.229423713272176,
                -117.01087296911727,
                32.238363980167094,
                -117.01140448250175,
                32.308364832153,
                -117.01141016903244,
                32.37877446433247,
                -117.01184538352842,
                32.448971491189674,
                -117.01087684964686,
                32.520162916412445,
                -117.01110936819921,
                32.55530496281725,
                -117.01087832549796,
                32.590789769726406,
                -117.01110809889376,
                32.625965582474606,
                -117.01087834891882,
                32.7322236195628,
                -117.01111520359805,
                32.8028633768691,
                -117.0107064813531,
                32.83860042450721,
                -117.01115039039618,
                32.98028586091439,
                -117.20104277791584,
                32.971077021193146,
                -117.20106612227012,
                32.82895390527638,
                -117.20019897522269,
                32.229423713272176
            ]);
        
            let result = viewer.entities.add({
                name: "Actual Data",
                polygon: {
                    hierarchy: positions,
                    material: Color.BLUE.withAlpha(0.0),
                    height: 0,
                    outline: true,
                    outlinWidth: 1,
                    outlineColor: Color.RED,
                }
            });
        
        }, 10000);
    </script>
  </body>
</html>