Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

NX Journal - Min/Max X Values of Parts in an Assembly

Status
Not open for further replies.

T3nk0

Aerospace
Jan 31, 2024
1
0
0
US
I'm trying to add the minimum and maximum X values of parts in an assembly as attributes. I found a thread in this forum (here) that almost does what I need. I was able to modify the code to provide the min/max X values and write them to attributes, however the coordinates used are the WCS coordinates for each individual part. Is there a way to have it use the WCS coordinates of the assembly? I'm using NX2206.

The code from the previous thread:
Code:
Option Strict Off

Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies

Module Module3

    Public theSession As Session = Session.GetSession()
    Public ufs As UFSession = UFSession.GetUFSession()
    Public lw As ListingWindow = theSession.ListingWindow

    Sub Main()
        Dim workPart As Part = theSession.Parts.Work
        Dim dispPart As Part = theSession.Parts.Display

        lw.Open()


        Dim myAsmInfo As New NXJ_Assembly_info
        myAsmInfo.Part = dispPart

        For Each temp As Component In myAsmInfo.AllComponents

            lw.WriteLine(temp.DisplayName)
            lw.WriteLine(temp.ReferenceSet)

            Dim tempBody As Body = GetCompBody(temp)
            If IsNothing(tempBody) Then
                lw.WriteLine("no body")
                lw.WriteLine("")
                Continue For
            Else
                lw.WriteLine("body tag: " & tempBody.Tag.ToString)
            End If

            Dim compBodyDims As New List(Of Double)
            compBodyDims = BodyBounds(tempBody)

            lw.WriteLine("X: " & compBodyDims.Item(0).ToString)
            lw.WriteLine("Y: " & compBodyDims.Item(1).ToString)
            lw.WriteLine("Z: " & compBodyDims.Item(2).ToString)

            lw.WriteLine("")

            PartStringAttribute(temp.Prototype.OwningPart, "BoundX", compBodyDims.Item(0).ToString)
            PartStringAttribute(temp.Prototype.OwningPart, "BoundY", compBodyDims.Item(1).ToString)
            PartStringAttribute(temp.Prototype.OwningPart, "BoundZ", compBodyDims.Item(2).ToString)

            compBodyDims.Sort()
            Dim bounds As String = compBodyDims.Item(0).ToString & " x " & compBodyDims.Item(1).ToString & " x " & compBodyDims.Item(2).ToString

            PartStringAttribute(temp.Prototype.OwningPart, "Bounds", bounds)


        Next


        lw.Close()

    End Sub

    Function GetCompBody(ByVal theComp As Component) As Body

        'return the first solid body found in the component's reference set

        Dim refSetName As String = theComp.ReferenceSet
        Dim thePart As Part = theComp.Prototype.OwningPart

        If refSetName.ToLower = "empty" Then
            Return Nothing
        End If

        If refSetName.ToLower = "entire part" Then
            For Each tempBody As Body In thePart.Bodies
                If tempBody.IsSolidBody Then
                    Return tempBody
                End If
            Next
            'no solid bodies in part
            Return Nothing
        End If

        For Each theRefSet As ReferenceSet In thePart.GetAllReferenceSets

            If theRefSet.Name = refSetName Then
                Dim refObjs() As NXObject = theRefSet.AskAllDirectMembers

                For Each temp As NXObject In refObjs
                    If TypeOf (temp) Is Body Then
                        Dim theBody As Body = temp
                        If theBody.IsSolidBody Then
                            Return theBody
                        End If
                    End If
                Next
                'no solid bodies in part
                Return Nothing
            End If
        Next

        'reference set not found
        Return Nothing

    End Function

    Function BodyBounds(ByVal theBody As Body) As List(Of Double)

        Dim bbox(5) As Double
        Dim boundX As Double
        Dim boundY As Double
        Dim boundZ As Double
        Dim boundingDims As New List(Of Double)

        'get solid body bounding box extents
        ufs.Modl.AskBoundingBox(theBody.Tag, bbox)
        ' msgbox ("min X: " & bbox(0) & " max X: " & bbox(3) & vbcrlf _
        ' & "min Y: " & bbox(1) & " max Y: " & bbox(4) & vbcrlf _
        ' & "min Z: " & bbox(2) & " max Z: " & bbox(5) & vbcrlf & vbcrlf & _
        ' "X dim: " & bbox(3) - bbox(0) & vbcrlf & _
        ' "Y dim: " & bbox(4) - bbox(1) & vbcrlf & _
        ' "Z dim: " & bbox(5) - bbox(2), vbokonly)

        boundX = bbox(3) - bbox(0)
        boundY = bbox(4) - bbox(1)
        boundZ = bbox(5) - bbox(2)

        boundingDims.Add(boundX)
        boundingDims.Add(boundY)
        boundingDims.Add(boundZ)

        Return boundingDims

    End Function

    Sub PartStringAttribute(ByVal thePart As Part, ByVal theTitle As String, ByVal theValue As String)

        Dim markId1 As Session.UndoMarkId
        markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, "part attribute")

        Dim objects1(0) As NXObject
        objects1(0) = thePart
        Dim attributePropertiesBuilder1 As AttributePropertiesBuilder
        attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(thePart, objects1, AttributePropertiesBuilder.OperationType.None)

        attributePropertiesBuilder1.IsArray = False

        attributePropertiesBuilder1.DataType = AttributePropertiesBaseBuilder.DataTypeOptions.String

        attributePropertiesBuilder1.Title = theTitle

        attributePropertiesBuilder1.StringValue = theValue

        Dim nXObject1 As NXObject
        nXObject1 = attributePropertiesBuilder1.Commit()

        Dim nErrs1 As Integer
        nErrs1 = theSession.UpdateManager.DoUpdate(markId1)

        attributePropertiesBuilder1.Destroy()


    End Sub

    Public Function GetUnloadOption(ByVal dummy As String) As Integer
        Return Session.LibraryUnloadOption.Immediately
    End Function

End Module




Public Class NXJ_Assembly_info

#Region "Private Variables"

    Private Const Version As String = "0.2.0"

    Private _theSession As Session = Session.GetSession()
    Private _theUfSession As UFSession = UFSession.GetUFSession

    Private _components As New List(Of Assemblies.Component)
    Private _uniqueParts As New List(Of Part)
    Private _allComponents As New List(Of Assemblies.Component)
    Private _allUniqueParts As New List(Of Part)
    Private _notLoaded As New List(Of String)

    Private lg As LogFile = _theSession.LogFile

#End Region

#Region "Properties"

    Private _isTCRunning As Boolean
    Public ReadOnly Property IsTCRunning() As Boolean
        Get
            Return _isTCRunning
        End Get
    End Property

    Private _thePart As Part = Nothing
    Public Property Part() As Part
        Get
            Return _thePart
        End Get
        Set(ByVal value As Part)
            _thePart = value
            'Me.GetInfo()
            Me.GetAllInfo()
        End Set
    End Property

    Public ReadOnly Property AllComponents() As List(Of Component)
        Get
            Return _allComponents
        End Get
    End Property

    Public ReadOnly Property AllUniqueParts() As List(Of Part)
        Get
            Return _allUniqueParts
        End Get
    End Property

    Public ReadOnly Property Components As List(Of Component)
        Get
            Return _components
        End Get
    End Property

    Public ReadOnly Property UniqueParts As List(Of Part)
        Get
            Return _uniqueParts
        End Get
    End Property

    Public ReadOnly Property NotLoaded As List(Of String)
        Get
            Return _notLoaded
        End Get
    End Property

#End Region

    Public Sub New()

        lg.WriteLine("")
        lg.WriteLine("~ NXJournaling.com: NXJ_Assembly_info object created ~")
        lg.WriteLine("  ~~ Version: " & Version & " ~~")
        lg.WriteLine("  ~~ Timestamp of run: " & DateTime.Now.ToString & " ~~")
        lg.WriteLine("NXJ_Assembly_info Sub New()")

        'determine if we are running under TC or native
        _theUfSession.UF.IsUgmanagerActive(_isTCRunning)
        lg.WriteLine("IsTcRunning: " & _isTCRunning.ToString)

        lg.WriteLine("exiting Sub New")
        lg.WriteLine("")


    End Sub

    Private Sub GetAllInfo()

        'get all component info from assembly (all levels)
        lg.WriteLine("Sub GetAllInfo()")

        Try
            Dim c As ComponentAssembly = Part.ComponentAssembly
            If Not IsNothing(c.RootComponent) Then
                '*** insert code to process 'root component' (assembly file)
                lg.WriteLine("  part has components")
                '*** end of code to process root component
                lg.WriteLine("  calling GetAllComponentChildren")
                GetAllComponentChildren(c.RootComponent)
            Else
                '*** insert code to process piece part, part has no components
                lg.WriteLine("  part has no components")
            End If
        Catch ex As NXException
            lg.WriteLine("Sub GetAllInfo error: " & ex.ErrorCode)
            lg.WriteLine("  " & ex.Message)
        End Try

        lg.WriteLine("exiting Sub GetAllInfo()")

    End Sub

    Private Sub GetAllComponentChildren(ByVal comp As Component)

        For Each child As Component In comp.GetChildren()
            lg.WriteLine(child.DisplayName)
            '*** insert code to process component or subassembly

            If Me.LoadComponent(child) Then

                _allComponents.Add(child)

                Dim tempPart As Part = child.Prototype.OwningPart
                If Not _allUniqueParts.Contains(tempPart) Then
                    _allUniqueParts.Add(tempPart)
                End If

            Else
                'component could not be loaded
            End If
            '*** end of code to process component or subassembly
            If child.GetChildren.Length <> 0 Then
                '*** this is a subassembly, add code specific to subassemblies

                '*** end of code to process subassembly
            Else
                'this component has no children (it is a leaf node)
                'add any code specific to bottom level components

            End If
            Me.GetAllComponentChildren(child)
        Next
    End Sub


    Private Sub GetInfo()

        'get top level component info from assembly (no recursion)
        lg.WriteLine("Sub GetInfo()")

        Try
            Dim c As ComponentAssembly = Part.ComponentAssembly
            If Not IsNothing(c.RootComponent) Then
                '*** insert code to process 'root component' (assembly file)
                lg.WriteLine("  part has components")
                '*** end of code to process root component
                lg.WriteLine("  calling GetComponentChildren")
                Me.GetComponentChildren(c.RootComponent)
            Else
                '*** insert code to process piece part, part has no components
                lg.WriteLine("  part has no components")
            End If
        Catch ex As NXException
            lg.WriteLine("Sub GetInfo error: " & ex.ErrorCode)
            lg.WriteLine("  " & ex.Message)
        End Try

        lg.WriteLine("exiting GetInfo()")

    End Sub

    Private Sub GetComponentChildren(ByVal comp As Component)

        For Each child As Component In comp.GetChildren()
            '*** insert code to process component or subassembly
            _components.Add(child)
            Dim tempPart As Part = child.Prototype.OwningPart
            If Not _uniqueParts.Contains(tempPart) Then
                _uniqueParts.Add(tempPart)
            End If
            '*** end of code to process component or subassembly
            If child.GetChildren.Length <> 0 Then
                '*** this is a subassembly, add code specific to subassemblies

                '*** end of code to process subassembly
            Else
                'this component has no children (it is a leaf node)
                'add any code specific to bottom level components

            End If
        Next
    End Sub

    Private Function LoadComponent(ByVal theComponent As Component) As Boolean

        lg.WriteLine("Sub LoadComponent()")

        Dim thePart As Part = theComponent.Prototype.OwningPart

        Dim partName As String = ""
        Dim refsetName As String = ""
        Dim instanceName As String = ""
        Dim origin(2) As Double
        Dim csysMatrix(8) As Double
        Dim transform(3, 3) As Double

        Dim curLoadOptions As UFAssem.Options
        _theUfSession.Assem.AskAssemOptions(curLoadOptions)

        Dim newLoadOptions As UFAssem.Options
        _theUfSession.Assem.AskAssemOptions(newLoadOptions)
        newLoadOptions.load_options = UFConstants.UF_ASSEM_load_as_saved
        _theUfSession.Assem.SetAssemOptions(newLoadOptions)

        Try
            If thePart.IsFullyLoaded Then
                'component is fully loaded
                lg.WriteLine("  component: " & theComponent.DisplayName & " is already fully loaded")
            Else
                'component is partially loaded
                lg.WriteLine("  component: " & theComponent.DisplayName & " is already partially loaded")
                lg.WriteLine("  attempting to fully load the part file")
                thePart.LoadThisPartFully()
            End If
            lg.WriteLine("  return: True")
            lg.WriteLine("exiting Sub LoadComponent()")
            lg.WriteLine("")
            Return True
        Catch ex As NullReferenceException
            'component is not loaded
            Try
                lg.WriteLine("  component not loaded, retrieving part information")
                _theUfSession.Assem.AskComponentData(theComponent.Tag, partName, refsetName, instanceName, origin, csysMatrix, transform)
                lg.WriteLine("  component part file: " & partName)

                Dim theLoadStatus As PartLoadStatus
                _theSession.Parts.Open(partName, theLoadStatus)

                If theLoadStatus.NumberUnloadedParts > 0 Then
                    If theLoadStatus.NumberUnloadedParts > 1 Then
                        lg.WriteLine("  problem loading " & theLoadStatus.NumberUnloadedParts.ToString & " components")
                    Else
                        lg.WriteLine("  problem loading 1 component")
                    End If

                    Dim allReadOnly As Boolean = True
                    For i As Integer = 0 To theLoadStatus.NumberUnloadedParts - 1
                        lg.WriteLine("part name: " & theLoadStatus.GetPartName(i))
                        lg.WriteLine("part status: " & theLoadStatus.GetStatus(i))
                        If theLoadStatus.GetStatus(i) = 641058 Then
                            'read-only warning, file loaded ok
                        Else
                            '641044: file not found
                            allReadOnly = False
                            If Not _notLoaded.Contains(partName) Then
                                _notLoaded.Add(partName)
                            End If
                        End If
                        lg.WriteLine("status description: " & theLoadStatus.GetStatusDescription(i))
                        lg.WriteLine("")
                    Next
                    If allReadOnly Then
                        lg.WriteLine("  'read-only' warnings only")
                        lg.WriteLine("  return: True")
                        Return True
                    Else
                        'warnings other than read-only...
                        lg.WriteLine("  return: False")
                        lg.WriteLine("exiting Sub LoadComponent()")
                        lg.WriteLine("")
                        Return False
                    End If
                Else
                    lg.WriteLine("  component(s) loaded successfully")
                    lg.WriteLine("  return: True")
                    lg.WriteLine("exiting Sub LoadComponent()")
                    lg.WriteLine("")
                    Return True
                End If

            Catch ex2 As NXException
                lg.WriteLine("  Load error: " & ex2.Message)
                lg.WriteLine("  error code: " & ex2.ErrorCode)
                lg.WriteLine("  return: False")
                lg.WriteLine("exiting Sub LoadComponent()")
                lg.WriteLine("")
                If ex2.Message.ToLower = "file not found" Then
                    If Not _notLoaded.Contains(partName) Then
                        _notLoaded.Add(partName)
                    End If
                End If
                Return False
            End Try
        Catch ex As NXException
            'unexpected error
            lg.WriteLine("  Error in Sub LoadComponent: " & ex.Message)
            lg.WriteLine("  return: False")
            lg.WriteLine("exiting Sub LoadComponent()")
            lg.WriteLine("")
            Return False
        Finally
            'Reset assembly load option to the user's preference.
            _theUfSession.Assem.SetAssemOptions(curLoadOptions)

        End Try

    End Function

End Class

Thank you!
 
Status
Not open for further replies.
Back
Top