private GH_Brep NonPlanarBrep(double depth, IList <PolylineCurve> curveList) { var nonPlanarBrep = new List <Brep>(); var topBrep = Brep.CreatePatch(new[] { curveList[0] }, 5, 5, _tolerance[0]); nonPlanarBrep.Add(topBrep); BrepFace face = topBrep.Faces[0]; Vector3d faceNormal = face.NormalAt(face.Domain(0).Mid, face.Domain(1).Mid); if (Vector3d.VectorAngle(faceNormal, Vector3d.ZAxis) < Vector3d.VectorAngle(faceNormal, -Vector3d.ZAxis)) { faceNormal = -faceNormal; } Brep bottomBrep = topBrep.DuplicateBrep(); bottomBrep.Translate(faceNormal * depth); nonPlanarBrep.Add(bottomBrep); IEnumerable <Curve> edgeCurveList = topBrep.Edges.Select(edge => edge.DuplicateCurve()); nonPlanarBrep.AddRange(edgeCurveList.Select(edgeCurve => Surface.CreateExtrusion(edgeCurve, faceNormal * depth).ToBrep())); return(new GH_Brep(Brep.JoinBreps(nonPlanarBrep, _tolerance[0])[0] ?? topBrep)); }
public static Point2d _GetMidPoint2d(this BrepFace face) { double u, v; if (face.ClosestPoint(face._GetCentroid(), out u, out v)) { return(new Point2d(u, v)); } else { u = face.Domain(0).Mid; v = face.Domain(1).Mid; return(new Point2d(u, v)); } }
private List <double[]> GetUVs(BrepFace bf, int numDivisions) { var uDom = bf.Domain(0); var vDom = bf.Domain(1); var uvs = new List <double[]>(); for (int u = 0; u <= numDivisions; u++) { for (int v = 0; v <= numDivisions; v++) { double pU = uDom.ParameterAt((double)u / numDivisions); double pV = vDom.ParameterAt((double)v / numDivisions); if (bf.IsPointOnFace(pU, pV) != PointFaceRelation.Exterior) { uvs.Add(new[] { pU, pV }); } } } return(uvs); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { double tolerance = doc.ModelAbsoluteTolerance; var opt_double = new OptionDouble(Radius, true, tolerance); // Select first surface to fillet var go0 = new GetObject(); go0.SetCommandPrompt("Select first surface to fillet"); go0.AddOptionDouble("Radius", ref opt_double, "Fillet radius"); go0.GeometryFilter = ObjectType.Surface; go0.EnablePreSelect(false, true); for (;;) { GetResult res = go0.Get(); if (res == GetResult.Option) { continue; } else if (res != GetResult.Object) { return(Result.Cancel); } break; } var obj_ref0 = go0.Object(0); BrepFace face0 = obj_ref0.Face(); if (null == face0) { return(Result.Failure); } double u0, v0; if (null == obj_ref0.SurfaceParameter(out u0, out v0)) { var pt = obj_ref0.SelectionPoint(); if (!pt.IsValid || !face0.ClosestPoint(pt, out u0, out v0)) { // Make surface selection scriptable u0 = face0.Domain(0).Min; v0 = face0.Domain(1).Min; } } // Juggle the pickpoint ever so slightly towards the middle of the domain // to get a better chance of getting a valid chord. if (u0 == face0.Domain(0).Min || u0 == face0.Domain(0).Max) { u0 = 0.99 * u0 + 0.01 * face0.Domain(0).Mid; } if (v0 == face0.Domain(1).Min || v0 == face0.Domain(1).Max) { v0 = 0.99 * v0 + 0.01 * face0.Domain(1).Mid; } // Select second surface to fillet var go1 = new GetObject(); go1.SetCommandPrompt("Select second surface to fillet"); go1.AddOptionDouble("Radius", ref opt_double, "Fillet radius"); go1.GeometryFilter = ObjectType.Surface; go1.EnablePreSelect(false, true); go1.DeselectAllBeforePostSelect = false; for (;;) { GetResult res = go1.Get(); if (res == GetResult.Option) { continue; } else if (res != GetResult.Object) { return(Result.Cancel); } break; } var obj_ref1 = go1.Object(0); BrepFace face1 = obj_ref1.Face(); if (null == face1) { return(Result.Failure); } double u1, v1; if (null == obj_ref1.SurfaceParameter(out u1, out v1)) { var pt = obj_ref1.SelectionPoint(); if (!pt.IsValid || !face1.ClosestPoint(pt, out u1, out v1)) { // Make surface selection scriptable u1 = face1.Domain(0).Min; v1 = face1.Domain(1).Min; } } // Juggle the pickpoint ever so slightly towards the middle of the domain // to get a better chance of getting a valid chord. if (u1 == face1.Domain(0).Min || u1 == face1.Domain(0).Max) { u1 = 0.99 * u0 + 0.01 * face1.Domain(0).Mid; } if (v1 == face1.Domain(1).Min || v1 == face1.Domain(1).Max) { v1 = 0.99 * v0 + 0.01 * face1.Domain(1).Mid; } var p0 = new Point2d(u0, v0); var p1 = new Point2d(u1, v1); var fillets = Surface.CreateRollingBallFillet(face0, p0, face1, p1, Radius, tolerance); foreach (var f in fillets) { doc.Objects.AddSurface(f); } doc.Views.Redraw(); Radius = opt_double.CurrentValue; return(Result.Success); }
public static Vector3d NormalCentroid(BrepFace brepFace) { return(brepFace.NormalAt(brepFace.Domain(0).Mid, brepFace.Domain(1).Mid)); }
public static Point3d FaceCentroid(BrepFace brepFace) { return(brepFace.PointAt(brepFace.Domain(0).Mid, brepFace.Domain(1).Mid)); }
public List <Point> PoissonDiskSampleGeodesic(Brep brep, double distance, int K, double I, int P, int seed) { Random random = new Random(seed); //Sample Si initial points ConcurrentBag <Point> initialPoints = new ConcurrentBag <Point>(); List <Task> tasks = new List <Task>(); for (int i = 0; i < brep.Faces.Count; i++) { tasks.Add(new Task(new Action <object>((iObj) => { int index = (int)iObj; BrepFace face = brep.Faces[index]; double area = AreaMassProperties.Compute(brep.Faces[index]).Area; int n = Convert.ToInt32((area / distance) * I); for (int j = 0; j < n; j++) { Point point = new Point(); point.PositionUV = new Point2d(face.Domain(0).ParameterAt(random.NextDouble()), face.Domain(1).ParameterAt(random.NextDouble())); if (face.IsPointOnFace(point.PositionUV.X, point.PositionUV.Y) > 0) { point.FaceID = index; point.Position = face.PointAt(point.PositionUV.X, point.PositionUV.Y); initialPoints.Add(point); } else { j--; } } }), i as object)); } DoTasksParallel(tasks); //Build grid partition double radius = distance / 2; double cellSize = radius / (Math.Sqrt(3)); Box boundingBoxPoints = new Box(new BoundingBox(initialPoints.Select(Point => Point.Position))); int nX = Convert.ToInt32(boundingBoxPoints.X.Length / cellSize); int nY = Convert.ToInt32(boundingBoxPoints.Y.Length / cellSize); int nZ = Convert.ToInt32(boundingBoxPoints.Z.Length / cellSize); if (nX == 0) { nX = 1; } if (nY == 0) { nY = 1; } if (nZ == 0) { nZ = 1; } Box boundingBoxCells = new Box(boundingBoxPoints.Plane, new Interval(0, nX * cellSize), new Interval(0, nY * cellSize), new Interval(0, nZ * cellSize)); boundingBoxCells.Transform(Transform.Translation(boundingBoxPoints.Center - boundingBoxCells.Center)); Cell[,,] cells = new Cell[nX, nY, nZ]; int nPhaseGroup = 0; for (int x = 0; x < P; x++) { for (int y = 0; y < P; y++) { for (int z = 0; z < P; z++) { for (int px = x; px < nX; px += P) { for (int py = y; py < nY; py += P) { for (int pz = z; pz < nZ; pz += P) { Cell cell = new Cell(); cell.X = px; cell.Y = py; cell.Z = pz; cell.PhaseGroup = nPhaseGroup; cells[px, py, pz] = cell; Point3d corner0 = boundingBoxCells.PointAt(cell.X / (double)nX, cell.Y / (double)nY, cell.Z / (double)nZ); Point3d corner1 = corner0 + new Point3d(cellSize, cellSize, cellSize); cell.Box = new Box(boundingBoxCells.Plane, new Point3d[2] { corner0, corner1 }); } } } nPhaseGroup++; } } } //Assign initial points to grid cells foreach (var point in initialPoints) { tasks.Add(new Task(new Action <object>((pointObj) => { Point currentPoint = (Point)pointObj; if (currentPoint == null) { return; } foreach (var cell in cells) { if (cell.Box.Contains(currentPoint.Position)) { cell.InitialPoints.Add(currentPoint); } } }), point)); } DoTasksParallel(tasks); //Get relevant cells into phase groups. int nPhaseGroups = P * P * P; List <ConcurrentBag <Cell> > phaseGroups = new List <ConcurrentBag <Cell> >(nPhaseGroups); for (int i = 0; i < nPhaseGroups; i++) { phaseGroups.Add(new ConcurrentBag <Cell>()); } foreach (var cell in cells) { if (cell.InitialPoints.Count > 0) { phaseGroups[cell.PhaseGroup].Add(cell); } } //currentPoint.Transform(Transform.PlaneToPlane(boundingBoxCells.Plane, Plane.WorldXY)); //int cellX = Convert.ToInt32(Math.Floor((currentPoint.X / boundingBoxCells.X.Length) * nX)); //int cellY = Convert.ToInt32(Math.Floor((currentPoint.Y / boundingBoxCells.Y.Length) * nY)); //int cellZ = Convert.ToInt32(Math.Floor((currentPoint.Z / boundingBoxCells.Z.Length) * nZ)); //Cell currentCell = cells[cellX, cellY, cellZ]; //currentCell.InitialPoints.Add((Point)point); //phaseGroups[currentCell.PhaseGroup].Add(currentCell); //Parallel sampling for (int i = 0; i < K; i++) { phaseGroups = phaseGroups.OrderBy(a => random.Next()).ToList(); foreach (var phaseGroup in phaseGroups) { foreach (var cell in phaseGroup) { if (i >= cell.InitialPoints.Count) { continue; } tasks.Add(new Task(new Action(() => { List <Point> nearPoints = new List <Point>(); for (int x = -2; x <= 2; x++) { int iX = cell.X + x; if (iX < 0 || iX >= nX) { continue; } for (int y = -2; y <= 2; y++) { int iY = cell.Y + y; if (iY < 0 || iY >= nY) { continue; } for (int z = -2; z <= 2; z++) { int iZ = cell.Z + z; if (iZ < 0 || iZ >= nZ) { continue; } nearPoints.AddRange(cells[iX, iY, iZ].Samples); } } } Point point = cell.InitialPoints[i]; if (point == null) { return; } point.normal = brep.Faces[point.FaceID].NormalAt(point.PositionUV.X, point.PositionUV.Y); nearPoints.Sort((x, y) => { return(x.Position.DistanceToSquared(point.Position).CompareTo(y.Position.DistanceToSquared(point.Position))); }); bool valid = true; foreach (var other in nearPoints) { double distanceEuclidien = other.Position.DistanceTo(point.Position); Vector3d vector = (other.Position - point.Position) / distanceEuclidien; double c1 = point.normal * vector; double c2 = other.normal * vector; double distanceGeodesic = 0; if (c1 != c2) { distanceGeodesic = ((Math.Asin(c1) - Math.Asin(c2)) / c1 - c2) * distanceEuclidien; } else { distanceGeodesic = distanceEuclidien / Math.Sqrt(1 - c1 * c1); } if (distanceGeodesic < distance) { valid = false; break; } } if (valid) { cell.Samples.Add(point); } }))); } DoTasksParallel(tasks); } } //Collect samples; List <Point> samples = new List <Point>(); foreach (var phaseGroup in phaseGroups) { foreach (var cell in phaseGroup) { samples.AddRange(cell.Samples); } } return(samples); }
public void Write(string path) { if (!System.IO.Directory.Exists(path)) { throw new Exception("Path does not exist."); } if (g == null || beam == null) { throw new Exception("Must add Glulam and Beam geometry!"); } Rhino.FileIO.File3dm file = new Rhino.FileIO.File3dm(); // Setup layers Layer lRoot = new Layer(); lRoot.Name = "tas"; file.AllLayers.Add(lRoot); lRoot = file.AllLayers.Last(); Layer lNC = new Layer(); lNC.Name = "NC"; lNC.IsVisible = false; lNC.IsLocked = true; file.AllLayers.Add(lNC); lNC = file.AllLayers.Last(); lNC.ParentLayerId = lRoot.Id; Layer lBL = new Layer(); lBL.Name = "BL"; lBL.IsLocked = true; file.AllLayers.Add(lBL); lBL = file.AllLayers.Last(); lBL.ParentLayerId = lRoot.Id; Layer lBE = new Layer(); lBE.Name = "BE"; lBE.IsLocked = true; file.AllLayers.Add(lBE); lBE = file.AllLayers.Last(); lBE.ParentLayerId = lRoot.Id; Layer lBL_Centreline = new Layer(); lBL_Centreline.Name = "BL_Centreline"; lBL_Centreline.Index = 1; lBL_Centreline.Color = Color.FromArgb(0, 0, 255); lBL_Centreline.ParentLayerId = lBL.Id; file.AllLayers.Add(lBL_Centreline); lBL_Centreline = file.AllLayers.Last(); Layer lBL_Geometry = new Layer(); lBL_Geometry.Name = "BL_Geometry"; lBL_Geometry.Color = Color.FromArgb(125, 200, 125); lBL_Geometry.ParentLayerId = lBL.Id; file.AllLayers.Add(lBL_Geometry); lBL_Geometry = file.AllLayers.Last(); Layer lBL_Safety = new Layer(); lBL_Safety.Name = "BL_Safety"; lBL_Safety.IsVisible = false; lBL_Safety.Color = Color.FromArgb(200, 200, 200); lBL_Safety.ParentLayerId = lBL.Id; file.AllLayers.Add(lBL_Safety); lBL_Safety = file.AllLayers.Last(); Layer lBE_Geometry = new Layer(); lBE_Geometry.Name = "BE_Geometry"; lBE_Geometry.Color = Color.FromArgb(100, 100, 100); lBE_Geometry.ParentLayerId = lBE.Id; file.AllLayers.Add(lBE_Geometry); lBE_Geometry = file.AllLayers.Last(); Layer lNC_Surface = new Layer(); lNC_Surface.Name = "NC_Surface"; lNC_Surface.Color = Color.FromArgb(255, 0, 255); lNC_Surface.ParentLayerId = lNC.Id; file.AllLayers.Add(lNC_Surface); lNC_Surface = file.AllLayers.Last(); Layer lNC_Normals = new Layer(); lNC_Normals.Name = "NC_SurfaceNormals"; lNC_Normals.Color = Color.FromArgb(255, 0, 150); lNC_Normals.ParentLayerId = lNC.Id; file.AllLayers.Add(lNC_Normals); lNC_Normals = file.AllLayers.Last(); Layer lNC_GlueFace = new Layer(); lNC_GlueFace.Name = "NC_GlueFace"; lNC_GlueFace.Color = Color.FromArgb(255, 0, 255); lNC_GlueFace.ParentLayerId = lNC.Id; file.AllLayers.Add(lNC_GlueFace); lNC_GlueFace = file.AllLayers.Last(); Layer lNC_Joints = new Layer(); lNC_Joints.Name = "NC_Joints"; lNC_Joints.Color = Color.FromArgb(255, 0, 255); lNC_Joints.ParentLayerId = lNC.Id; file.AllLayers.Add(lNC_Joints); lNC_Joints = file.AllLayers.Last(); Layer lNC_Drill = new Layer(); lNC_Drill.Name = "NC_Drill"; lNC_Drill.Color = Color.FromArgb(255, 0, 0); lNC_Drill.ParentLayerId = lNC.Id; file.AllLayers.Add(lNC_Drill); lNC_Drill = file.AllLayers.Last(); // Add objects ObjectAttributes oa; oa = new ObjectAttributes(); oa.LayerIndex = lBL_Centreline.Index; oa.Name = "Glulam_Centreline"; file.Objects.AddCurve(g.Centreline, oa); oa.LayerIndex = lBL_Geometry.Index; oa.UserDictionary.Set("LamWidth", g.Data.LamWidth); oa.UserDictionary.Set("LamHeight", g.Data.LamHeight); oa.UserDictionary.Set("NumWidth", g.Data.NumWidth); oa.UserDictionary.Set("NumHeight", g.Data.NumHeight); oa.Name = "Glulam_BoundingMesh"; Guid blank_id = file.Objects.AddBrep(g.GetBoundingBrep(), oa); oa.LayerIndex = lBE_Geometry.Index; oa.UserDictionary.Clear(); oa.Name = "Beam_Geometry"; file.Objects.AddBrep(beam, oa); oa.LayerIndex = lBL_Safety.Index; oa.Name = "Glulam_Safety"; Brep blank_safety = g.GetBoundingBrep(50.0); if (blank_safety != null) { file.Objects.AddBrep(blank_safety, oa); } for (int i = 0; i < Cuts_Surface.Count; ++i) { oa.LayerIndex = lNC_Surface.Index; oa.Name = string.Format("Machining_Surface_{0:00}", i); file.Objects.AddBrep(Cuts_Surface[i], oa); oa.LayerIndex = lNC_Normals.Index; oa.Name = string.Format("Machining_Surface_Normal_{0:00}", i); BrepFace bf = Cuts_Surface[i].Faces[0]; Vector3d normal = bf.NormalAt(bf.Domain(0).Mid, bf.Domain(1).Mid); Point3d point = bf.PointAt(bf.Domain(0).Mid, bf.Domain(1).Mid); file.Objects.AddTextDot(string.Format("NC_Srf_{0:00}", i), point + normal * 100.0, oa); file.Objects.AddLine(new Line(point, point + normal * 100.0), oa); } for (int i = 0; i < Cuts_GlueSurface.Count; ++i) { oa.LayerIndex = lNC_Surface.Index; oa.Name = string.Format("Glue_Surface_{0:00}", i); file.Objects.AddBrep(Cuts_GlueSurface[i], oa); oa.LayerIndex = lNC_Normals.Index; oa.Name = string.Format("Glue_Surface_Normal_{0:00}", i); BrepFace bf = Cuts_GlueSurface[i].Faces[0]; Vector3d normal = bf.NormalAt(bf.Domain(0).Mid, bf.Domain(1).Mid); Point3d point = bf.PointAt(bf.Domain(0).Mid, bf.Domain(1).Mid); file.Objects.AddTextDot(string.Format("NC_Glu_{0:00}", i), point + normal * 100.0, oa); file.Objects.AddLine(new Line(point, point + normal * 100.0), oa); } for (int i = 0; i < Cuts_Joint.Count; ++i) { oa.LayerIndex = lNC_Joints.Index; oa.Name = string.Format("Joint_Surface_{0:00}", i); file.Objects.AddBrep(Cuts_Joint[i], oa); oa.LayerIndex = lNC_Normals.Index; oa.Name = string.Format("Joint_Surface_Normal_{0:00}", i); BrepFace bf = Cuts_Joint[i].Faces[0]; Vector3d normal = bf.NormalAt(bf.Domain(0).Mid, bf.Domain(1).Mid); Point3d point = bf.PointAt(bf.Domain(0).Mid, bf.Domain(1).Mid); file.Objects.AddTextDot(string.Format("NC_Jnt_{0:00}", i), point + normal * 100.0, oa); file.Objects.AddLine(new Line(point, point + normal * 100.0), oa); } for (int i = 0; i < Drills_Joint.Count; ++i) { oa.LayerIndex = lNC_Drill.Index; oa.Name = string.Format("Joint_Drill_{0:00}", i); Vector3d dir = Drills_Joint[i].Direction; dir.Unitize(); file.Objects.AddTextDot(string.Format("NC_Drill_{0:00}", i), Drills_Joint[i].From - dir * 40.0, oa); file.Objects.AddLine(Drills_Joint[i], oa); } // Write notes and data string notes = ""; notes += "This file was created with tasTools (Tom Svilans, 2017).\n\n"; notes += "Blank data:\n\n"; notes += string.Format("LamWidth\n{0}\n", g.Data.LamWidth); notes += string.Format("LamHeight\n{0}\n", g.Data.LamHeight); notes += string.Format("NumWidth\n{0}\n", g.Data.NumWidth); notes += string.Format("NumHeight\n{0}\n", g.Data.NumHeight); notes += string.Format("Length\n{0}\n", g.Centreline.GetLength()); file.Notes.Notes = notes; file.Settings.ModelUnitSystem = UnitSystem.Millimeters; file.Write(path + "\\" + Name + ".3dm", 5); }