Bounding box error

Bounding box error

b.tarek
Enthusiast Enthusiast
537 Views
4 Replies
Message 1 of 5

Bounding box error

b.tarek
Enthusiast
Enthusiast

I've created a rule that creates a bounding box for each component in an assembly and puts the dimensions inside of custom iProperties.

It currently causes an error when I run it with content center components like bolts and nuts in the assembly but the rule runs normally for the rest of the assembly+sub-assemblies.

How do I fix this ?

btarek_0-1704793018853.png

' iLogic Rule to calculate and store maximum dimensions in separate custom iProperties (in mm)

Sub Main()
    Dim oAsmDoc As Document = ThisApplication.ActiveDocument

    ' Check if the active document is an assembly
    If oAsmDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
        Dim oAsmDef As AssemblyComponentDefinition = CType(oAsmDoc.ComponentDefinition, AssemblyComponentDefinition)

        ' Iterate through all occurrences in the assembly
        For Each oOccurrence As ComponentOccurrence In oAsmDef.Occurrences
            ProcessComponent(oOccurrence)
        Next

        ' Update the assembly to reflect changes
        oAsmDoc.Update()
    Else
        MessageBox.Show("This rule is intended for Assembly documents only.", "Rule Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End If
End Sub

' Function to add or update a custom property with a given name and value
Sub AddOrUpdateCustomProperty(oDoc As Document, propertyName As String, propertyValue As Object)
    Try
        Dim customPropertiesSet As PropertySet = oDoc.PropertySets.Item("Inventor User Defined Properties")
        Dim existingProperty As Inventor.Property = customPropertiesSet.Item(propertyName)
        
        ' If the property exists, update its value
        existingProperty.Value = propertyValue
    Catch ex As Exception
        ' If the property doesn't exist, create it with a default value ""
        Dim newProperty As Inventor.Property = oDoc.PropertySets.Item("Inventor User Defined Properties").Add("", propertyName)
        newProperty.Value = propertyValue
    End Try
End Sub


' Recursive function to process components and sub-assemblies
Sub ProcessComponent(oOccurrence As ComponentOccurrence)
    Try
        If oOccurrence.DefinitionDocumentType = DocumentTypeEnum.kPartDocumentObject Then
            ' If the occurrence is a part
            Dim oPartDoc As PartDocument = TryCast(oOccurrence.Definition.Document, PartDocument)

            If oPartDoc IsNot Nothing Then
                ' Get the bounding box of the component
                Dim oBoundingBox As Box = oOccurrence.RangeBox

                ' Calculate dimensions in mm
                Dim componentWidth As Double = (oBoundingBox.MaxPoint.X - oBoundingBox.MinPoint.X) * 10 ' Convert to mm
                Dim componentLength As Double = (oBoundingBox.MaxPoint.Y - oBoundingBox.MinPoint.Y) * 10 ' Convert to mm
                Dim componentHeight As Double = (oBoundingBox.MaxPoint.Z - oBoundingBox.MinPoint.Z) * 10 ' Convert to mm

                ' Store dimensions in separate custom iProperties with default value ""
                AddOrUpdateCustomProperty(oPartDoc, "MaxWidth", componentWidth)
                AddOrUpdateCustomProperty(oPartDoc, "MaxLength", componentLength)
                AddOrUpdateCustomProperty(oPartDoc, "MaxHeight", componentHeight)
            End If
        ElseIf oOccurrence.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
            ' If the occurrence is a sub-assembly
            Dim oSubAsmDoc As AssemblyDocument = TryCast(oOccurrence.Definition.Document, AssemblyDocument)

            If oSubAsmDoc IsNot Nothing Then
                ' Create a bounding box for the sub-assembly
                Dim oSubAsmBoundingBox As Box = oOccurrence.RangeBox

                ' Calculate dimensions in mm
                Dim subAsmWidth As Double = (oSubAsmBoundingBox.MaxPoint.X - oSubAsmBoundingBox.MinPoint.X) * 10 ' Convert to mm
                Dim subAsmLength As Double = (oSubAsmBoundingBox.MaxPoint.Y - oSubAsmBoundingBox.MinPoint.Y) * 10 ' Convert to mm
                Dim subAsmHeight As Double = (oSubAsmBoundingBox.MaxPoint.Z - oSubAsmBoundingBox.MinPoint.Z) * 10 ' Convert to mm

                ' Store dimensions in separate custom iProperties with default value ""
                AddOrUpdateCustomProperty(oSubAsmDoc, "MaxWidth", subAsmWidth)
                AddOrUpdateCustomProperty(oSubAsmDoc, "MaxLength", subAsmLength)
                AddOrUpdateCustomProperty(oSubAsmDoc, "MaxHeight", subAsmHeight)

                ' Iterate through all occurrences in the sub-assembly
                For Each oSubOccurrence As ComponentOccurrence In oOccurrence.SubOccurrences
                    ProcessComponent(oSubOccurrence)
                Next
            End If
        End If
    Catch ex As Exception
        MessageBox.Show("Error processing component: " & ex.Message, "Rule Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub

 

0 Likes
Accepted solutions (2)
538 Views
4 Replies
Replies (4)
Message 2 of 5

b.tarek
Enthusiast
Enthusiast

Here's the assembly I was testing the rule on.

0 Likes
Message 3 of 5

BM_Ashraf
Advocate
Advocate
Accepted solution

Hi,

Maybe you should try this one
https://forums.autodesk.com/t5/inventor-programming-ilogic/bounding-box-from-assembly-to-parts/td-p/...

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.

Blue Mech

Add-ins for Inventor!

0 Likes
Message 4 of 5

FINET_Laurent
Advisor
Advisor
Accepted solution

Hi @b.tarek,

 

The rule is throwing an error when trying to add a new property to the content center document.

 

Those parts are on some sort of read only mode. If you manually try to add an iProperty or make any modification to those documents you would get the folowing error :

FINET_Laurent_0-1704802168996.png

(sorry for baguette language)

 

I guess you could check if the component is a content centerfile first & then skip it if the answer is yes.

Dim occ As Inventor.ComponentOccurrence = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kAssemblyOccurrenceFilter, "pick an occ")
Dim partDef As Inventor.PartComponentDefinition = occ.ReferencedDocumentDescriptor.ReferencedDocument.ComponentDefinition
MsgBox(partDef.IsContentMember)

Note you need to select a part and not a part inside a sub-assembly.

 

Kind regards,

FINET L.

If this post solved your question, please kindly mark it as "Solution"

If this post helped out in any way to solve your question, please drop a "Like"

@LinkedIn     @JohnCockerill

0 Likes
Message 5 of 5

b.tarek
Enthusiast
Enthusiast

Thank you @BM_Ashraf and @FINET_Laurent for your help.

I had to do some edits to the code @BM_Ashraf but I've reached a solution.

My final code:

Sub Main
	If ThisDoc.Document.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Return
	Dim oADoc As AssemblyDocument = ThisDoc.Document
	Dim oADef As AssemblyComponentDefinition = oADoc.ComponentDefinition
	Dim oOccs As ComponentOccurrences = oADef.Occurrences
	oProcessedDocs = New List(Of String) 'initialize the list
	RecurseComponents(oOccs, AddressOf ProcessComponent)
	If oADoc.RequiresUpdate Then oADoc.Update2(True)
	'If oADoc.Dirty Then oADoc.Save2(True)
	MsgBox("This rule's work has finished.", vbInformation, "Job Is Done!")
End Sub

Dim oProcessedDocs As List(Of String)

Sub RecurseComponents(oComps As ComponentOccurrences, ComponentProcess As Action(Of ComponentOccurrence))
	If oComps Is Nothing OrElse oComps.Count = 0 Then Return
	For Each oComp As ComponentOccurrence In oComps
		ComponentProcess(oComp)
		If oComp.Suppressed = False AndAlso _
			oComp.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
			RecurseComponents(oComp.Definition.Occurrences, ComponentProcess)
		End If
	Next
End Sub

Sub ProcessComponent(oComp As ComponentOccurrence)
    Try
        If oComp Is Nothing OrElse oComp.Suppressed Then Return
        If TypeOf oComp.Definition Is VirtualComponentDefinition Then Return
        If TypeOf oComp.Definition Is WeldsComponentDefinition Then Return

        Dim oCompDoc As Inventor.Document = oComp.Definition.Document
        If oCompDoc Is Nothing OrElse oCompDoc.IsModifiable = False Then Return

        ' Avoid processing the same referenced document more than once
        If oProcessedDocs.Contains(oCompDoc.FullDocumentName) Then
            Return
        Else
            oProcessedDocs.Add(oCompDoc.FullDocumentName)
        End If

        Dim UOM As Inventor.UnitsOfMeasure = oCompDoc.UnitsOfMeasure

        If oComp IsNot Nothing Then
            Try
                Dim oBox As OrientedBox = oComp.OrientedMinimumRangeBox

                ' Check if the component is a sheet metal part using SubType
                If oCompDoc.SubType = "{9C464203-9BAE-11D3-8BAD-0060B0CE6BB4}" Then ' Sheet Metal Part SubType
                    Dim oSheetMetalDef As SheetMetalComponentDefinition = DirectCast(oComp.Definition, SheetMetalComponentDefinition)

                    ' Get the flat pattern size
                    Dim componentWidth As Double = UOM.ConvertUnits(oSheetMetalDef.FlatPattern.Width, UnitsTypeEnum.kDatabaseLengthUnits, UOM.LengthUnits)
                    Dim componentLength As Double = UOM.ConvertUnits(oSheetMetalDef.FlatPattern.Length, UnitsTypeEnum.kDatabaseLengthUnits, UOM.LengthUnits)
                    Dim componentHeight As Double = UOM.ConvertUnits(oSheetMetalDef.Thickness.Value, UnitsTypeEnum.kDatabaseLengthUnits, UOM.LengthUnits)

                    ' Create or update custom iProperties
                    Dim oCProps As Inventor.PropertySet = oCompDoc.PropertySets.Item(4) 'the Custom set

                    ' Max_Width
                    Dim oCPropMaxWidth As Inventor.Property = Nothing
                    Dim sCPropNameMaxWidth As String = "Max_Width"
                    Dim sCPropValueMaxWidth As String = componentWidth.ToString

                    Try
                        oCPropMaxWidth = oCProps.Item(sCPropNameMaxWidth)
                    Catch
                        oCPropMaxWidth = oCProps.Add(sCPropValueMaxWidth, sCPropNameMaxWidth)
                    End Try

                    If oCPropMaxWidth IsNot Nothing AndAlso oCPropMaxWidth.Value <> sCPropValueMaxWidth Then
                        oCPropMaxWidth.Value = sCPropValueMaxWidth
                    End If

                    ' Max_Length
                    Dim oCPropMaxLength As Inventor.Property = Nothing
                    Dim sCPropNameMaxLength As String = "Max_Length"
                    Dim sCPropValueMaxLength As String = componentLength.ToString

                    Try
                        oCPropMaxLength = oCProps.Item(sCPropNameMaxLength)
                    Catch
                        oCPropMaxLength = oCProps.Add(sCPropValueMaxLength, sCPropNameMaxLength)
                    End Try

                    If oCPropMaxLength IsNot Nothing AndAlso oCPropMaxLength.Value <> sCPropValueMaxLength Then
                        oCPropMaxLength.Value = sCPropValueMaxLength
                    End If

                    ' Max_Height
                    Dim oCPropMaxHeight As Inventor.Property = Nothing
                    Dim sCPropNameMaxHeight As String = "Max_Height"
                    Dim sCPropValueMaxHeight As String = componentHeight.ToString

                    Try
                        oCPropMaxHeight = oCProps.Item(sCPropNameMaxHeight)
                    Catch
                        oCPropMaxHeight = oCProps.Add(sCPropValueMaxHeight, sCPropNameMaxHeight)
                    End Try

                    If oCPropMaxHeight IsNot Nothing AndAlso oCPropMaxHeight.Value <> sCPropValueMaxHeight Then
                        oCPropMaxHeight.Value = sCPropValueMaxHeight
                    End If
                Else
                    ' The component is not a sheet metal part, use the oriented box dimensions
                    Dim maxDimensions As New List(Of Double)
                    maxDimensions.Add(UOM.ConvertUnits(oBox.DirectionOne.Length, UnitsTypeEnum.kDatabaseLengthUnits, UOM.LengthUnits))
                    maxDimensions.Add(UOM.ConvertUnits(oBox.DirectionTwo.Length, UnitsTypeEnum.kDatabaseLengthUnits, UOM.LengthUnits))
                    maxDimensions.Add(UOM.ConvertUnits(oBox.DirectionThree.Length, UnitsTypeEnum.kDatabaseLengthUnits, UOM.LengthUnits))

                    maxDimensions.Sort()

                    ' Create or update custom iProperties
                    Dim oCProps As Inventor.PropertySet = oCompDoc.PropertySets.Item(4) 'the Custom set

                    ' Max_Width
                    Dim oCPropMaxWidth As Inventor.Property = Nothing
                    Dim sCPropNameMaxWidth As String = "Max_Width"
                    Dim sCPropValueMaxWidth As String = maxDimensions(2).ToString

                    Try
                        oCPropMaxWidth = oCProps.Item(sCPropNameMaxWidth)
                    Catch
                        oCPropMaxWidth = oCProps.Add(sCPropValueMaxWidth, sCPropNameMaxWidth)
                    End Try

                    If oCPropMaxWidth IsNot Nothing AndAlso oCPropMaxWidth.Value <> sCPropValueMaxWidth Then
                        oCPropMaxWidth.Value = sCPropValueMaxWidth
                    End If

                    ' Max_Length
                    Dim oCPropMaxLength As Inventor.Property = Nothing
                    Dim sCPropNameMaxLength As String = "Max_Length"
                    Dim sCPropValueMaxLength As String = maxDimensions(1).ToString

                    Try
                        oCPropMaxLength = oCProps.Item(sCPropNameMaxLength)
                    Catch
                        oCPropMaxLength = oCProps.Add(sCPropValueMaxLength, sCPropNameMaxLength)
                    End Try

                    If oCPropMaxLength IsNot Nothing AndAlso oCPropMaxLength.Value <> sCPropValueMaxLength Then
                        oCPropMaxLength.Value = sCPropValueMaxLength
                    End If

                    ' Max_Height
                    Dim oCPropMaxHeight As Inventor.Property = Nothing
                    Dim sCPropNameMaxHeight As String = "Max_Height"
                    Dim sCPropValueMaxHeight As String = maxDimensions(0).ToString

                    Try
                        oCPropMaxHeight = oCProps.Item(sCPropNameMaxHeight)
                    Catch
                        oCPropMaxHeight = oCProps.Add(sCPropValueMaxHeight, sCPropNameMaxHeight)
                    End Try

                    If oCPropMaxHeight IsNot Nothing AndAlso oCPropMaxHeight.Value <> sCPropValueMaxHeight Then
                        oCPropMaxHeight.Value = sCPropValueMaxHeight
                    End If
                End If
            Catch ex As Exception
                MsgBox("Error processing component box for " & oComp.Name & ":" & vbCrLf & ex.Message, vb)
            End Try
        End If
    Catch ex As Exception
        MsgBox("Error processing component: " & oComp.Name & vbCrLf & ex.Message, vbExclamation, "Error")
    End Try
End Sub

Sub AddOrUpdateCustomProperty(oDoc As Document, propName As String, propValue As Double)
    Dim customProps As PropertySet = oDoc.PropertySets.Item("Inventor User Defined Properties")
    Dim customProp = Nothing

    Try
        customProp = customProps.Item(propName)
    Catch
        customProp = customProps.Add(propValue, propName)
    End Try

    If customProp IsNot Nothing AndAlso customProp.Value <> propValue Then
        customProp.Value = propValue
    End If
End Sub