public static double EstimateRefinementCells(IGH_GeometricGoo geo, double baseCellSize) { var regionName = Geometry.getUserString(geo, "ComputeName"); var refinementDetails = Geometry.getUserString(geo, "ComputeRefinementRegion"); if (string.IsNullOrEmpty(regionName) || string.IsNullOrEmpty(refinementDetails)) { return(0.0); } var details = new RefinementDetails().FromJson(refinementDetails); details.CellSize = baseCellSize; var cellSize = baseCellSize / Math.Pow(2, int.Parse(details.Levels.Split(' ')[1])); var mesh = new Mesh(); geo.CastTo(out mesh); return(mesh.Volume() / Math.Pow(cellSize, 3)); }
public static double EstimateSurfaceAreaCells(IGH_GeometricGoo geo, double baseCellSize) { var surfaceName = Geometry.getUserString(geo, "ComputeName"); var levels = Geometry.getUserString(geo, "ComputeMeshLevels"); if (string.IsNullOrEmpty(surfaceName) || string.IsNullOrEmpty(levels)) { return(0.0); } var meshLevel = new MeshLevelDetails().FromJson(levels); meshLevel.CellSize = baseCellSize; var cellSize = baseCellSize / Math.Pow(2, meshLevel.Level.Min); var mesh = new Mesh(); geo.CastTo(out mesh); var area = AreaMassProperties.Compute(mesh).Area; return((area / Math.Pow(cellSize, 2)) * 4); }
/// <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); }