Beispiel #1
0
        public static Vector3d ClosestNormal(this Brep brep, Point3d testPoint)
        {
            double   u, v;
            BrepFace bf = BrepFaceFromPoint(brep, testPoint);

            bf.ClosestPoint(testPoint, out u, out v);
            return(bf.NormalAt(u, v));
        }
Beispiel #2
0
        public Vector3d GetBrepFaceNormal(BrepFace bf)
        {
            Point3d point0 = new Point3d(0, 0, 0);
            double  u, v;

            bf.ClosestPoint(point0, out u, out v);
            Vector3d normal = bf.NormalAt(u, v);

            return(normal);
        }
Beispiel #3
0
        public static Plane GetPlaneAtAreaPoint(Point3d areaPoint, BrepFace bf)
        {
            double u;
            double v;

            bf.ClosestPoint(areaPoint, out u, out v);
            Plane oPlane = new Plane();

            bf.FrameAt(u, v, out oPlane);
            return(oPlane);
        }
Beispiel #4
0
        public static Vector3d _NormalAt(this BrepFace face, Point3d point)
        {
            double u;
            double v;

            if (face.ClosestPoint(point, out u, out v))
            {
                var normal = face.NormalAt(u, v);
                return(normal);
            }
            return(Vector3d.Unset);
        }
Beispiel #5
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));
            }
        }
Beispiel #6
0
        public static Brep TurnUp(this Brep brep)
        {
            var      props  = AreaMassProperties.Compute(brep);
            Point3d  center = props.Centroid;
            BrepFace face   = brep.Faces[0];


            face.ClosestPoint(center, out double u, out double v);
            Vector3d normal = face.NormalAt(u, v);

            normal.Unitize();
            if (normal.Z < 0)
            {
                brep.Flip();
            }
            return(brep);
        }
Beispiel #7
0
        /// <summary>
        /// Create frames that are aligned with a Brep. The input curve does not
        /// necessarily have to lie on the Brep.
        /// </summary>
        /// <param name="curve">Input centreline of the glulam.</param>
        /// <param name="brep">Brep to align the glulam orientation to.</param>
        /// <param name="num_samples">Number of orientation frames to use for alignment.</param>
        /// <returns>New Glulam oriented to the brep.</returns>
        public static Plane[] FramesNormalToSurface(Curve curve, Brep brep, int num_samples = 20)
        {
            num_samples = Math.Max(num_samples, 2);
            double[]       t = curve.DivideByCount(num_samples - 1, true);
            Plane[]        planes = new Plane[num_samples];
            Vector3d       xaxis, yaxis, zaxis;
            Point3d        pt;
            ComponentIndex ci;

            for (int i = 0; i < t.Length; ++i)
            {
                brep.ClosestPoint(curve.PointAt(t[i]), out pt, out ci, out double u, out double v, 0, out yaxis);

                // From: https://discourse.mcneel.com/t/brep-closestpoint-normal-is-not-normal/15147/8
                // If the closest point is found on an edge, average the face normals
                if (ci.ComponentIndexType == ComponentIndexType.BrepEdge)
                {
                    BrepEdge edge  = brep.Edges[ci.Index];
                    int[]    faces = edge.AdjacentFaces();
                    yaxis = Vector3d.Zero;
                    for (int j = 0; j < faces.Length; ++j)
                    {
                        BrepFace bf = edge.Brep.Faces[j];
                        if (bf.ClosestPoint(pt, out u, out v))
                        {
                            Vector3d faceNormal = bf.NormalAt(u, v);
                            yaxis += faceNormal;
                        }
                    }
                    yaxis.Unitize();
                }

                zaxis     = curve.TangentAt(t[i]);
                xaxis     = Vector3d.CrossProduct(zaxis, yaxis);
                planes[i] = new Plane(pt, xaxis, yaxis);
            }

            return(planes);
        }
Beispiel #8
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Brep   m_brep = null;
            int    m_side = 0;
            double m_path_extension = 10.0, m_depth_extension = 3.0, m_max_depth = 50.0;

            if (!DA.GetData("Workplane", ref Workplane))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Workplane missing. Default used (WorldXY).");
            }

            if (!DA.GetData("MachineTool", ref Tool))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "MachineTool missing. Default used.");
            }

            bool zigzag = false;

            DA.GetData("Brep", ref m_brep);
            DA.GetData("Side", ref m_side);
            DA.GetData("PathExtension", ref m_path_extension);
            DA.GetData("DepthExtension", ref m_depth_extension);
            DA.GetData("MaxDepth", ref m_max_depth);
            DA.GetData("Zigzag", ref zigzag);

            if (m_brep == null)
            {
                return;
            }

            // Find the UV direction
            int D  = (m_side & (1 << 0)) > 0 ? 1 : 0;
            int nD = (m_side & (1 << 0)) > 0 ? 0 : 1;

            // Find out if we are on the opposite edges
            int S  = (m_side & (1 << 1)) > 0 ? 1 : 0;
            int nS = (m_side & (1 << 1)) > 0 ? 0 : 1;


            BrepFace face = m_brep.Faces[0];

            // Warn if the surface is not suitable for flank machining
            if (face.Degree(nD) != 1)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Surface isn't ruled in this direction!");
            }

            // Get appropriate surface edge
            Curve flank_edge = m_brep.Faces[0].IsoCurve(D, m_brep.Faces[0].Domain(nD)[S]);


            // Discretize flank edge using angle and length tolerances
            Polyline flank_pts = flank_edge.ToPolyline(0, 0, 0.01, 0.1, 0, 0.1, 0, 0, true).ToPolyline();

            // If we are on opposite edge, reverse the flank curve for consistent direction
            if (S > 0)
            {
                flank_pts.Reverse();
            }

            // Get corresponding edge parameter from discretized curve points
            int N = flank_pts.Count;

            double[] tt = new double[N];
            for (int i = 0; i < N; ++i)
            {
                flank_edge.ClosestPoint(flank_pts[i], out tt[i]);
            }

            // Get all isocurves corresponding to the vertices of the discretized edge curev
            var rules = tt.Select(x => m_brep.Faces[0].IsoCurve(nD, x));

            // Get the length of all isocurves
            var lengths = rules.Select(x => x.GetLength()).ToList();

            List <Vector3d> directions;

            // Make sure to use tangent at right end of the isocurve
            // (S == 1 when we are on the opposite side)
            if (S == 0)
            {
                directions = rules.Select(x => x.TangentAtStart).ToList();
            }
            else
            {
                directions = rules.Select(x => - x.TangentAtEnd).ToList();
            }

            // Determine maximum depth based on longest isocurve and depth limit
            double deepest = Math.Min(m_max_depth, lengths.Max());

            // Determine number of passes based on deepest cut and stepdown
            int passes = (int)Math.Ceiling(deepest / Tool.StepDown);


            List <Path> paths = new List <Path>();

            // Declare variables for Brep closest point calculation
            double   u, v;
            Vector3d normal;

            // Create paths for each pass
            for (int i = 0; i <= passes; ++i)
            {
                Path path = new Path();
                for (int j = 0; j < N; ++j)
                {
                    // Find closest normal
                    face.ClosestPoint(flank_pts[j], out u, out v);
                    normal = face.NormalAt(u, v);

                    // Calculate pass depth
                    double depth = Math.Min(m_max_depth,
                                            Math.Min(
                                                lengths[j] + m_depth_extension,
                                                Tool.StepDown * i));

                    Point3d origin = flank_pts[j]
                                     + (directions[j] * (Math.Min(m_max_depth, lengths[j] + m_depth_extension) / passes * i)
                                        + (normal * Tool.Diameter / 2));

                    path.Add(new Plane(origin, directions[j]));
                }

                // If the path is extended, add extra planes at the start and end
                if (m_path_extension > 0.0)
                {
                    // Path vector at start
                    Vector3d start = new Vector3d(path.First.Origin - path[1].Origin);
                    start.Unitize();

                    // Path vector at end
                    Vector3d end = new Vector3d(path.Last.Origin - path[path.Count - 2].Origin);
                    end.Unitize();

                    Plane pStart = path.First;
                    Plane pEnd   = path.Last;

                    // Shift plane origins by path vectors
                    pStart.Origin = pStart.Origin + start * m_path_extension;
                    pEnd.Origin   = pEnd.Origin + end * m_path_extension;

                    // Add extension planes to path
                    path.Insert(0, pStart);
                    path.Add(pEnd);
                }
                if (zigzag && i.Modulus(2) > 0)
                {
                    path.Reverse();
                }
                paths.Add(path);
            }

            /*
             #region OLD
             *          int D = (iSide & (1 << 0)) > 0 ? 1 : 0;
             *          int nD = (iSide & (1 << 0)) > 0 ? 0 : 1;
             *
             *          int S = (iSide & (1 << 1)) > 0 ? 1 : 0;
             *          int nS = (iSide & (1 << 1)) > 0 ? 0 : 1;
             *
             *
             *          double tMin = iBrep.Faces[0].Domain(nD).Min;
             *          double tMax = iBrep.Faces[0].Domain(nD).Max;
             *
             *          Curve[] cEdges = new Curve[2];
             *
             *          cEdges[S] = iBrep.Faces[0].IsoCurve(D, tMin);
             *          cEdges[nS] = iBrep.Faces[0].IsoCurve(D, tMax);
             *
             *          double[] len = new double[2];
             *          for (int i = 0; i < 2; ++i)
             *          {
             *              len[i] = cEdges[i].GetLength();
             *          }
             *
             *          List<Point3d>[] subdivs = new List<Point3d>[2];
             *          for (int i = 0; i < 2; ++i)
             *          {
             *              subdivs[i] = new List<Point3d>();
             *              double[] ts = cEdges[i].DivideByCount(iN - 1, true);
             *              subdivs[i].AddRange(ts.Select(x => cEdges[i].PointAt(x)));
             *          }
             *
             *          List<Line> rules = new List<Line>();
             *          List<Vector3d> directions = new List<Vector3d>();
             *
             *          for (int i = 0; i < iN; ++i)
             *          {
             *              rules.Add(new Line(subdivs[0][i], subdivs[1][i]));
             *              Vector3d d = new Vector3d(subdivs[0][i] - subdivs[1][i]);
             *              d.Unitize();
             *              directions.Add(d);
             *          }
             *
             *
             *          double max = 0;
             *
             *          for (int i = 0; i < iN; ++i)
             *          {
             *              max = Math.Min(Math.Max(max, rules[i].Length + iDepthExt), iMaxDepth);
             *          }
             *
             *          int Nsteps = (int)Math.Ceiling(max / iStepDown);
             *
             *          List<PPolyline> paths = new List<PPolyline>();
             *          Point3d cpt;
             *          ComponentIndex ci;
             *          double s, t;
             *          Vector3d normal;
             *
             *          for (int i = 0; i < Nsteps; ++i)
             *          {
             *              PPolyline poly = new PPolyline();
             *              for (int j = 0; j < rules.Count; ++j)
             *              {
             *                  double l = Math.Min(rules[j].Length + iDepthExt, iMaxDepth) / Nsteps;
             *                  Point3d pt = rules[j].From - directions[j] * l * i;
             *                  iBrep.ClosestPoint(pt, out cpt, out ci, out s, out t, 3.0, out normal);
             *                  poly.Add(new Plane(pt + normal * iToolDiameter / 2, Vector3d.CrossProduct(directions[j], normal), normal));
             *              }
             *
             *              if (iPathExt > 0.0)
             *              {
             *                  Vector3d start = new Vector3d(poly.First.Origin - poly[1].Origin);
             *                  start.Unitize();
             *
             *                  Vector3d end = new Vector3d(poly.Last.Origin - poly[poly.Count - 2].Origin);
             *                  end.Unitize();
             *
             *                  Plane pStart = poly.First;
             *                  Plane pEnd = poly.Last;
             *                  pStart.Origin = pStart.Origin + start * iPathExt;
             *                  pEnd.Origin = pEnd.Origin + end * iPathExt;
             *                  poly.Insert(0, pStart);
             *                  poly.Add(pEnd);
             *              }
             *
             *              paths.Add(poly);
             *          }
             *
             #region Last layer
             *
             *          PPolyline last = new PPolyline();
             *          for (int j = 0; j < rules.Count; ++j)
             *          {
             *              double l = Math.Min(rules[j].Length + iDepthExt, iMaxDepth);
             *              Point3d pt = rules[j].From - directions[j] * l;
             *              iBrep.ClosestPoint(pt, out cpt, out ci, out s, out t, 3.0, out normal);
             *              last.Add(new Plane(pt + normal * iToolDiameter / 2, Vector3d.CrossProduct(directions[j], normal), normal));
             *          }
             *
             *          if (iPathExt > 0.0)
             *          {
             *              Vector3d start = new Vector3d(last.First.Origin - last[1].Origin);
             *              start.Unitize();
             *
             *              Vector3d end = new Vector3d(last.Last.Origin - last[last.Count - 2].Origin);
             *              end.Unitize();
             *
             *              Plane pStart = last.First;
             *              Plane pEnd = last.Last;
             *              pStart.Origin = pStart.Origin + start * iPathExt;
             *              pEnd.Origin = pEnd.Origin + end * iPathExt;
             *              last.Insert(0, pStart);
             *              last.Add(pEnd);
             *          }
             *
             *          last.Add(paths.First().Last);
             *
             *          paths.Add(last);
             *
             #endregion
             #endregion
             */

            DA.SetDataList("Paths", paths.Select(x => new GH_tasPath(x)));
        }
Beispiel #9
0
        public static Point3d _GetCentroidAndArea(this BrepFace face, out double area)
        {
            area = 0;
            //return GetAvaragePoint(face);
            var mesh = face.GetMesh(MeshType.Render);

            if (mesh == null)
            {
                mesh = face.GetMesh(MeshType.Any);
            }

            //if (mesh != null)
            //{
            //    return GetAvaragePoint(mesh); // a bit fast than 'AreaMassProperties.Compute'
            //}

            AreaMassProperties mas = (mesh != null && mesh.Faces.Count > 0)
                ? AreaMassProperties.Compute(mesh) // faster 10x times then compute from face
                : null                             //AreaMassProperties.Compute(face)  - can be very-very-slow!
            ;

            if (mas != null)
            {
                area = mas.Area;
            }

            Point3d c = (mas != null)
                ? mas.Centroid
                : face.OuterLoop._GetCentroid(true); // In case when object is new and mesh is not generated yet - use avarage point calculations

            if (c == Point3d.Origin)
            {
                // how to get brep to try last chance to get centroid ???
            }

            //Point3f start = Point3f.Unset;
            //foreach (var v in mesh.Vertices)
            //{
            //    if (start == Point3f.Unset)
            //    {
            //        start = v;
            //    }
            //    else
            //    {
            //        start.X += v.X;
            //        start.Y += v.Y;
            //        start.Z += v.Z;
            //    }
            //}
            //c.X = start.X / mesh.Vertices.Count;
            //c.Y = start.Y / mesh.Vertices.Count;
            //c.Z = start.Z / mesh.Vertices.Count;

            //var mas = AreaMassProperties.Compute(face);
            //var c = mas.Centroid;

            double uclosest, vclosest;

            if (face.ClosestPoint(c, out uclosest, out vclosest))
            {
                c = face.PointAt(uclosest, vclosest);
            }
            return(c);
        }
Beispiel #10
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);
        }
Beispiel #11
0
    public void  GetElements(Box box, int divX, int divY, BrepFace face, Brep brep, double stepZ, int inX, int inY)
    {
        midPts = new HashSet <Point3d>();
        Random rnd = new Random();

        grid = new DataTree <Point3d>();  columns = new DataTree <Line>();

        xConn = new DataTree <Line>();    yConn = new DataTree <Line>();

        Mesh M = BrepToMesh(brep);

        // int maxDivZ = GetMaxDivInZ(M, stepZ);
        // sampled = new bool[divX, divY, maxDivZ];

        Point3d[] p  = box.GetCorners();
        Vector3d  dx = (p[1] - p[0]) / (double)divX;
        Vector3d  dy = (p[3] - p[0]) / (double)divY;

        for (int i = 0; i < divX; i++)
        {
            for (int j = 0; j < divY; j++)
            {
                Point3d           pt = p[0] + i * dx + j * dy;
                double            u, v; face.ClosestPoint(pt, out u, out v);
                PointFaceRelation pfr = face.IsPointOnFace(u, v);

                if (pfr == PointFaceRelation.Exterior)
                {
                    continue;
                }
                grid.Add(pt, new GH_Path(i));

                Ray3d  ray = new Ray3d(pt + new Vector3d(0, 0, 0.01), Z);
                double t   = Rhino.Geometry.Intersect.Intersection.MeshRay(M, ray);

                Line column = new Line(pt, ray.PointAt(t));
                columns.Add(column, new GH_Path(i));

                int divZ = (int)(column.Length / (double)stepZ);
                for (int k = 1; k < divZ; k++)
                {
                    Point3d zPt = pt + new Vector3d(0, 0, 1) * k * stepZ;

                    int posX = rnd.Next(0, inX + 1);
                    if (posX != 0)
                    {
                        UpdateConnections(zPt, dx, posX, i, j, k, 1, 0);
                    }

                    int negX = rnd.Next(0, inX + 1);
                    if (negX != 0)
                    {
                        UpdateConnections(zPt, dx, negX, i, j, k, -1, 0);
                    }

                    int posY = rnd.Next(0, inY + 1);
                    if (posY != 0)
                    {
                        UpdateConnections(zPt, dy, posY, i, j, k, 1, 1);
                    }

                    int negY = rnd.Next(0, inY + 1);
                    if (negY != 0)
                    {
                        UpdateConnections(zPt, dy, negY, i, j, k, -1, 1);
                    }
                }
            }
        }
    }