Cancel
Showing results for 
Search instead for 
Did you mean: 

Select and Apply Material or Density value to component bodies of an assembly

Valued Contributor
Valued Contributor

Does anyone have a trick, HD3D usage, or API that can locate any and all components that don't have a density or material applied and be able to apply a material or density value to those bodies while at the top assembly that contains those components?

 

I've found I can find the bodies lacking a density or material using HD3D reporting and I can select them, but I can't seem to figure out a way to apply a material or density without having to open each part individually.

 

This would only be an at the moment application to run an analysis and these parts wouldn't be saved.

 

Thanks!

18 REPLIES

Re: Select and Apply Material or Density value to component bodies of an assembly

Valued Contributor
Valued Contributor

I had a journal file created, but I'm at loss given my lack of NXOpen programming skills on making this run faster. Currently the code below does what I need, but given it makes each and every part a work part to verify the body densities and to apply the density to the bodies found to have a zero density, it takes quite a bit of time to run.

 

Does anyone have NXOpen skills taking the below code and incorporating the visual reporting functionality?

My theory is that could be used to locate the bodies with a density of zero and create a shorter list array to then apply the densities to only those bodies, which would mean only those components would have to be made the work part.

 

When using the visual reporting to find the components that contain bodies with a density of zero it is capable of locating them without ever having to make any part the work part, which in turn means those parts don't need to be fully loaded. I'm hoping that aspect of visual reporting can be used in the journal code to make a usable array of components to affect the density change. Any suggestions? Thanks!

 

Option Strict Off

Imports System
Imports NXOpen
Imports NXOpen.UF

Module Apply_Default_Density

	Private Dim theSession As NXOpen.Session = NXOpen.Session.GetSession()
	Private Dim ufs As UFSession = UFSession.GetUFSession()
    Dim lw As ListingWindow = theSession.ListingWindow
	Dim workPart As Part
	
    Sub Main()
	
		Dim sessionParts As PartCollection = theSession.Parts
		Dim parts() As NXOpen.BasePart = sessionParts.ToArray()
        Dim originalPart as NXOpen.Part = theSession.Parts.Work
		Dim loadStatus As PartLoadStatus
		Dim b As Body
		Dim bodies() As Body
		Dim density As Double 
		lw.Open()

        For Each workPart In parts
		    theSession.Parts.SetWork(workPart)
			bodies = GetBodiesInReferenceSet("MODEL")
			lw.WriteLine("Part: " & workPart.FullPath())
            For Each b In bodies
				ufs.Modl.AskBodyDensity(b.Tag, UFModl.DensityUnits.KilogramsMeters, density)
				If density = 0 Then
					If Not theSession.Parts.Work Is Nothing Then
						lw.WriteLine("change body density from 0 to 1")
						ufs.Modl.SetBodyDensity(b.Tag, UFModl.DensityUnits.KilogramsMeters, 1.0)
					End If
				Else
					lw.WriteLine("body density: " & density)
				End If
			Next
		Next
        theSession.Parts.SetWork(originalPart)
		lw.Close()
    End Sub

    Sub Echo(ByVal output As String)
        theSession.ListingWindow.Open()
        theSession.ListingWindow.WriteLine(output)
        theSession.LogFile.WriteLine(output)
    End Sub
	
	
	Function GetBodiesInReferenceSet(ByVal refSetName As String) As Body()
        Dim theRefset As ReferenceSet = GetReferenceSet(refSetName)
        Dim theMembers As NXObject() = theRefset.AskMembersInReferenceSet()

        Dim bodyList As System.Collections.ArrayList = New System.Collections.ArrayList
        For Each anObject As NXObject In theMembers
            Try
                Dim aBody As Body = CType(anObject, Body)
                bodyList.Add(aBody)
            Catch ex As Exception
                ' the cast failed so this one is NOT a Body
            End Try
        Next

        Return bodyList.ToArray(GetType(Body))

    End Function

    Function GetReferenceSet(ByVal refSetName As String) As ReferenceSet

        Dim refSetTag As Tag = Tag.Null

        ufs.Obj.CycleByNameAndType(workPart.Tag, refSetName, _
            UFConstants.UF_reference_set_type, False, refSetTag)

        If (refSetTag = Tag.Null) Then Return Nothing

        Dim theRefSet As ReferenceSet = _
            CType(Utilities.NXObjectManager.Get(refSetTag), ReferenceSet)

        Return theRefSet

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


End Module

Re: Select and Apply Material or Density value to component bodies of an assembly

Gears Esteemed Contributor Gears Esteemed Contributor
Gears Esteemed Contributor

The code below will find bodies with zero density and change them to a density value of 1. I don't have a large assembly to test it on, but I think it will be faster than your current journal. It only processes bodies with a density value of zero and it only operates on the currently displayed assembly.

 

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF

Module Module2

    Private theSession As NXOpen.Session = NXOpen.Session.GetSession()
    Private ufs As UFSession = UFSession.GetUFSession()
    Dim lw As ListingWindow = theSession.ListingWindow
    Dim workPart As Part

    Sub Main()

        lw.Open()

        Dim assemblyBodies As New List(Of Body)
        assemblyBodies = AskAllUniqueBodies(theSession.Parts.Display)

        For Each b As Body In assemblyBodies
            'lw.WriteLine("body: " & b.Tag.ToString)
            'lw.WriteLine("occurrence: " & b.IsOccurrence.ToString)
            'If b.IsOccurrence Then
            '    Dim protoBody As Body = b.Prototype
            '    lw.WriteLine("body prototype tag: " & protoBody.Tag.ToString)
            '    lw.WriteLine("owning component: " & b.OwningComponent.DisplayName)
            'End If
            'lw.WriteLine("owning part: " & b.OwningPart.Leaf)
            'lw.WriteLine("density: " & b.Density.ToString)
            'lw.WriteLine("")

            If b.Density <= 0 Then
                If b.IsOccurrence Then
                    theSession.Parts.SetWork(b.Prototype.OwningPart)
                    Dim bProto As Body = b.Prototype
                    bProto.Density = 1
                Else
                    b.Density = 1
                End If
            End If
        Next

        theSession.Parts.SetWork(Nothing)

        lw.Close()
    End Sub

    Function AskAllUniqueBodies(ByVal thePart As Part) As List(Of Body)

        Dim theBodies As New List(Of Body)
        Dim protoBodies As New List(Of Tag)

        Dim aBodyTag As Tag = Tag.Null
        Do
            ufs.Obj.CycleObjsInPart(thePart.Tag,
                UFConstants.UF_solid_type, aBodyTag)
            If aBodyTag = Tag.Null Then
                Exit Do
            End If

            Dim theType As Integer, theSubtype As Integer
            ufs.Obj.AskTypeAndSubtype(aBodyTag, theType, theSubtype)
            If theSubtype = UFConstants.UF_solid_body_subtype Then
                Dim someBody As Body = Utilities.NXObjectManager.Get(aBodyTag)
                If someBody.IsOccurrence Then
                    Dim someProtoBody As Body = someBody.Prototype
                    If Not protoBodies.Contains(someProtoBody.Tag) Then
                        theBodies.Add(someBody)
                        protoBodies.Add(someProtoBody.Tag)
                    End If
                End If

            End If
        Loop While True

        Return theBodies

    End Function

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

End Module

Re: Select and Apply Material or Density value to component bodies of an assembly

Valued Contributor
Valued Contributor

You never cease to amaze me! :-)

Works perfectly!

Tried it on a very large assembly and placed a random component deep in the assembly structure with a density of zero, it located it, and updated it to 1.

It also avoided the bodies that weren't on the Model reference set since I'm assuming the code only affected the bodies that were visible. Exactly what I needed!

 

Thank you!

Re: Select and Apply Material or Density value to component bodies of an assembly

Gears Esteemed Contributor Gears Esteemed Contributor
Gears Esteemed Contributor

Glad it helped, thanks for the feedback!

Re: Select and Apply Material or Density value to component bodies of an assembly

Gears Esteemed Contributor Gears Esteemed Contributor
Gears Esteemed Contributor

cowski -

Copied this down, un-commented all the "lw" output (and commented out the code to set the density).

I ran against a couple assemblies, and the density for ALL solids was reported as "7830.643699..."

 

NX10.0.3.5 MP16.

 

"Info" on one of the bodies reports

Density (Lb/Cu Inch) = 0.28290000000

 

??

Ken Akerboom Sr CAx Systems Engr, Moog, Inc.
Production: NX10.0.3.5 MP16/TC11.2
I'd rather be e-steamed than e-diseaseled


Re: Select and Apply Material or Density value to component bodies of an assembly

Gears Esteemed Contributor Gears Esteemed Contributor
Gears Esteemed Contributor

@Ken_A, the .Density property always reports values in kilograms per cubic meter. Not super useful, in my opinion, but it is what it is.

Re: Select and Apply Material or Density value to component bodies of an assembly

Gears Esteemed Contributor Gears Esteemed Contributor
Gears Esteemed Contributor

@Ken_A

Below is an updated journal that converts the density value based on the displayed part's units. If the display part's units are inches, the density is converted to lbm/in^3; if the units are mm, the density is converted to g/cm^3.

 

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF

Module Module2

    Private theSession As NXOpen.Session = NXOpen.Session.GetSession()
    Private ufs As UFSession = UFSession.GetUFSession()
    Dim lw As ListingWindow = theSession.ListingWindow
    Dim workPart As Part

    Sub Main()

        lw.Open()

        Dim assemblyBodies As New List(Of Body)
        assemblyBodies = AskAllUniqueBodies(theSession.Parts.Display)

        Dim partUnitDensity As Double     'g/cm^3 for metric files, lbm/in^3 for inch files

        'The .Density property always reports kg/m^3
        Dim kgPERm3 As Unit = theSession.Parts.Display.UnitCollection.FindObject("KilogramPerCubicMeter")
        Dim lbPERin3 As Unit = theSession.Parts.Display.UnitCollection.FindObject("PoundMassperCubicInch")
        Dim gPERcm3 As Unit = theSession.Parts.Display.UnitCollection.FindObject("GramPerCubicCentiMeter")

        For Each b As Body In assemblyBodies
            lw.WriteLine("body: " & b.Tag.ToString)
            lw.WriteLine("occurrence: " & b.IsOccurrence.ToString)
            If b.IsOccurrence Then
                Dim protoBody As Body = b.Prototype
                lw.WriteLine("body prototype tag: " & protoBody.Tag.ToString)
                lw.WriteLine("owning component: " & b.OwningComponent.DisplayName)
            End If
            lw.WriteLine("owning part: " & b.OwningPart.Leaf)
            lw.WriteLine("density (kg/m^3): " & b.Density.ToString)
            If theSession.Parts.Display.PartUnits = BasePart.Units.Millimeters Then
                'metric part
                'convert kg/m^3 to g/cm^3
                partUnitDensity = theSession.Parts.Display.UnitCollection.Convert(kgPERm3, gPERcm3, b.Density)
                lw.WriteLine("density (g/cm^3): " & partUnitDensity.ToString)
            Else
                'inch part
                'covert kg/m^3 to lbm/in^3
                partUnitDensity = theSession.Parts.Display.UnitCollection.Convert(kgPERm3, lbPERin3, b.Density)
                lw.WriteLine("density (lbm/in^3): " & partUnitDensity.ToString)
            End If
            lw.WriteLine("")

            If b.Density <= 0 Then
                If b.IsOccurrence Then
                    theSession.Parts.SetWork(b.Prototype.OwningPart)
                    Dim bProto As Body = b.Prototype
                    bProto.Density = 1
                Else
                    b.Density = 1
                End If
            End If
        Next

        theSession.Parts.SetWork(Nothing)

        lw.Close()
    End Sub

    Function AskAllUniqueBodies(ByVal thePart As Part) As List(Of Body)

        Dim theBodies As New List(Of Body)
        Dim protoBodies As New List(Of Tag)

        Dim aBodyTag As Tag = Tag.Null
        Do
            ufs.Obj.CycleObjsInPart(thePart.Tag,
                UFConstants.UF_solid_type, aBodyTag)
            If aBodyTag = Tag.Null Then
                Exit Do
            End If

            Dim theType As Integer, theSubtype As Integer
            ufs.Obj.AskTypeAndSubtype(aBodyTag, theType, theSubtype)
            If theSubtype = UFConstants.UF_solid_body_subtype Then
                Dim someBody As Body = Utilities.NXObjectManager.Get(aBodyTag)
                If someBody.IsOccurrence Then
                    Dim someProtoBody As Body = someBody.Prototype
                    If Not protoBodies.Contains(someProtoBody.Tag) Then
                        theBodies.Add(someBody)
                        protoBodies.Add(someProtoBody.Tag)
                    End If
                End If

            End If
        Loop While True

        Return theBodies

    End Function

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

End Module

Re: Select and Apply Material or Density value to component bodies of an assembly

Valued Contributor
Valued Contributor

Hi @cowski1,

Can I ask another favor?

If you have time could you tweak your original code shown below to somehow ignore any zero density applied to model via an applied Material File? We have some serious mess up material files I guess.

 

The problem I came across is if the code finds a body with a zero density, but that zero density is because of an applied material file the code will error and stop since the Edit Density function can't apply a density when there is an applied Material File. It results in this error:

Error1.png

Thank you again for your help with this.

 

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF

Module Module2

    Private theSession As NXOpen.Session = NXOpen.Session.GetSession()
    Private ufs As UFSession = UFSession.GetUFSession()
    Dim lw As ListingWindow = theSession.ListingWindow
    Dim workPart As Part

    Sub Main()
	If IsNothing(theSession.Parts.BaseWork) Then
		'active part required
		Return
    End If

        lw.Open()

        Dim assemblyBodies As New List(Of Body)
        assemblyBodies = AskAllUniqueBodies(theSession.Parts.Display)

        For Each b As Body In assemblyBodies
            'lw.WriteLine("body: " & b.Tag.ToString)
            'lw.WriteLine("occurrence: " & b.IsOccurrence.ToString)
            'If b.IsOccurrence Then
                'Dim protoBody As Body = b.Prototype
                'lw.WriteLine("body prototype tag: " & protoBody.Tag.ToString)
                'lw.WriteLine("owning component: " & b.OwningComponent.DisplayName)
            'End If
            'lw.WriteLine("owning part: " & b.OwningPart.Leaf)
            'lw.WriteLine("density: " & b.Density.ToString)
            'lw.WriteLine("")

            If b.Density <= 0 Then
                If b.IsOccurrence Then
                    theSession.Parts.SetWork(b.Prototype.OwningPart)
                    Dim bProto As Body = b.Prototype
                    bProto.Density = 1000000
                Else
                    b.Density = 1000000
                End If
            End If
        Next

        theSession.Parts.SetWork(Nothing)

        lw.Close()
    End Sub

    Function AskAllUniqueBodies(ByVal thePart As Part) As List(Of Body)

        Dim theBodies As New List(Of Body)
        Dim protoBodies As New List(Of Tag)

        Dim aBodyTag As Tag = Tag.Null
        Do
            ufs.Obj.CycleObjsInPart(thePart.Tag,
                UFConstants.UF_solid_type, aBodyTag)
            If aBodyTag = Tag.Null Then
                Exit Do
            End If

            Dim theType As Integer, theSubtype As Integer
            ufs.Obj.AskTypeAndSubtype(aBodyTag, theType, theSubtype)
            If theSubtype = UFConstants.UF_solid_body_subtype Then
                Dim someBody As Body = Utilities.NXObjectManager.Get(aBodyTag)
                If someBody.IsOccurrence Then
                    Dim someProtoBody As Body = someBody.Prototype
                    If Not protoBodies.Contains(someProtoBody.Tag) Then
                        theBodies.Add(someBody)
                        protoBodies.Add(someProtoBody.Tag)
                    End If
                End If

            End If
        Loop While True

        Return theBodies

    End Function

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

End Module

Re: Select and Apply Material or Density value to component bodies of an assembly

Valued Contributor
Valued Contributor

@cowski1

 

I guess another alternative is to somehow edit the applied material instead of ignoring the model, if the file is found to have a zero density as well via a applied material. But I'm again clueless on how to edit that with journal code.

 

Thanks so much!