示例#1
0
        public static Polyline CurveToPolyline(Curve c, double dist = 0)
        {
            Polyline polyline = new Polyline();



            bool flag = c.TryGetPolyline(out polyline);

            if (!flag)
            {
                if (dist <= 0)
                {
                    PolylineCurve pc = c.ToPolyline(c.SpanCount, 0, 0, 0);
                    polyline = pc.ToPolyline();
                    //Point3d[] pts;
                    //c.DivideByCount(c.SpanCount, true, out pts);
                    //polyline = new Polyline(pts);
                }
                else
                {
                    //        Point3d[] pts;
                    //        c.DivideByCount(Math.Min((int) Math.Ceiling(c.GetLength() / dist), 100), true, out pts);
                    //        polyline = new Polyline(pts);

                    PolylineCurve pc = c.ToPolyline(0, 0, 0, dist);
                    polyline = pc.ToPolyline();
                }
                polyline.Add(polyline[0]);
            }
            return(polyline);
        }
示例#2
0
        public void CalculateWidthHeightFromCurve(PolylineCurve curve)
        {
            var rect = Rectangle3d.CreateFromPolyline(curve.ToPolyline());

            Width  = rect.Width;
            Height = rect.Height;

            var plane = this.Plane;

            plane.Origin = rect.Corner(0);

            Plane = plane;
        }
示例#3
0
        public static Voxels Run(Mesh M, double S)
        {
            // Logic starts
            var V = new List <Box>();
            var P = new List <Point3d>();

            M.Weld(Math.PI);

            // Get bounding of the mesh
            BoundingBox box = M.GetBoundingBox(Plane.WorldXY);

            double min_x = int.MaxValue;
            double max_x = int.MinValue;
            double min_y = int.MaxValue;
            double max_y = int.MinValue;
            double min_z = int.MaxValue;
            double max_z = int.MinValue;

            Point3d[] pts = box.GetCorners();

            foreach (Point3d p in pts)
            {
                if (p.X > max_x)
                {
                    max_x = p.X;
                }

                if (p.X < min_x)
                {
                    min_x = p.X;
                }

                if (p.Y > max_y)
                {
                    max_y = p.Y;
                }

                if (p.Y < min_y)
                {
                    min_y = p.Y;
                }

                if (p.Z > max_z)
                {
                    max_z = p.Z;
                }

                if (p.Z < min_z)
                {
                    min_z = p.Z;
                }
            }

            // If the size lacks or is an inappropriate value, set a reasonable value to it
            if (S <= 0)
            {
                double max_length = Math.Max(max_z - min_z, Math.Max(max_y - min_y, max_x - min_x));

                S = (int)(max_length / 10);
            }

            Interval unit_interval = new Interval(-S * 0.5, S * 0.5);

            // remap the bounding values taking the center position into account
            int num_x = (int)((max_x - min_x) / S);
            int num_y = (int)((max_y - min_y) / S);
            int num_z = (int)((max_z - min_z) / S);

            min_x = (max_x + min_x) * 0.5 - (num_x * S * 0.5);
            min_y = (max_y + min_y) * 0.5 - (num_y * S * 0.5);
            min_z = (max_z + min_z) * 0.5 - (num_z * S * 0.5);

            var horizontal_curves_by_plane = new Dictionary <Plane, Curve[]>();
            var vertical_curves_by_planes  = new Dictionary <Plane, Curve[]>();


            // vertical contours of the mesh
            for (var i = 0; i < num_z + 1; i++)
            {
                double z = min_z + i * S;

                Point3d p     = new Point3d(0, 0, z);
                Plane   plane = new Plane(p, Plane.WorldXY.Normal);

                Curve[] curves = Mesh.CreateContourCurves(M, plane);

                vertical_curves_by_planes[plane] = curves;
            }

            // horizontal contours of the mesh
            for (var i = 0; i < num_x + 1; i++)
            {
                double x = min_x + i * S;

                Point3d p     = new Point3d(x, 0, 0);
                Plane   plane = new Plane(p, Plane.WorldXY.XAxis);

                Curve[] curves = Mesh.CreateContourCurves(M, plane);

                horizontal_curves_by_plane[plane] = curves;
            }

            Point3d reference_min_pt = new Point3d(0, 0, min_z - int.MaxValue);
            Point3d reference_max_pt = new Point3d(0, 0, max_z + int.MaxValue);

            foreach (KeyValuePair <Plane, Curve[]> item in horizontal_curves_by_plane)
            {
                double  x      = item.Key.OriginX;
                Curve[] curves = item.Value;

                foreach (Curve curve in curves)
                {
                    PolylineCurve pl = curve.ToPolyline(0.01, 0.001, 0.0001, int.MaxValue);

                    Polyline polyline = pl.ToPolyline();

                    if (!polyline.IsClosed)
                    {
                        polyline.Add(polyline[0]);
                    }

                    Point3d min_pt = polyline.ClosestPoint(reference_min_pt);
                    Point3d max_pt = polyline.ClosestPoint(reference_max_pt);

                    foreach (Plane plane in vertical_curves_by_planes.Keys)
                    {
                        if (plane.OriginZ < min_pt.Z || max_pt.Z < plane.OriginZ)
                        {
                            continue;
                        }

                        NurbsCurve nurbs_curve = polyline.ToNurbsCurve();

                        var intersections = Rhino.Geometry.Intersect.Intersection.CurvePlane(nurbs_curve, plane, S * 0.0001);

                        if (intersections.Count < 2)
                        {
                            continue;
                        }

                        Point3d min_y_pt = new Point3d(0, int.MaxValue, 0);
                        Point3d max_y_pt = new Point3d(0, int.MinValue, 0);


                        foreach (Rhino.Geometry.Intersect.IntersectionEvent intersect in intersections)
                        {
                            if (min_y_pt.Y > intersect.PointA.Y)
                            {
                                min_y_pt = intersect.PointA;
                            }

                            if (max_y_pt.Y < intersect.PointA.Y)
                            {
                                max_y_pt = intersect.PointA;
                            }

                            int start_index = (int)((min_y_pt.Y - min_y) / S) + 1;
                            int end_index   = (int)((max_y_pt.Y - min_y) / S) + 1;


                            for (var y_index = start_index; y_index < end_index; y_index++)
                            {
                                double y = min_y + S * y_index;

                                Point3d grid_pt = new Point3d(x, y, plane.OriginZ);

                                Plane grid_plane = new Plane(grid_pt, Plane.WorldXY.ZAxis);

                                Box voxel = new Box(grid_plane, unit_interval, unit_interval, unit_interval);

                                V.Add(voxel);
                                P.Add(grid_pt);
                            }
                        }
                    }
                }
            }

            return(new Voxels(V, P, max_x, min_x, max_y, min_y, max_z, min_z));
        }
示例#4
0
        public static IGH_GeometricGoo BldgPartToRoof(BuildingPart bldgPart)
        {
            IGH_GeometricGoo roof = bldgPart.PartGoo;
            PolylineCurve    pL   = bldgPart.PartFootprint; ///Already at min height

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:shape", out string roofShape);

            bldgPart.PartOsmGeo.Tags.TryGetValue("height", out string heightString);
            double height = GetHeightDimensioned(heightString);

            bldgPart.PartOsmGeo.Tags.TryGetValue("min_height", out string minHeightString);
            double min_height = GetHeightDimensioned(minHeightString);

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:height", out string roofHeightString);
            double roofHeight = GetHeightDimensioned(roofHeightString);

            double facadeHeight = height - roofHeight;

            ///Make sure there's a minium facade height for SF Transamerica Pyramid case
            if (facadeHeight <= 0)
            {
                facadeHeight = 2 * DocumentTolerance();
            }

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:orientation", out string roofOrientationString);

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:direction", out string roofDirectionString);
            double   roofDirection       = System.Convert.ToDouble(roofDirectionString);
            Vector3d roofDirectionVector = Plane.WorldXY.YAxis;

            roofDirectionVector.Rotate(RhinoMath.ToRadians(-roofDirection), Plane.WorldXY.ZAxis);

            Line[]  edges    = pL.ToPolyline().GetSegments();
            Point3d centroid = AreaMassProperties.Compute(pL).Centroid;

            switch (roofShape)
            {
            case "pyramidal":
                centroid.Z = height;
                pL.TryGetPolyline(out Polyline pLPolyline);
                Line[]      pLLines         = pLPolyline.GetSegments();
                List <Brep> pyramidBrepList = Brep.CreatePlanarBreps(pL, DocumentTolerance()).ToList();

                if (!string.IsNullOrEmpty(roofHeightString))
                {
                    Plane facadeHeightPlane = Plane.WorldXY;
                    facadeHeightPlane.Translate(new Vector3d(0, 0, facadeHeight));
                    pLPolyline.Transform(Transform.PlanarProjection(facadeHeightPlane));

                    ///Creating individual faces seems to work better/cleaner than lofting curves
                    for (int i = 0; i < pLLines.Count(); i++)
                    {
                        Line bottomEdge = pLLines[i];
                        Line topEdge    = bottomEdge;
                        topEdge.Transform(Transform.PlanarProjection(facadeHeightPlane));
                        pyramidBrepList.Add(Brep.CreateFromCornerPoints(bottomEdge.PointAt(0), bottomEdge.PointAt(1), topEdge.PointAt(1), topEdge.PointAt(0), DocumentTolerance()));
                    }
                }

                foreach (Line edge in pLPolyline.GetSegments())
                {
                    pyramidBrepList.Add(Brep.CreateFromCornerPoints(edge.PointAt(0), centroid, edge.PointAt(1), DocumentTolerance()));
                }

                Brep[] pyramidBrep = Brep.CreateSolid(pyramidBrepList, DocumentTolerance());
                if (pyramidBrep[0].IsSolid)
                {
                    roof = GH_Convert.ToGeometricGoo(pyramidBrep[0]);
                }
                break;

            case "skillion":
                Line   frontEdge     = new Line();
                Line   backEdge      = new Line();
                double frontAngleMin = RhinoMath.ToRadians(90);
                double backAngleMin  = RhinoMath.ToRadians(90);

                foreach (Line edge in edges)
                {
                    Point3d  closestPt       = edge.ClosestPoint(centroid, true);
                    Vector3d perpVector      = closestPt - centroid;
                    double   angleDifference = Vector3d.VectorAngle(roofDirectionVector, perpVector);
                    if (angleDifference < frontAngleMin)
                    {
                        frontEdge     = edge;
                        frontAngleMin = angleDifference;
                    }
                    if (angleDifference > backAngleMin)
                    {
                        backEdge     = edge;
                        backAngleMin = angleDifference;
                    }
                }

                Point3d backEdgeFrom = backEdge.From;
                backEdgeFrom.Z = height;
                Point3d backEdgeTo = backEdge.To;
                backEdgeTo.Z = height;
                Point3d frontEdgeFrom = frontEdge.From;
                frontEdgeFrom.Z = facadeHeight;
                Point3d frontEdgeTo = frontEdge.To;
                frontEdgeTo.Z = facadeHeight;

                List <Point3d> basePtList = new List <Point3d> {
                    backEdge.From, backEdge.To, frontEdge.From, frontEdge.To, backEdge.From
                };
                Polyline       basePolyline = new Polyline(basePtList);
                List <Point3d> topPtList    = new List <Point3d> {
                    backEdgeFrom, backEdgeTo, frontEdgeFrom, frontEdgeTo, backEdgeFrom
                };
                Polyline topPolyline = new Polyline(topPtList);

                ///Creating individual faces seems to work better/cleaner than lofting curves
                List <Brep> skillionBreps = new List <Brep>();
                Line[]      baseLines     = basePolyline.GetSegments();
                Line[]      topLines      = topPolyline.GetSegments();
                for (int i = 0; i < baseLines.Count(); i++)
                {
                    Line bottomEdge = baseLines[i];
                    Line topEdge    = topLines[i];
                    skillionBreps.Add(Brep.CreateFromCornerPoints(bottomEdge.PointAt(0), bottomEdge.PointAt(1), topEdge.PointAt(1), topEdge.PointAt(0), DocumentTolerance()));
                }
                Brep baseSkillion = Brep.CreateFromCornerPoints(backEdge.From, backEdge.To, frontEdge.From, frontEdge.To, DocumentTolerance());
                Brep topSkillion  = Brep.CreateFromCornerPoints(backEdgeFrom, backEdgeTo, frontEdgeFrom, frontEdgeTo, DocumentTolerance());

                skillionBreps.Add(baseSkillion);
                skillionBreps.Add(topSkillion);
                Brep[] skillion = Brep.CreateSolid(skillionBreps, DocumentTolerance());
                if (skillion.Count() > 0)
                {
                    roof = GH_Convert.ToGeometricGoo(skillion[0]);
                }

                break;

            case "gabled":
                ///TODO: Look into getting oriented bbox using front edge as orientation plane,
                ///extrude gable roof profile from face of bbox, trim roof geo from footprint,
                ///loft between footprint and trimmed roof edges and join everything.

                ///Need to simply polylines with colinear segments. Angle tolerance based on Notre-Dame de Paris case
                //pL.Simplify(CurveSimplifyOptions.All, 0, RhinoMath.ToRadians(2)).TryGetPolyline(out Polyline pLSimplified);
                Polyline pLSimplified = pL.ToPolyline();
                pLSimplified.MergeColinearSegments(DocumentAngleTolerance() * 5, true);

                Line[] edgesSimplified = pLSimplified.GetSegments();
                if (edgesSimplified.Count() != 4)
                {
                    break;
                }
                Line        ridge            = new Line();
                Line        eaveOne          = new Line();
                Line        eaveTwo          = new Line();
                Polyline    topGablePolyline = new Polyline();
                List <Brep> gableBreps       = new List <Brep>();

                if ((edgesSimplified[0].Length > edgesSimplified[1].Length && roofOrientationString != "across") || ((edgesSimplified[0].Length < edgesSimplified[1].Length && roofOrientationString == "across")))
                {
                    ridge         = new Line(edgesSimplified[3].PointAt(0.5), edgesSimplified[1].PointAt(0.5));
                    ridge.FromZ   = height;
                    ridge.ToZ     = height;
                    eaveOne       = edgesSimplified[0];
                    eaveOne.FromZ = facadeHeight;
                    eaveOne.ToZ   = facadeHeight;
                    eaveTwo       = edgesSimplified[2];
                    eaveTwo.Flip();
                    eaveTwo.FromZ    = facadeHeight;
                    eaveTwo.ToZ      = facadeHeight;
                    topGablePolyline = new Polyline {
                        eaveOne.From, eaveOne.To, ridge.To, eaveTwo.To, eaveTwo.From, ridge.From, eaveOne.From
                    };

                    Brep[] gableRoof = Brep.CreateFromLoft(new List <Curve> {
                        eaveOne.ToNurbsCurve(), ridge.ToNurbsCurve(), eaveTwo.ToNurbsCurve()
                    }, Point3d.Unset, Point3d.Unset, LoftType.Straight, false);
                    gableRoof[0].Faces.SplitKinkyFaces();
                    gableBreps.Add(gableRoof[0]);
                }

                if ((edgesSimplified[0].Length > edgesSimplified[1].Length && roofOrientationString == "across") || (edgesSimplified[0].Length < edgesSimplified[1].Length && roofOrientationString != "across"))
                {
                    ridge         = new Line(edgesSimplified[0].PointAt(0.5), edgesSimplified[2].PointAt(0.5));
                    ridge.FromZ   = height;
                    ridge.ToZ     = height;
                    eaveOne       = edgesSimplified[1];
                    eaveOne.FromZ = facadeHeight;
                    eaveOne.ToZ   = facadeHeight;
                    eaveTwo       = edgesSimplified[3];
                    eaveTwo.Flip();
                    eaveTwo.FromZ    = facadeHeight;
                    eaveTwo.ToZ      = facadeHeight;
                    topGablePolyline = new Polyline {
                        eaveTwo.From, ridge.From, eaveOne.From, eaveOne.To, ridge.To, eaveTwo.To, eaveTwo.From
                    };

                    Brep[] gableRoof = Brep.CreateFromLoft(new List <Curve> {
                        eaveOne.ToNurbsCurve(), ridge.ToNurbsCurve(), eaveTwo.ToNurbsCurve()
                    }, Point3d.Unset, Point3d.Unset, LoftType.Straight, false);
                    gableRoof[0].Faces.SplitKinkyFaces();
                    gableBreps.Add(gableRoof[0]);
                }

                Brep[] gablewalls = Brep.CreateFromLoft(new List <Curve> {
                    pLSimplified.ToPolylineCurve(), topGablePolyline.ToPolylineCurve()
                }, Point3d.Unset, Point3d.Unset, LoftType.Straight, false);
                gablewalls[0].Faces.SplitKinkyFaces();
                gablewalls[0].MergeCoplanarFaces(DocumentTolerance());
                gableBreps.Add(gablewalls[0]);

                Brep baseGable = Brep.CreateFromCornerPoints(edgesSimplified[0].From, edgesSimplified[0].To, edgesSimplified[2].From, edgesSimplified[2].To, DocumentTolerance());
                gableBreps.Add(baseGable);
                Brep[] gable = Brep.JoinBreps(gableBreps, DocumentTolerance());

                if (gable[0].IsValid)
                {
                    roof = GH_Convert.ToGeometricGoo(gable[0]);
                }
                break;

            default:
                break;
            }

            return(roof);
        }
示例#5
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp      = commandData.Application;
            UIDocument    uidoc      = uiapp.ActiveUIDocument;
            Application   app        = uiapp.Application;
            Document      doc        = uidoc.Document;
            View          activeView = doc.ActiveView;

            //duplicated in the helper file! remember to change both
            double scale = 304.8;

            //string path = @"C:\Users\gbrog\Desktop\test.3dm";

            string path = @"C:\Users\giovanni.brogiolo\Desktop\ST00-0221.3dm";

            File3dm rhinoModel = File3dm.Read(path);

            List <Rhino.DocObjects.Layer> m_layers = rhinoModel.AllLayers.ToList();

            List <string> layers = Get_RhinoLayerNames(rhinoModel);

            File3dmObject[] rhinoObjects = Get_RhinoObjects(rhinoModel);

            List <Rhino.Geometry.LineCurve> rh_lines = new List <Rhino.Geometry.LineCurve>();

            List <Rhino.Geometry.ArcCurve> rh_arc = new List <Rhino.Geometry.ArcCurve>();

            List <Rhino.Geometry.TextEntity> rh_text = new List <TextEntity>();

            List <Rhino.Geometry.Leader> rh_textLeader = new List <Rhino.Geometry.Leader>();

            List <Rhino.Geometry.LinearDimension> rh_linearDimension = new List <LinearDimension>();

            List <List <Rhino.Geometry.Point3d> > rh_polylineCurvePoints = new List <List <Point3d> >();

            List <Tuple <string, XYZ> > rh_Blocks = new List <Tuple <string, XYZ> >();

            foreach (var item in rhinoObjects)
            {
                GeometryBase geo = item.Geometry;

                // check if geometry is a curve
                if (geo is Rhino.Geometry.LineCurve)
                {
                    // add curve to list
                    Rhino.Geometry.LineCurve ln = geo as Rhino.Geometry.LineCurve;
                    rh_lines.Add(ln);
                }

                if (geo is Rhino.Geometry.ArcCurve)
                {
                    // add curve to list
                    Rhino.Geometry.ArcCurve arc = geo as Rhino.Geometry.ArcCurve;
                    rh_arc.Add(arc);
                }


                if (!item.Attributes.IsInstanceDefinitionObject && geo is Rhino.Geometry.PolylineCurve)
                {
                    PolylineCurve pc = geo as PolylineCurve;

                    Polyline pl = pc.ToPolyline();

                    rh_polylineCurvePoints.Add(pl.ToList());
                }

                if (geo is Rhino.Geometry.TextEntity)
                {
                    TextEntity te = geo as Rhino.Geometry.TextEntity;
                    rh_text.Add(te);
                }

                if (geo is Rhino.Geometry.Leader)
                {
                    rh_textLeader.Add(geo as Rhino.Geometry.Leader);

                    //var text = geo as Rhino.Geometry.Leader;

                    //TaskDialog.Show("r", text.PlainText);
                }

                if (geo is Rhino.Geometry.AnnotationBase)
                {
                    var text = geo as Rhino.Geometry.AnnotationBase;

                    //TaskDialog.Show("r", text.PlainText);
                }

                if (geo is Rhino.Geometry.LinearDimension)
                {
                    LinearDimension ld = geo as Rhino.Geometry.LinearDimension;
                    rh_linearDimension.Add(ld);
                }

                if (geo is Rhino.Geometry.InstanceReferenceGeometry)
                {
                    InstanceReferenceGeometry refGeo = (InstanceReferenceGeometry)geo;

                    // Lookup the parent block definition
                    System.Guid blockDefId         = refGeo.ParentIdefId;
                    InstanceDefinitionGeometry def = rhinoModel.AllInstanceDefinitions.FindId(blockDefId);

                    // block definition name
                    string defname = def.Name;

                    //TaskDialog.Show("R", defname);

                    // transform data for block instance
                    Rhino.Geometry.Transform xform = refGeo.Xform;

                    double x = refGeo.Xform.M03 / scale;
                    double y = refGeo.Xform.M13 / scale;

                    XYZ placementPt = new XYZ(x, y, 0);

                    rh_Blocks.Add(new Tuple <string, XYZ>(defname, placementPt));
                }
            }

            //TaskDialog.Show("r", rh_linearDimension.Count.ToString());

            Rhynamo.clsGeometryConversionUtils rh_ds = new Rhynamo.clsGeometryConversionUtils();

            using (Transaction t = new Transaction(doc, "Convert lines"))
            {
                t.Start();

                rh_ds.Convert_rhLinesToRevitDetailCurve(doc, rh_lines, "3 Arup Continuous Line");

                rh_ds.Convert_PolycurveToLines(doc, rh_polylineCurvePoints, "1 Arup Continuous Line");

                rh_ds.Convert_ArcsToDS(doc, rh_arc);

                rh_ds.RhinoTextToRevitNote(doc, rh_text);

                rh_ds.RhinoLeaderToRevitNote(doc, rh_textLeader);

                rh_ds.RhinoToRevitDimension(doc, rh_linearDimension);

                rh_ds.Convert_rhBlocks(doc, rh_Blocks);

                t.Commit();
            }

            TaskDialog.Show("r", "Done");

            return(Result.Succeeded);
        }
示例#6
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Mesh topoMesh = new Mesh();

            DA.GetData <Mesh>("Topography Mesh", ref topoMesh);

            GH_Structure <IGH_GeometricGoo> featureGoo = new GH_Structure <IGH_GeometricGoo>();

            DA.GetDataTree <IGH_GeometricGoo>("Feature Geometry", out featureGoo);

            ///Reserve one processor for GUI
            totalMaxConcurrancy = System.Environment.ProcessorCount - 1;

            ///Tells us how many threads were using
            //Message = totalMaxConcurrancy + " threads";


            ///Get Rtree of points and flat mesh for processing in detailed feature mesh projection
            Mesh topoFlat = new Mesh();

            Point3d[] topoFlatPoints = null;
            RTree     rTree          = new RTree();

            if (!fast)
            {
                topoFlat = topoMesh.DuplicateMesh();
                for (int i = 0; i < topoFlat.Vertices.Count; i++)
                {
                    Point3f v = topoFlat.Vertices[i];
                    v.Z = 0;
                    topoFlat.Vertices.SetVertex(i, v);
                }

                topoFlatPoints = topoFlat.Vertices.ToPoint3dArray();
                rTree          = RTree.CreateFromPointArray(topoFlatPoints);
            }

            ///Create a dictionary that works in parallel
            var gooTree = new System.Collections.Concurrent.ConcurrentDictionary <GH_Path, List <IGH_GeometricGoo> >();

            ///Multi-threading the loop
            System.Threading.Tasks.Parallel.ForEach(featureGoo.Paths,
                                                    new System.Threading.Tasks.ParallelOptions {
                MaxDegreeOfParallelism = totalMaxConcurrancy
            },
                                                    pth =>
            {
                ///Create containers for translating from GH Goo
                Point3d pt               = new Point3d();
                Polyline pLine           = null;
                PolylineCurve pLineCurve = null;
                Curve curve              = null;
                Mesh mesh       = new Mesh();
                Surface surface = null;
                Brep brep       = new Brep();

                ///Output container list
                List <IGH_GeometricGoo> gGooList = new List <IGH_GeometricGoo>();
                List <IGH_GeometricGoo> fGooList = new List <IGH_GeometricGoo>();
                var branchFeatures    = featureGoo.get_Branch(pth);
                BoundingBox branchBox = new BoundingBox();

                if (branchFeatures.Count > 0)
                {
                    foreach (var bGoo in branchFeatures)
                    {
                        ///Get geometry type(s) in branch
                        string geomType       = string.Empty;
                        IGH_GeometricGoo fGoo = GH_Convert.ToGeometricGoo(bGoo);

                        if (fGoo != null && fGoo.IsValid)
                        {
                            if (grouped)
                            {
                                ///Need to duplicate geometry or else move vector piles on similar to the following
                                ///https://www.grasshopper3d.com/forum/topics/c-component-refresh-problem
                                fGooList.Add(fGoo.DuplicateGeometry());
                                branchBox.Union(fGoo.Boundingbox);
                            }

                            geomType = fGoo.TypeName;

                            switch (geomType)
                            {
                            case "Point":
                                fGoo.CastTo <Point3d>(out pt);
                                gGooList.Add(ProjectPointToTopo(topoMesh, pt));
                                break;

                            case "Line":
                            case "Polyline":
                                fGoo.CastTo <Polyline>(out pLine);

                                if (fast)
                                {
                                    gGooList.Add(ProjectPolylineToTopo(topoMesh, pLine));
                                }
                                else
                                {
                                    ///Lock topoMesh so it's not accessed by mutliple threads at once in a "deadlock"
                                    ///https://docs.microsoft.com/en-us/dotnet/standard/threading/managed-threading-best-practices
                                    lock (topoMesh)
                                    {
                                        gGooList.AddRange(ProjectCurveToTopo(topoMesh, pLine.ToNurbsCurve()));
                                    }
                                }

                                break;

                            case "PolylineCurve":
                                fGoo.CastTo <PolylineCurve>(out pLineCurve);
                                if (fast)
                                {
                                    gGooList.Add(ProjectPolylineToTopo(topoMesh, pLineCurve.ToPolyline()));
                                }
                                else
                                {
                                    lock (topoMesh)
                                    {
                                        gGooList.AddRange(ProjectCurveToTopo(topoMesh, pLineCurve.ToNurbsCurve()));
                                    }
                                }
                                break;

                            case "Curve":
                                fGoo.CastTo <Curve>(out curve);
                                if (fast)
                                {
                                    if (curve.TryGetPolyline(out pLine))
                                    {
                                        gGooList.Add(ProjectPolylineToTopo(topoMesh, pLine));
                                    }
                                    else
                                    {
                                        gGooList.AddRange(ProjectCurveToTopo(topoMesh, curve));
                                    }
                                }
                                else
                                {
                                    lock (topoMesh)
                                    {
                                        gGooList.AddRange(ProjectCurveToTopo(topoMesh, curve));
                                    }
                                }
                                break;

                            case "Mesh":
                                fGoo.CastTo <Mesh>(out mesh);
                                if (mesh.IsClosed)
                                {
                                    gGooList.Add(ProjectSolidMeshToTopo(topoMesh, mesh));
                                }
                                else
                                {
                                    if (fast)
                                    {
                                        gGooList.Add(ProjectMeshToTopoFast(topoMesh, mesh));
                                    }
                                    else
                                    {
                                        lock (topoMesh)
                                        {
                                            gGooList.Add(ProjectMeshToTopoSlow(topoMesh, topoFlat, topoFlatPoints, rTree, mesh));
                                        }
                                    }
                                }
                                break;

                            case "Surface":
                                fGoo.CastTo <Surface>(out surface);
                                gGooList.Add(ProjectSurfaceToTopoFast(topoMesh, surface));
                                break;

                            case "Brep":
                                fGoo.CastTo <Brep>(out brep);
                                gGooList.Add(ProjectBrepToTopo(topoMesh, brep));
                                break;

                            default:
                                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not able to move " + geomType + " geometry to mesh" +
                                                  ". Geometry must be a Point, Curve, Mesh, Surface or Brep.");
                                break;
                            }
                        }
                        else
                        {
                        }
                    }

                    ///Move objects in branch a minimum distance if grouped selected
                    ///If only one feature in a branch, not need to group
                    if (grouped && gGooList.Count > 1)
                    {
                        ///Get the minimum move vector
                        Point3d lowestPoint = new Point3d();
                        double minDistance  = double.MaxValue;
                        Vector3d minimumVec = new Vector3d();
                        foreach (var gi in gGooList)
                        {
                            if (gi != null)
                            {
                                Point3d gGooMin     = gi.Boundingbox.Min;
                                Vector3d distVector = gGooMin - branchBox.Min;
                                if (distVector.Length < minDistance && distVector.Length > 0 && distVector.IsValid)
                                {
                                    lowestPoint = gGooMin;
                                    minDistance = distVector.Length;
                                    minimumVec  = new Vector3d(0, 0, distVector.Z);
                                }
                            }
                        }

                        ///Move orignal feature geometry the minimum move vector
                        if (minDistance != double.MaxValue)
                        {
                            Transform transform = Transform.Translation(minimumVec);
                            for (int f = 0; f < fGooList.Count; f++)
                            {
                                fGooList[f].Transform(transform);
                            }
                            gooTree[pth] = fGooList;
                        }
                    }
                    else
                    {
                        gooTree[pth] = gGooList;
                    }
                }
            });
            ///End of multi-threaded loop


            ///Convert dictionary to regular old data tree
            GH_Structure <IGH_GeometricGoo> gTree = new GH_Structure <IGH_GeometricGoo>();

            foreach (KeyValuePair <GH_Path, List <IGH_GeometricGoo> > g in gooTree)
            {
                gTree.AppendRange(g.Value, g.Key);
            }

            topoFlat.Dispose();
            topoMesh.Dispose();

            DA.SetDataTree(0, gTree);
        }