Esempio n. 1
0
        public void SortAndAppendTo(Vector2d startPoint, IFillPathScheduler2d scheduler)
        {
            var saveHint = scheduler.SpeedHint;

            OutPoint = startPoint;

            List <Index3i> sorted = find_short_path_v1(startPoint);

            foreach (Index3i idx in sorted)
            {
                FillCurveSet2d paths = new FillCurveSet2d();

                SchedulerSpeedHint pathHint = SchedulerSpeedHint.Default;
                if (idx.a == 0)   // loop
                {
                    PathLoop loop = Loops[idx.b];
                    pathHint = loop.speedHint;
                    if (idx.c != 0)
                    {
                        int           iStart = idx.c;
                        FillPolygon2d o      = new FillPolygon2d();
                        int           N      = loop.curve.VertexCount;
                        for (int i = 0; i < N; ++i)
                        {
                            o.AppendVertex(loop.curve[(i + iStart) % N]);
                        }
                        o.TypeFlags = loop.curve.TypeFlags;
                        paths.Append(o);
                        OutPoint = o.Vertices[0];
                    }
                    else
                    {
                        paths.Append(loop.curve);
                        OutPoint = loop.curve.Vertices[0];
                    }
                }
                else      // span
                {
                    PathSpan span = Spans[idx.b];
                    if (idx.c == 1)
                    {
                        span.curve.Reverse();
                    }
                    paths.Append(span.curve);
                    OutPoint = span.curve.End;
                    pathHint = span.speedHint;
                }

                scheduler.SpeedHint = pathHint;
                scheduler.AppendCurveSets(new List <FillCurveSet2d>()
                {
                    paths
                });
            }

            scheduler.SpeedHint = saveHint;
        }
        /// <summary>
        /// Fill polygon with solid fill strategy.
        /// If bIsInfillAdjacent, then we optionally add one or more shells around the solid
        /// fill, to give the solid fill something to stick to (imagine dense linear fill adjacent
        /// to sparse infill area - when the extruder zigs, most of the time there is nothing
        /// for the filament to attach to, so it pulls back. ugly!)
        /// </summary>
        protected virtual void fill_solid_region(int layer_i, GeneralPolygon2d solid_poly,
                                                 IFillPathScheduler2d scheduler,
                                                 bool bIsInfillAdjacent = false)
        {
            List <GeneralPolygon2d> fillPolys = new List <GeneralPolygon2d>()
            {
                solid_poly
            };

            // if we are on an infill layer, and this shell has some infill region,
            // then we are going to draw contours around solid fill so it has
            // something to stick to
            // [TODO] should only be doing this if solid-fill is adjecent to infill region.
            //   But how to determine this? not easly because we don't know which polys
            //   came from where. Would need to do loop above per-polygon
            if (bIsInfillAdjacent && Settings.Part.InteriorSolidRegionShells > 0)
            {
                ShellsFillPolygon interior_shells = new ShellsFillPolygon(solid_poly, Settings.FillTypeFactory.Solid());
                interior_shells.PathSpacing            = Settings.SolidFillPathSpacingMM();
                interior_shells.ToolWidth              = Settings.Machine.NozzleDiamMM;
                interior_shells.Layers                 = Settings.Part.InteriorSolidRegionShells;
                interior_shells.PreserveOuterShells    = true;
                interior_shells.InsetFromInputPolygonX = 0;
                interior_shells.Compute();
                scheduler.AppendCurveSets(interior_shells.Shells);
                fillPolys = interior_shells.InnerPolygons;
            }

            // now actually fill solid regions
            foreach (GeneralPolygon2d fillPoly in fillPolys)
            {
                var solidFillSpacing        = Settings.SolidFillPathSpacingMM();
                TiledFillPolygon tiled_fill = new TiledFillPolygon(fillPoly)
                {
                    TileSize    = 13.1 * solidFillSpacing,
                    TileOverlap = 0.3 * solidFillSpacing
                };
                tiled_fill.TileFillGeneratorF = (tilePoly, index) =>
                {
                    int odd = ((index.x + index.y) % 2 == 0) ? 1 : 0;
                    RasterFillPolygon solid_gen = new RasterFillPolygon(tilePoly, Settings.FillTypeFactory.Solid())
                    {
                        InsetFromInputPolygon = false,
                        PathSpacing           = solidFillSpacing,
                        ToolWidth             = Settings.Machine.NozzleDiamMM,
                        AngleDeg = LayerFillAngleF(layer_i + odd)
                    };
                    return(solid_gen);
                };

                tiled_fill.Compute();
                scheduler.AppendCurveSets(tiled_fill.FillCurves);
            }
        }
Esempio n. 3
0
        public virtual void SortAndAppendTo(Vector2d startPoint, IFillPathScheduler2d scheduler)
        {
            var saveHint = scheduler.SpeedHint;

            CurrentPosition = startPoint;

            List <Index3i> sorted = find_short_path_v1(startPoint);

            foreach (Index3i idx in sorted)
            {
                FillCurveSet2d paths = new FillCurveSet2d();

                SpeedHint pathHint = SpeedHint.Default;
                if (idx.a == 0)
                { // loop
                    PathLoop loop = Loops[idx.b];
                    pathHint = loop.speedHint;
                    if (idx.c != 0)
                    {
                        var rolled = loop.loop.RollToVertex(idx.c);
                        paths.Append(rolled);
                        CurrentPosition = rolled.Entry;
                    }
                    else
                    {
                        paths.Append(loop.loop);
                        CurrentPosition = loop.loop.Entry;
                    }
                }
                else
                {  // span
                    PathSpan span = Spans[idx.b];
                    if (idx.c == 1)
                    {
                        span.curve = span.curve.Reversed();
                    }
                    paths.Append(span.curve);
                    CurrentPosition = span.curve.Exit;
                    pathHint        = span.speedHint;
                }

                scheduler.SpeedHint = pathHint;
                scheduler.AppendCurveSets(new List <FillCurveSet2d>()
                {
                    paths
                });
            }

            scheduler.SpeedHint = saveHint;
        }
Esempio n. 4
0
 public PassThroughGroupScheduler(IFillPathScheduler2d target, Vector2d startPoint) : base(target, startPoint)
 {
 }
Esempio n. 5
0
 public GroupScheduler2d(IFillPathScheduler2d target, Vector2d startPoint)
 {
     TargetScheduler = target;
     lastPoint       = startPoint;
 }
Esempio n. 6
0
        protected virtual void fill_bridge_region_decompose(GeneralPolygon2d poly, IFillPathScheduler2d scheduler, PrintLayerData layer_data)
        {
            poly.Simplify(0.1, 0.01, true);
            TriangulatedPolygonGenerator generator = new TriangulatedPolygonGenerator()
            {
                Polygon = poly, Subdivisions = 16
            };
            DMesh3 mesh = generator.Generate().MakeDMesh();
            //Util.WriteDebugMesh(mesh, "/Users/rms/scratch/bridgemesh.obj");


            //List<Polygon2d> polys = decompose_mesh_recursive(mesh);
            List <Polygon2d> polys = decompose_cluster_up(mesh);

            Util.WriteDebugMesh(mesh, "/Users/rms/scratch/bridgemesh_reduce.obj");

            double spacing = Settings.BridgeFillPathSpacingMM();

            foreach (Polygon2d polypart in polys)
            {
                Box2d    box   = polypart.MinimalBoundingBox(0.00001);
                Vector2d axis  = (box.Extent.x > box.Extent.y) ? box.AxisY : box.AxisX;
                double   angle = Math.Atan2(axis.y, axis.x) * MathUtil.Rad2Deg;

                GeneralPolygon2d gp = new GeneralPolygon2d(polypart);

                ShellsFillPolygon shells_fill = new ShellsFillPolygon(gp);
                shells_fill.PathSpacing            = Settings.SolidFillPathSpacingMM();
                shells_fill.ToolWidth              = Settings.Machine.NozzleDiamMM;
                shells_fill.Layers                 = 1;
                shells_fill.InsetFromInputPolygonX = 0.25;
                shells_fill.ShellType              = ShellsFillPolygon.ShellTypes.BridgeShell;
                shells_fill.FilterSelfOverlaps     = false;
                shells_fill.Compute();
                scheduler.AppendCurveSets(shells_fill.GetFillCurves());
                var fillPolys = shells_fill.InnerPolygons;

                double offset = Settings.Machine.NozzleDiamMM * Settings.SolidFillBorderOverlapX;
                fillPolys = ClipperUtil.MiterOffset(fillPolys, offset);

                foreach (var fp in fillPolys)
                {
                    BridgeLinesFillPolygon fill_gen = new BridgeLinesFillPolygon(fp)
                    {
                        InsetFromInputPolygon = false,
                        PathSpacing           = spacing,
                        ToolWidth             = Settings.Machine.NozzleDiamMM,
                        AngleDeg = angle,
                    };
                    fill_gen.Compute();
                    scheduler.AppendCurveSets(fill_gen.GetFillCurves());
                }
            }

            // fit bbox to try to find fill angle that has shortest spans
            //Box2d box = poly.Outer.MinimalBoundingBox(0.00001);
            //Vector2d axis = (box.Extent.x > box.Extent.y) ? box.AxisY : box.AxisX;
            //double angle = Math.Atan2(axis.y, axis.x) * MathUtil.Rad2Deg;

            // [RMS] should we do something like this?
            //if (Settings.SolidFillBorderOverlapX > 0) {
            //	double offset = Settings.Machine.NozzleDiamMM * Settings.SolidFillBorderOverlapX;
            //	fillPolys = ClipperUtil.MiterOffset(fillPolys, offset);
            //}
        }
Esempio n. 7
0
 /// <summary>
 /// Fill a bridge region. Goal is to use shortest paths possible.
 /// So, instead of just using fixed angle, we fit bounding box and
 /// use the shorter axis.
 /// </summary>
 protected override void fill_bridge_region(GeneralPolygon2d poly, IFillPathScheduler2d scheduler, PrintLayerData layer_data)
 {
     base.fill_bridge_region(poly, scheduler, layer_data);
     //fill_bridge_region_decompose(poly, scheduler, layer_data);
 }