protected static List <TPVertexFlags> CreateToolpathVertexFlags <TSegment>(FillCurve <TSegment> curve)
            where TSegment : IFillSegment, new()
        {
            var flags = new List <TPVertexFlags>(curve.Elements.Count + 1);

            for (int i = 0; i < curve.Elements.Count + 1; i++)
            {
                var flag = TPVertexFlags.None;

                if (i == 0)
                {
                    flag = TPVertexFlags.IsPathStart;
                }
                else
                {
                    var segInfo = curve.Elements[i - 1].Edge;
                    if (segInfo.IsConnector)
                    {
                        flag = TPVertexFlags.IsConnector;
                    }
                }

                flags.Add(flag);
            }

            return(flags);
        }
예제 #2
0
        protected FillCurveSet2d ComputeFillPaths(GeneralPolygon2d poly, SegmentSet2d polyCache)
        {
            var stepSpans = ComputeSegments(poly, polyCache);

            // [TODO] need a pathfinder here, that can chain segments efficiently
            // (for now just do dumb things?)

            FillCurveSet2d paths = new FillCurveSet2d();

            foreach (var seglist in stepSpans)
            {
                foreach (Segment2d seg in seglist)
                {
                    // Discard paths that are too short
                    if (seg.Length < MinPathLengthMM)
                    {
                        continue;
                    }

                    var fill_seg = new FillCurve <FillSegment>()
                    {
                        FillType = FillType,
                    };
                    fill_seg.BeginCurve(seg.P0);
                    fill_seg.AddToCurve(seg.P1, new FillSegment());
                    paths.Append(fill_seg);
                }
            }

            return(paths);
        }
        protected void BuildCurveConcrete <TSegment>(FillCurve <TSegment> curve, double useSpeed) where TSegment : IFillSegment, new()
        {
            var vertices   = curve.Vertices().ToList();
            var flags      = CreateToolpathVertexFlags(curve);
            var dimensions = GetFillDimensions(curve);

            Builder.AppendExtrude(vertices, useSpeed, dimensions, curve.FillType, curve.IsHoleShell, flags);
        }
 protected virtual void BuildCurve(FillCurve curve, double useSpeed)
 {
     if (!(curve is FillCurve <FillSegment> o))
     {
         throw new NotImplementedException($"FillPathScheduler2d.BuildCurve does not support type {curve.GetType()}.");
     }
     BuildCurveConcrete(o, useSpeed);
 }
        protected static FillCurve OrientCurve(FillCurve curve, Vector2d currentPos2)
        {
            if (curve.Entry.DistanceSquared(currentPos2) > curve.Exit.DistanceSquared(currentPos2))
            {
                return(curve.Reversed());
            }

            return(curve);
        }
        protected void AssertValidCurve(FillCurve curve)
        {
            int N = curve.ElementCount;

            if (N < 1)
            {
                StackFrame frame  = new StackFrame(1);
                var        method = frame.GetMethod();
                var        type   = method.DeclaringType;
                var        name   = method.Name;
                throw new ArgumentException($"{type}.{name}: degenerate curve; must have at least 1 edge.");
            }
        }
        // [TODO] would it ever make sense to break polyline to avoid huge travel??
        public virtual void AppendFillCurve(FillCurve curve)
        {
            Vector3d currentPos  = Builder.Position;
            Vector2d currentPos2 = currentPos.xy;

            AssertValidCurve(curve);

            var oriented = OrientCurve(curve, currentPos2);

            AppendTravel(currentPos2, oriented.Entry);

            BuildCurve(oriented, SelectSpeed(oriented));
        }
예제 #8
0
        // (approximately) clip insetPoly to band around clipPoly.
        // vertices are discarded if outside clipPoly, or within clip_dist
        // remaining polylines are returned
        // In all-pass case currently returns polyline w/ explicit first==last vertices
        public List <FillBase> clip_to_band(Polygon2d insetpoly, GeneralPolygon2d clipPoly, double clip_dist)
        {
            double clipSqr = clip_dist * clip_dist;

            int N = insetpoly.VertexCount;

            Vector2d[] midline  = new Vector2d[N];
            bool[]     clipped  = new bool[N];
            int        nClipped = 0;

            for (int i = 0; i < N; ++i)
            {
                Vector2d po = insetpoly[i];
                if (clipPoly.Contains(po) == false)
                {
                    clipped[i] = true;
                    nClipped++;
                    continue;
                }

                int    iHole, iSeg; double segT;
                double distSqr = clipPoly.DistanceSquared(po, out iHole, out iSeg, out segT);
                if (distSqr < clipSqr)
                {
                    clipped[i] = true;
                    nClipped++;
                    continue;
                }

                // not ideal...
                midline[i] = po;
            }
            if (nClipped == N)
            {
                return(new List <FillBase>());
            }
            if (nClipped == 0)
            {
                var all = new FillCurve <FillSegment>(midline);
                return(new List <FillBase>()
                {
                    all.CloseCurve()
                });
            }

            return(find_polygon_spans(midline, clipped));
        }
예제 #9
0
        private FillCurve <FillSegment> SimplifyPath(FillCurve <FillSegment> path)
        {
            var simp = new PolySimplification2(new PolyLine2d(path.Vertices()));

            switch (SimplifyAmount)
            {
            default:
            case SimplificationLevel.Minor:
                simp.SimplifyDeviationThreshold = ToolWidth / 4; break;

            case SimplificationLevel.Moderate:
                simp.SimplifyDeviationThreshold = ToolWidth / 2; break;

            case SimplificationLevel.Aggressive:
                simp.SimplifyDeviationThreshold = ToolWidth; break;
            }
            simp.Simplify();
            path = new FillCurve <FillSegment>(simp.Result.ToArray())
            {
                FillType = this.FillType
            };
            return(path);
        }
예제 #10
0
        private FillCurveSet2d WalkPathGraph(DGraph2 pathGraph)
        {
            var boundaries = IdentifyBoundaryHashSet(pathGraph);

            var paths = new FillCurveSet2d();

            // walk paths from boundary vertices
            while (boundaries.Count > 0)
            {
                int start_vid = boundaries.First();
                boundaries.Remove(start_vid);
                int vid = start_vid;
                int eid = pathGraph.GetVtxEdges(vid)[0];

                var path = new FillCurve <FillSegment>()
                {
                    FillType = this.FillType
                };

                path.BeginCurve(pathGraph.GetVertex(vid));
                while (true)
                {
                    Index2i next = DGraph2Util.NextEdgeAndVtx(eid, vid, pathGraph);
                    eid = next.a;
                    vid = next.b;
                    int gid = pathGraph.GetEdgeGroup(eid);
                    if (gid < 0)
                    {
                        path.AddToCurve(pathGraph.GetVertex(vid), new FillSegment(true));
                    }
                    else
                    {
                        path.AddToCurve(pathGraph.GetVertex(vid));
                    }

                    if (boundaries.Contains(vid))
                    {
                        boundaries.Remove(vid);
                        break;
                    }
                }

                // discard paths that are too short
                if (path.TotalLength() < MinPathLengthMM)
                {
                    continue;
                }

                // run polyline simplification to get rid of unneccesary detail in connectors
                // [TODO] we could do this at graph level...)
                // [TODO] maybe should be checking for collisions? we could end up creating
                //  non-trivial overlaps here...
                if (SimplifyAmount != SimplificationLevel.None && path.Elements.Count > 1)
                {
                    path = SimplifyPath(path);
                }

                paths.Append(path);
            }
            return(paths);
        }
예제 #11
0
 public void Append(FillCurve curve)
 {
     Curves.Add(curve);
 }
예제 #12
0
 public abstract void Extend(FillCurve other, double vertexComparisonTolerance = 1e-6);