Feb 16, 2016

Extending SOLIDWORKS Interference Detection

Model c/o Malcom Ma


Have you ever run the SOLIDWORKS Interference Detection tool and thought, "If I could only save this list of interfering components?"

I was talking with a colleague who recently hit this problem square-on.  He wanted to work through hundreds of interference problems resulting from the lackluster design of a printed circuit board.  Here comes the SOLIDWORKS API to the rescue!

The fundamentals come from an API help example here.  Minor modifications were made to store the data being sent to the Debug window and save it to a text file.  Finally, to give the macro some real flair, adding the option to turn the interfering volumes into bodies in a part.

Rather than packing all of the code into the macro's main procedure, I've created new classes named InterferenceChecking and LocalInterferences.  These two classes have all of the routines needed and can be called from a separate application if you don't want to just run it as a macro.

Download the macro source code here (VB.NET)

Implement the new class like this.

Public Sub main()
    Dim model As ModelDoc2 = swApp.ActiveDoc
    Dim intCheck As New InterferenceChecking
    intCheck.CheckInterference(model, swApp)
    intCheck = Nothing

End Sub

The following is all code for the project, not including the calling reference.

Imports SolidWorks.Interop.sldworks
Imports SolidWorks.Interop.swconst
Imports System.Runtime.InteropServices
Imports System
Imports System.Diagnostics
Imports System.Windows.Forms

Public Class InterferenceChecking

    Public Sub CheckInterference(ByVal model As ModelDoc2, _
    ByRef swApp As SldWorks)
        Dim swModelDoc As ModelDoc2 = model
        Dim swAssemblyDoc As AssemblyDoc
        Dim pIntMgr As InterferenceDetectionMgr
        Dim vInts As Object
        Dim i As Long
        Dim j As Long
        Dim interference As IInterference
        Dim vComps As Object = Nothing
        Dim comp As Component2
        Dim vol As Double
        Dim vTrans As Object = Nothing
        Dim ret As Boolean

        Dim repMessage As String = "Interference report for: " _
        & model.GetTitle & vbCrLf

        swAssemblyDoc = swModelDoc
        pIntMgr = swAssemblyDoc.InterferenceDetectionManager

        ' Specify the interference detection settings and options
        pIntMgr.TreatCoincidenceAsInterference = False
        pIntMgr.TreatSubAssembliesAsComponents = True
        pIntMgr.IncludeMultibodyPartInterferences = True
        pIntMgr.MakeInterferingPartsTransparent = False
        pIntMgr.CreateFastenersFolder = True
        pIntMgr.IgnoreHiddenBodies = True
        pIntMgr.ShowIgnoredInterferences = False
        pIntMgr.UseTransform = True

        ' Specify how to display non-interfering components
        pIntMgr.NonInterferingComponentDisplay = _
        swNonInterferingComponentDisplay_e. _
        swNonInterferingComponentDisplay_Wireframe

        ' Run interference detection
        vInts = pIntMgr.GetInterferences
        Debug.Print("Total number of interferences: " _
        & pIntMgr.GetInterferenceCount)
        repMessage = repMessage _
  & "Total number of interferences: " _
        & pIntMgr.GetInterferenceCount & vbCrLf

        ' Get interfering components and transforms
        ret = pIntMgr.GetComponentsAndTransforms(vComps, vTrans)
        Dim bodies(0) As Object

        ' Get interference information
        For i = 0 To UBound(vInts)

            Debug.Print("Interference " & (i + 1))
            repMessage = repMessage & "Interference " & (i + 1) _
& vbCrLf
            interference = vInts(i)
            ReDim Preserve bodies(i)
            bodies(i) = interference.GetInterferenceBody()
            Debug.Print( _
"  Number of components in this interference: " _
            & interference.GetComponentCount)
            repMessage = repMessage _
            & "  Number of components in this interference: " _
            & interference.GetComponentCount & vbCrLf
            vComps = interference.Components
            For j = 0 To UBound(vComps)

                comp = vComps(j)
                Dim cName As String = comp.ComponentReference
                If cName = "" Then cName = comp.Name2
                Debug.Print("   " & cName)
                repMessage = repMessage & "   " & cName & vbCrLf
            Next j
            vol = interference.Volume
            Dim volMessage As String = _
            "  Interference volume: " _
            & Format((vol * 1000000000), "#.###") & " mm^3"
            Debug.Print(volMessage)
            repMessage = repMessage & volMessage & vbCrLf
        Next i

        ' Stop interference detection
        pIntMgr.Done()

        If MsgBox("Save report to file?", MsgBoxStyle.YesNo _
        + MsgBoxStyle.Question) = MsgBoxResult.Yes Then
            'write out the report
            WriteReport(repMessage, model.GetTitle & ".txt")
        End If

        If MsgBox("Create intereference volume part?" & vbCrLf _
        & "*Complex interference can take time.", _
        MsgBoxStyle.YesNo + MsgBoxStyle.Question) _
  = MsgBoxResult.Yes Then
            'Create a part with the bodies array
            Dim intf As New LocalInterferences(bodies)
            intf.CreateInterferingBodiesPart(swApp)
            intf = Nothing
        End If

    End Sub

    Private Sub WriteReport(ByVal repMessage As String, _
    Optional ByVal defaultName As String = "")
        Dim sfd As New SaveFileDialog
        sfd.DefaultExt = "txt"
        sfd.Filter = "Text file(*.txt)|*.txt"
        sfd.FileName = defaultName
        sfd.OverwritePrompt = True
        Dim diaRes As DialogResult = sfd.ShowDialog()
        If diaRes = DialogResult.OK Then
            Dim filePath As String = sfd.FileName
            My.Computer.FileSystem.WriteAllText(sfd.FileName, _
            repMessage, False)
            Process.Start(sfd.FileName)
        End If

    End Sub
End Class


Class LocalInterferences

  Dim intBodies As Object

  Friend Sub CreateInterferingBodiesPart( _
  ByRef swApp As SldWorks)
    If intBodies Is Nothing Then
      Exit Sub
    End If
    Dim part As PartDoc
    part = swApp.NewPart()
    For i As Integer = 0 To UBound(intBodies)
      Dim feat As Feature
      feat = part.CreateFeatureFromBody3(intBodies(i), _
      False, swCreateFeatureBodyOpts_e.swCreateFeatureBodyCheck _
      + swCreateFeatureBodyOpts_e.swCreateFeatureBodySimplify)
    Next i
  End Sub

  Public Sub New(ByVal bodies As Object)
    intBodies = bodies
  End Sub
End Class

2 comments:

  1. I have an assembly with 2 parts. Keeping one part stationary, I want to rotate another around a particular axis and find the exact position where the interference between these two parts just starts. And I have number of such pairs of parts for which I want to do the same.

    I have written an Add-In doing all this. It runs fine. But as I go on increasing the number of pairs, the program takes more and more time - e.g. for the first pair it takes say 1 minute but for the last pair the add-in almost takes 3 minutes. The entire program takes about 20 hours.

    Complexity of parts is same for all the pairs. How to increase this performance?

    My logic is - open parts, make an assembly, create mates, start rotating the movable part in steps and find the interference, stop when the interference is found. Repeat the same logic for the next pairs.

    Thanks and regards,
    Bharati Page.

    ReplyDelete

  2. What's up, I read your new stuff daily. Your writing style is awesome, keep it up! facebook log in

    ReplyDelete