Loop each SurfaceBody inside an Assembly

Loop each SurfaceBody inside an Assembly

Gabriel_Watson
Mentor Mentor
958 Views
3 Replies
Message 1 of 4

Loop each SurfaceBody inside an Assembly

Gabriel_Watson
Mentor
Mentor

I am attempting to:
1- Ask the user to select two assemblies on the display;
2- Iterate through every SurfaceBody or part inside that first assembly;
3- Compare hole-alignment between those parts and the holes in the second assembly's parts.

However, I am not having success in finding enough study material to explain how to access the subcomponents of an assembly in such a way. Please advise if you can.

My code below, for the user selection of 2 assemblies, plus calling the function:

Dim oAssy1 As ComponentOccurrence
oAssy1 = _invApp.CommandManager.Pick(Inventor.SelectionFilterEnum.kAssemblyOccurrenceFilter, "Select first Assembly")
Dim oAssy2 As ComponentOccurrence
oAssy2 = _invApp.CommandManager.Pick(Inventor.SelectionFilterEnum.kAssemblyOccurrenceFilter, "Select another Assembly to compare")

CheckHolesAlignment_Assys(oAssy1, oAssy2, e)

And the function definition:

Public Sub CheckHolesAlignment_Assys(oAssy1 As Inventor.ComponentOccurrence, oAssy2 As Inventor.ComponentOccurrence, e As DoWorkEventArgs)
    Dim oBody1 As Inventor.SurfaceBody
    Dim oBody2 As Inventor.SurfaceBody
    For Each oBody1 In oAssy1.SurfaceBodies
        For Each oBody2 In oAssy2.SurfaceBodies
            CheckHolesAlignment_Parts(oBody1, oBody2, e)
            MsgBox("Test")
        Next
    Next
End Sub

As you can imagine, the "CheckHolesAlignment_Parts" function inside will check something between two SurfaceBody parts. That part I got covered already.

When running the code as is, the "For" loops basically never run. The ComponentOccurrence oAssy1 (as well as oAssy2) seem empty. 🤔

Thank you for your attention.

0 Likes
959 Views
3 Replies
Replies (3)
Message 2 of 4

JelteDeJong
Mentor
Mentor

I think you need the the surface bodies from the parts in the sub assemblys. those are a bit more complicated to get but you can try this:

Public Sub CheckHolesAlignment_Assys(oAssy1 As Inventor.ComponentOccurrence, oAssy2 As Inventor.ComponentOccurrence)
    Dim assembly1 As AssemblyDocument = oAssy1.ReferencedDocumentDescriptor.ReferencedDocument
    Dim assembly2 As AssemblyDocument = oAssy2.ReferencedDocumentDescriptor.ReferencedDocument
    For Each subOcc1 As ComponentOccurrence In assembly1.ComponentDefinition.Occurrences
        ' the next line only works if your subassebly only contains parts (nono assemblies)
        Dim partFromSubAssembly1 As PartDocument = subOcc1.ReferencedDocumentDescriptor.ReferencedDocument
        ' a part can have multiple surface bodies i use only the first here.
        Dim body1FromSubAssembly1 As SurfaceBody = partFromSubAssembly1.ComponentDefinition.SurfaceBodies.Item(1)
        For Each subOcc2 As ComponentOccurrence In assembly2.ComponentDefinition.Occurrences
            Dim partFromSubAssembly2 As PartDocument = subOcc2.ReferencedDocumentDescriptor.ReferencedDocument
            Dim body1FromSubAssembly2 As SurfaceBody = partFromSubAssembly2.ComponentDefinition.SurfaceBodies.Item(1)
            CheckHolesAlignment_Parts(oBody1, oBody2, e)
            MsgBox("Test")
        Next
    Next
End Sub

Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Blog: hjalte.nl - github.com

0 Likes
Message 3 of 4

Gabriel_Watson
Mentor
Mentor

Thank you so much @JelteDeJong !

 

Your reply was half what I needed to put this together. Mainly, it helped me to get an AssemblyDocument from a given Component Occurrence (picked by the user). The other missing link to me was acquired from the link below, which taught me how to iterate through AllReferencedDocuments inside a given document (assembly or not), and VERY EFFICIENTLY get all the SurfaceBodies inside each of those documents:

https://forums.autodesk.com/t5/inventor-customization/set-all-surfacebodies-to-invisible-vba-code-at...


This is brilliant, now I can call on my other sub that compares two SurfaceBodies, passing all the pairs of Bodies found from Assy1 and Assy2:

Public Sub CheckHolesAlignment_Assys(oAssembly1 As Inventor.AssemblyDocument, oAssembly2 As Inventor.AssemblyDocument, e As DoWorkEventArgs)

    Dim ListOfBodies1 As New List(Of Inventor.SurfaceBody)
    Dim oDoc As Inventor.Document
    Dim oBody1 As Inventor.SurfaceBody
    Dim oBody2 As Inventor.SurfaceBody

    For Each oDoc In oAssembly1.AllReferencedDocuments
        For Each oBody1 In oDoc.ComponentDefinition.SurfaceBodies
            ListOfBodies1.Add(oBody1)
        Next
    Next
    For Each oDoc In oAssembly2.AllReferencedDocuments
        For Each oBody2 In oDoc.ComponentDefinition.SurfaceBodies
            For Each oBody1 In ListOfBodies1
                CheckHolesAlignment_Parts(oBody1, oBody2, e)
            Next
        Next
    Next
End Sub

 
EDIT: My only doubt is if I'll need an extra function to loop through the assemblies, in case "AllReferencedDocuments" does not pick up lower levels, only one below the used document. In short, the code above MAY only work if the assemblies given to it do not have sub-assemblies underneath them.

0 Likes
Message 4 of 4

J-Camper
Advisor
Advisor

"AllReferencedDocuments" should pick up all documents in the assembly, no matter what level, but it can access documents that don't exist directly.  Example: We use a part with profiles per project, every architect likes to use their own profiles in custom millwork, and we derive the profiles into room specific parts so that any profile adjustments happen in one place.  The profile part is included in "AllReferencedDocuments" even though it is only referenced as a derived profile within a part.

 

As for the limitation with sub assemblies, you can look at each referenced document type and determine how to handle it, see code below:

Public Sub CheckHolesAlignment_Assys(oAssembly1 As Inventor.AssemblyDocument, oAssembly2 As Inventor.AssemblyDocument, e As DoWorkEventArgs)

    Dim ListOfBodies1 As New List(Of Inventor.SurfaceBody)
    Dim oDoc As Inventor.Document
    Dim oBody1 As Inventor.SurfaceBody
    Dim oBody2 As Inventor.SurfaceBody

    For Each oDoc In oAssembly1.AllReferencedDocuments
        If oDoc.DocumentType = kAssemblyDocumentObject 
			'Do nothing, or add a function to dig deeper. However you want to handle assemblies
		Else If oDoc.DocumentType = kPartDocumentObject
			For Each oBody1 In oDoc.ComponentDefinition.SurfaceBodies
            ListOfBodies1.Add(oBody1)
       		Next
		End If	
    Next
    For Each oDoc In oAssembly2.AllReferencedDocuments
        If oDoc.DocumentType = kAssemblyDocumentObject 
			'Do nothing, or add a function to dig deeper. However you want to handle assemblies
		Else If oDoc.DocumentType = kPartDocumentObject 	
			For Each oBody2 In oDoc.ComponentDefinition.SurfaceBodies
	            For Each oBody1 In ListOfBodies1
	                CheckHolesAlignment_Parts(oBody1, oBody2, e)
	            Next
	        Next
		End If
    Next
End Sub
0 Likes