TGeoVolumes -> automatically cutting a complex detector for viewing

I have a very detailed 3d model for an experiment and I would like to do a 3D boolean operation - a cutout - so that I can export it for proper viewing. I am trying already to do that with this code:

The cutting I am trying to do is fairly simple: the detector is cylindrical and I want to cut out half of it, so the internals can be viewed. I figured the detector itself (see here) is made out of TGeoVolumeAssembly objects that I need to cycle through to do the operation, but I am for sure not doing it correctly at the moment.

The current procedure I do is to cycle through all objects and attempt a TGeoCompositeShape creation with the boolean subtraction of the object and a box that basically selects x>0, but this gives me a confusing output… I was wondering what it is that I am doing wrong and if someone could give me a helping hand - sorry if this is a stupid question! And thanks a lot!

ROOT Version: 6.26/06
Platform: Mac Catalina 10.15.6
Compiler: Not Provided


I’ll check with an expert and get back to you.

@agheata please!

Super thanks!!

Hi David, you took the difficult path for this task by altering the geometry to produce a clipped version using composite shapes. You would have to:

  • Produce a new geometry that flattens the current logical volume hierarchy creating every single physical instance of a volume with its global transformation matrix inside a top volume. You cannot simply make a composite out of a logical volume because this may be replicated, so you would need to clone it anyway, and if you do it on top of the same geometry manager it is way too complicated (see what TGeoPhysicalNode::Align does)
  • You can do flattening by iterating the volume you want to clip with a TGeoIterator, which keeps track of the global transformation of the sub-nodes being visited. Then you would have to clone the shape of the visited node (skipping assemblies), check if it may lie in the clipping region or not (based on its bounding box and node transformation matrix), then either produce a volume with the same shape (if not clipped out), not produce a volume at all (if fully clipped), or if not sure make a composite shape from the shape with its global matrix and the clipping shape. This new volume you add as node to the top volume of the new geometry, with a transformation depending on the choice (if composed with the clipping shape, use identity, if not, position it with the global transformation of the node). Repeat this until the iteration is done.

Now, all this can become quite complicated, in particular, the part cloning shapes (using TObject::Clone may behave badly with pointers), but also adding volumes to a new geometry while having already a geometry in memory.

Why don’t you use the pre-built clipping functionality of the ROOT GL viewer? This allows you to clip with an arbitrary plane or a box after drawing a volume.

Hi Andrei,

Super thanks for the very fast reply! It’s very nice that the GLviewer has that functionality.

As I mentioned in my first message, I want to actually have the cut-out geometry exported to a ROOT file. Can the GL viewer cutting functionality be exploited for that too? If not, I am afraid I will have to try the harder way. But I can try to be stubborn about it :smiley:

Thank you very much!

No, the viewer does not modify the geometry, it only clips at the scene level before displaying. Sure, you can try the hard way, let me know in case you find issues you cannot solve. If you really need to keep the same hierarchy of volumes and not go with the flattening approach, you can try using the TGeoPhysicalNode::Align functionality in a TGeoIterator loop. The method allows you to change both the local transformation and the shape of the aligned node. Good luck!

Hi Andrei,

Thanks for your help! I have made some very good progress (see code here), but I’ve had to go a bit in the hardest way because I want to export sub-geometries preserving broad-scale hierarchy (because my subsequent processing cannot handle 5M nodes all at once). So, I kept the recursiveness and I kept track of all rotations and translations manually in the recursion. If you do look at the code, please don’t judge me too much - I did it in a pedestrian way :slight_smile:

Still, I am facing one remaining problem: see screenshot below. The exported mesh is OK and received well for further processing, but elements that would be completely clipped out apparently aren’t removed. I did not yet implement the bounding box check that would completely eliminate those objects by hand. I guess this goes via ::ComputeBBox? I was secretly hoping for the ability to check volume or shape overlaps with some existing functionality (even if only for boxes), also because there are often TGeoMatrices involved.

Is it expected that shapes that would otherwise be killed completely in a subtraction survive? What is the best way of dealing with this - is it really just the box check or can I check that the TGeoCompositeShape has some remaining volume? I see there’s ::Capacity but that’s quite slow…

Super thanks!!!

Okay, so I’ve managed to deal with the cutting on the side of the other application, so that’s fully settled. However, I would still like to flatten the TGeoNode structure a bit, and for that, I need to deal with the geometry as suggested - using the TGeoIterator, for instance.

To get this going, however, I would like to understand the following: if I initialize the TGeoIterator with a sub-volume of the geometry and then ask the iterator for the current TGeoMatrix (via next.GetCurrentMatrix();), do I get a global transform or a top-node-to-this-node transform? My current attempt at flattening a specific sub-geometry is here and for some reason, while within a specific group of nodes the relative arrangement is fine, it seems like the relative arrangement of the bigger hierarchies is still wrong, regardless of what I do… So I just wanted to understand a bit better how to proceed with the displacements/rotations… Thanks!!!

Okay, I managed! I am happy.

I will write here just to explain how I did it: to avoid the hassle of fully keeping track of geometry matrices (transformations from global to local), I did everything within an iterator on the master volume; to split into multiple volumes and identify those, I just used the path.

Thanks for all the help and enjoy your weekend!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.