Cesium point tile rendering with deckgl

I have asked this question on Stackoverflow.

Basically I am trying to render a cesium point tile data on deckgl with mapbox basemap.
Point cloud gets rendered but is sort of hanging in air. Seems like projection issue, but I am not sure how to make it compatible.

Any input would be helpful.

There are many possible reasons for why the height of this point cloud data does not seem to match.

It might be related to the projection that is used. It might also be that there is some tile.transform in that data that transforms the points to a certain height (maybe to match the geoid and not only the ellipsoid). In that case, one couldn’t even say that the positions are necessarily “wrong” - only that they do not match what one might expect. And finally: It might simply be ~“a bug, somewhere”…

Some further investigation might be possible, but that would rather be exploratory (i.e. aiming at ruling out possible reasons , and maybe confirming the actual reason). Is that tileset available publicly, or can it be shared?

EDIT: One first debugging step could be to look at this asset in Cesium ion, and see whether it matches the ellipsoid surface there.

@Marco13, I can share the .las file. Would that help?

Dataset is at:

https://ion.cesium.com/assets/2965720/tileset.json

Can you please elaborate how we do that? So when I upload .las file on cesium ion, I can see it as below.

If this has a “reasonable” size for sharing, then I could upload it to ion myself and have a look.

From the screenshot that you posted, it looks like the resulting ion does not have a specific location in ion. There should be a button “Adjust tileset location” above the preview window. Is this enabled/available for this data set?

Asset id for above dataset is 3008393.

https://ion.cesium.com/assets/3008393

I also have attached zip for it(~20mb)

Yes, I can see “Adjust tileset location” button.
Pu000114.zip (20.0 MB)

OK, that tileset is definitely in a strange place. When you open the location editor with “Adjust Tileset Location” and click “Next”, it zooms to the tileset: You’ll see that it floats somewhere over Africa, and its (presumed) center is waaay off from where the actual data is.

If this was tiled from a LAS file with Cesium ion, then it strongly looks like something went wrong there. It’s hard to tell what exactly that was. Maybe there is something in the LAS file that suggested a different location…? If this was supposed to be investigated further, the it could be helpful if you could provide that LAS file. (Maybe some of this will then be moved to the “Cesium ion” section or tracked as an issue internally). If you can not share the LAS file, then maybe providing the output of tools like lasinfo could give further hints.

In any case, and in the meantime, there may be workarounds for that. You could

  • adjust the tileset location at runtime, by setting the proper tileset.modelMatrix
  • ajdust the tileset JSON, to include this matrix as the tile.transform or the root tile

For the first approach:

The following sandcastle assumes that the tileset is hosted locally. (You could change the tileset creation to await Cesium.Cesium3DTileset.fromIonAssetId(3008393) if you want to do this for your ion asset). The sandcastle examines the translation of the root node, and moves the tileset to the origin. Afterwards, you can additionally apply a transform to the tileset that was computed with eastNorthUpToFixedFrame, to place it at a certain position on the globe:

const viewer = new Cesium.Viewer("cesiumContainer");

// Create the tileset in the viewer
const tileset = viewer.scene.primitives.add(
  await Cesium.Cesium3DTileset.fromUrl(
    "http://localhost:8003/tileset.json", {
    debugShowBoundingVolume: true,
    maximumScreenSpaceError: 8
  })
);

// Fetch the center of the bounding box of the root tile
// (assuming that it is an oriented bounding box)
const center = tileset.root.boundingVolume.boundingVolume.center; 
console.log("center:" + center);
const translation = Cesium.Cartesian3.negate(
  center, new Cesium.Cartesian3());
const translationMatrix = Cesium.Matrix4.fromTranslation(
  translation, new Cesium.Matrix4());

// Move the tileset to the origin
const matrix = Cesium.Matrix4.clone(Cesium.Matrix4.IDENTITY);
Cesium.Matrix4.multiply(matrix, translationMatrix, matrix);

console.log("transform " + Cesium.Matrix4.toArray(matrix));

// Move the tileset to a certain position on the globe
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(
  Cesium.Cartesian3.fromDegrees(-75.152408, 39.946975, 10)
);
Cesium.Matrix4.multiply(transform, matrix, matrix);
tileset.modelMatrix = matrix;

// Zoom to the tileset, with a small offset so that
// it is fully visible
const offset = new Cesium.HeadingPitchRange(
  Cesium.Math.toRadians(-22.5),
  Cesium.Math.toRadians(-22.5),
  60.0
);
viewer.zoomTo(tileset, offset);

For the second approach:

You could add the following transform in the root tile of the tileset JSON:

{
  ...
  "root": {
    "transform": [1,0,0,0,0,1,0,0,0,0,1,0,-379389.30500000005,-2048616.1500000001,-551.605,1],
    "boundingVolume": ...

This will have the same effect visually, and you can then set the tileset.modelMatrix to a transform that was computed with eastNorthUpToFixedFrame as well.

You could also apply the full transform as the root transform, so that you can load the tileset directly, and don’t have to manually adjust the transform afterwards. For that, however, it would be necessary to know the longitude/latitude of where the tileset is supposed to be located.
(If you know that, I can post the required matrix here as well).

2 posts were split to a new topic: Tiling LAS files from UTM zone 43N