9 Replies Latest reply on Jun 20, 2013 2:43 PM by Guru Subramani

    Mass-Properties for Sub-assemblies addin

    Guru Subramani

      Hi,

      I'm trying to create an addin which can extract mass properties from selected components in assemblies. I'm having trouble when there are more than one subassemblies in the document. When there is just one subassembly it macro works, when there are two different subassemblies in the assembly document I just get zero for all the mass properties. I know that all the bodies of all the components are being passed into the AddBodies() method. I think it maybe because I'm using the active document to create the IMassproperty object. I don't know how to work around this either. This seems quite bizarre and I've been stuck with this issue for quite some time. A few code snippets of what I'm trying to do is bellow:

      The program is all in c#

       

      NOTE:

       

      static public DispatchWrapper[] GetallBodies(Component2 comp)

              {

                  if (comp.IGetChildrenCount() > 0) // assembly subcomponent

                  {

                      Object[] subcomponents = ((Object[])comp.GetChildren());

                      List<DispatchWrapper> DWList = new List<DispatchWrapper>();

                      foreach (Object subcomponent in subcomponents)

                      {

                          if (((Component2)subcomponent).Visible == (int)swComponentVisibilityState_e.swComponentVisible)

                          {

                              DispatchWrapper[] DWarr = GetallBodies((Component2)subcomponent);

                              if (DWarr != null)

                              {

                                  foreach (DispatchWrapper DW in DWarr)

                                  {

                                      DWList.Add(DW);

                                  }

                              }

                          }

                      }

                      if (DWList.Count != 0) return DWList.ToArray();

                      else return null;

                  }

                  else // part subcomponent

                  {

                      Object scrap;

                      Object[] bodies = comp.GetBodies3((int)swBodyType_e.swSolidBody, out scrap);

                      bodies = comp.GetBodies((int)swBodyType_e.swSolidBody);

                      if (bodies != null)

                      {

                          DispatchWrapper[] DWarr = (DispatchWrapper[])ObjectArrayToDispatchWrapperArray(bodies);

                          return DWarr;

                      }

                      else

                      {

                          return null;

                      }

                  }

              }

       

      static public DispatchWrapper[] ObjectArrayToDispatchWrapperArray(object[] SwObjects)

              {

                  int arraySize = 0;

                  arraySize = SwObjects.GetUpperBound(0);

                  DispatchWrapper[] dispwrap = new DispatchWrapper[arraySize + 1];

                  int arrayIndex = 0;

                  for (arrayIndex = 0; arrayIndex <= arraySize; arrayIndex++)

                  {

                      dispwrap[arrayIndex] = new DispatchWrapper(SwObjects[arrayIndex]);

                  }

                  return dispwrap;

              }

       

      //// IN THE MAIN CODE THAT CREATES THE MASSPROPERTY OBJECT///

      {

      //doc is the active document

      MassProperty MP = doc.Extension.CreateMassProperty();

      //theseones are the components that are selected, a lot of gibberish for selecting and kind of irrelevant so I ommited it all

      for (int i = 0; i < theseones.Length; i++)

                  {

                      Component2 thisone = (Component2)theseones[i];

                      bodylist = GetallBodies(thisone);

                  }

      foreach (DispatchWrapper body in bodylist) { bdlist.Add(body); } // to create a single array //bdlist just holds the array elements all together to use later

      bodylist = bdlist.ToArray();

      bool check = MP.AddBodies(bodylist);

      MP.Mass.ToString(); // returns "0" when component is a subassembly

      }

       

       

      Thanks a lot for going through my code!! I absolutely cannot procede without a solution to this.

        • Re: Mass-Properties for Sub-assemblies addin
          Jacob Cordingley

          Try this

           

          using SolidWorks.Interop.sldworks;

          using SolidWorks.Interop.swconst;

          using System.Runtime.InteropServices;

          using System;

           

          namespace Macro1.csproj

          {

              public partial class SolidWorksMacro

              {

           

                  public class Components

                  {

                 public      ModelDoc2 model;

                      public double mass;

                  }

                  public void Main()

                  {

                      System.Collections.Generic.List<Components> components = new System.Collections.Generic.List<Components>();

                      SelectionMgr swselmgr;

                      MassProperty MassProp;

                       swselmgr =(SelectionMgr)swApp.IActiveDoc.SelectionManager;

                      for (int SC = 1; SC <= swselmgr.GetSelectedObjectCount(); SC++)

                      {

                          Component2 swcomp = swselmgr.GetSelectedObjectsComponent3(SC, 0);

                          if (swcomp != null)

                          {

                              ModelDoc2 SelectedMod =(ModelDoc2) swcomp.GetModelDoc();

                              MassProp = (MassProperty)SelectedMod.Extension.CreateMassProperty();

                              Components Comp = new Components();

                              Comp.model = (ModelDoc2)swcomp.GetModelDoc();

                              Comp.mass = MassProp.Mass;

                              components.Add(Comp);

                          }

           

                      }

                    

                      foreach (Components cc in components)

                      {

                          string info =string.Format("{0} Mass:{1}", cc.model.GetPathName(),cc.mass.ToString());

           

                          System.Windows.Forms.MessageBox.Show(info);

                      }

                   

                  }

                  /// <summary>

                  ///  The SldWorks swApp variable is pre-assigned for you.

                  /// </summary>

                  public SldWorks swApp;

              }

          }

           

           

            • Re: Mass-Properties for Sub-assemblies addin
              Guru Subramani

              Hi Jacob,

              Thanks for the quick response! But I'm wondering how to create the MassProperties for the active document. I need this because I'm selecting multipule components. If it was just mass then I could just add them all, but I also need Moment of inertia and center of gravity. So for that I need to find the mass properties of a collection of components. I'll also need to assign a reference coordinate system to it too. Is there any way of telling solidworks to calculate everything for me?

               

              Thanks again!!

                • Re: Mass-Properties for Sub-assemblies addin
                  Jacob Cordingley

                  the above code will grab every selected part or assembly so you can add up the mass.  this will not do mass for selected bodies

                   

                  under the Components Class you can add other items to it to store per component

                  I don't know where you will get the moment of inertia, the center of gravity, or reference coordinate from the API

                   

                  are all part the same material?

                    • Re: Mass-Properties for Sub-assemblies addin
                      Guru Subramani

                      Hi Jacob,

                      Well you can get Center of mass and Moment of Inertal by using the MassProperties object,

                       

                      MassProperty MassProp;

                       

                      double mass = MassProp.mass; // mass of what ever is selected by AddBodies() method

                      double[] CM =  MassProp.CenterOfMass; // Center of mass

                       

                      But I don't know how to get around the document stuff, because it appears that solidworks needs all of its parts from one document for AddBodies method to work. If you look in the API reference especially the IMassProperty class then the AddBodies method will make sense. Basically it lets you select what bodies you want to use to calculate the mass properties.

                       

                      Well if it was just mass then I would just add them up but since I need Center of gravity and Moment of intertia I cant just add them so its becoming a pain.

                       

                      Thanks!

                    • Re: Mass-Properties for Sub-assemblies addin
                      Patrick Ohern

                      You could have SW create a temporary assembly of the selected components.  That should let you get all the data you need, that just delete the assembly at the end of the macro.

                  • Re: Mass-Properties for Sub-assemblies addin
                    Guru Subramani

                    I found out how to capture the Center of Mass from the subassemblies and transform them so that they are meaningful in the current document. It turns out you can do coordinate transforms and use these to translate the coordinate system. Once this is done for all the components you can easily add them all up. For center of mass the masses have to be added by weighing them with thier masses.

                     

                    The coordinate transformations are done by using the  MathTransform class.