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); }
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; }
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)); }
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); }
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); }
/// <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); }