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