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

Jan 26, 2016

SOLIDWORKS Document Manager API Toolkit


The SOLIDWORKS Document Manager is a powerful tool used for reporting content and manipulating SOLIDWORKS parts, assemblies and drawings.  I’ve used it to export custom properties from thousands of SOLIDWORKS files in seconds!  It can be used to read bill of materials and other tables from drawings as well as update references when files are renamed.

But, just like any other project, it can take time to get started and get familiar with the calls needed.  To make that all easier, I’ve put together a Visual Studio 2010 project in VB.NET I’m calling the Document Manager Toolkit.

I’ll be presenting the toolkit along with a general discussion of the SOLIDWORKS Document Manager at SOLIDWORKS World 2016 in Dallas, TX next week.  Hope to see you there!

“What’s in the toolkit?” you ask?  Download the project here for a sample implementation and read up on the general functionality below.

Document Manager Toolkit Download
Document Manager Presentation PDF (SOLIDWORKS World 2016)

MyDocMan Class


The MyDocMan class is the basis for the toolkit.  It takes care of license validation and a plethora of common operations shared below.  The functions and procedures are documented in the project to make it easier to use in your own tools.

Instantiating the class will connect to the SOLIDWORKS Document Manager and is built to read your Document Manager license from a text file named “DocMgrLicense.txt” from C:\.  Edit the GetDocManApp procedure to insert and compile your license, redirect the license file location, or point to license information saved in My.Settings.

Common Operations



GetDocument

Summary:
From a full file path, return an opened SwDMDocument.

Parameters:
FilePath: full path to the desired SOLIDWORKS file
forReadOnly: True to open the file read-only, False to open with write access.

Return Values:
Returns an SwDMDocument interface if successful.

GetAllProperties

Summary:
Function to read all file and configuration specific custom properties from a document.

Parameters:
dmDoc: Document Manager document

Return Values:
A tab-delimited string containing all configuration names, properties and values. An empty string in the configuration column indicates a file property.

Remarks:
Each line in the string will terminate in a carriage return character.

GetDelimitedTableText

Summary:
Get all text from a named table with the desired delimiter.

Parameters:
tableName: Name of the table in the SOLIDWORKS file
dmDoc: the SwDMDocument10 interface containing the table
delimiter: the desired column delimiter

Return Values:
A string representing the text of the entire table, including headers. Return characters are applied between rows.

GetBOMTableNames

Summary:
Gets all table names from a document.

Parameters:
dmDoc: The desired document containing tables.

Return Values:
An array of strings in an Object.

Remarks:
Use this function before calling GetDelimitedTableText to retrieve a valid BOM table name.

GetMissingReferences

Summary:
Recursive routine to report all missing file references.

Parameters:
dmDoc: Parent document of reported children, typically an assembly or drawing.

Remarks:
Reports back a string of missing reference files separated by a return character.

File Operations


BrowseForFile
GetFilesFromPath

BrowseForFile

Summary:
Browse for a SOLIDWORKS file using the Windows OpenFileDialog

Return Values:
Returns the full path to the selected file.

GetFilesFromPath

Summary:
Get all file paths from a user-selected directory.

Parameters:
extensionFilter: a file extension to filter. "*.sld*" would retrieve all SOLIDWORKS files.
includeSubFolders: Set to True to get files from all sub folders

Return Values:
Returns an array of full file paths.

Remarks:
Temp files, ~$Part1.sldprt, should be filtered from your results before processing.