How to determine clash in Mesh(Fabrication object)

How to determine clash in Mesh(Fabrication object)

sahin.ikbal
Advocate Advocate
778 Views
10 Replies
Message 1 of 11

How to determine clash in Mesh(Fabrication object)

sahin.ikbal
Advocate
Advocate

I am working of a Fabrication Hanger placement project through Revit api. 
Now I’m trying to make it more intelligent so that the placed hanger avoids making any clash with any thing other than the floor and the host.

But as FabricationPart is giving me only mesh and not any solid I’m struggling to check for any clash with it.

How do we normally check clash of mesh with mesh or mesh with solid?

0 Likes
Accepted solutions (1)
779 Views
10 Replies
Replies (10)
Message 2 of 11

RPTHOMAS108
Mentor
Mentor

What does the hanger look like? Is there a side that would exhibit a closed profile that could be extruded to create a solid in a similar form? Is the part so compact that adding points to an Outline object will allow you to use BoundingBoxIntersectsFilter to get reasonable results?

0 Likes
Message 3 of 11

sahin.ikbal
Advocate
Advocate

The Hanger can be any hanger that is accepted by Revit Fabrication, i.e., whichever gives IsAHanger() == true.
BoundingBoxIntersection will give me unnecessary clashes if the hanger is not in horizontal or vertically aligned as the Boundingbox for that would exceed much beyond the geometry.
@RPTHOMAS108 

0 Likes
Message 4 of 11

sahin.ikbal
Advocate
Advocate

As the hanger can be of an shape allowed by fabrication CADmep, Is there any general conversion mechanism from mesh to solid which can give approximate solid geometry.
@RPTHOMAS108 

0 Likes
Message 5 of 11

RPTHOMAS108
Mentor
Mentor

One other idea is to create small solid spheres at each mesh geometry point using GeometryCreationUtilities you could then clash check against those.

 

You could use one of the shape builders such as TessellatedShapeBuilder to create a direct shape but it is probably not necessary for just clash checking and would have to manage those temporary objects created.

0 Likes
Message 6 of 11

sahin.ikbal
Advocate
Advocate

Problem with mesh geometry is that its not giving vertexes as Tessalation of Voume.
Vertexes given in above shaped hanger is black positions.

2021-08-16_17-09-24.png

0 Likes
Message 7 of 11

sahin.ikbal
Advocate
Advocate

I only found one way I can hit a Mesh geometry that's through ReferenceIntersector. 
And can check everywhere and can then identify the positions through brute force.0dc0cd1bd2de4a03bc16f1788953ba1a.jpeg

But it would be very time consuming.
Is there any other methods that can hit mesh objects?

@RPTHOMAS108 @Anonymous 

0 Likes
Message 8 of 11

RPTHOMAS108
Mentor
Mentor

If you have the vertices of the mesh can you reconstruct Lines between them and then divide such lines with points?

 

Then at each point create sphere solid to detect clash that way? Alternative may be to extrude cylindrical bar elements along such lines.

 

Could you share an example file for this fabrication part?

0 Likes
Message 9 of 11

sahin.ikbal
Advocate
Advocate

From getting points from in between lines would be problematic as it will take the hollow spaces in between as solid as well. 
Here is a sample of hanger .rvt file. 

@RPTHOMAS108 

0 Likes
Message 10 of 11

RPTHOMAS108
Mentor
Mentor
Accepted solution

I've created a filter based on extracting the triangles from the mesh and extruding them.

 

The first filter stage is a bounding box filter to reduce the overhead on later slow filters.

 

Filter class:

Public Class ElementIntersectsElementMeshFilter
        Private IntDoc As Document = Nothing
        Private IntEl As Element = Nothing
        Public Sub New(Element As Element)
            IntDoc = Element.Document
            IntEl = Element
        End Sub

        Public Function ToElements() As List(Of Element)
            Dim Out As IEnumerable(Of Element) = From x As ElementId In ToElementIds()
                                                 Let e As Element = IntDoc.GetElement(x)
                                                 Where e Is Nothing = False
                                                 Select e

            Return Out.ToList
        End Function

        Public Function ToElementIds() As List(Of ElementId)
            Dim Eids As New List(Of ElementId)

            'Dim BB As BoundingBoxXYZ = IntEl.Geometry(New Options With {.DetailLevel = ViewDetailLevel.Fine}).GetBoundingBox
            Dim BB As BoundingBoxXYZ = IntEl.BoundingBox(Nothing)

            Dim Points As XYZ() = New XYZ() {BB.Min, BB.Max}
            Dim MaxX As Double = Points.Max(Function(j) j.X)
            Dim MaxY As Double = Points.Max(Function(j) j.Y)
            Dim MaxZ As Double = Points.Max(Function(j) j.Z)

            Dim MinX As Double = Points.Min(Function(j) j.X)
            Dim MinY As Double = Points.Min(Function(j) j.Y)
            Dim MinZ As Double = Points.Min(Function(j) j.Z)

            Dim BBFilt As New BoundingBoxIntersectsFilter(New Outline(New XYZ(MinX, MinY, MinZ), New XYZ(MaxX, MaxY, MaxZ)))
            Dim FEC As New FilteredElementCollector(IntDoc)
            Dim Eids_L0 As List(Of ElementId) = FEC.WherePasses(BBFilt).ToElementIds
            If Eids_L0.Count = 0 Then
                Return Eids
            End If

            Dim Triangles As Solid() = GetMeshtriangleSolids(IntEl)
            If Triangles Is Nothing Then Return Eids Else

            For i = 0 To Triangles.Length - 1
                Dim FECx As New FilteredElementCollector(IntDoc, Eids_L0)
                Dim SFilt As New ElementIntersectsSolidFilter(Triangles(i))

                Dim C0 As List(Of ElementId) = FECx.WherePasses(SFilt).ToElementIds

                Eids = Eids.Union(C0).ToList
            Next
            Return Eids

        End Function
        Private Shared Function MakeTriangle(CurveTol As Double, Pt0 As XYZ, Pt1 As XYZ, Pt2 As XYZ) As Solid
            Dim V0 As XYZ = (Pt1 - Pt0).Normalize
            Dim V1 As XYZ = (Pt2 - Pt0).Normalize
            Dim N As XYZ = V0.CrossProduct(V1)

            'check short curve tolerance
            If Pt0.DistanceTo(Pt1) < CurveTol Then Return Nothing Else
            If Pt1.DistanceTo(Pt2) < CurveTol Then Return Nothing Else
            If Pt2.DistanceTo(Pt0) < CurveTol Then Return Nothing Else

            Dim LN As Line() = New Line() {Line.CreateBound(Pt0, Pt1), Line.CreateBound(Pt1, Pt2), Line.CreateBound(Pt2, Pt0)}
            Dim CL As New CurveLoop
            For i = 0 To LN.Length - 1
                CL.Append(LN(i))
            Next
            Dim S As Solid = GeometryCreationUtilities.CreateExtrusionGeometry({CL}.ToList, N, 0.05 / 304.8)
            Return S
        End Function

        'Only made this public to highlight form in direct shape
        Public Shared Function GetMeshtriangleSolids(El As Element) As Solid()
            Dim GeomEl As GeometryElement = El.Geometry(New Options With {.DetailLevel = ViewDetailLevel.Fine})
            Dim GeomInst As GeometryInstance = GeomEl.FirstOrDefault(Function(j) j.GetType = GetType(GeometryInstance))
            If GeomInst Is Nothing Then Return Nothing Else

            Dim GeomEl_Inst As GeometryElement = GeomInst.GetInstanceGeometry()
            Dim GeomMesh As Mesh = GeomEl_Inst.FirstOrDefault(Function(j) j.GetType = GetType(Mesh))
            If GeomMesh Is Nothing Then Return Nothing Else

            Dim TList As New List(Of Solid)
            For i = 0 To GeomMesh.NumTriangles - 1
                Dim T As MeshTriangle = GeomMesh.Triangle(i)
                Dim TSol As Solid = ElementIntersectsElementMeshFilter.MakeTriangle _
                    (El.Document.Application.ShortCurveTolerance, T.Vertex(0), T.Vertex(1), T.Vertex(2))
                If TSol IsNot Nothing Then
                    TList.Add(TSol)
                End If
            Next
            Return TList.ToArray
        End Function
    End Class

Usage:

Private Function Obj_210816b(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData,
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result

        Dim UIDoc As UIDocument = commandData.Application.ActiveUIDocument
        If UIDoc Is Nothing Then Return Result.Cancelled Else
        Dim IntDoc As Document = UIDoc.Document

        Dim R As Reference = Nothing
        Try
            R = UIDoc.Selection.PickObject(Selection.ObjectType.Element, "Pick element")
        Catch ex As Exception
            Return Result.Cancelled
        End Try
        Dim El As Element = IntDoc.GetElement(R)

        Dim Filt As New ElementIntersectsElementMeshFilter(El)
        Dim Els As List(Of Element) = Filt.ToElements

        For i = 0 To Els.Count - 1
            Debug.WriteLine(Els(i).Name)
        Next
        Return Result.Succeeded

End Function

 

To visualise the solids being created by the extruded triangles I used this:

Private Function Obj_210816a(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData,
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result

        Dim UIDoc As UIDocument = commandData.Application.ActiveUIDocument
        If UIDoc Is Nothing Then Return Result.Cancelled Else
        Dim IntDoc As Document = UIDoc.Document

        Dim R As Reference = Nothing
        Try
            R = UIDoc.Selection.PickObject(Selection.ObjectType.Element, "Pick element")
        Catch ex As Exception
            Return Result.Cancelled
        End Try
        Dim El As Element = IntDoc.GetElement(R)

        Dim SList_A As Solid() = ElementIntersectsElementMeshFilter.GetMeshtriangleSolids(El)
        If SList_A Is Nothing Then Return Result.Cancelled Else

        Dim TList As List(Of GeometryObject) = SList_A.Cast(Of GeometryObject).ToList

        Using tx As New Transaction(IntDoc, "Solid mesh")
            If tx.Start = TransactionStatus.Started Then
                Dim DS As DirectShape = DirectShape.CreateElement(IntDoc, New ElementId(BuiltInCategory.OST_GenericModel))
                DS.AppendShape(TList)
                tx.Commit()
            End If
        End Using

        Return Result.Succeeded

    End Function

Example direct shape created by above:

210816.png

 

I've only done some basic testing with it i.e. three close structural framing elements with one clashing expected but the principle seems sound.

 

Message 11 of 11

sahin.ikbal
Advocate
Advocate

@RPTHOMAS108 thanks a lot.
Yes, the principle seems good and sound.
Will do further testing after implementing thanks for the initial testing.

0 Likes