Fast multiple solid intersections

Hi,

I have two sets of entities. Set A has 1 entity, typically larger than the rest in volume. Set B may or may not have more than one entity and may or may not be continuous (i.e., not a single entity, as shown in the image). All entities are closed polysurfaces that were created as solids. What I ultimately want is to determine the intersection volumes.

This is what I’ve tried:

  1. Select the sets as two breps (A and B), use Solid Intersect and compute the volume of the result → did not work because Set B has more than one entity

  2. Select the sets as two breps (A and B), mesh the breps, use Mesh Intersect and compute the volume of the result → despite the mesh being an approximation due to the element size, it is more than fine for what I need. However, it was quite slow to compute the results. In fact, when Set B has a large amount of entities (much more than 2), Rhino crashed.

Any ideias on how to improve this? Thanks!

Hi @Filipe_Belga,

Without a specific code example or more detail it’s hard to see exactly what the issue is?

Does this suffice for your needs?
You can graft the cylinders input to get the volume for each intersection or trim the tree one depth and use mass addition to get the total volume for all intersecting cylinders.

If you need a speed increase, grab the C# component here which supports multi-threading:

Script Space:

20250317_Solid_Intersection_Volume_Calculation.gh (28.5 KB)

2 Likes

Can you attach the geometry data and the .gh file you used to test this?
This looks something doable in c#, multithreaded, fast and reliable…

… and what if the intersection between A and one of the B entities result as multiple volumes? You just want the intersection volume total?

Dear Riccardo and Michael,

Thanks a lot for your contributions.

@michaelvollrath indeed swapping A/B solved the problem

@maje90 I’m now really thinking about getting into scripting because I’m bumping into walls that come from the fact that grasshopper works “linearly” and does not allow for loops or recursiveness. I’m not sure if this is the way though…

After re-thinking what I actually need to compute, this is a brief summary of it: I have two main layers: Compartments and Pipes. Inside each, I have sub-layers. Sub-layers contain either closed polysurfaces, closed surfaces or a closed meshes. The main goal is to go through the objects in each pipe sub-layer and determine the intersecting volume with the objects in each compartment sub-layer.

I was able to do this partially, by inputting the list of layers and selecting a pair à priori to compute the intersection (see below and attachments).

However, this does not cover the full scope of the problem. My brain map is telling me that I need to somehow compute a matrix with all combinations first, go through them in a loop and obtain the intersecting volumes. I need this output to be organized because I need to be able to trace back from the results matrix and determine which pipe - compartment pair generated each result.

I’m open to suggestions. Thanks!

Compartment Script.gh (22.8 KB)
Intersecting volumes.3dm (1.1 MB)

Hi @Filipe_Belga ,

Based on your outline and layer structure I don’t see a need for looping here, although you are correct that scripting can give you some capabilities that Vanilla Grasshopper will not.

Since you already have your pipes and your compartments organized in layers, effectively you have a DataTree already…

You have a list containing nested lists.

Therefore, you can work on it like a data tree and then get relevant information such as “which layer aka compartment” is this pipe intersection volume on?

I’ll see if I can come back with a gh script here demonstrating this… one moment.

Hi Michael, I think I was able to do it through data trees as well!

I will also share my achievements in a moment.Thanks!

1 Like

Compartment Script V2.gh (24.9 KB)

Here it is. I it is working properly. My only concern has to do with the fact that my model mixes meshes with surfaces/polysurfaces. Hence the current warnings when computing volumes and Mesh intersect. I used Mesh intersect because Solid Intersect was not working with mesh objects, whereas Mesh Intersect works with solid objects.

1 Like

Hi @Filipe_Belga,

Thanks for sharing the updated script.

I couldn’t get your version working as I don’t have the plugins you do but take a look at this and see if it helps you take your script any further…

I convert all breps to meshes so that we can work exclusively with meshes and then I have some logic to preview the different pieces and such…

It looked like there were discrepancies between volume between my version and the version you shared. Maybe that was because of how I was processing your data void of the plugins initially? I create duplicate sets of pipes here to compare against each individual compartment if that makes sense?

I added a multi threaded mesh intersection solver here:

Diagram:

Compartments (Unique Colors Per Layer):

Pipes (Unique Colors Per Layer):

Pipe Intersections (Colored by Compartment Color):

Graph Space:

Disclaimer… I didn’t fully vet or test this script as I ran out of time to play with it… but sharing if it helps

20250320_Pipe_Compartment_Intersections_Response_01b.gh (32.6 KB)

1 Like

Hi @michaelvollrath,

Thanks a lot for this. I’m thinking of implementing the color module into mine! Interesting…

Anyway, I’ve checked your file and it’s seems it is jumping a few of the compartments. Not all of them are showing and colored I mean… Any idea why?

One another note, thinking about efficiency and time… I was wondering how I could speed this for bigger models (larger number of layers and objects for example)… Particularly the Mesh Intersect and Volume commands are the slowest. So, if I could avoid running them on objects like Pipe A and Compartment B (see image below), which do not even touch each other, that could save processing time I guess. Tomorrow I will try comparing bounding box extents to filter unnecessary intersect operations. Other suggestions are also welcome!

Hi @Filipe_Belga, I recommend pre filtering components for intersection logic by first using the Clash component. This component is fast and you can use it to group the clashing objects into data tree branches so that you then only run the intersection logic on “known” clashes.

This should substantially improve performance on large models and you can set limits on the component as well.

I actually was working on his exact thing for you but scrapped it when I ran out of time.

EDIT: interesting on the missing compartments. Possibly a failed mesh conversion, layer issue, or oversight elsewhere on my part. I’ll take a look when I’m in the studio again

Hopefully that helps you though!

@michaelvollrath sure, I’m coming back to this tomorrow as well. Anyway, I found out that the missing geometry is somehow invalid/null but I’m not sure why as it is a “normal” closed solid polysurface like many others…

Anyway, I will also try your tip on using clash component for performance.

Finally, for reference, the plugin I’m using is elefront for filtering objects by layers.

Thank you!

Yes ‘selbadobjects’ will show it:

when exploding it and looking around it has tiny pieces that extend past the form both on top and bottom:

Hi again, any idea on what is faster: Mesh Intersection or Solid Intersection?

Thanks!

I believe the clash component compares everything as meshes anyways for quicker detection so my guess would be mesh will win out for clash and physics computations… but I’m certainly not well enough versed on the differences for the actual boolean operators and would think mileage may vary based on the complexity of the geometry in question? Like a super dense mesh with many faces vs a brep representation of that same object with all faces merged would, I assume, be faster to operate on despite the overall volume/form of it being similar.


With rendering stuff it seems like mesh typically wins out in speed because my (limited) understanding is GPU wants everything as triangles for rendering anyways… and you can get performance gains by “merging meshes” to be less draw calls but I have no idea how booleans which I think are CPU computations compare in mesh vs brep.


Hopefully another user can weigh in on this, I know there are some boolean wizards in these forums lurking about :wink:

1 Like

One small note regarding Clash component. I just tested it a few moments ago and it seems it doesn’t recognize 1 object fully inside another as a “clash” and this detail is quite important in my algorithm.

I just saw a post on the forums about this exact thing… let me see if I can dig it up

1 Like

Hello @michaelvollrath ,

I’m sorry to be a pain in the a** but, once you mentioned it, I started searching for posts about this “issue” but could not find any…

I suppose people are generally more interested in “intersection-type” clashes rather than detecting “fully-contained” bodies inside others.

@Filipe_Belga not a pita, don’t worry haha.

Perhaps you could get the bounding box points of set A and then check for “PointInBrep” of set B.

To speed this up I would use bounding boxes for A and B.

If any of the A.bbox vertices are inside B.bbox brep shape, that means there is potentially an overlap.

Then you could more specifically check with the A set by using DeconstructBrep or get the Mesh vertices and compare again so that its not the generic bounds of an object but more specifically a piece o the geometry itself is inside of the other object (the vertex or vertices of A in this example)

I did some testes with DeMesh (Deconstruct Mesh) + Read the vextex coordinates + MInc (Test a Point for Mesh inclusion) and it seems to have worked quite well also! I basically run through it what did not pass the Clash Detection test to check if there are no clash at all or if there are objects/pipes “fully inside” any compartment. However, this increased the processing time quite a bit… Therefore, since in most of the cases there are no pipe route that pass through single compartments, i.e. is “fully inside”, I will most likely bypass this with a stream filter so that it only runs when I want it too.

1 Like