After clipping a small portion of a point cloud, I want to access the coordinates of the remaining points. Any hint on how to do that?
const clippingPlaneCollection = new Cesium.ClippingPlaneCollection({
planes: clippingPlanes,
unionClippingRegions: true,
edgeWidth: 1.0
});
tileset.clippingPlanes = clippingPlaneCollection;
If I am trying to access the points with tileset.root.content.getFeature(0) I am getting the following error: “No feature ID set is selected. Make sure Cesium3DTileset.featureIdLabel or Cesium3DTileset.instanceFeatureIdLabel is defined”
What is the way to access the point coordinates from the object tileset?
Hi @julesmorel,
Welcome to the Cesium community! First of all, if you can provide a sandcastle demoing the issue, that would help me investigate your problem and propose changes.
I will say, though, that clipping the point cloud shouldn’t affect the available features on the CPU-side. It should only cull those points when rendering. I’d imagine, for instance, that tileset.root.content.getFeature(0) still fails even if you remove the clipping plane code? (This is the sort of thing I would check myself with a sandcastle example
).
The second note I have, is that your specific error results from the Model3DTileContent not having a featureTableID for the tile. The feature table for a point cloud contains the data for each point that dictates where and how to render each point. The lack of said table leads me to wonder if your tileset is valid. Cesium offers a tool for validating 3D tiles, that you may be interested in.
If that doesn’t help enough, please feel free to respond with more questions (and a sandcastle example if you can!).
Hi @mzschwartz5,
Thank you for your prompt reply.
So I tried to simplify the problem and just print in the console the coordinates of the first point of a 3D tileset point cloud (without any clipping this time). Here is the sandcastle of this test : Cesium Sandcastle
I am not sure why but I do not have the same behaviour in the sandcastle as tileset.root.content is undefined. So I might be totally wrong on the way to access point features. Any hint on this would be a great help.
About your second note, my 3D tileset point cloud is stored on Cesium ION, and there is no error on the Cesium ION interface, I can visualize it correctly, so I guess it should be valid.
Thanks for the example sandcastle!
I am not sure why but I do not have the same behaviour
It looks like the tileset root content hadn’t loaded yet. When you wait for it to load (hacky sandcastle), it does yield the same error.
I’m going to reach out to see if I can you a better answer from someone more knowledgeable than myself. I stepped through the code a bit to try to see what’s going on, and it doesn’t look like the model content contains a feature table. I was under the impression a feature table is required, but I’ll find out more and get back to you!
@julesmorel it seems that trying to access coordinates of points in a point cloud on the CPU isn’t feasible in CesiumJS. Since point clouds contain a lot of data, it’s generally too slow to do anything with them CPU-side. In fact, in Cesium they’re often (always?) uploaded straight to the GPU from their binary CPU representation.
While there may be a workaround involving copying back buffers to the CPU, interpreting them, and getting the right point out, it’s not a path I would recommend pursuing.
@mzschwartz5 Thanks for the detailed explanation, that makes sense. In my case, though, the processing I want to do would be asynchronous, so performance constraints on the main thread wouldn’t be a major issue.
To give a bit more context: my use case is to generate a 2D profile of the point cloud. The idea is to extract a vertical cross section of the 3D point cloud (based on two user-selected points), and then plot this extracted slice in a separate sub-window. This would allow users to visually analyze the vertical structure of the point cloud data.
If you have ideas or suggestions on how to implement this kind of feature in CesiumJS, I’d love to hear your thoughts!
@julesmorel, that sounds like a cool idea, but unfortunately I don’t think Cesium has a native way to do exactly that. You may be able to achieve it with your own custom logic, building on top of Cesium, though. I can’t offer much help there, but here’s an outline of one potential path that may work for you:
- Get the screen space position of the mouse using a
ScreenSpaceEventHandler
- Get the depth of your point cloud entity relative to the Camera.
- Using those two pieces of information, and the camera projection matrices, you can do some math to put your mouse position into world space at the depth of the point cloud.
- Using that world-space position, you can create a clipping plane.
- Repeat with another mouse position, and use those two clipping planes to clip the point cloud and show the user a cross section.
Good luck!
Thanks @mzschwartz5 !
I managed to implement the clipping panel part using two mouse positions and Cesium’s clipping planes. Now I’m trying to move to the next step: retrieving the actual cross-section points (i.e., the point cloud data inside the clipped region) so I can plot them in a separate 2D profile window.
This is where I’m stuck. Since point clouds in Cesium are GPU-side, it’s not clear to me how to extract the coordinates of the points that fall within the profile box. Has anyone found some way to intercept the geometry in the clipping volume? Any tips or directions would be much appreciated!
Hi @julesmorel, I’m trying to think if there’s another strategy to achieve what you need. Can you clarify a little about the purpose and requirements for this “2D profile window”?
- Is the data a true point cloud with arbitrary positions, or are the points on a regular 3D grid?
- Do you need the exact numerical values of the coordinates of the selected data, or do you only need an accurate visual representation in your 2D profile?
Hi @julesmorel, exporting the points from Cesium will be challenging. As discussed in Retrieve point cloud point positions on click · Issue #7953 · CesiumGS/cesium · GitHub and some of the linked threads, we do not retain the point cloud positions on the CPU, and retrieving them from the GPU is non-trivial.
One possible workaround would be to use Cesium (and your own clipping panel code) to position your clipping planes. Then write out the clipping plane positions. These positions could be used in a point-cloud processing tool to apply those clipping planes to the raw point cloud data.