AskMassProps3d in NXOpen

Hi,

I am trying to fetch the following info out of my workpart(an assembly).

1. Mass
2. Centre of mass
3. RadiusOfGyration

I am using the below code to get the same.It works fine in part level,whereas isn't returning any value in assembly level..Please advise if I'm missing out on something.

Cheers,
Aditya


Part workPart = theSession.Parts.Work;
Part displayPart = theSession.Parts.Display;

double[] dblAcc_Value = new double[11];
double[] dblMass_Props = new double[47];
double[] dblStats = new double[13];

//Tag[] taglist = new Tag[1];
dblAcc_Value[0] = 0.99;

foreach (Body sb in workPart.Bodies)
{
//taglist[1] = sb.Tag;

Tag[] taglist = new Tag[1] { sb.Tag };

ufSession.Modl.AskMassProps3d(taglist, 1, 1, 1, 0.0375, 1, dblAcc_Value, dblMass_Props, dblStats);

MessageBox.Show("Mass = " + dblMass_Props[2].ToString() + "\nCentre of mass X = " + dblMass_Props[3].ToString() + "\nCentre of mass Y = " + dblMass_Props[4].ToString() + "\nCentre of mass Z = " + dblMass_Props[5].ToString() + "\nRadiusOfGyration X = " + dblMass_Props[37].ToString() + "\nRadiusOfGyration Y = " + dblMass_Props[38].ToString() + "\nRadiusOfGyration Z = " + dblMass_Props[39].ToString());

}

}

There are two major items of note about the code above.

1) Arrays in C++ and C# are zero based. Your code declares an array that holds two items, item 0 and item 1. Nothing is assigned to item 0 and later in the call to AskMassProps3d, the array of two items are passed in, but you tell it that you are only passing in one item.

Telling the AskMassProps3d function that you are passing in one item, then passing in a two item array where the first one is empty may confuse the function, or it may simply look at the first item, which happens to be empty. Either way, I doubt that the code gets that far because...

2) Component bodies do not appear in the assembly file .Bodies collection. In the code above, you are processing the bodies in the "displayPart.Bodies" collection; if the display part is the assembly file, you will not find the component bodies here. Component bodies are owned by the component part files. However, there is a UF function that will return all of the occurrence (component) bodies that are loaded in the assembly file: CycleObjsInPart.

You can use the CycleObjsInPart function to get the bodies of interest, or you can iterate through the components, getting the body(ies) used in each. Of the two choices, CycleObjsInPart is easier.

Hi,

Thanks for the reply.I have changed the issue with Array...but not able to figure out how do I use CycleObjsInPart function clubbed with AskMassProps3d..can you please guide?

Regards,
Aditya

Here's an example.

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

Module Module1

Dim theSession As Session = Session.GetSession()
Dim theUfSession As UFSession = UFSession.GetUFSession()
Dim lw As ListingWindow = theSession.ListingWindow

Sub Main()

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

Dim workPart As Part = theSession.Parts.Work
lw.Open()

Const undoMarkName As String = "report assembly mass props"
Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, undoMarkName)

Dim bodyTags As New List(Of Tag)
bodyTags = AskAllBodyTags(theSession.Parts.Display)
'lw.WriteLine("number of body tags found: " & bodyTags.Count.ToString)

Dim acc_value(10) As Double
acc_value(0) = 0.95
Dim mass_props(46) As Double
Dim stats(12) As Double
theUfSession.Modl.AskMassProps3d(bodyTags.ToArray, bodyTags.Count, 1, 1, 0.03, 1, acc_value, mass_props, stats)

lw.WriteLine("surface area: " & mass_props(0).ToString)
lw.WriteLine("mass: " & mass_props(2).ToString)
lw.WriteLine("center of mass: " & "(" & mass_props(3).ToString & ", " & mass_props(4).ToString & ", " & mass_props(5).ToString & ")")

lw.Close()

End Sub

Function AskAllBodyTags(ByVal thePart As Part) As List(Of Tag)

Dim theBodyTags As New List(Of Tag)

Dim aBodyTag As Tag = Tag.Null
Do
theUfSession.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
theUfSession.Obj.AskTypeAndSubtype(aBodyTag, theType, theSubtype)
If theSubtype = UFConstants.UF_solid_body_subtype Then

Dim bodyType As Integer = 0
theUfSession.Modl.AskBodyType(aBodyTag, bodyType)
If bodyType = UFConstants.UF_MODL_SOLID_BODY Then
theBodyTags.Add(aBodyTag)
End If

End If

Loop While True

Return theBodyTags

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image immediately after execution within NX
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately

End Function

End Module

Thanks,

It worked perfectly fine.I was missing out on the do loop.Now I have tweeked your portion of code to my need and its serving my purpose..One question though..CycleObjsInPart-does this work only for work part/display part or it can be used for any random part in the part list?

Regards,
Aditya

The CycleObjsInPart can be used on any fully-loaded part in session.

Thanks for the replies...It been really helpful..I have found one more issue in my code.I am cycling through selected set of components in an assy and trying to fetch information with AskMassProps3d. My code works fine for the first run,but from the second run onwards its adding the values from the first run..Eg.Lets say in the 1st run I got a weight of 1 lb and for the second component it should be 1 lb,but it is adding 1 lb from previous run and returning 2 lb as result and so on..I tried clearing the array after each run still no good.In debug mode,I found it is actually clearing the array yet returning absurd value.Below is my code snippet.Please have a look and advise where I am going wrong..


foreach (Component aNXComp in selectedParts)
{

aNXPart = (Part)theSession.Parts.FindObject(aNXComp.Name);

do
{
ufSession.Obj.CycleObjsInPart(aNXPart.Tag, UFConstants.UF_solid_type, ref objectTag);

if (objectTag == Tag.Null) break;

ufSession.Obj.AskTypeAndSubtype(objectTag, out theType, out theSubtype);
if (theSubtype == UFConstants.UF_solid_body_subtype)
{

theBodies.Add(objectTag);
}

} while (true);

if (theBodies.Count != 0)
{

ufSession.Modl.AskMassProps3d(theBodies.ToArray(), theBodies.Count, 1, 1, 0.0375, 1, dblAcc_Value, dblMass_Props, dblStats);

}
MessageBox.Show("Part Name=" + aNXComp.Name + "\nMass = " + dblMass_Props[2].ToString() + "\nCentre of mass X = " + dblMass_Props[3].ToString() + "\nCentre of mass Y = " + dblMass_Props[4].ToString() + "\nCentre of mass Z = " + dblMass_Props[5].ToString() + "\nRadiusOfGyration X = " + dblMass_Props[37].ToString() + "\nRadiusOfGyration Y = " + dblMass_Props[38].ToString() + "\nRadiusOfGyration Z = " + dblMass_Props[39].ToString());
Array.Clear(dblMass_Props, 0, dblMass_Props.Length);
}

Currently, your code processes each component in "selectedParts", adding the body tags found in each part to the "theBodies" list. If you want to report the weight of each individual part, you will need to clear out the list at the start of each iteration.

foreach (Component aNXComp in selectedParts)
{

aNXPart = (Part)theSession.Parts.FindObject(aNXComp.Name);
theBodies.Clear;

do
{
...

It worked out!!Thank you very much!I was trying to figure it out for last 2 hrs...