Compute Intersection Volume

Compute Intersection Volume

Anonymous
Not applicable
9,198 Views
21 Replies
Message 1 of 22

Compute Intersection Volume

Anonymous
Not applicable

Hi All,

 

I'm trying to compute the intersection volume of the collision of beams, columns, walls, floor slabs, and foundations. Searching the forum I found this topic:

https://forums.autodesk.com/t5/revit-api-forum/check-intersection-between-solid-objects/m-p/7467536#...

 

 

#region #### Se prueba la intersección de geometrias - TEMPORAL #### 

            List<Solid> solids = new List<Solid>();

            foreach (Element e in elementos)
            {
                solids.Add(get_solid(e));
            }

            Solid col_solid = solids[0]; // Column
            Solid beam_solid = solids[1]; // Beam
            Solid fslab_solid = solids[2]; // Floor Slab

            Solid interSolid = BooleanOperationsUtils.ExecuteBooleanOperation(col_solid, fslab_solid, BooleanOperationsType.Intersect);
            if (Math.Abs(interSolid.Volume) > 0.000001)
            {
                TaskDialog.Show("debug", "intersecting");
                return;
            }

            Solid unionSolid = BooleanOperationsUtils.ExecuteBooleanOperation(col_solid, fslab_solid, BooleanOperationsType.Union);
            double dArea = Math.Abs(col_solid.SurfaceArea + fslab_solid.SurfaceArea - unionSolid.SurfaceArea);
            if (dArea < 0.00001 && col_solid.Edges.Size + fslab_solid.Edges.Size == unionSolid.Edges.Size)
            { TaskDialog.Show("debug", "not intersecting, not touching"); }
            else { TaskDialog.Show("debug", "touching"); }

            #endregion

 

I implemented this on my code, but for the "interSolid" I get Volume = 0, and I'm intersecting the floor slab with the column. The results for the "intersection" between Column/Beam throws the same result.

Intersection.gif

What am I missing here? Has someone managed to compute the intersection volume between elements?

 

Any tip of advice will be very well received!

 

Regards!

0 Likes
Accepted solutions (1)
9,199 Views
21 Replies
Replies (21)
Message 2 of 22

jeremytammik
Autodesk
Autodesk

Dear Jorge,

 

Thank you for your query.

 

As far as I can see from your GIF animation, the floor and column do not intersect, since the column solid volume has a piece cut out of it for the floor to slot into. Hence, there is no intersection between those two.

 

I assume the same applies to the beam and column as well. The beam has been cut back, so there is no intersection with the column.

 

This virtual reality corresponds well to the real world, as you would expect from a BIM system, which is attempting to model the real world as precisely as possible.

 

You cannot have a floor and a column in the same place at the same time, because physics prevents two different solid objects from occupying the same volume in the universe.

 

I hope this helps.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 22

recepagah12
Advocate
Advocate

I reproduce the same case and I got the expected result.

If the column and slab have different material, there is an intersection because it doesn't join each other.

If they have the same material, they join each other and there will be no intersection. 

In your case, the material is the same so you get 0 intersection volume.

But in any case, there is union and same surface area.

 

I hope this helps,

Recep.

0 Likes
Message 4 of 22

Anonymous
Not applicable

Hi @jeremytammik ,

 

Thanks for your reply. I understand what you mean, but this cutback in the column was made automatically (which is correct).

Although, those 2 elements (column and floor slab) do intersect from construction and I need to compute this "intersecting" volume.

 

Intersection Floor Slab.gif

I agree that the 3D representation is correct, but the reason that I'm looking for this volume is that in my country, we have certain regulations that the concrete volumes in the project are computed differently than how Revit does this job. This means, for example, that floor slabs have the least priority from the structural usage, so primarily volume computation is assigned to vertical elements (columns, walls), then horizontal (beams) and finally to Floor-slabs. 

 

image.png

 

In Revit, the red box's volume is only counted one time by the floor slab. This volume is subtracted for the column, which is OK.

 

I need that volume to be virtually subtracted to the floor-slab  (in terms of quantities) and added to the column.

 

Hope it clarifies what I'm looking for. I know that Revit does the calculations properly, but I need them to be delivered in a particular way.

 

Any tip of advice on how to get this geometry would be very well received.

 

Thanks in advance for your time!

0 Likes
Message 5 of 22

Anonymous
Not applicable

Hi @recepagah12 , 

 

Thanks a lot! I'll try to assign different materials to this couple of elements in a transaction, then compute the volume and store the result, so finally, I'll do a rollback. I'll post here my results 😄

 

Thanks!

0 Likes
Message 6 of 22

Anonymous
Not applicable

@recepagah12 I replicated my code with your suggestion, so I manually changed the material for the slab, but I'm getting the same result (Volume = 0).

 

public Solid get_solid(Element ele)
        {
            Solid salida = null;

            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.DetailLevel = ViewDetailLevel.Fine;

            GeometryElement geomElem = ele.get_Geometry(opt);

            foreach (GeometryObject geomObj in geomElem)
            {
                double vol = 0;

                if ((geomObj as Solid) != null)
                {
                    vol = (geomObj as Solid).Volume;
                }

                if (vol != 0)
                {
                    salida = geomObj as Solid;
                }
            }

            return salida;
        }

I'm guessing that maybe the method I created to get the solid from the element is returning some weird Solid. I checked the volumes for solids before the comparison, and they correspond with the volumes shown by "Volume" parameter in Revit.

 

Any guess?

0 Likes
Message 7 of 22

recepagah12
Advocate
Advocate
Did you join the elements when applying the same material? Sometimes Revit doesn't automatically join elements. Try to join them then calculate the volume. Try this solid converter method. That's the only code differs from yours. All others are the same. Sorry for the not enclosed code snippet. When writing message today I can't edit even in Rich text. /// /// Return the solid geometry of an element. /// /// Makes an assumption that each element consists of only one /// positive-volume solid, and returns the first one it finds. public static Solid GetGeometry(GeometryElement geomElem) { foreach (GeometryObject geomObj in geomElem) { // Walls and some columns will have a solid directly in its geometry if (geomObj is Solid solid) { if (solid.Volume > 0) return solid; } // Some columns will have a instance pointing to symbol geometry if (geomObj is GeometryInstance geomInst) { // Instance geometry is obtained so that the intersection works as // expected without requiring transformation GeometryElement instElem = geomInst.GetInstanceGeometry(); foreach (GeometryObject instObj in instElem) { if (instObj is Solid solidq) { if (solidq.Volume > 0) return solidq; } } } } return null; }
0 Likes
Message 8 of 22

recepagah12
Advocate
Advocate
Sorry for really bad code layout. Please look attached file.
0 Likes
Message 9 of 22

Anonymous
Not applicable

Thanks @recepagah12! It was the "Unjoin" that I needed to do before checking. I'll create a transaction that "unjoins" the elements and compute the volume and finally rolls back. I'll stop here when I implement this in my code.

 

Again, thanks!

0 Likes
Message 10 of 22

Anonymous
Not applicable

Thanks!, It was just fine before! Thanks for your time.

0 Likes
Message 11 of 22

jeremytammik
Autodesk
Autodesk

There may be no need to unjoin.

 

Look at these two methods on the GeometryInstance class:

 

 

If you use the former, you get the cut geometry.

 

The latter returns the uncut geometry with no need to unjoin.

 

Can you confirm?

 

Thank you!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 12 of 22

jeremytammik
Autodesk
Autodesk

In fact, maybe all you need to compute is the difference between the column symbol geometry and instance geometry.

 

  red volume = symbol geometry - instance geometry

  

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 13 of 22

Anonymous
Not applicable
@Anonymous, thanks for your aproach. I'm trying to get the Geometry Instance for the elements involved, but I'm getting "null" so I can't get the GetInstanceGeometry() nor GetSymbolGeometry(). I know that my error is in gathering the GeometryInstance, what am I missing here? Thanks in advance!
0 Likes
Message 14 of 22

Anonymous
Not applicable
here is the code when I'm computing the volume.
0 Likes
Message 15 of 22

Anonymous
Not applicable

As the other approach, I created this code:

 

using (Transaction tx = new Transaction(doc))
                                {
                                    tx.Start("UnJoin elements");

                                    //Se saca el sólido de la viga
                                    Solid solid_col = get_solid(columna);

                                    try
                                    {
                                        // Se hace un unjoin de los elementos a comparar
                                        JoinGeometryUtils.UnjoinGeometry(doc, losa, columna);
                                    }
                                    catch (Exception)
                                    {                                        
                                    }

                                    // Se crea un "Solid" con el volumen de intersección.
                                    Solid interSolid = BooleanOperationsUtils.ExecuteBooleanOperation(solid_col, solid_losa, BooleanOperationsType.Intersect);
                                    volume = interSolid.Volume;

                                    tx.RollBack();
                                    tx.Dispose();
                                }

Here, I still get the volume = 0. My intuition is that I am not using JoinGeometryUtils.UnjoinGeometry properly. 

 

What am I missing here?

 

Thanks in advance

0 Likes
Message 16 of 22

Anonymous
Not applicable

Hi @jeremytammik

 

Searching on the web I found your Compatibility Methods and declaration for UnjoinGeometry2. 

double volume = 0;

                                using (Transaction tx = new Transaction(doc))
                                {
                                    tx.Start("UnJoin elements");

                                    //Se saca el sólido de la viga
                                    Solid solid_col = get_solid(columna);

                                    // Se verifica si los elementos estan con la propiedad "Join"
                                    if (JoinGeometryUtils.AreElementsJoined(doc, columna, losa))
                                    {
                                        // Se hace un unjoin de los elementos a comparar
                                        CompatibilityMethods.UnjoinGeometry2(doc, columna, losa); <<<< A

                                        //// Se hace un unjoin de los elementos a comparar
                                        //JoinGeometryUtils.UnjoinGeometry(doc, columna, losa); <<<<< B
Solid s1 = get_solid(columna); Solid s2= get_solid(losa); // Se crea un "Solid" con el volumen de intersección. Solid interSolid = BooleanOperationsUtils.ExecuteBooleanOperation(s1, s2, BooleanOperationsType.Intersect); volume = interSolid.Volume; } else { // Se crea un "Solid" con el volumen de intersección. Solid interSolid = BooleanOperationsUtils.ExecuteBooleanOperation(solid_col, solid_losa, BooleanOperationsType.Intersect); volume = interSolid.Volume; } tx.RollBack(); tx.Dispose(); }

Neither of the two ways (A or B) really "unjoins" my two elements. At this point, I don't really know what am I doing wrong... 😞

 

If I UnJoin elements manually in Revit, I get the desired result.

 

Any tip of advice will be very well received.

 

Regards!

0 Likes
Message 17 of 22

Anonymous
Not applicable
Finally! I managed to get the desired result. The issue was that I was trying to do the "Unjoin" and check intersection inside the same transaction. What I did, was to use 2 transactions. The first one to "Unjoin" elements them compute the volume and after that "Join" the elements back together. (Don't know why I can't paste the code here - don't have the option - so I attach my piece of code). Hope it helps someone else! Thanks to @Anonymous and @recepagah12 for the time and help provided. If you have any comments about my solution, it will be very well received. Regards!
0 Likes
Message 18 of 22

recepagah12
Advocate
Advocate

I am glad you did it. When you say unjoin the elements via API it doesn't work, I was curious and tried myself and it is really interesting. I tried regenerating the document even then I searched through API and realized the boolean operation don't get directly Revit Element, it gets a temporary copy. Because of that, you need 2 separate transactions.

Your code seems true but I think you should create a transaction group and create 2 transactions inside it. So there will be an only one visible transaction in the redo/undo dropdown menu. And you can rollback the process with one undo. 

 

Have a good day,

Recep.

0 Likes
Message 19 of 22

Anonymous
Not applicable

Hi All, 

 

Sadly, I'm back. I managed to compute intersection volumes for all of my elements despite the way they were created. Now, I'm looking for a property or parameter to trigger if the slab in joined like the model in the left or not joined like the model in the right.

 

Slab Joined.gif

 

I used "JoinGeometryUtils.AreElementsJoined" method to check if the slab element is joined to the footing element, but in both cases, I get "True".

 

Any tip of advice will be very well received!

 

Thanks in advance

 

0 Likes
Message 20 of 22

jeremytammik
Autodesk
Autodesk
Accepted solution

Dear Jorge,

 

Thank you for your new query.

 

I get the impression from the animated GIF image that you can determine whether the slab is joined to the footing or not by calculating their mutual intersection:

 

  • No intersection --> joined
  • Non-empty intersection --> unjoined

 

But I suppose you already thought of this yourself and have good reasons why this approach cannot be used.

 

When you say 'trigger' do you mean you need to react when the slab switches from one state to the other?

 

What is the full context, please?

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder