Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations MintJulep on being selected by the Eng-Tips community for having the most helpful posts in the forums last week. Way to Go!

mass properties problem 1

Status
Not open for further replies.

tbischel

Aerospace
Joined
Apr 2, 2009
Messages
6
Location
US
Hello,
I'm trying to write a C# program to get the mass properties of a selected subassembly in a large assembly. I thought I was following the documentation properly, but I run into one of two problems:
the "AddBodies" function for a mass property object throws an exception if I use the type "swBodyType_e.swSolidBody" as an input.

the mass value returned is that for the entire assembly instead of the added part if I use the type "swBodyType_e.swGeneralBody".

I've attached the function below.
---------
private void APIexample(SldWorks swApp)
{
try
{
ModelDoc2 swModel;
ModelDocExtension swDocExt;
MassProperty swMass;
SelectionMgr swSelMgr;
Component2 swComp;

swModel = (ModelDoc2)swApp.ActiveDoc;
swDocExt = (ModelDocExtension)swModel.Extension;
swMass = (MassProperty)swDocExt.CreateMassProperty();
swSelMgr = (SelectionMgr)swModel.SelectionManager;
swComp = (Component2)swSelMgr.GetSelectedObjectsComponent2(1);

int type = (int)swBodyType_e.swSolidBody;
//This is the line that fails...
swMass.AddBodies(swComp.GetBodies2(type));
MessageBox.Show("Mass: " + swMass.Mass);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
---------
Thanks,
--Tyler
 
The Sub-Assembly itself doesn't contain the bodies. You should traverse the assembly, find the Part Components and call this method.

Your swComp.GetBodies2(type) returns NULL. Just for check preselect the Part Component and the code will work correct.

For traversing use Component2::GetChildren method and recursively call it until the component haven't the children (that means it is a Part based component and you can get the bodies).

Please refer the API Help. There are several examples of Traversing the Assembly.

Artem Taturevich
CSWP
 
So actually I had been selecting parts instead of subassemblies, I don't think that was the problem. GetBodies2 would return an object array with a couple elements, but when I call AddBodies with that array, it throws the exception.. "Attempted to read or write protected memory. This is often
an indication that other memory is corrupt".

I actually do have traversal code you recommended, but came up with this example to isolate the problem getting the mass of specific parts, which I still can't seem to figure out.
 
Hello Tyler,

I'm sorry for the delay. I've missed you reply by some reasons ((.

Please find the attached C# addin which outputs the overall mass and the bodies count of the selected component (both Assembly or Part) to Message Box.

Hope this help.

Artem Taturevich
CSWP
 
 http://files.engineering.com/getfile.aspx?folder=a179a491-feca-407a-85ac-bb7c953ea5b7&file=SwCSharpGetSubAssyMassProps.zip
Artem,
So the source that I received didn't quite work for me... Sometimes it will only return the total mass of the entire assembly instead of the selected part (for instance, when I select a single part), and other times it will just throw an exception "Object reference not set to an instance of an object".

If this worked for you, I'm baffled. Maybe something about working with Visual Studio 2008? Something about working with Solidworks 2009? *shrug*
 
Tyler,

It is really strange. I've created this Addin in VS 2008 and tested with SolidWorks 2009.

BTW. What the line where you have received the "Object reference not set to an instance of an object" exception?

Could you please attach some sample assembly and post what mass values you are expected to have on correspondings sub-assemblies/parts?

Artem Taturevich
CSWP
 
Artem,
So the exception appears to be that GetBodies2 will return null if there are no bodies associated with a bottom level feature (maybe a suppressed part?), so you can't get the length of a null object array. No biggie there...

however, the mass properties never update to the selected bodies, it always just returns the mass for the entire assembly.

I've attached a sample assembly for this:
I should get 110.93 grams for the dish,
522597.02 grams for the sat2 subassembly,
133500.00 grams for each panel within the sat2 subassembly,
255597.02 grams for the body within the sat2 subassembly.

No matter what I select, I get 522.707958041958 kg returned, which equals the sum of all the parts. The correct number of selected bodies is returned though, and when I run through it with the stepper, I can see that it adds the bodies ok. Just not the right output number.

--Tyler
 
 http://files.engineering.com/getfile.aspx?folder=98da952a-bfac-4051-84c0-f3f5a3358fd8&file=Assem1.zip
Tyler,

Thank you for the clarification. Now I can see the issue.

You can use the following workaround. Create the mass properties object not from the Entire Assembly's model doc but from the Component's model doc.

Just change the try-catch code snippet in the GetMass function to the following code snippet:

- - - - - -
IModelDoc2 swModel;
IModelDocExtension swDocExt;
IMassProperty swMass;
ISelectionMgr swSelMgr;
IComponent2 swComp;

swModel = this.iSwApp.IActiveDoc2;
swDocExt = swModel.Extension;

swSelMgr = swModel.ISelectionManager;
swComp = (Component2)swSelMgr.GetSelectedObjectsComponent2(1);
swMass = swComp.IGetModelDoc().Extension.CreateMassProperty();
GetCompBodies(swComp);
bool bRet = swMass.AddBodies(this.swBodies);

this.iSwApp.SendMsgToUser("Bodies: " + this.swBodies.Count + "; Overall Mass: " + swMass.Mass.ToString());
- - - - - -

This should fix the issue. With this modification I get the results exactly as you posted.

Hope this help.

Artem Taturevich
CSWP
 
Thanks Artem! this gets me 90% of the way to what I need. It seems that the swMass.AddBodies has no effect on the mass properties... so if I want to combine the properties of two distinct selected components, I'm not quite sure how to do it. But at least I could manually add the masses of multiple mass property objects (gotta think about how to do the inertia matrix though) If you have any ideas or if I find something, I'll keep monitoring this thread.

Thanks again,
--Tyler
 
Hi Tyler,

I think I understand the problem with mass properties from the Top Assembly.

The MassProperties::AddBodies method expects an array of bodies as the parameter while we have passed an List object. In this case SolidWorks considers it as NULL value and as mentioned in API Help discards this call and calculates the overall mass of the document.

So to fix this issue all we need is convert the list value to array using the List<>::ToArray method. Like the following line:

...
bool bRet = swMass.AddBodies(this.swBodies.ToArray());
...

So the mass properties object can be retrieved from the Top Level Document like in the first version of the sample and bodies will be added correctly.

Please take a look at the following modified version of the GetMass function. BTW. It supports the multi-components selection.

- - - - - - - - - -
public void GetMass()
{
this.swBodies = new List<IBody2>();

IModelDoc2 swModel;
IModelDocExtension swDocExt;
IMassProperty swMass;
ISelectionMgr swSelMgr;
List<IComponent2> swComp = new List<IComponent2>();

swModel = this.iSwApp.IActiveDoc2;
swDocExt = swModel.Extension;
swMass = swDocExt.CreateMassProperty();
swSelMgr = swModel.ISelectionManager;

for (int i = 0; i < swSelMgr.GetSelectedObjectCount2(-1); i++ )
{
IComponent2 curComp = swSelMgr.GetSelectedObjectsComponent2(i + 1) as IComponent2;
//To refrain from components repetition in case the different entities from one component are selected
if (!swComp.Contains(curComp))
{
swComp.Add(curComp);

}

for (int i = 0; i < swComp.Count; i++)
{
GetCompBodies(swComp);
}

bool bRet = swMass.AddBodies(this.swBodies.ToArray());

this.iSwApp.SendMsgToUser("Bodies: " + this.swBodies.Count + "; Overall Mass: " + swMass.Mass.ToString());

double[] axesOfIntertia = (double[])swMass.get_PrincipleAxesOfInertia(1);
double[] momentOfInertia = (double[])swMass.PrincipleMomentsOfInertia;

}
- - - - - - - - - -

Artem Taturevich
CSWP
 
Thanks Artem, it works great!

I wonder if that means the main reason my original code didn't work was a casting problem? Funny way to express itself.

Thanks for the help, I've been banging my head against this one for far too long.

--Tyler
 
>> I wonder if that means the main reason my original code didn't work was a casting problem?

I don't think so. It isn't look like the casting problem.

Artem Taturevich
CSWP
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top