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());
}
}
re: AskMassProps3d
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,
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
re: cycle objects
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
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
re: cycle objects
The CycleObjsInPart can be used on any fully-loaded part in session.
AskMassProps3d
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);
}
re: AskMassProps3d
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
{
...
Amazing...
It worked out!!Thank you very much!I was trying to figure it out for last 2 hrs...