public static Rhino.Commands.Result AddTruncatedCone(Rhino.RhinoDoc doc)
    {
        Point3d      bottom_pt     = new Point3d(0, 0, 0);
        const double bottom_radius = 2;
        Circle       bottom_circle = new Circle(bottom_pt, bottom_radius);

        Point3d      top_pt     = new Point3d(0, 0, 10);
        const double top_radius = 6;
        Circle       top_circle = new Circle(top_pt, top_radius);

        LineCurve  shapeCurve = new LineCurve(bottom_circle.PointAt(0), top_circle.PointAt(0));
        Line       axis       = new Line(bottom_circle.Center, top_circle.Center);
        RevSurface revsrf     = RevSurface.Create(shapeCurve, axis);
        Brep       tcone_brep = Brep.CreateFromRevSurface(revsrf, true, true);

        if (doc.Objects.AddBrep(tcone_brep) != Guid.Empty)
        {
            doc.Views.Redraw();
            return(Rhino.Commands.Result.Success);
        }
        return(Rhino.Commands.Result.Failure);
    }
        private Result CreateNoseCone(RhinoDoc doc, XmlNode compNd, ref double stackLength)
        {
            Result      result     = Rhino.Commands.Result.Failure;
            XmlElement  compEle    = compNd as XmlElement;
            XmlNodeList subCompNds = compNd.SelectNodes("subcomponents/*");

            double            length               = 0;
            double            thickness            = 0;
            NoseConeShapeType shape                = NoseConeShapeType.Ogive;
            double            shapeParameter       = 0;
            double            aftRadius            = 0;
            double            aftShoulderRadius    = 0;
            double            aftShoulderLength    = 0;
            double            aftShoulderThickness = 0;
            bool aftShoulderCapped = false;

            foreach (XmlNode nd in compEle.ChildNodes)
            {
                if (nd.Name == "length")
                {
                    length = Double.Parse(nd.InnerText);
                }
                else if (nd.Name == "thickness")
                {
                    thickness = Double.Parse(nd.InnerText);
                }
                else if (nd.Name == "shape")
                {
                    shape = (NoseConeShapeType)Enum.Parse(typeof(NoseConeShapeType), nd.InnerText, true);
                }
                else if (nd.Name == "shapeparameter")
                {
                    shapeParameter = Double.Parse(nd.InnerText);
                }
                else if (nd.Name == "aftradius")
                {
                    if (nd.InnerText == "auto")
                    {
                        XmlNode sibNd = compNd.NextSibling;
                        foreach (XmlNode sibChild in sibNd.ChildNodes)
                        {
                            if (sibNd.Name == "bodytube" && sibChild.Name == "radius")
                            {
                                aftRadius = Double.Parse(sibChild.InnerText);
                            }
                        }
                    }
                    else
                    {
                        aftRadius = Double.Parse(nd.InnerText);
                    }
                }
                else if (nd.Name == "aftshoulderradius")
                {
                    aftShoulderRadius = Double.Parse(nd.InnerText);
                }
                else if (nd.Name == "aftshoulderlength")
                {
                    aftShoulderLength = Double.Parse(nd.InnerText);
                }
                else if (nd.Name == "aftshoulderthickness")
                {
                    aftShoulderThickness = Double.Parse(nd.InnerText);
                }
                else if (nd.Name == "aftshouldercapped")
                {
                    aftShoulderCapped = Boolean.Parse(nd.InnerText);
                }
            }

            // generate geometry and create solid.
            int            numberDivisions = 100;
            OgiveCurve     ogive           = new OgiveCurve(aftRadius, length);
            double         xa     = ogive.SphericalCapApex(0);
            double         delta  = (length - xa) / (numberDivisions - 1);
            double         x      = xa;
            double         y      = 0;
            List <Point3d> points = new List <Point3d>();

            for (int i = 0; i < numberDivisions; i++)
            {
                double angle = (double)i * System.Math.PI / (double)numberDivisions;
                y = ogive.Evaluate(x);

                points.Add(new Point3d(x, y, 0));

                x += delta;
            }

            Polyline curve = new Polyline(points);

            NurbsCurve nbCurve = curve.ToNurbsCurve();

            Curve[] offsetsCurves = nbCurve.Offset(new Plane(new Point3d(0, 0, 0), Vector3d.XAxis, Vector3d.YAxis), thickness, 0.0001, CurveOffsetCornerStyle.None);

            Plane plane = new Plane(new Point3d(0, 0, 0), Vector3d.XAxis, Vector3d.ZAxis);

            Curve[] splits = offsetsCurves[0].Split(new PlaneSurface(plane, new Interval(0, 100), new Interval(0, 100)), 0.0001);

            LineCurve line1 = new LineCurve(nbCurve.PointAtStart, splits[1].PointAtStart);
            LineCurve line2 = new LineCurve(nbCurve.PointAtEnd, splits[1].PointAtEnd);

            List <Curve> curves = new List <Curve>()
            {
                nbCurve, splits[1], line1, line2
            };

            Curve[] joined = Curve.JoinCurves(curves);

            RevSurface revsrf = RevSurface.Create(joined[0], new Line(new Point3d(0, 0, 0), new Point3d(length, 0, 0)), 0, 2 * Math.PI);
            Brep       brep   = Brep.CreateFromRevSurface(revsrf, true, true);

            brep.Flip();

            if (aftShoulderLength > 0)
            {
                double innerRadius = aftShoulderRadius - aftShoulderThickness;
                double outerRadius = aftShoulderRadius;
                Plane  planeCyl    = new Plane(new Point3d(0, 0, 0), Vector3d.XAxis);
                Circle innerCir    = new Circle(planeCyl, innerRadius);
                Circle outerCir    = new Circle(planeCyl, outerRadius);

                Cylinder innerCyl = new Cylinder(innerCir, aftShoulderThickness + aftShoulderLength);
                Cylinder outerCyl = new Cylinder(outerCir, aftShoulderThickness + aftShoulderLength);

                Brep brepInner = Brep.CreateFromCylinder(innerCyl, true, true);
                Brep brepOuter = Brep.CreateFromCylinder(outerCyl, true, true);

                Brep[]    tube  = Brep.CreateBooleanDifference(brepOuter, brepInner, 0.0001);
                Transform trans = Transform.Translation(new Vector3d(length - aftShoulderThickness, 0, 0));

                tube[0].Transform(trans);

                Brep[] withShoulder = Brep.CreateBooleanUnion(new List <Brep>()
                {
                    brep, tube[0]
                }, 0.001);
                brep = withShoulder[0];
            }


            if (doc.Objects.AddBrep(brep) != Guid.Empty)
            {
                doc.Views.Redraw();
                result = Rhino.Commands.Result.Success;
            }

            stackLength = length; // cone seems to start a new stack

            foreach (XmlNode subNd in subCompNds)
            {
                if (subNd.Name == "tubecoupler")
                {
                    result = CreateTubeCoupler(doc, subNd, stackLength);
                }
            }

            return(result);
        }