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));
        }
Пример #2
0
        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));
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
 public static Vector3d NormalCentroid(BrepFace brepFace)
 {
     return(brepFace.NormalAt(brepFace.Domain(0).Mid, brepFace.Domain(1).Mid));
 }
Пример #6
0
 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);
        }
Пример #8
0
        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);
        }