示例#1
0
            public GeomVue(View vue, Sketch esquisse)
            {
                MathUtility SwMath = App.Sw.GetMathUtility();

                gPoint ptCentreVue = new gPoint(vue.Position);
                gPoint ptMin       = new gPoint(Double.PositiveInfinity, Double.PositiveInfinity, 0);
                gPoint ptMax       = new gPoint(Double.NegativeInfinity, Double.NegativeInfinity, 0);

                foreach (SketchPoint s in esquisse.GetSketchPoints2())
                {
                    MathPoint swStartPoint = SwMath.CreatePoint(new Double[3] {
                        s.X, s.Y, s.Z
                    });
                    MathTransform SketchXform = esquisse.ModelToSketchTransform;
                    SketchXform  = SketchXform.Inverse();
                    swStartPoint = swStartPoint.MultiplyTransform(SketchXform);
                    MathTransform ViewXform = vue.ModelToViewTransform;
                    swStartPoint = swStartPoint.MultiplyTransform(ViewXform);
                    gPoint swViewStartPt = new gPoint(swStartPoint);
                    ptMin.Min(swViewStartPt);
                    ptMax.Max(swViewStartPt);
                }

                ptMinX = ptMin.X;
                ptMinY = ptMin.Y;
                ptMaxX = ptMax.X;
                ptMaxY = ptMax.Y;
                MajCentreRectangle();
                ptCentreVueX = ptCentreVue.X;
                ptCentreVueY = ptCentreVue.Y;
            }
示例#2
0
        private Double AngleCubeDeVisualisation(View vue, Sketch esquisse)
        {
            MathUtility SwMath = App.Sw.GetMathUtility();

            List <gPoint> LstPt = new List <gPoint>();

            foreach (SketchPoint s in esquisse.GetSketchPoints2())
            {
                MathPoint point = SwMath.CreatePoint(new Double[3] {
                    s.X, s.Y, s.Z
                });
                MathTransform SketchXform = esquisse.ModelToSketchTransform;
                SketchXform = SketchXform.Inverse();
                point       = point.MultiplyTransform(SketchXform);
                MathTransform ViewXform = vue.ModelToViewTransform;
                point = point.MultiplyTransform(ViewXform);
                gPoint swViewStartPt = new gPoint(point);
                LstPt.Add(swViewStartPt);
            }

            // On recherche le point le point le plus à droite puis le plus haut
            LstPt.Sort(new gPointComparer(ListSortDirection.Descending, p => p.X));
            LstPt.Sort(new gPointComparer(ListSortDirection.Descending, p => p.Y));

            // On le supprime
            LstPt.RemoveAt(0);

            // On recherche le point le point le plus à gauche puis le plus bas
            LstPt.Sort(new gPointComparer(ListSortDirection.Ascending, p => p.X));
            LstPt.Sort(new gPointComparer(ListSortDirection.Ascending, p => p.Y));


            // C'est le point de rotation
            gPoint pt1 = LstPt[0];

            // On recherche le plus loin
            gPoint pt2;
            Double d1 = pt1.Distance(LstPt[1]);
            Double d2 = pt1.Distance(LstPt[2]);

            if (d1 > d2)
            {
                pt2 = LstPt[1];
            }
            // En cas d'égalité, on renvoi le point le plus à gauche
            else if (d1 == d2)
            {
                pt2 = (LstPt[1].X < LstPt[2].X) ? LstPt[1] : LstPt[2];
            }
            else
            {
                pt2 = LstPt[2];
            }

            gVecteur v = new gVecteur(pt1, pt2);

            return(Math.Atan2(v.Y, v.X));
        }
示例#3
0
        public static bool ConvertMateToPython(
            ref Feature swMateFeature,
            ref string asciitext,
            ref ISldWorks mSWApplication,
            ref Hashtable saved_parts,
            ref int num_link,
            ref MathTransform roottrasf,
            ref Component2 assemblyofmates
            )
        {
            if (swMateFeature == null)
            {
                return(false);
            }

            Mate2 swMate = (Mate2)swMateFeature.GetSpecificFeature2();

            if (swMate == null)
            {
                return(false);
            }

            object foo = null;

            bool[] suppressedflags;
            suppressedflags = (bool[])swMateFeature.IsSuppressed2((int)swInConfigurationOpts_e.swThisConfiguration, foo);
            if (suppressedflags[0] == true)
            {
                return(false);
            }

            if (swMate.GetMateEntityCount() >= 2)
            {
                // Get the mated parts
                MateEntity2 swEntityA = swMate.MateEntity(0);
                MateEntity2 swEntityB = swMate.MateEntity(1);
                Component2  swCompA   = swEntityA.ReferenceComponent;
                Component2  swCompB   = swEntityB.ReferenceComponent;
                double[]    paramsA   = (double[])swEntityA.EntityParams;
                double[]    paramsB   = (double[])swEntityB.EntityParams;
                // this is needed because parts might reside in subassemblies, and mate params are expressed in parent subassembly
                MathTransform invroottrasf = (MathTransform)roottrasf.Inverse();
                MathTransform trA          = roottrasf;
                MathTransform trB          = roottrasf;

                if (assemblyofmates != null)
                {
                    MathTransform partrasfA = assemblyofmates.GetTotalTransform(true);
                    if (partrasfA != null)
                    {
                        trA = partrasfA.IMultiply(invroottrasf); // row-ordered transf. -> reverse mult.order!
                    }
                    MathTransform partrasfB = assemblyofmates.GetTotalTransform(true);
                    if (partrasfB != null)
                    {
                        trB = partrasfB.IMultiply(invroottrasf); // row-ordered transf. -> reverse mult.order!
                    }
                }


                // Fetch the python names using hash map (python names added when scanning parts)
                ModelDocExtension swModelDocExt = default(ModelDocExtension);
                ModelDoc2         swModel       = (ModelDoc2)mSWApplication.ActiveDoc;
                swModelDocExt = swModel.Extension;
                String name1 = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompA)];
                String name2 = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompB)];

                // Only constraints between two parts or part & layout can be created
                if (((name1 != null) || (name2 != null)) && (name1 != name2))
                {
                    CultureInfo bz = new CultureInfo("en-BZ");

                    if (name1 == null)
                    {
                        name1 = "body_0";
                    }
                    if (name2 == null)
                    {
                        name2 = "body_0";
                    }

                    // Add some comment in Python, to list the referenced SW items
                    asciitext += "\n# Mate constraint: " + swMateFeature.Name + " [" + swMateFeature.GetTypeName2() + "]" + " type:" + swMate.Type + " align:" + swMate.Alignment + " flip:" + swMate.Flipped + "\n";
                    for (int e = 0; e < swMate.GetMateEntityCount(); e++)
                    {
                        MateEntity2 swEntityN = swMate.MateEntity(e);
                        Component2  swCompN   = swEntityN.ReferenceComponent;
                        String      ce_nameN  = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompN)];
                        if (ce_nameN == "")
                        {
                            ce_nameN = "body_0"; // reference assembly
                        }
                        asciitext += "#   Entity " + e + ": C::E name: " + ce_nameN + " , SW name: " + swCompN.Name2 + " ,  SW ref.type:" + swEntityN.Reference.GetType() + " (" + swEntityN.ReferenceType2 + ")\n";
                    }
                    asciitext += "\n";

                    //
                    // For each type of SW mate, see which C::E mate constraint(s)
                    // must be created. Some SW mates correspond to more than one C::E constraints.
                    //

                    bool   swapAB_1             = false;
                    bool   do_CHmate_Xdistance  = false;
                    double do_distance_val      = 0.0;
                    bool   do_CHmate_parallel   = false;
                    bool   do_parallel_flip     = false;
                    bool   do_CHmate_orthogonal = false;
                    bool   do_CHmate_spherical  = false;
                    bool   do_CHmate_pointline  = false;

                    // to simplify things later...
                    // NOTE: swMate.MateEntity(0).Reference.GetType() seems equivalent to  swMate.MateEntity(0).ReferenceType2
                    // but in some cases the latter fails.

                    /*
                     * bool entity_0_as_FACE   = (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelFACES);
                     * bool entity_0_as_EDGE   = (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelEDGES) ||
                     *                        (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelSKETCHSEGS) ||
                     *                        (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelDATUMAXES);
                     * bool entity_0_as_VERTEX = (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelVERTICES) ||
                     *                        (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                     *                        (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelDATUMPOINTS);
                     *
                     * bool entity_1_as_FACE   = (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelFACES);
                     * bool entity_1_as_EDGE   = (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelEDGES) ||
                     *                        (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelSKETCHSEGS) ||
                     *                        (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelDATUMAXES);
                     * bool entity_1_as_VERTEX = (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelVERTICES) ||
                     *                        (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                     *                        (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelDATUMPOINTS);
                     */

                    // NOTE: swMate.MateEntity(0).Reference.GetType() seems equivalent to  swMate.MateEntity(0).ReferenceType2
                    // but in some cases the latter fails. However, sometimes swMate.MateEntity(0).Reference.GetType() is null ReferenceType2 is ok,
                    // so do the following trick:
                    int entity0_ref = swMate.MateEntity(0).Reference.GetType();
                    if (entity0_ref == (int)swSelectType_e.swSelNOTHING)
                    {
                        entity0_ref = swMate.MateEntity(0).ReferenceType2;
                    }
                    int entity1_ref = swMate.MateEntity(1).Reference.GetType();
                    if (entity1_ref == (int)swSelectType_e.swSelNOTHING)
                    {
                        entity1_ref = swMate.MateEntity(1).ReferenceType2;
                    }

                    bool entity_0_as_FACE = (entity0_ref == (int)swSelectType_e.swSelFACES) ||
                                            (entity0_ref == (int)swSelectType_e.swSelDATUMPLANES);
                    bool entity_0_as_EDGE = (entity0_ref == (int)swSelectType_e.swSelEDGES) ||
                                            (entity0_ref == (int)swSelectType_e.swSelSKETCHSEGS) ||
                                            (entity0_ref == (int)swSelectType_e.swSelDATUMAXES);
                    bool entity_0_as_VERTEX = (entity0_ref == (int)swSelectType_e.swSelVERTICES) ||
                                              (entity0_ref == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                              (entity0_ref == (int)swSelectType_e.swSelDATUMPOINTS);

                    bool entity_1_as_FACE = (entity1_ref == (int)swSelectType_e.swSelFACES) ||
                                            (entity1_ref == (int)swSelectType_e.swSelDATUMPLANES);
                    bool entity_1_as_EDGE = (entity1_ref == (int)swSelectType_e.swSelEDGES) ||
                                            (entity1_ref == (int)swSelectType_e.swSelSKETCHSEGS) ||
                                            (entity1_ref == (int)swSelectType_e.swSelDATUMAXES);
                    bool entity_1_as_VERTEX = (entity1_ref == (int)swSelectType_e.swSelVERTICES) ||
                                              (entity1_ref == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                              (entity1_ref == (int)swSelectType_e.swSelDATUMPOINTS);


                    Point3D  cA = new Point3D(0, 0, 0);
                    Point3D  cB = new Point3D(0, 0, 0);
                    Vector3D dA = new Vector3D(1, 0, 0);
                    Vector3D dB = new Vector3D(1, 0, 0);

                    Point3D cAloc = new Point3D(paramsA[0], paramsA[1], paramsA[2]);
                    cA = SWTaskpaneHost.PointTransform(cAloc, ref trA);
                    Point3D cBloc = new Point3D(paramsB[0], paramsB[1], paramsB[2]);
                    cB = SWTaskpaneHost.PointTransform(cBloc, ref trB);

                    if (!entity_0_as_VERTEX)
                    {
                        Vector3D dAloc = new Vector3D(paramsA[3], paramsA[4], paramsA[5]);
                        dA = SWTaskpaneHost.DirTransform(dAloc, ref trA);
                    }

                    if (!entity_1_as_VERTEX)
                    {
                        Vector3D dBloc = new Vector3D(paramsB[3], paramsB[4], paramsB[5]);
                        dB = SWTaskpaneHost.DirTransform(dBloc, ref trB);
                    }



                    if (swMateFeature.GetTypeName2() == "MateCoincident")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_spherical = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_pointline = true;
                            swapAB_1            = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_Xdistance = true;
                            swapAB_1            = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance  = true;
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_Xdistance  = true;
                            do_CHmate_orthogonal = true;
                            swapAB_1             = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                        {
                            do_parallel_flip = true;
                        }
                    }

                    if (swMateFeature.GetTypeName2() == "MateConcentric")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_pointline = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_pointline = true;
                            swapAB_1            = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel  = true;
                            swapAB_1            = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                        {
                            do_parallel_flip = true;
                        }
                    }

                    if (swMateFeature.GetTypeName2() == "MateParallel")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_orthogonal = true;
                            swapAB_1             = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                        {
                            do_parallel_flip = true;
                        }
                    }


                    if (swMateFeature.GetTypeName2() == "MatePerpendicular")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_parallel = true;
                            swapAB_1           = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                        {
                            do_parallel_flip = true;
                        }
                    }

                    if (swMateFeature.GetTypeName2() == "MateDistanceDim")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_Xdistance = true;
                            swapAB_1            = true;
                        }

                        //***TO DO*** cases of distance line-vs-line and line-vs-vertex and vert-vert.
                        //           Those will require another .cpp ChLinkMate specialized class(es).

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                        {
                            do_parallel_flip = true;
                        }

                        // Get the imposed distance value, in SI units
                        string confnames = "";
                        do_distance_val = swMate.DisplayDimension.GetDimension2(0).IGetSystemValue3((int)swInConfigurationOpts_e.swThisConfiguration, 0, ref confnames);

                        if (swMate.Flipped)
                        {
                            do_distance_val = -do_distance_val;
                        }
                    }

                    ////
                    //// WRITE PYHTON CODE CORRESPONDING TO CONSTRAINTS
                    ////

                    if (do_CHmate_Xdistance)
                    {
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateXdistance()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cA.X * ChScale.L,
                                                   cA.Y * ChScale.L,
                                                   cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cB.X * ChScale.L,
                                                   cB.Y * ChScale.L,
                                                   cB.Z * ChScale.L);
                        if (!entity_0_as_VERTEX)
                        {
                            asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       dA.X, dA.Y, dA.Z);
                        }
                        if (!entity_1_as_VERTEX)
                        {
                            asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       dB.X, dB.Y, dB.Z);
                        }

                        // Initialize link, by setting the two csys, in absolute space,
                        if (!swapAB_1)
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dB)\n", linkname, name1, name2);
                        }
                        else
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dA)\n", linkname, name2, name1);
                        }

                        //if (do_distance_val!=0)
                        asciitext += String.Format(bz, "{0}.SetDistance({1})\n", linkname,
                                                   do_distance_val * ChScale.L * -1);

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

                    if (do_CHmate_parallel)
                    {
                        if (Math.Abs(Vector3D.DotProduct(dA, dB)) > 0.98)
                        {
                            num_link++;
                            String linkname = "link_" + num_link;
                            asciitext += String.Format(bz, "{0} = chrono.ChLinkMateParallel()\n", linkname);

                            asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       cA.X * ChScale.L,
                                                       cA.Y * ChScale.L,
                                                       cA.Z * ChScale.L);
                            asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       dA.X, dA.Y, dA.Z);
                            asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       cB.X * ChScale.L,
                                                       cB.Y * ChScale.L,
                                                       cB.Z * ChScale.L);
                            asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       dB.X, dB.Y, dB.Z);

                            if (do_parallel_flip)
                            {
                                asciitext += String.Format(bz, "{0}.SetFlipped(True)\n", linkname);
                            }

                            // Initialize link, by setting the two csys, in absolute space,
                            if (!swapAB_1)
                            {
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);
                            }
                            else
                            {
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dB,dA)\n", linkname, name2, name1);
                            }

                            asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);
                            // Insert to a list of exported items
                            asciitext += String.Format(bz, "exported_items.append({0})\n\n", linkname);
                        }
                        else
                        {
                            asciitext += "\n# ChLinkMateParallel skipped because directions not parallel! \n";
                        }
                    }

                    if (do_CHmate_orthogonal)
                    {
                        if (Math.Abs(Vector3D.DotProduct(dA, dB)) < 0.02)
                        {
                            num_link++;
                            String linkname = "link_" + num_link;
                            asciitext += String.Format(bz, "{0} = chrono.ChLinkMateOrthogonal()\n", linkname);

                            asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       cA.X * ChScale.L,
                                                       cA.Y * ChScale.L,
                                                       cA.Z * ChScale.L);
                            asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       dA.X, dA.Y, dA.Z);
                            asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       cB.X * ChScale.L,
                                                       cB.Y * ChScale.L,
                                                       cB.Z * ChScale.L);
                            asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                       dB.X, dB.Y, dB.Z);

                            // Initialize link, by setting the two csys, in absolute space,
                            if (!swapAB_1)
                            {
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);
                            }
                            else
                            {
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dB,dA)\n", linkname, name2, name1);
                            }

                            asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);
                            // Insert to a list of exported items
                            asciitext += String.Format(bz, "exported_items.append({0})\n\n", linkname);
                        }
                        else
                        {
                            asciitext += "\n# ChLinkMateOrthogonal skipped because directions not orthogonal! \n";
                        }
                    }

                    if (do_CHmate_spherical)
                    {
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateSpherical()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cA.X * ChScale.L,
                                                   cA.Y * ChScale.L,
                                                   cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cB.X * ChScale.L,
                                                   cB.Y * ChScale.L,
                                                   cB.Z * ChScale.L);

                        // Initialize link, by setting the two csys, in absolute space,
                        if (!swapAB_1)
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB)\n", linkname, name1, name2);
                        }
                        else
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA)\n", linkname, name2, name1);
                        }

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

                    if (do_CHmate_pointline)
                    {
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateGeneric()\n", linkname);
                        asciitext += String.Format(bz, "{0}.SetConstrainedCoords(False, True, True, False, False, False)\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cA.X * ChScale.L,
                                                   cA.Y * ChScale.L,
                                                   cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cB.X * ChScale.L,
                                                   cB.Y * ChScale.L,
                                                   cB.Z * ChScale.L);
                        if (!entity_0_as_VERTEX)
                        {
                            asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n", dA.X, dA.Y, dA.Z);
                        }
                        else
                        {
                            asciitext += String.Format(bz, "dA = chrono.VNULL\n");
                        }
                        if (!entity_1_as_VERTEX)
                        {
                            asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n", dB.X, dB.Y, dB.Z);
                        }
                        else
                        {
                            asciitext += String.Format(bz, "dB = chrono.VNULL\n");
                        }

                        // Initialize link, by setting the two csys, in absolute space,
                        if (!swapAB_1)
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);
                        }
                        else
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dB,dA)\n", linkname, name2, name1);
                        }

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



                    // Now, do some other special mate type that did not fall in combinations
                    // of do_CHmate_pointline, do_CHmate_spherical, etc etc

                    if (swMateFeature.GetTypeName2() == "MateHinge")
                    {
                        // auto flip direction if anti aligned (seems that this is assumed automatically in MateHinge in SW)
                        if (Vector3D.DotProduct(dA, dB) < 0)
                        {
                            dB.Negate();
                        }

                        // Hinge constraint must be splitted in two C::E constraints: a coaxial and a point-vs-plane
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateCoaxial()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cA.X * ChScale.L,
                                                   cA.Y * ChScale.L,
                                                   cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   dA.X, dA.Y, dA.Z);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cB.X * ChScale.L,
                                                   cB.Y * ChScale.L,
                                                   cB.Z * ChScale.L);
                        asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   dB.X, dB.Y, dB.Z);

                        asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);


                        // Initialize link, by setting the two csys, in absolute space,
                        asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);

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


                        // NOTE!!! The 'hinge' mate uses 4 references: fetch the two others remaining
                        // and build another C::E link, for point-vs-face mating

                        MateEntity2   swEntityC = swMate.MateEntity(2);
                        MateEntity2   swEntityD = swMate.MateEntity(3);
                        Component2    swCompC   = swEntityC.ReferenceComponent;
                        Component2    swCompD   = swEntityD.ReferenceComponent;
                        double[]      paramsC   = (double[])swEntityC.EntityParams;
                        double[]      paramsD   = (double[])swEntityD.EntityParams;
                        String        name3     = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompC)];
                        String        name4     = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompD)];
                        MathTransform trC       = roottrasf;
                        MathTransform trD       = roottrasf;

                        if (assemblyofmates != null)
                        {
                            MathTransform partrasfC = assemblyofmates.GetTotalTransform(true);
                            if (partrasfC != null)
                            {
                                trC = partrasfC.IMultiply(invroottrasf);
                            }
                            MathTransform partrasfD = assemblyofmates.GetTotalTransform(true);
                            if (partrasfD != null)
                            {
                                trD = partrasfD.IMultiply(invroottrasf);
                            }
                        }

                        // NOTE: swMate.MateEntity(0).Reference.GetType() seems equivalent to  swMate.MateEntity(0).ReferenceType2
                        // but in some cases the latter fails. However, sometimes swMate.MateEntity(0).Reference.GetType() is null ReferenceType2 is ok,
                        // so do the following trick:
                        int entity2_ref = swMate.MateEntity(2).Reference.GetType();
                        if (entity2_ref == (int)swSelectType_e.swSelNOTHING)
                        {
                            entity2_ref = swMate.MateEntity(2).ReferenceType2;
                        }
                        int entity3_ref = swMate.MateEntity(3).Reference.GetType();
                        if (entity3_ref == (int)swSelectType_e.swSelNOTHING)
                        {
                            entity3_ref = swMate.MateEntity(3).ReferenceType2;
                        }

                        bool entity_2_as_VERTEX = (entity2_ref == (int)swSelectType_e.swSelVERTICES) ||
                                                  (entity2_ref == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                                  (entity2_ref == (int)swSelectType_e.swSelDATUMPOINTS);
                        bool entity_3_as_VERTEX = (entity3_ref == (int)swSelectType_e.swSelVERTICES) ||
                                                  (entity3_ref == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                                  (entity3_ref == (int)swSelectType_e.swSelDATUMPOINTS);

                        Point3D  cC = new Point3D(0, 0, 0);
                        Point3D  cD = new Point3D(0, 0, 0);
                        Vector3D dC = new Vector3D(1, 0, 0);
                        Vector3D dD = new Vector3D(1, 0, 0);

                        Point3D cCloc = new Point3D(paramsC[0], paramsC[1], paramsC[2]);
                        cC = SWTaskpaneHost.PointTransform(cCloc, ref trC);
                        Point3D cDloc = new Point3D(paramsD[0], paramsD[1], paramsD[2]);
                        cD = SWTaskpaneHost.PointTransform(cDloc, ref trD);

                        if (!entity_2_as_VERTEX)
                        {
                            Vector3D dCloc = new Vector3D(paramsC[3], paramsC[4], paramsC[5]);
                            dC = SWTaskpaneHost.DirTransform(dCloc, ref trC);
                        }

                        if (!entity_3_as_VERTEX)
                        {
                            Vector3D dDloc = new Vector3D(paramsD[3], paramsD[4], paramsD[5]);
                            dD = SWTaskpaneHost.DirTransform(dDloc, ref trD);
                        }

                        num_link++;
                        linkname   = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateXdistance()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cC.X * ChScale.L,
                                                   cC.Y * ChScale.L,
                                                   cC.Z * ChScale.L);
                        asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   dC.X, dC.Y, dC.Z);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   cD.X * ChScale.L,
                                                   cD.Y * ChScale.L,
                                                   cD.Z * ChScale.L);
                        asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                                   dD.X, dD.Y, dD.Z);

                        asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);


                        // Initialize link, by setting the two csys, in absolute space,
                        if (entity_2_as_VERTEX)
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA)\n", linkname, name3, name4);
                        }
                        else
                        {
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dB)\n", linkname, name3, name4);
                        }

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

                        return(true);
                    }
                }
            }
            return(false);
        }
        public static bool ConvertMateToPython( 
                                    ref Feature swMateFeature,
                                    ref string asciitext, 
                                    ref ISldWorks mSWApplication,
                                    ref Hashtable saved_parts,
                                    ref int num_link,
                                    ref MathTransform roottrasf,
                                    ref Component2 assemblyofmates
                                    )
        {
            if (swMateFeature == null)
                return false;

            Mate2 swMate = (Mate2)swMateFeature.GetSpecificFeature2();

            if (swMate == null)
                return false;

            object foo =null;
            bool[] suppressedflags;
            suppressedflags = (bool[])swMateFeature.IsSuppressed2((int)swInConfigurationOpts_e.swThisConfiguration, foo);
            if (suppressedflags[0] == true)
                return false;

            if (swMate.GetMateEntityCount() >= 2)
            {
                 // Get the mated parts
                MateEntity2 swEntityA = swMate.MateEntity(0);
                MateEntity2 swEntityB = swMate.MateEntity(1);
                Component2 swCompA = swEntityA.ReferenceComponent;
                Component2 swCompB = swEntityB.ReferenceComponent;
                double[] paramsA = (double[])swEntityA.EntityParams;
                double[] paramsB = (double[])swEntityB.EntityParams;
                 // this is needed because parts might reside in subassemblies, and mate params are expressed in parent subassembly
                MathTransform invroottrasf = (MathTransform)roottrasf.Inverse();
                MathTransform trA = roottrasf;
                MathTransform trB = roottrasf;

                if (assemblyofmates != null)
                {
                    MathTransform partrasfA = assemblyofmates.GetTotalTransform(true);
                    if (partrasfA != null)
                        trA = partrasfA.IMultiply(invroottrasf); // row-ordered transf. -> reverse mult.order!
                    MathTransform partrasfB = assemblyofmates.GetTotalTransform(true);
                    if (partrasfB != null)
                        trB = partrasfB.IMultiply(invroottrasf); // row-ordered transf. -> reverse mult.order!
                }

                 // Fetch the python names using hash map (python names added when scanning parts)
                ModelDocExtension swModelDocExt = default(ModelDocExtension);
                ModelDoc2 swModel = (ModelDoc2)mSWApplication.ActiveDoc;
                swModelDocExt = swModel.Extension;
                String name1 = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompA)];
                String name2 = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompB)];

                 // Only constraints between two parts or part & layout can be created
                if ( ((name1 != null) || (name2 != null)) && (name1 != name2) )
                {
                    CultureInfo bz = new CultureInfo("en-BZ");

                    if (name1 == null)
                        name1 = "body_0";
                    if (name2 == null)
                        name2 = "body_0";

                    // Add some comment in Python, to list the referenced SW items
                    asciitext += "\n# Mate constraint: " + swMateFeature.Name + " [" + swMateFeature.GetTypeName2() + "]" + " type:" + swMate.Type + " align:" + swMate.Alignment + " flip:" + swMate.Flipped + "\n";
                    for (int e = 0; e < swMate.GetMateEntityCount(); e++)
                    {
                        MateEntity2 swEntityN = swMate.MateEntity(e);
                        Component2 swCompN = swEntityN.ReferenceComponent;
                        String ce_nameN = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompN)];
                        asciitext += "#   Entity " + e + ": C::E name: " + ce_nameN + " , SW name: " + swCompN.Name2 + " ,  SW ref.type:" + swEntityN.Reference.GetType() + " (" + swEntityN.ReferenceType2 + ")\n";
                    }
                    asciitext += "\n";

                    //
                    // For each type of SW mate, see which C::E mate constraint(s)
                    // must be created. Some SW mates correspond to more than one C::E constraints.
                    //

                    bool swapAB_1 = false;
                    bool do_CHmate_Xdistance  = false;
                    double do_distance_val  = 0.0;
                    bool do_CHmate_parallel   = false;
                    bool   do_parallel_flip     = false;
                    bool do_CHmate_orthogonal = false;
                    bool do_CHmate_spherical  = false;
                    bool do_CHmate_pointline  = false;

                    // to simplify things later...
                    // NOTE: swMate.MateEntity(0).Reference.GetType() seems equivalent to  swMate.MateEntity(0).ReferenceType2
                    // but in some cases the latter fails.
                    bool entity_0_as_FACE   = (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelFACES);
                    bool entity_0_as_EDGE   = (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelEDGES) ||
                                              (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelSKETCHSEGS) ||
                                              (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelDATUMAXES);
                    bool entity_0_as_VERTEX = (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelVERTICES) ||
                                              (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                              (swMate.MateEntity(0).Reference.GetType() == (int)swSelectType_e.swSelDATUMPOINTS);

                    bool entity_1_as_FACE   = (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelFACES);
                    bool entity_1_as_EDGE   = (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelEDGES) ||
                                              (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelSKETCHSEGS) ||
                                              (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelDATUMAXES);
                    bool entity_1_as_VERTEX = (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelVERTICES) ||
                                              (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                              (swMate.MateEntity(1).Reference.GetType() == (int)swSelectType_e.swSelDATUMPOINTS);

                    Point3D cA  = new Point3D(0, 0, 0);
                    Point3D cB  = new Point3D(0, 0, 0);
                    Vector3D dA = new Vector3D(1, 0, 0);
                    Vector3D dB = new Vector3D(1, 0, 0);

                    Point3D cAloc = new Point3D(paramsA[0], paramsA[1], paramsA[2]);
                    cA = SWTaskpaneHost.PointTransform(cAloc, ref trA);
                    Point3D cBloc = new Point3D(paramsB[0], paramsB[1], paramsB[2]);
                    cB = SWTaskpaneHost.PointTransform(cBloc, ref trB);

                    if (!entity_0_as_VERTEX)
                    {
                        Vector3D dAloc = new Vector3D(paramsA[3], paramsA[4], paramsA[5]);
                        dA = SWTaskpaneHost.DirTransform(dAloc, ref trA);
                    }

                    if (!entity_1_as_VERTEX)
                    {
                        Vector3D dBloc = new Vector3D(paramsB[3], paramsB[4], paramsB[5]);
                        dB = SWTaskpaneHost.DirTransform(dBloc, ref trB);
                    }

                    if (swMateFeature.GetTypeName2() == "MateCoincident")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel  = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_spherical = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_pointline = true;
                            swapAB_1 = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_Xdistance = true;
                            swapAB_1 = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_Xdistance = true;
                            do_CHmate_orthogonal = true;
                            swapAB_1 = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                            do_parallel_flip = true;
                    }

                    if (swMateFeature.GetTypeName2() == "MateConcentric")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_pointline = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_pointline = true;
                            swapAB_1 = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_pointline = true;
                            do_CHmate_parallel = true;
                            swapAB_1 = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                            do_parallel_flip = true;
                    }

                    if (swMateFeature.GetTypeName2() == "MateParallel")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_orthogonal = true;
                            swapAB_1 = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                            do_parallel_flip = true;
                    }

                    if (swMateFeature.GetTypeName2() == "MatePerpendicular")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_orthogonal = true;
                        }
                        if ((entity_0_as_EDGE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_parallel = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_EDGE))
                        {
                            do_CHmate_parallel = true;
                            swapAB_1 = true;
                        }

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                            do_parallel_flip = true;
                    }

                    if (swMateFeature.GetTypeName2() == "MateDistanceDim")
                    {
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance  = true;
                            do_CHmate_parallel   = true;
                        }
                        if ((entity_0_as_VERTEX) &&
                            (entity_1_as_FACE))
                        {
                            do_CHmate_Xdistance = true;
                        }
                        if ((entity_0_as_FACE) &&
                            (entity_1_as_VERTEX))
                        {
                            do_CHmate_Xdistance = true;
                            swapAB_1 = true;
                        }

                        //***TO DO*** cases of distance line-vs-line and line-vs-vertex and vert-vert.
                        //           Those will require another .cpp ChLinkMate specialized class(es).

                        if (swMate.Alignment == (int)swMateAlign_e.swMateAlignANTI_ALIGNED)
                            do_parallel_flip = true;

                        // Get the imposed distance value, in SI units
                        string confnames = "";
                        do_distance_val = swMate.DisplayDimension.GetDimension2(0).IGetSystemValue3((int)swInConfigurationOpts_e.swThisConfiguration, 0, ref confnames);

                        if (swMate.Flipped)
                            do_distance_val = -do_distance_val;
                    }

                    ////
                    //// WRITE PYHTON CODE CORRESPONDING TO CONSTRAINTS
                    ////

                    if (do_CHmate_Xdistance)
                    {
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateXdistance()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cA.X * ChScale.L,
                                  cA.Y * ChScale.L,
                                  cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cB.X * ChScale.L,
                                  cB.Y * ChScale.L,
                                  cB.Z * ChScale.L);
                        if (!entity_0_as_VERTEX)
                         asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  dA.X, dA.Y, dA.Z);
                        if (!entity_1_as_VERTEX)
                         asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  dB.X, dB.Y, dB.Z);

                        // Initialize link, by setting the two csys, in absolute space,
                        if (!swapAB_1)
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dB)\n", linkname, name1, name2);
                        else
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dA)\n", linkname, name2, name1);

                        //if (do_distance_val!=0)
                            asciitext += String.Format(bz, "{0}.SetDistance({1})\n", linkname,
                                do_distance_val * ChScale.L *-1);

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

                    if (do_CHmate_parallel)
                    {
                        if (Math.Abs(Vector3D.DotProduct(dA, dB)) > 0.98)
                        {
                            num_link++;
                            String linkname = "link_" + num_link;
                            asciitext += String.Format(bz, "{0} = chrono.ChLinkMateParallel()\n", linkname);

                            asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      cA.X * ChScale.L,
                                      cA.Y * ChScale.L,
                                      cA.Z * ChScale.L);
                            asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      dA.X, dA.Y, dA.Z);
                            asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      cB.X * ChScale.L,
                                      cB.Y * ChScale.L,
                                      cB.Z * ChScale.L);
                            asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      dB.X, dB.Y, dB.Z);

                            if (do_parallel_flip)
                                asciitext += String.Format(bz, "{0}.SetFlipped(True)\n", linkname);

                            // Initialize link, by setting the two csys, in absolute space,
                            if (!swapAB_1)
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);
                            else
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dB,dA)\n", linkname, name2, name1);

                            asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);
                            // Insert to a list of exported items
                            asciitext += String.Format(bz, "exported_items.append({0})\n\n", linkname);
                        }
                        else
                        {
                            asciitext += "\n# ChLinkMateParallel skipped because directions not parallel! \n";
                        }
                    }

                    if (do_CHmate_orthogonal)
                    {
                        if (Math.Abs(Vector3D.DotProduct(dA, dB)) < 0.02)
                        {
                            num_link++;
                            String linkname = "link_" + num_link;
                            asciitext += String.Format(bz, "{0} = chrono.ChLinkMateOrthogonal()\n", linkname);

                            asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      cA.X * ChScale.L,
                                      cA.Y * ChScale.L,
                                      cA.Z * ChScale.L);
                            asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      dA.X, dA.Y, dA.Z);
                            asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      cB.X * ChScale.L,
                                      cB.Y * ChScale.L,
                                      cB.Z * ChScale.L);
                            asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                      dB.X, dB.Y, dB.Z);

                            // Initialize link, by setting the two csys, in absolute space,
                            if (!swapAB_1)
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);
                            else
                                asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dB,dA)\n", linkname, name2, name1);

                            asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);
                            // Insert to a list of exported items
                            asciitext += String.Format(bz, "exported_items.append({0})\n\n", linkname);
                        }
                        else
                        {
                            asciitext += "\n# ChLinkMateOrthogonal skipped because directions not orthogonal! \n";
                        }
                    }

                    if (do_CHmate_spherical)
                    {
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateSpherical()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cA.X * ChScale.L,
                                  cA.Y * ChScale.L,
                                  cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cB.X * ChScale.L,
                                  cB.Y * ChScale.L,
                                  cB.Z * ChScale.L);

                        // Initialize link, by setting the two csys, in absolute space,
                        if (!swapAB_1)
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB)\n", linkname, name1, name2);
                        else
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA)\n", linkname, name2, name1);

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

                    if (do_CHmate_pointline)
                    {
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateGeneric()\n", linkname);
                        asciitext += String.Format(bz, "{0}.SetConstrainedCoords(False, True, True, False, False, False)\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cA.X * ChScale.L,
                                  cA.Y * ChScale.L,
                                  cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cB.X * ChScale.L,
                                  cB.Y * ChScale.L,
                                  cB.Z * ChScale.L);
                        if (!entity_0_as_VERTEX)
                            asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n", dA.X, dA.Y, dA.Z);
                        else
                            asciitext += String.Format(bz, "dA = chrono.VNULL\n");
                        if (!entity_1_as_VERTEX)
                            asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n", dB.X, dB.Y, dB.Z);
                        else
                            asciitext += String.Format(bz, "dB = chrono.VNULL\n");

                        // Initialize link, by setting the two csys, in absolute space,
                        if (!swapAB_1)
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);
                        else
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cB,cA,dB,dA)\n", linkname, name2, name1);

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

                    // Now, do some other special mate type that did not fall in combinations
                    // of do_CHmate_pointline, do_CHmate_spherical, etc etc

                    if (swMateFeature.GetTypeName2() == "MateHinge")
                    {
                        // auto flip direction if anti aligned (seems that this is assumed automatically in MateHinge in SW)
                        if (Vector3D.DotProduct(dA, dB) < 0)
                            dB.Negate();

                        // Hinge constraint must be splitted in two C::E constraints: a coaxial and a point-vs-plane
                        num_link++;
                        String linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateCoaxial()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cA.X * ChScale.L,
                                  cA.Y * ChScale.L,
                                  cA.Z * ChScale.L);
                        asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  dA.X, dA.Y, dA.Z);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cB.X * ChScale.L,
                                  cB.Y * ChScale.L,
                                  cB.Z * ChScale.L);
                        asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  dB.X, dB.Y, dB.Z);

                        asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);

                        // Initialize link, by setting the two csys, in absolute space,
                        asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA,dB)\n", linkname, name1, name2);

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

                        // NOTE!!! The 'hinge' mate uses 4 references: fetch the two others remaining
                        // and build another C::E link, for point-vs-face mating

                        MateEntity2 swEntityC = swMate.MateEntity(2);
                        MateEntity2 swEntityD = swMate.MateEntity(3);
                        Component2 swCompC = swEntityC.ReferenceComponent;
                        Component2 swCompD = swEntityD.ReferenceComponent;
                        double[] paramsC = (double[])swEntityC.EntityParams;
                        double[] paramsD = (double[])swEntityD.EntityParams;
                        String name3 = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompC)];
                        String name4 = (String)saved_parts[swModelDocExt.GetPersistReference3(swCompD)];
                        MathTransform trC = roottrasf;
                        MathTransform trD = roottrasf;

                        if (assemblyofmates != null)
                        {
                            MathTransform partrasfC = assemblyofmates.GetTotalTransform(true);
                            if (partrasfC != null)
                                trC = partrasfC.IMultiply(invroottrasf);
                            MathTransform partrasfD = assemblyofmates.GetTotalTransform(true);
                            if (partrasfD != null)
                                trD = partrasfD.IMultiply(invroottrasf);
                        }

                        bool entity_2_as_VERTEX = (swMate.MateEntity(2).Reference.GetType() == (int)swSelectType_e.swSelVERTICES) ||
                                                  (swMate.MateEntity(2).Reference.GetType() == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                                  (swMate.MateEntity(2).Reference.GetType() == (int)swSelectType_e.swSelDATUMPOINTS);
                        bool entity_3_as_VERTEX = (swMate.MateEntity(3).Reference.GetType() == (int)swSelectType_e.swSelVERTICES) ||
                                                  (swMate.MateEntity(3).Reference.GetType() == (int)swSelectType_e.swSelSKETCHPOINTS) ||
                                                  (swMate.MateEntity(3).Reference.GetType() == (int)swSelectType_e.swSelDATUMPOINTS);
                        Point3D cC  = new Point3D(0, 0, 0);
                        Point3D cD  = new Point3D(0, 0, 0);
                        Vector3D dC = new Vector3D(1, 0, 0);
                        Vector3D dD = new Vector3D(1, 0, 0);

                        Point3D cCloc = new Point3D(paramsC[0], paramsC[1], paramsC[2]);
                        cC = SWTaskpaneHost.PointTransform(cCloc, ref trC);
                        Point3D cDloc = new Point3D(paramsD[0], paramsD[1], paramsD[2]);
                        cD = SWTaskpaneHost.PointTransform(cDloc, ref trD);

                        if (!entity_2_as_VERTEX)
                        {
                            Vector3D dCloc = new Vector3D(paramsC[3], paramsC[4], paramsC[5]);
                            dC = SWTaskpaneHost.DirTransform(dCloc, ref trC);
                        }

                        if (!entity_3_as_VERTEX)
                        {
                            Vector3D dDloc = new Vector3D(paramsD[3], paramsD[4], paramsD[5]);
                            dD = SWTaskpaneHost.DirTransform(dDloc, ref trD);
                        }

                        num_link++;
                        linkname = "link_" + num_link;
                        asciitext += String.Format(bz, "{0} = chrono.ChLinkMateXdistance()\n", linkname);

                        asciitext += String.Format(bz, "cA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cC.X * ChScale.L,
                                  cC.Y * ChScale.L,
                                  cC.Z * ChScale.L);
                        asciitext += String.Format(bz, "dA = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  dC.X, dC.Y, dC.Z);
                        asciitext += String.Format(bz, "cB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  cD.X * ChScale.L,
                                  cD.Y * ChScale.L,
                                  cD.Z * ChScale.L);
                        asciitext += String.Format(bz, "dB = chrono.ChVectorD({0:g},{1:g},{2:g})\n",
                                  dD.X, dD.Y, dD.Z);

                        asciitext += String.Format(bz, "{0}.SetName(\"{1}\")\n", linkname, swMateFeature.Name);

                        // Initialize link, by setting the two csys, in absolute space,
                        if (entity_2_as_VERTEX)
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dA)\n", linkname, name3, name4);
                        else
                            asciitext += String.Format(bz, "{0}.Initialize({1},{2},False,cA,cB,dB)\n", linkname, name3, name4);

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

                        return true;
                    }
                }
            }
            return false;
        }
        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
        }
            protected override void Command()
            {
                Ass = MdlBase.eAssemblyDoc();

                try
                {
                    CurveDrivenPatternFeatureData def = FonctionRepetition.GetDefinition();
                    Object[] tabB = def.PatternBodyArray;
                    Body2    b    = (Body2)tabB[0];

                    MathTransform compRepetTrans  = ComposantRepetition.Transform2;
                    MathTransform baseMarcheTrans = Marche.Transform2;

                    Vertex v = (Vertex)Point;
                    Edge   e = (Edge)Arrete;

                    List <Face2> ListeFace = FonctionRepetition.eListeDesFaces();

                    Sketch  sk           = PointMarche.GetSketch();
                    Feature fPointMarche = (Feature)sk;

                    List <Component2> ListeComposants = new List <Component2>()
                    {
                        Marche
                    };

                    Double arr = 0.0001;

                    for (int i = 1; i <= (def.D1InstanceCount + def.D2InstanceCount); i++)
                    {
                        MathTransform bodyTrans = def.GetTransform(i);
                        if (bodyTrans.IsNull())
                        {
                            break;
                        }

                        MathTransform Transform = compRepetTrans.Inverse();
                        Transform = Transform.Multiply(bodyTrans);
                        Transform = Transform.Multiply(compRepetTrans);
                        Transform = baseMarcheTrans.Multiply(Transform);

                        gPoint   pt = new gPoint(v);
                        gSegment sg = new gSegment(e);
                        pt.MultiplyTransfom(bodyTrans);
                        sg.MultiplyTransfom(bodyTrans);

                        Vertex vertex = null;
                        Edge   edge   = null;

                        foreach (Face2 face in ListeFace)
                        {
                            foreach (Edge ed in face.eListeDesArretes())
                            {
                                gSegment s = new gSegment(ed);

                                if (sg.Compare(s, arr))
                                {
                                    edge = ed;
                                }

                                if (s.Start.Comparer(pt, arr))
                                {
                                    vertex = ed.GetStartVertex();
                                }

                                if (s.End.Comparer(pt, arr))
                                {
                                    vertex = ed.GetEndVertex();
                                }

                                if (edge.IsRef() && vertex.IsRef())
                                {
                                    break;
                                }
                            }

                            if (edge.IsRef() && vertex.IsRef())
                            {
                                break;
                            }
                        }

                        Entity eVertex = (Entity)vertex;
                        Entity eEdge   = (Entity)edge;

                        Component2 cp = Ass.AddComponent5(Marche.GetPathName(), (int)swAddComponentConfigOptions_e.swAddComponentConfigOptions_CurrentSelectedConfig, "", false, "", 0, 0, 0);
                        if (cp.IsNull())
                        {
                            continue;
                        }

                        // Quand on réinsere un composant, les précédentes contraintes sont recrées.
                        // On les supprime pour eviter des conflits
                        Object[] Mates = cp.GetMates();

                        if (Mates.IsRef())
                        {
                            foreach (Feature mate in Mates)
                            {
                                mate.eSelect();
                                MdlBase.Extension.DeleteSelection2((int)swDeleteSelectionOptions_e.swDelete_Absorbed);
                            }
                        }

                        WindowLog.Ecrire(cp.Name2);

                        cp.Transform2 = Transform;
                        ListeComposants.Add(cp);

                        int longstatus = 0;

                        MdlBase.eEffacerSelection();
                        eVertex.eSelectEntite(false);
                        Feature     f             = cp.FeatureByName(fPointMarche.Name);
                        Sketch      sketchOrigine = f.GetSpecificFeature2();
                        Object[]    tabPt         = sketchOrigine.GetSketchPoints2();
                        SketchPoint origine       = (SketchPoint)tabPt[0];
                        origine.Select4(true, null);
                        Mate2 mPoint = Ass.AddMate5((int)swMateType_e.swMateCOINCIDENT,
                                                    (int)swMateAlign_e.swMateAlignCLOSEST, false, 0, 0, 0, 0, 0, 0, 0, 0, false, false, 0, out longstatus);
                        MdlBase.eEffacerSelection();

                        MdlBase.eEffacerSelection();
                        eEdge.eSelectEntite(false);
                        cp.FeatureByName(AxeMarche.Name).eSelect(true);
                        Mate2 mAxe = Ass.AddMate5((int)swMateType_e.swMateANGLE,
                                                  (int)swMateAlign_e.swAlignNONE, false, 0, 0, 0, 0, 0, 0, 0, 0, false, false, 0, out longstatus);
                        MdlBase.eEffacerSelection();

                        MdlBase.eEffacerSelection();
                        Plan.eSelect(false);
                        cp.FeatureByName(PlanMarche.Name).eSelect(true);
                        Mate2 mPlan = Ass.AddMate5((int)swMateType_e.swMatePARALLEL,
                                                   (int)swMateAlign_e.swAlignNONE, false, 0, 0, 0, 0, 0, 0, 0, 0, false, false, 0, out longstatus);
                        MdlBase.eEffacerSelection();

                        Feature m = (Feature)mPoint;
                        WindowLog.Ecrire("   " + m.Name);
                        m = (Feature)mAxe;
                        WindowLog.Ecrire("   " + m.Name);
                        m = (Feature)mPlan;
                        WindowLog.Ecrire("   " + m.Name);
                    }

                    MdlBase.eEffacerSelection();

                    foreach (var cp in ListeComposants)
                    {
                        cp.eSelectById(MdlBase, -1, true);
                    }

                    Feature Dossier = MdlBase.FeatureManager.InsertFeatureTreeFolder2((int)swFeatureTreeFolderType_e.swFeatureTreeFolder_Containing);
                    Dossier.eRenommerFonction(String.Format("Marches ({0} {1}) ", ComposantRepetition.Name2, FonctionRepetition.Name));
                }
                catch (Exception e)
                {
                    this.LogErreur(new Object[] { e });
                }
            }