Ejemplo n.º 1
0
        public static List <LineStrip> PlanPaths(TriangleMesh triangles, List <Tabs> tabs, Router router)
        {
            List <LineStrip> routs = new List <LineStrip>();

            foreach (Tabs tab in tabs)
            {
                tab.TabHeight = router.TabHeight;
            }

            float toolRadius      = router.ToolDiameter / 2.0f;
            float maxCutDepth     = router.MaxCutDepth;
            float lastPassHeight  = router.LastPassHeight;
            float cleanPassFactor = 0.90f; // 90% of the tool radius will be removed on the clean pass

            float minZ = triangles.MinPoint.Z;
            float maxZ = triangles.MaxPoint.Z;

            var slices = GetSlices(triangles, router);
            //GL.PushMatrix();
            //foreach (var s in slices)
            //{
            //    GL.Translate(triangles.MaxPoint.X - triangles.MinPoint.X, 0, 0);
            //    DrawSlice(Color.Orange, Color.Black, s);
            //}
            //GL.PopMatrix();

            Slice top = slices[0];

            slices.RemoveAt(0);
            Slice boundary = new Slice(slices[slices.Count - 1]);

            boundary.Offset(toolRadius * (cleanPassFactor + 1.05f)); // Note: this is slightly larger to allow some polygon width to exist

            // Enable complete removal of holes with no tabs
            foreach (var tab in tabs)
            {
                if (tab.TabLocations.Count() == 0)
                {
                    boundary.Union(tab.Boundary);
                }
            }

            top.SubtractFrom(boundary);

            //GL.PushMatrix();
            //GL.Translate(0, 0, 1);
            //DrawSlice(Color.Black, Color.DarkGray, boundary);
            //GL.PopMatrix();

            Slice holes = top.PolygonsWithoutHoles();

            List <Hole> holeRouts = new List <Hole>();

            foreach (var polygon in holes.IndividualPolygons())
            {
                holeRouts.Add(new Hole(polygon, toolRadius, cleanPassFactor));
            }

            foreach (Slice current in slices)
            {
                current.Offset(toolRadius);
                //GL.PushMatrix();
                //GL.Translate(0, 0, -0.001f);
                ////DrawSlice(Color.Tan, Color.Gray, boundary);
                //GL.PopMatrix();
                ////DrawSlice(Color.Red, Color.Blue, current);

                Slice original = new Slice(current);
                current.SubtractFrom(boundary);

                // current will now be several polygons representing the area to rout out, minus the tool radius offset on either side.
                // Split it into polygons around the outside and inside of parts (the first two will be outside polygons, the next two inside, next two outside, ...).
                Slice outsidePairs = current.GetOutsidePairs();
                //DrawSlice(Color.Gold, Color.Yellow, outsidePairs);

                Slice insidePairs = current.GetInsidePairs();
                //DrawSlice(Color.Orange, Color.NavajoWhite, insidePairs);


                // If a polygon has no holes, that means it's a hole in the actual shape to be cut out.
                // These can be cut first before outside cuts are done.
                holes = current.PolygonsWithoutHoles();
                foreach (var holePolygon in insidePairs.PolygonsWithoutHoles().IndividualPolygons())
                {
                    foreach (var hole in holeRouts)
                    {
                        if (hole.Contains(holePolygon))
                        {
                            hole.AddPolygon(holePolygon);
                            break;
                        }
                    }
                }


                // Rout all outside paths.  These will be done from top down, one layer at a time for structural reasons.
                // For the top several layers, two paths could be combined...
                var outsideRouts = RoutAreasWithHoles(insidePairs.PolygonsWithHoles(), toolRadius, cleanPassFactor, tabs, true);
                var newLines     = new List <LineStrip>();
                foreach (var line in outsideRouts)
                {
                    var r = new LineStrip();
                    r.AddRange(line.Vertices);
                    r.Append(line.Vertices[0]);
                    r.Vertices.Reverse();
                    newLines.Add(r);
                }
                routs.AddRange(newLines);


                outsideRouts = RoutAreasWithHoles(outsidePairs, toolRadius, cleanPassFactor, tabs, false);
                newLines     = new List <LineStrip>();
                foreach (var line in outsideRouts)
                {
                    var r = new LineStrip();
                    r.AddRange(line.Vertices);
                    r.Append(line.Vertices[0]);
                    newLines.Add(r);
                }
                routs.AddRange(newLines);
            }

            foreach (var hole in holeRouts)
            {
                var newRouts = new List <LineStrip>();
                foreach (var line in hole.GetRouts())
                {
                    LineStrip r = new LineStrip();
                    // Note: these might not start and end in the same place, but that's OK.
                    r.AddRange(line.Vertices);
                    newRouts.Add(r);
                }
                routs.InsertRange(0, newRouts);
            }

            // Adjust the lowest point - allow plunging through the bottom of the material for a clean cut.
            foreach (LineStrip r in routs)
            {
                for (int i = 0; i < r.Vertices.Count; i++)
                {
                    var point = r.Vertices[i];
                    if (point.Z < (minZ + .005f))
                    {
                        r.Vertices[i] = new Vector3(point.X, point.Y, lastPassHeight);
                    }
                }
            }
            return(routs);
        }