Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering Error caused by Scene.pick #12438

Open
fawick opened this issue Jan 16, 2025 · 6 comments
Open

Rendering Error caused by Scene.pick #12438

fawick opened this issue Jan 16, 2025 · 6 comments

Comments

@fawick
Copy link

fawick commented Jan 16, 2025

What happened?

In my Viewer, GeoJSON Datasources may be reload based on user interaction with parameters defined outside of cesium. The GeoJSON is fetched in a dedicated request and the method GeoJsonDataSource.load(data, options) is called on the response data.

In a callback for Cesium.ScreenSpaceEventType.MOUSE_MOVE, I call Scene.pick in a Viewer to generate tooltips and change the mouse cursor depending on what is below the mouse cursor. Occasionally, the call to pick results in a rendering error like so:

Image

This seems to correlate with the loading of new GeoJSON data. With Chrome developer tools I located the throw of the underlying exception to TaskProcessor.js

This is the callstack of the exception:

TaskProcessor.js:244 Uncaught DataCloneError: Failed to execute 'postMessage' on 'Worker': [object Array] could not be cloned.
    at runTask (TaskProcessor.js:244:21)
    at async scheduleTask (TaskProcessor.js:261:20)
runTask @ TaskProcessor.js:244
await in runTask
scheduleTask @ TaskProcessor.js:261
TaskProcessor.scheduleTask @ TaskProcessor.js:308
loadAsynchronous @ Primitive.js:1266
Primitive.update @ Primitive.js:2137
PrimitiveCollection.update @ PrimitiveCollection.js:416
PrimitiveCollection.update @ PrimitiveCollection.js:416
PrimitiveCollection.update @ PrimitiveCollection.js:416
updateAndRenderPrimitives @ Scene.js:3564
executeCommandsInViewport @ Scene.js:3336
Scene4.updateAndExecuteCommands @ Scene.js:3066
Picking.pick @ Picking.js:329
Scene4.pick @ Scene.js:4339
mouseMove @ router.js:278
handleMouseMove @ ScreenSpaceEventHandler.js:373
handlePointerMove @ ScreenSpaceEventHandler.js:891
listener @ ScreenSpaceEventHandler.js:54

The Sandcastle link below is for demonstrating the general layout of my code, i.e. reloading GeoJSON at the same time a mouseMove handler calls pick. However, in Sandcastle, the rendering loop does not crash. I was unable to reproduce the crash with Sandcastle.

By setting a breakpoint at the throw in scheduleTask I could fetch this screenshot for the state of the parameter for scheduleTask

Image

Reproduction steps

In my application:

  1. Wiggle the mouse over the Viewer while GeoJSON datasources are loaded.

Sandcastle example

https://sandcastle.cesium.com/#c=nVVtb+M2DP4rWoChMhbI6W6fljRY5mZrdm1T1OkBQ1McVJtJtMqSIclJs6H/fZTfEvdywG354MjSQ/Ih+VBOtLKOWJ3BLAXlxEqAIRfkLNt/XoP+y2p1NlyqpEQ93F9bPHtcKkLONs7l9ucw3Ink5VkbxRS40HKVJtw6CSl3POSs8dH/Zpvn/2GTtDZL9YR0JThSGDlTKbwi4QFuNTlsBezKDBXsSARWFBn7VO7RZS8p3yOtHBcKzLLXJ/9407fgyEOmCws3egvohEJALsYeREh1ugLuCuPPqkjMJqCA5cieAgOV3mkrnNAqGJIwJKOL+kei+0l8ReZR9HAfk8vp9I7MbsniakqiyfV1vJhEH8n8N3I3iz76YGJF6Hd1rKCKT7y/FGvg8Em42ruNUGuPVLqlJSwpsCqmyoLkWiiHiZbmHcIJV1tumXV7iS+FsbqUhReDxxpAd6p8eSMg0VXNoVOFWBcmgVue+XrUe0ykzAvN7SMtJSS+FkzvsNxMIXB4cKMxstRr+oWzoIrrH9/COcNeed5vR03coIBkqYPWgwFQcc4TmG6R31UFQJMayiy4mcoLNykp01YG/UZG8TsXi30O7Gb+EE8/38w/TSsNrQpV2hO74/nvoP+I57e07uCRZGmz/uE8IN+TD2XGK3DJhvopfGyOn4KqXsxtQFEDNsf0wGuyWTM/FzTo4OppaaV7aBy8Cuu8bNrC+AGrSm9xytyve98B2r0wgmHjxeuy8cEkqLXbkDEZBIc4TaQUQzTIx8HT8HCeMrvRO68YjsLqHEjN04Z9UOXSFpR2ghy5caY49vJ2YNuV7hE3270gfJ8w4mVbiq/mj2Htf2J5oso8TWlqg69QrhblTr3uPpeqFCpO9ZZLeqSyPvlxMBhUKlyqMLwHBBJkR8rpITvkiaoUqDEvgBQybdlSxe1Vy0xpgX15n8yJJAz4sZtISauILShB+RiONdIvE0cr1nWZI24crrj6wFZGZ5ewxoGydNBHAfUr5FFTDmg6YB7jH+cD/KvAVc1ORV0YruxKm4zWrm64M+L1Jza7nN4uZos/g/q26PV7o/I2GTfl/0VkuTbl14UyFjrIcsmRRvhcJC/gWGLbxo3CY9NRKrZEpBcnPjIkkdxaPFkVUsbib1j2xqMQ8V+YemFhb+ZbMJLvPWxzPr6uNhljoxBfT1s6reUzN+88/ws

Environment

Browser: Google Chrome 131.0.6778.265 (Official Build) (64-bit)
CesiumJS Version: 1.125
Operating System: Windows 10 22H2

@ggetz
Copy link
Contributor

ggetz commented Feb 4, 2025

Apologies for the delayed response @fawick.

The Sandcastle link below is for demonstrating the general layout of my code, i.e. reloading GeoJSON at the same time a mouseMove handler calls pick. However, in Sandcastle, the rendering loop does not crash. I was unable to reproduce the crash with Sandcastle.

I can't reproduce this in Sandcastle either. It would be helpful to identify what's different between Sandcastle and your app's environment which allows the crash to happen. Is it the same geojson data in both cases?

As a workaround, maybe your mouse move handler could return early if [GeoJsonDataSource.isLoading](https://cesium.com/learn/ion-sdk/ref-doc/GeoJsonDataSource.html#isLoading) is true.

@ggetz ggetz added the needs feedback On hold until additional info is supplied label Feb 4, 2025
@fawick
Copy link
Author

fawick commented Feb 4, 2025

@ggetz The GeoJSON example data in the sandcastle is representative for the real data. In our production use use, the GeoJSON is generated dynamically by a HTTP backend.

I am alreading using DataSource.isLoading in the handler. Also, I am checking Scene.globe.tilesLoaded. Here is the relevant snippet from the mouse move handler in the application.

  for (let i = 0; i < map.dataSources.length; i++) {
    if (map.dataSources.get(i).isLoading) {
      console.log(map.dataSources.get(i).name, "is still loading");
      map.scene.canvas.style.cursor = '';
      clearTooltip();
      return;
    }
  }

  if (!map.scene.globe.tilesLoaded) {
    console.log("still loading tiles");
    map.scene.canvas.style.cursor = '';
    clearTooltip();
    return;
  }

  const feature = map.scene.pick(e.endPosition, 1, 1);
  if (!feature) {
    // don't do anything if no feature is under mouse pointer
    map.scene.canvas.style.cursor = '';
    clearTooltip();
    return;
  }

In the event of the error all datasources are reporting back to be fully loaded.

Is there a chance, that the isLoading flag is never actually set? I cannot find any assignment of true to _isLoading in the GeoJSONDataSource

@ggetz ggetz removed the needs feedback On hold until additional info is supplied label Feb 17, 2025
@ggetz
Copy link
Contributor

ggetz commented Feb 17, 2025

The GeoJSON example data in the sandcastle is representative for the real data. In our production use use, the GeoJSON is generated dynamically by a HTTP backend.

The error seems to be coming from a particular geometry primitive, the underlying graphical representation of an individual feature. It'll be difficult to track down the error without some data that can reproduce it.

Is there a chance, that the isLoading flag is never actually set? I cannot find any assignment of true to _isLoading in the GeoJSONDataSource

It's not clear from only looking at GeoJSONDataSource, but the flag is updated via the DataSource.setLoading function.

@fawick
Copy link
Author

fawick commented Feb 18, 2025

(NB: Since opening this issue I've rewritten my code to manually parse and convert data fetched via HTTP as GeoJSON into PolygonGraphics instances that I then assign to the polygon member of Entity instances. The error still occurs, so at least we can already rule out the problem to be related to the GeoJSONDataSource source. I also reduced the complexity of the geometry by having each polygon be replaced by a bounding box, i.e. a polygon with 4 edges)

The error seems to be coming from a particular geometry primitive, the underlying graphical representation of an individual feature. It'll be difficult to track down the error without some data that can reproduce it.

I'll try to come up with example data that reproduces the error in a Sandcastle. I'm a bit at at loss how to do that best, given that the error only seems to occur when I replace geometry. The scheduled task that fails is combineGeometry; I guess that in that task the polygon data is rearranged by Cesium internally for more efficient rendering?
So, anyway, for the Sandcastle, I reckon, I need a way to replace polygons dynamically somehow. Or would you be open to accepting a different way of demonstrating the error than a Sandcastle link? For example, I could try to provide a static website and/or a Github Gist?

One more thought: If there were a way to determine when Cesium had finished all combineGeometry tasks (and similar preparation) I could simply skip calling Scene.pick in my handler for MOUSE_MOVE as long as that condition is not fulfilled. That would effectively solve the whole issue for me.

It's not clear from only looking at GeoJSONDataSource, but the flag is updated via the DataSource.setLoading function.

Ah, of course, thanks. I totally overlooked that.

@ggetz
Copy link
Contributor

ggetz commented Feb 18, 2025

The scheduled task that fails is combineGeometry; I guess that in that task the polygon data is rearranged by Cesium internally for more efficient rendering?

Yes, exactly. We batch together geometry data (think polygons, rectangles, circles, and other triangle-based primitives) for better runtime performance. Once the geometry has been broken down into the components needed for rendering, like vertices and indices, the combineGeometry step runs.

If there were a way to determine when Cesium had finished all combineGeometry tasks (and similar preparation) I could simply skip calling Scene.pick in my handler for MOUSE_MOVE as long as that condition is not fulfilled. That would effectively solve the whole issue for me.

The tricky part about troubleshooting this is there are two levels of abstraction at play here— The Entity API, which is higher-level and manages dynamic changes; and the lower-level Primitive API which handle the geometry rendering and are created under-the-hood by the Entity API. What you're looking for here would be accessible from the Primitive API, but not easily through the Entity API.

Overall, this is likely symptomatic of something going amiss with processing the geometry at the primitive level. And that's why having representative data (the suspect geometry data) would be so helpful to determine the root issue.

So, anyway, for the Sandcastle, I reckon, I need a way to replace polygons dynamically somehow. Or would you be open to accepting a different way of demonstrating the error than a Sandcastle link? For example, I could try to provide a static website and/or a Github Gist?

Sure! As long as it's fairly minimal to reduce the risk of interactions with other code.

@fawick
Copy link
Author

fawick commented Feb 19, 2025

I have created a Sandcastle with a representative set of the polygon geometries:

https://sandcastle.cesium.com/#c=jVZdT+M4FP0rXl7qaCKnMDzM0oKWLdUMEgxo2h1pRREyidt4cezIdtrtrvrf5zp20qYtuwMSre17zz33w8ekShqLjCrYbcak5XPONLpEvWL9smDqL6NkbzCTM5nWdkvOVvW5ZCs0YoZXBfle7+HZSVqvR0payiXTs5MY/etcN9EOQkYtnahKp6yLMqqMVcVNe4qBgVv1vLMPTLbehtAsw9u1N5tXMrVcSZQqpTMuqWXmWmu6nqoR1bDgVNZrvGMQOZoIeX6lMtwhmEDvwJoIJhc2d/EQmiuNsGAWcTDvD+BjiA5tYf/DhxAFbSM88WfwavJv6H0kcw2FYAvNmNkNDOZP/ecY7W2dPnsqG/dHM1tpuQ0BJ5tt7QtVGXavlq70mEXo8mo38zmj4OzOQrFNyiQjJU/fMCNMZo8B1cfjc4R/CT5tbkmCMpgYaLNCVK5tzuXCWUrVwnODKpnBENVsgCqXFoaldu8ETqlcUkOMXQtYVNqoejB7A2/rU/WpIyYAKnDoZOOH4ystXF5hj/CMuFG365ESgtUDQ9QKRpZIMBxsYRREFmqBD8B2Sv4znEOSjvpm5y7kVGaivk4tCDRdTkqasvESKH7xBuASTIlh9laWlb2uWeO2o3EzR5M9iOm6ZOT+4Y/J+OX+4ft475oIRTN3y3Do4JzZNMe93NrSXCTJCnr/qrQkktnEAIWUGiuYu3XJ3fj3u5eFVtBMwxfSvMwrIW4Y3H1BGuWIfCmJzZnEmpkS0mZu7JrvxJnh6F270FK0dQitMASu3pgC2aY5MeJRxwW1/QY6BbN6TXavZuNfKrFeKPk52OxBHJOF/9WWPUi4tdHgEDKH6XJwT8+dw46knHpJ2QM8KivNTw1LysrkeEdeHz3CF1B3qtO8o2g/lwR/jqJuGpsjOTX4XXE/iN6WM/Z8j9UnEDiK9FnTMuepwV3H4EIKSEtzKnbkVQmla2UdGVMvJlaDODXTQ0qtSqYtd5PBhTiO+056IyrEK03fHj3GGrf3Cx+0Jyh0i9StaIysrlg3+LuVGdca1qXi9/BeUCdrF06Gar9e3D0N2xfNl71jk6vVRc2rc7Dpsty+xF5beXihO1y7LqBlU14wVdluwbr5ERcfknQEBq5CH/v9LU7LInypP8JgzuROhEbpYnTW9wDuN0m+MTBCIDyoVnC0AglCZsVBB93blbFCGTKTk1b8iK494DXZb3IQ8RSKrSm8G+rt2mJP5b8f+TPS/xSj81Ny9msUatyZrsYJ90k/RvWfc0iC9L21z/xY9Kmm0oCgFDhg3VOY+r/Pye3N+Ov0dvpnFF6kk/hkWD9aV01hf+NFqbRFlRaYkMSyohROLJLXKn1jlqSmvbTDZNd1mPEl4tnlkf8HUSqoMXDinooJ/4fNTq6GCdgfuLpuQfkflkwLunZm+enVnd8khAwTWB73tErBXdR7yD8A

The real application works a bit differently, as the GeoJSON for each sign is fetched individually from the backend and converted and colored. But the full set of polygons is exactly the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants