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