public void StoreToSelection(SelectionMgr swSelMgr, ref AttributeDef mdefattr_chbody)//, ref AttributeDef defattr_chconveyor)
        {
            System.Windows.Forms.MessageBox.Show("StoreToSelection()");

            // If user pressed OK, apply settings to all selected parts (i.e. ChBody in C::E):
            for (int isel = 1; isel <= swSelMgr.GetSelectedObjectCount2(-1); isel++)
            {
                if ((swSelectType_e)swSelMgr.GetSelectedObjectType3(isel, -1) == swSelectType_e.swSelCOMPONENTS)
                {
                    Component2 swPart      = (Component2)swSelMgr.GetSelectedObject6(isel, -1);
                    ModelDoc2  swPartModel = (ModelDoc2)swPart.GetModelDoc();

                    // fetch SW attribute with Chrono parameters for ChBody
                    SolidWorks.Interop.sldworks.Attribute myattr = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(mdefattr_chbody, 0);
                    if (myattr == null)
                    {
                        // if not already added to part, create and attach it
                        myattr = mdefattr_chbody.CreateInstance5(swPartModel, swPart, "Chrono ChBody data", 0, (int)swInConfigurationOpts_e.swThisConfiguration);
                        swPartModel.ForceRebuild3(false); // needed?
                        if (myattr == null)
                        {
                            System.Windows.Forms.MessageBox.Show("myattr null in setting!!");
                        }
                    }

                    ((Parameter)myattr.GetParameter("collision_on")).SetDoubleValue2(
                        Convert.ToDouble(m_collide), (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    ((Parameter)myattr.GetParameter("friction")).SetDoubleValue2(
                        m_friction, (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    ((Parameter)myattr.GetParameter("rolling_friction")).SetDoubleValue2(
                        m_rolling_friction, (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    ((Parameter)myattr.GetParameter("spinning_friction")).SetDoubleValue2(
                        m_spinning_friction, (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    ((Parameter)myattr.GetParameter("restitution")).SetDoubleValue2(
                        m_restitution, (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    ((Parameter)myattr.GetParameter("collision_margin")).SetDoubleValue2(
                        m_collision_margin, (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    ((Parameter)myattr.GetParameter("collision_envelope")).SetDoubleValue2(
                        m_collision_envelope, (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    ((Parameter)myattr.GetParameter("collision_family")).SetDoubleValue2(
                        (double)m_collision_family, (int)swInConfigurationOpts_e.swThisConfiguration, "");

                    /*
                     * // fetch SW attribute with Chrono parameters for ChConveyor
                     * SolidWorks.Interop.sldworks.Attribute myattr_conveyor = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(defattr_chconveyor, 0);
                     * if (myattr_conveyor == null)
                     * {
                     *  // if not already added to part, create and attach it
                     *  myattr_conveyor = defattr_chconveyor.CreateInstance5(swPartModel, swPart, "Chrono ChConveyor data", 0, (int)swInConfigurationOpts_e.swThisConfiguration);
                     *  if (myattr_conveyor == null)
                     *      System.Windows.Forms.MessageBox.Show("myattr null in setting!!");
                     * }
                     *
                     * ((Parameter)myattr_conveyor.GetParameter("conveyor_speed")).SetDoubleValue2(
                     *            m_conveyor_speed, (int)swInConfigurationOpts_e.swThisConfiguration, "");
                     */
                }
            }
        }
        public void UpdateFromSelection(SelectionMgr swSelMgr, ref AttributeDef mdefattr_chbody)//, ref AttributeDef defattr_chconveyor)
        {
            // Fetch current properties from the selected part(s) (i.e. ChBody in C::E)
            for (int isel = 1; isel <= swSelMgr.GetSelectedObjectCount2(-1); isel++)
            {
                if ((swSelectType_e)swSelMgr.GetSelectedObjectType3(isel, -1) == swSelectType_e.swSelCOMPONENTS)
                {
                    Component2 swPart      = (Component2)swSelMgr.GetSelectedObject6(isel, -1);
                    ModelDoc2  swPartModel = (ModelDoc2)swPart.GetModelDoc();

                    // fetch SW attribute with Chrono parameters for ChBody
                    SolidWorks.Interop.sldworks.Attribute myattr = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(mdefattr_chbody, 0);
                    if (myattr == null)
                    {
                        // if not already added to part, create and attach it
                        myattr = mdefattr_chbody.CreateInstance5(swPartModel, swPart, "Chrono::ChBody_data", 0, (int)swInConfigurationOpts_e.swAllConfiguration);

                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntityInvalid))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntityInvalid!");
                        }
                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntitySuppressed))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntitySuppressed!");
                        }
                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntityAmbiguous))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntityAmbiguous!");
                        }
                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntityDeleted))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntityDeleted!");
                        }

                        swPartModel.ForceRebuild3(false); // needed?
                    }

                    Set_collision_on(Convert.ToBoolean(((Parameter)myattr.GetParameter(
                                                            "collision_on")).GetDoubleValue()));
                    Set_friction(((Parameter)myattr.GetParameter(
                                      "friction")).GetDoubleValue());
                    Set_rolling_friction(((Parameter)myattr.GetParameter(
                                              "rolling_friction")).GetDoubleValue());
                    Set_spinning_friction(((Parameter)myattr.GetParameter(
                                               "spinning_friction")).GetDoubleValue());
                    Set_restitution(((Parameter)myattr.GetParameter(
                                         "restitution")).GetDoubleValue());
                    Set_collision_envelope(((Parameter)myattr.GetParameter(
                                                "collision_envelope")).GetDoubleValue());
                    Set_collision_margin(((Parameter)myattr.GetParameter(
                                              "collision_margin")).GetDoubleValue());
                    Set_collision_family((int)((Parameter)myattr.GetParameter(
                                                   "collision_family")).GetDoubleValue());



                    // fetch SW attribute with Chrono parameters for ChConveyor

                    /*
                     * SolidWorks.Interop.sldworks.Attribute myattr_conv = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(defattr_chconveyor, 0);
                     * if (myattr_conv == null)
                     * {
                     *  // if not already added to part, create and attach it
                     *  //myattr_conv = defattr_chconveyor.CreateInstance5(swPartModel, swPart, "Chrono::ChConveyor_data", 0, (int)swInConfigurationOpts_e.swThisConfiguration);
                     * }
                     */
                    /*
                     * // fetch SW attribute with Chrono parameters for ChConveyor (if any!)
                     * SolidWorks.Interop.sldworks.Attribute myattr_conveyor = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(defattr_chconveyor, 0);
                     * if (myattr_conveyor != null)
                     * {
                     *  show_conveyor_params = true;
                     *
                     *  Set_conveyor_speed(((Parameter)myattr_conveyor.GetParameter(
                     *                  "conveyor_speed")).GetDoubleValue());
                     * }
                     */
                }
            }
        }
        public void PythonTraverseFeatures_for_collshapes(Component2 swComp, long nLevel, ref  string asciitext, int nbody, ref MathTransform chbodytransform, ref bool found_collisionshapes, Component2 swCompBase)
        {
            CultureInfo bz = new CultureInfo("en-BZ");
            Feature swFeat;
            swFeat = (Feature)swComp.FirstFeature();

            String bodyname = "body_" + nbody;

            MathTransform subcomp_transform = swComp.GetTotalTransform(true);
            MathTransform invchbody_trasform = (MathTransform)chbodytransform.Inverse();
            MathTransform collshape_subcomp_transform = subcomp_transform.IMultiply(invchbody_trasform); // row-ordered transf. -> reverse mult.order!

            // Export collision shapes
            if (this.checkBox_collshapes.Checked)
            {
                object[] bodies;
                object bodyInfo;
                bodies = (object[])swComp.GetBodies3((int)swBodyType_e.swAllBodies, out bodyInfo);

                if (bodies != null)
                {
                    // see if it contains some collision shape
                    bool build_collision_model = false;
                    for (int ib = 0; ib < bodies.Length; ib++)
                    {
                        Body2 swBody = (Body2)bodies[ib];
                        if (swBody.Name.StartsWith("COLL."))
                            build_collision_model = true;
                    }

                    if (build_collision_model)
                    {
                        if (!found_collisionshapes)
                        {
                            found_collisionshapes = true;

                            // fetch SW attribute with Chrono parameters
                            SolidWorks.Interop.sldworks.Attribute myattr = (SolidWorks.Interop.sldworks.Attribute)swCompBase.FindAttribute(this.mSWintegration.defattr_chbody, 0);

                            if (myattr != null)
                            {
                                asciitext += "\n# Collision parameters \n";
                                double param_friction = ((Parameter)myattr.GetParameter("friction")).GetDoubleValue();
                                double param_restitution = ((Parameter)myattr.GetParameter("restitution")).GetDoubleValue();
                                double param_rolling_friction = ((Parameter)myattr.GetParameter("rolling_friction")).GetDoubleValue();
                                double param_spinning_friction = ((Parameter)myattr.GetParameter("spinning_friction")).GetDoubleValue();
                                double param_collision_envelope = ((Parameter)myattr.GetParameter("collision_envelope")).GetDoubleValue();
                                double param_collision_margin = ((Parameter)myattr.GetParameter("collision_margin")).GetDoubleValue();
                                int    param_collision_family = (int)((Parameter)myattr.GetParameter("collision_family")).GetDoubleValue();

                                asciitext += String.Format(bz, "{0}.SetFriction({1:g});\n", bodyname, param_friction);
                                if (param_restitution != 0)
                                    asciitext += String.Format(bz, "{0}.SetImpactC({1:g});\n", bodyname, param_restitution);
                                if (param_rolling_friction != 0)
                                    asciitext += String.Format(bz, "{0}.SetRollingFriction({1:g});\n", bodyname, param_rolling_friction);
                                if (param_spinning_friction != 0)
                                    asciitext += String.Format(bz, "{0}.SetSpinningFriction({1:g});\n", bodyname, param_spinning_friction);
                                //if (param_collision_envelope != 0.03)
                                    asciitext += String.Format(bz, "{0}.GetCollisionModel().SetEnvelope({1:g});\n", bodyname, param_collision_envelope * ChScale.L);
                                //if (param_collision_margin != 0.01)
                                    asciitext += String.Format(bz, "{0}.GetCollisionModel().SetSafeMargin({1:g});\n", bodyname, param_collision_margin * ChScale.L);
                                if (param_collision_family != 0)
                                    asciitext += String.Format(bz, "{0}.GetCollisionModel().SetFamily({1});\n", bodyname, param_collision_family);
                            }

                            // clear model only at 1st subcomponent where coll shapes are found in features:
                            asciitext += "\n# Collision shapes \n";
                            asciitext += String.Format(bz, "{0}.GetCollisionModel().ClearModel()\n", bodyname);
                        }

                        for (int ib = 0; ib < bodies.Length; ib++)
                        {
                            Body2 swBody = (Body2)bodies[ib];

                            if (swBody.Name.StartsWith("COLL."))
                            {
                                bool rbody_converted = false;
                                if (ConvertToCollisionShapes.SWbodyToSphere(swBody))
                                {
                                    Point3D center_l = new Point3D(); // in local subcomponent
                                    double rad = 0;
                                    ConvertToCollisionShapes.SWbodyToSphere(swBody, ref rad, ref center_l);
                                    Point3D center = SWTaskpaneHost.PointTransform(center_l, ref collshape_subcomp_transform);
                                    asciitext += String.Format(bz, "{0}.GetCollisionModel().AddSphere({1}, chrono.ChVectorD({2},{3},{4}))\n", bodyname,
                                        rad * ChScale.L,
                                        center.X * ChScale.L,
                                        center.Y * ChScale.L,
                                        center.Z * ChScale.L);
                                    rbody_converted = true;
                                }
                                if (ConvertToCollisionShapes.SWbodyToBox(swBody))
                                {
                                    Point3D  vC_l = new Point3D();
                                    Vector3D eX_l = new Vector3D(); Vector3D eY_l = new Vector3D(); Vector3D eZ_l = new Vector3D();
                                    ConvertToCollisionShapes.SWbodyToBox(swBody, ref vC_l, ref eX_l, ref eY_l, ref eZ_l);
                                    Point3D  vC = SWTaskpaneHost.PointTransform(vC_l, ref collshape_subcomp_transform);
                                    Vector3D eX = SWTaskpaneHost.DirTransform(eX_l, ref collshape_subcomp_transform);
                                    Vector3D eY = SWTaskpaneHost.DirTransform(eY_l, ref collshape_subcomp_transform);
                                    Vector3D eZ = SWTaskpaneHost.DirTransform(eZ_l, ref collshape_subcomp_transform);
                                    double hsX = eX.Length * 0.5;
                                    double hsY = eY.Length * 0.5;
                                    double hsZ = eZ.Length * 0.5;
                                    Point3D  vO = vC + 0.5 * eX + 0.5 * eY + 0.5 * eZ;
                                    Vector3D Dx = eX; Dx.Normalize();
                                    Vector3D Dy = eY; Dy.Normalize();
                                    Vector3D Dz = Vector3D.CrossProduct(Dx, Dy);
                                    asciitext += String.Format(bz, "mr = chrono.ChMatrix33D()\n");
                                    asciitext += String.Format(bz, "mr[0,0]={0}; mr[1,0]={1}; mr[2,0]={2} \n", Dx.X, Dx.Y, Dx.Z);
                                    asciitext += String.Format(bz, "mr[0,1]={0}; mr[1,1]={1}; mr[2,1]={2} \n", Dy.X, Dy.Y, Dy.Z);
                                    asciitext += String.Format(bz, "mr[0,2]={0}; mr[1,2]={1}; mr[2,2]={2} \n", Dz.X, Dz.Y, Dz.Z);
                                    asciitext += String.Format(bz, "{0}.GetCollisionModel().AddBox({1},{2},{3},chrono.ChVectorD({4},{5},{6}),mr)\n", bodyname,
                                        hsX * ChScale.L,
                                        hsY * ChScale.L,
                                        hsZ * ChScale.L,
                                        vO.X * ChScale.L,
                                        vO.Y * ChScale.L,
                                        vO.Z * ChScale.L);
                                    rbody_converted = true;
                                }
                                if (ConvertToCollisionShapes.SWbodyToCylinder(swBody))
                                {
                                    Point3D p1_l = new Point3D();
                                    Point3D p2_l = new Point3D();
                                    double rad = 0;
                                    ConvertToCollisionShapes.SWbodyToCylinder(swBody, ref p1_l, ref p2_l, ref rad);
                                    Point3D p1 = SWTaskpaneHost.PointTransform(p1_l, ref collshape_subcomp_transform);
                                    Point3D p2 = SWTaskpaneHost.PointTransform(p2_l, ref collshape_subcomp_transform);
                                    Vector3D Dy = p1 - p2; Dy.Normalize();
                                    double hsY = (p1 - p2).Length * 0.5;
                                    double hsZ = rad;
                                    double hsX = rad;
                                    Point3D  vO = p1 + 0.5 * (p2 - p1);
                                    Vector3D Dx = new Vector3D();
                                    if (Dy.X < 0.9)
                                    {
                                        Vector3D Dtst = new Vector3D(1, 0, 0);
                                        Dx = Vector3D.CrossProduct(Dtst, Dy);
                                    }
                                    else
                                    {
                                        Vector3D Dtst = new Vector3D(0, 1, 0);
                                        Dx = Vector3D.CrossProduct(Dtst, Dy);
                                    }
                                    Vector3D Dz = Vector3D.CrossProduct(Dx, Dy);
                                    asciitext += String.Format(bz, "mr = chrono.ChMatrix33D()\n");
                                    asciitext += String.Format(bz, "mr[0,0]={0}; mr[1,0]={1}; mr[2,0]={2} \n", Dx.X, Dx.Y, Dx.Z);
                                    asciitext += String.Format(bz, "mr[0,1]={0}; mr[1,1]={1}; mr[2,1]={2} \n", Dy.X, Dy.Y, Dy.Z);
                                    asciitext += String.Format(bz, "mr[0,2]={0}; mr[1,2]={1}; mr[2,2]={2} \n", Dz.X, Dz.Y, Dz.Z);
                                    asciitext += String.Format(bz, "{0}.GetCollisionModel().AddCylinder({1},{2},{3},chrono.ChVectorD({4},{5},{6}),mr)\n", bodyname,
                                        hsX * ChScale.L,
                                        hsZ * ChScale.L,
                                        hsY * ChScale.L,
                                        vO.X * ChScale.L,
                                        vO.Y * ChScale.L,
                                        vO.Z * ChScale.L); // note order hsX-Z-Y
                                    rbody_converted = true;
                                }

                                if (ConvertToCollisionShapes.SWbodyToConvexHull(swBody, 30) && !rbody_converted)
                                {
                                    Point3D[] vertexes = new Point3D[1]; // will be resized by SWbodyToConvexHull
                                    ConvertToCollisionShapes.SWbodyToConvexHull(swBody, ref vertexes, 30);
                                    if (vertexes.Length > 0)
                                    {
                                        asciitext += String.Format(bz, "pt_vect = chrono.vector_ChVectorD()\n");
                                        for (int iv = 0; iv < vertexes.Length; iv++)
                                        {
                                            Point3D vert_l = vertexes[iv];
                                            Point3D vert   = SWTaskpaneHost.PointTransform(vert_l, ref collshape_subcomp_transform);
                                            asciitext += String.Format(bz, "pt_vect.push_back(chrono.ChVectorD({0},{1},{2}))\n",
                                                vert.X * ChScale.L,
                                                vert.Y * ChScale.L,
                                                vert.Z * ChScale.L);
                                        }
                                        asciitext += String.Format(bz, "{0}.GetCollisionModel().AddConvexHull(pt_vect)\n", bodyname);
                                    }
                                }

                            } // end dealing with a collision shape

                        } // end solid bodies traversal for converting to coll.shapes

                    } // end if build_collision_model
                }

            } // end collision shapes export
        }
        public void UpdateFromSelection(SelectionMgr swSelMgr, ref AttributeDef mdefattr_chbody)//, ref AttributeDef defattr_chconveyor)
        {
            // Fetch current properties from the selected part(s) (i.e. ChBody in C::E)
            for (int isel = 1; isel <= swSelMgr.GetSelectedObjectCount2(-1); isel++)
            {
                if ((swSelectType_e)swSelMgr.GetSelectedObjectType3(isel, -1) == swSelectType_e.swSelCOMPONENTS)
                {
                    //Component2 swPart = (Component2)swSelMgr.GetSelectedObject6(isel, -1);
                    Component2 swPart      = swSelMgr.GetSelectedObjectsComponent3(isel, -1);
                    ModelDoc2  swPartModel = (ModelDoc2)swPart.GetModelDoc2();
                    Component2 swPartcorr  = swPartModel.Extension.GetCorresponding(swPart); // ***TODO*** for instanced parts? does not work...
                    swPartcorr = swPart;                                                     // ***TODO***

                    if (swPartModel.GetType() == (int)swDocumentTypes_e.swDocASSEMBLY)
                    {
                        if (swPart.Solving == (int)swComponentSolvingOption_e.swComponentFlexibleSolving)
                        {
                            System.Windows.Forms.MessageBox.Show("Fexible assemblies not supported as ChBody (set as Rigid?)");
                            return;
                        }
                        if (swPart.Solving == (int)swComponentSolvingOption_e.swComponentRigidSolving)
                        {
                            System.Windows.Forms.MessageBox.Show("Setting props to rigid assembly as ChBody");
                            AssemblyDoc swAssemblyDoc = (AssemblyDoc)swPartModel;
                            swPart.Select(false);
                            swAssemblyDoc.EditAssembly();
                            swAssemblyDoc.EditRebuild();
                            //return;
                        }
                    }

                    // fetch SW attribute with Chrono parameters for ChBody
                    SolidWorks.Interop.sldworks.Attribute myattr = null;
                    if (swPartcorr != null)
                    {
                        myattr = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(mdefattr_chbody, 0);
                    }
                    if (myattr == null)
                    {
                        // if not already added to part, create and attach it
                        //System.Windows.Forms.MessageBox.Show("Create data");
                        myattr = mdefattr_chbody.CreateInstance5(swPartModel, swPartcorr, "Chrono::ChBody_data", 0, (int)swInConfigurationOpts_e.swAllConfiguration);

                        swPartModel.ForceRebuild3(false); // needed, but does not work...
                        //swPartModel.Rebuild((int)swRebuildOptions_e.swRebuildAll); // needed but does not work...

                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntityInvalid))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntityInvalid!");
                        }
                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntitySuppressed))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntitySuppressed!");
                        }
                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntityAmbiguous))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntityAmbiguous!");
                        }
                        if (myattr.GetEntityState((int)swAssociatedEntityStates_e.swIsEntityDeleted))
                        {
                            System.Windows.Forms.MessageBox.Show("swIsEntityDeleted!");
                        }
                    }

                    Set_collision_on(Convert.ToBoolean(((Parameter)myattr.GetParameter(
                                                            "collision_on")).GetDoubleValue()));
                    Set_friction(((Parameter)myattr.GetParameter(
                                      "friction")).GetDoubleValue());
                    Set_rolling_friction(((Parameter)myattr.GetParameter(
                                              "rolling_friction")).GetDoubleValue());
                    Set_spinning_friction(((Parameter)myattr.GetParameter(
                                               "spinning_friction")).GetDoubleValue());
                    Set_restitution(((Parameter)myattr.GetParameter(
                                         "restitution")).GetDoubleValue());
                    Set_collision_envelope(((Parameter)myattr.GetParameter(
                                                "collision_envelope")).GetDoubleValue());
                    Set_collision_margin(((Parameter)myattr.GetParameter(
                                              "collision_margin")).GetDoubleValue());
                    Set_collision_family((int)((Parameter)myattr.GetParameter(
                                                   "collision_family")).GetDoubleValue());



                    // fetch SW attribute with Chrono parameters for ChConveyor

                    /*
                     * SolidWorks.Interop.sldworks.Attribute myattr_conv = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(defattr_chconveyor, 0);
                     * if (myattr_conv == null)
                     * {
                     *  // if not already added to part, create and attach it
                     *  //myattr_conv = defattr_chconveyor.CreateInstance5(swPartModel, swPart, "Chrono::ChConveyor_data", 0, (int)swInConfigurationOpts_e.swThisConfiguration);
                     * }
                     */
                    /*
                     * // fetch SW attribute with Chrono parameters for ChConveyor (if any!)
                     * SolidWorks.Interop.sldworks.Attribute myattr_conveyor = (SolidWorks.Interop.sldworks.Attribute)swPart.FindAttribute(defattr_chconveyor, 0);
                     * if (myattr_conveyor != null)
                     * {
                     *  show_conveyor_params = true;
                     *
                     *  Set_conveyor_speed(((Parameter)myattr_conveyor.GetParameter(
                     *                  "conveyor_speed")).GetDoubleValue());
                     * }
                     */
                }
            }
        }
        public void PythonTraverseComponent_for_ChBody(Component2 swComp, long nLevel, ref  string asciitext,  int nbody)
        {
            CultureInfo bz = new CultureInfo("en-BZ");
            object[] vmyChildComp = (object[])swComp.GetChildren();
            bool found_chbody_equivalent = false;

            if (nLevel > 1)
                if (nbody == -1)
                    if ((swComp.Solving == (int)swComponentSolvingOption_e.swComponentRigidSolving) ||
                        (vmyChildComp.Length == 0))
            {
                // OK! this is a 'leaf' of the tree of ChBody equivalents (a SDW subassebly or part)

                found_chbody_equivalent = true;

                this.num_comp++;

                nbody = this.num_comp;  // mark the rest of recursion as 'n-th body found'

                if (this.swProgress != null)
                {
                    this.swProgress.UpdateTitle("Exporting " + swComp.Name2 + " ...");
                    this.swProgress.UpdateProgress(this.num_comp % 5);
                }

                // fetch SW attribute with Chrono parameters
                SolidWorks.Interop.sldworks.Attribute myattr = (SolidWorks.Interop.sldworks.Attribute)swComp.FindAttribute(this.mSWintegration.defattr_chbody, 0);

                MathTransform chbodytransform = swComp.GetTotalTransform(true);
                double[] amatr;
                amatr = (double[])chbodytransform.ArrayData;
                string bodyname = "body_" + this.num_comp;

                // Write create body
                asciitext += "# Rigid body part\n";
                asciitext += bodyname + "= chrono.ChBodyAuxRef()" + "\n";

                // Write name
                asciitext += bodyname + ".SetName('" + swComp.Name2 + "')" + "\n";

                // Write position
                asciitext += bodyname + ".SetPos(chrono.ChVectorD("
                           + (amatr[9] * ChScale.L).ToString("g", bz) + ","
                           + (amatr[10]* ChScale.L).ToString("g", bz) + ","
                           + (amatr[11]* ChScale.L).ToString("g", bz) + "))" + "\n";

                // Write rotation
                double[] quat = GetQuaternionFromMatrix(ref chbodytransform);
                asciitext += String.Format(bz, "{0}.SetRot(chrono.ChQuaternionD({1:g},{2:g},{3:g},{4:g}))\n",
                           bodyname, quat[0], quat[1], quat[2], quat[3]);

                // Compute mass

                int nvalid_bodies = 0;
                PythonTraverseComponent_for_countingmassbodies(swComp, ref nvalid_bodies);

                int addedb = 0;
                object[] bodies_nocollshapes = new object[nvalid_bodies];
                PythonTraverseComponent_for_massbodies(swComp, ref bodies_nocollshapes, ref addedb);

                MassProperty swMass;
                swMass = (MassProperty)swComp.IGetModelDoc().Extension.CreateMassProperty();
                bool boolstatus = false;
                boolstatus = swMass.AddBodies((object[])bodies_nocollshapes);
                swMass.SetCoordinateSystem(chbodytransform);
                swMass.UseSystemUnits = true;
                //note: do not set here the COG-to-REF position because here SW express it in absolute coords
                // double cogX = ((double[])swMass.CenterOfMass)[0];
                // double cogY = ((double[])swMass.CenterOfMass)[1];
                // double cogZ = ((double[])swMass.CenterOfMass)[2];
                double mass = swMass.Mass;
                double[] Itensor = (double[])swMass.GetMomentOfInertia((int)swMassPropertyMoment_e.swMassPropertyMomentAboutCenterOfMass);
                double Ixx = Itensor[0];
                double Iyy = Itensor[4];
                double Izz = Itensor[8];
                double Ixy = Itensor[1];
                double Izx = Itensor[2];
                double Iyz = Itensor[5];

                MassProperty swMassb;
                swMassb = (MassProperty)swComp.IGetModelDoc().Extension.CreateMassProperty();
                bool boolstatusb = false;
                boolstatusb = swMassb.AddBodies(bodies_nocollshapes);
                swMassb.UseSystemUnits = true;
                double cogXb = ((double[])swMassb.CenterOfMass)[0];
                double cogYb = ((double[])swMassb.CenterOfMass)[1];
                double cogZb = ((double[])swMassb.CenterOfMass)[2];

                asciitext += String.Format(bz, "{0}.SetMass({1:g})\n",
                           bodyname,
                           mass * ChScale.M);

                // Write inertia tensor
                asciitext += String.Format(bz, "{0}.SetInertiaXX(chrono.ChVectorD({1:g},{2:g},{3:g}))\n",
                           bodyname,
                           Ixx * ChScale.M * ChScale.L * ChScale.L,
                           Iyy * ChScale.M * ChScale.L * ChScale.L,
                           Izz * ChScale.M * ChScale.L * ChScale.L);
                // Note: C::E assumes that's up to you to put a 'minus' sign in values of Ixy, Iyz, Izx
                asciitext += String.Format(bz, "{0}.SetInertiaXY(chrono.ChVectorD({1:g},{2:g},{3:g}))\n",
                           bodyname,
                           -Ixy * ChScale.M * ChScale.L * ChScale.L,
                           -Izx * ChScale.M * ChScale.L * ChScale.L,
                           -Iyz * ChScale.M * ChScale.L * ChScale.L);

                // Write the position of the COG respect to the REF
                asciitext += String.Format(bz, "{0}.SetFrame_COG_to_REF(chrono.ChFrameD(chrono.ChVectorD({1:g},{2:g},{3:g}),chrono.ChQuaternionD(1,0,0,0)))\n",
                            bodyname,
                            cogXb * ChScale.L,
                            cogYb * ChScale.L,
                            cogZb * ChScale.L);

                // Write 'fixed' state
                if (swComp.IsFixed())
                    asciitext += String.Format(bz, "{0}.SetBodyFixed(True)\n", bodyname);

                // Write shapes (saving also Wavefront files .obj)
                if (this.checkBox_surfaces.Checked)
                {
                    int nvisshape = 0;

                    if (swComp.Visible == (int)swComponentVisibilityState_e.swComponentVisible)
                        PythonTraverseComponent_for_visualizationshapes(swComp, nLevel, ref asciitext, nbody, ref nvisshape, swComp);
                }

                // Write markers (SW coordsystems) contained in this component or subcomponents
                // if any.
                PythonTraverseComponent_for_markers(swComp, nLevel, ref asciitext, nbody);

                // Write collision shapes (customized SW solid bodies) contained in this component or subcomponents
                // if any.
                bool param_collide = true;
                if (myattr != null)
                    param_collide = Convert.ToBoolean(((Parameter)myattr.GetParameter("collision_on")).GetDoubleValue());

                if (param_collide)
                {
                    bool found_collisionshapes = false;
                    PythonTraverseComponent_for_collshapes(swComp, nLevel, ref asciitext, nbody, ref chbodytransform, ref found_collisionshapes, swComp);
                    if (found_collisionshapes)
                    {
                        asciitext += String.Format(bz, "{0}.GetCollisionModel().BuildModel()\n", bodyname);
                        asciitext += String.Format(bz, "{0}.SetCollide(True)\n", bodyname);
                    }
                }

                // Insert to a list of exported items
                asciitext += String.Format(bz, "\n" +"exported_items.append({0})\n", bodyname);

                // End writing body in Python-
                asciitext += "\n\n\n";

            } // end if ChBody equivalent (tree leaf or non-flexible assembly)

            // Things to do also for sub-components of 'non flexible' assemblies:
            //

                // store in hashtable, will be useful later when adding constraints
            if ((nLevel > 1) && (nbody != -1))
            try
            {
                string bodyname = "body_" + this.num_comp;

                ModelDocExtension swModelDocExt = default(ModelDocExtension);
                ModelDoc2 swModel = (ModelDoc2)this.mSWApplication.ActiveDoc;
                //if (swModel != null)
                swModelDocExt = swModel.Extension;
                this.saved_parts.Add(swModelDocExt.GetPersistReference3(swComp), bodyname);
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Cannot add part to hashtable?");
            }

            // Traverse all children, proceeding to subassemblies and parts, if any
            //

            object[] vChildComp;
            Component2 swChildComp;

            vChildComp = (object[])swComp.GetChildren();

            for (long i = 0; i < vChildComp.Length; i++)
            {
                swChildComp = (Component2)vChildComp[i];

                PythonTraverseComponent_for_ChBody(swChildComp, nLevel + 1, ref asciitext, nbody);
            }
        }