Esempio n. 1
0
        protected virtual List <GeneralPolygon2d> make_solid(GeneralPolygon2d poly, bool bIsSupportSolid)
        {
            // always do a self-union of outer polygon. This allows Clipper to clean up many
            // problems in input polygons, eg self-intersections and other junk
            GeneralPolygon2d        gouter        = new GeneralPolygon2d(poly.Outer);
            List <GeneralPolygon2d> resolvedSolid =
                ClipperUtil.Union(gouter, gouter, MIN_AREA);

            // solid may contain overlapping holes. We need to resolve these before continuing,
            // otherwise those overlapping regions will be filled by Clipper even/odd rules
            foreach (Polygon2d hole in poly.Holes)
            {
                GeneralPolygon2d holePoly = new GeneralPolygon2d(hole);
                resolvedSolid = ClipperUtil.PolygonBoolean(resolvedSolid, holePoly, ClipperUtil.BooleanOp.Difference, MIN_AREA);
            }

            if (bIsSupportSolid == false && Thickened != null)
            {
                // Subtract away any clearance solids
                foreach (var pair in Thickened)
                {
                    if (pair.Key != poly)
                    {
                        resolvedSolid = ClipperUtil.Difference(resolvedSolid, pair.Value);
                    }
                }
            }
            return(filter_solids(resolvedSolid));
        }
Esempio n. 2
0
        public bool Compute()
        {
            AxisAlignedBox2d bounds = Polygon.Bounds;

            ScaleGridIndexer2 index = new ScaleGridIndexer2()
            {
                CellSize = TileSize
            };

            Vector2i min = index.ToGrid(bounds.Min) - Vector2i.One;
            Vector2i max = index.ToGrid(bounds.Max);

            List <Tile> Tiles = new List <Tile>();

            for (int y = min.y; y <= max.y; ++y)
            {
                for (int x = min.x; x <= max.x; ++x)
                {
                    Tile t = new Tile();
                    t.index = new Vector2i(x, y);
                    Vector2d         tile_min = index.FromGrid(t.index);
                    Vector2d         tile_max = index.FromGrid(t.index + Vector2i.One);
                    AxisAlignedBox2d tile_box = new AxisAlignedBox2d(tile_min, tile_max);
                    tile_box.Expand(TileOverlap);
                    t.poly = new Polygon2d(new Vector2d[] { tile_box.GetCorner(0), tile_box.GetCorner(1), tile_box.GetCorner(2), tile_box.GetCorner(3) });
                    Tiles.Add(t);
                }
            }

            gParallel.ForEach(Tiles, (tile) =>
            {
                tile.regions =
                    ClipperUtil.PolygonBoolean(Polygon, new GeneralPolygon2d(tile.poly), ClipperUtil.BooleanOp.Intersection);
            });

            List <ICurvesFillPolygon> all_fills = new List <ICurvesFillPolygon>();

            foreach (Tile t in Tiles)
            {
                if (t.regions.Count == 0)
                {
                    continue;
                }
                t.fills = new ICurvesFillPolygon[t.regions.Count];
                for (int k = 0; k < t.regions.Count; ++k)
                {
                    t.fills[k] = TileFillGeneratorF(t.regions[k], t.index);
                    if (t.fills[k] != null)
                    {
                        all_fills.Add(t.fills[k]);
                    }
                }
            }

            gParallel.ForEach(all_fills, (fill) =>
            {
                fill.Compute();
            });

            FillCurves = new List <FillCurveSet2d>();
            foreach (ICurvesFillPolygon fill in all_fills)
            {
                List <FillCurveSet2d> result = fill.GetFillCurves();
                if (result != null && result.Count > 0)
                {
                    FillCurves.AddRange(result);
                }
            }

            return(true);
        }
Esempio n. 3
0
 protected virtual List <GeneralPolygon2d> combine_solids(List <GeneralPolygon2d> all_solids, List <GeneralPolygon2d> new_solids)
 {
     return(ClipperUtil.PolygonBoolean(all_solids, new_solids, ClipperUtil.BooleanOp.Union, MIN_AREA));
 }
Esempio n. 4
0
        /// <summary>
        /// Convert assembly of polygons, polylines, etc, into a set of printable solids and paths
        /// </summary>
        public virtual void Resolve()
        {
            // combine solids, process largest-to-smallest
            if (InputSolids.Count > 0)
            {
                GeneralPolygon2d[] solids = InputSolids.ToArray();

                solids = process_input_polys_before_sort(solids);

                // sort by decreasing weight
                double[] weights = new double[solids.Length];
                for (int i = 0; i < solids.Length; ++i)
                {
                    weights[i] = sorting_weight(solids[i]);
                }
                Array.Sort(weights, solids); Array.Reverse(solids);

                solids = process_input_polys_after_sort(solids);

                Solids = new List <GeneralPolygon2d>();
                for (int k = 0; k < solids.Length; ++k)
                {
                    // convert this polygon into the solid we want to use
                    List <GeneralPolygon2d> resolvedSolid = make_solid(solids[k], false);

                    // now union in with accumulated solids
                    if (Solids.Count == 0)
                    {
                        Solids.AddRange(resolvedSolid);
                    }
                    else
                    {
                        Solids = combine_solids(Solids, resolvedSolid);
                    }
                }
            }

            // subtract input cavities
            foreach (var cavity in InputCavities)
            {
                Solids = remove_cavity(Solids, cavity);
            }

            // subtract thickened embedded paths from solids
            if (EmbeddedPaths.Count > 0 && EmbeddedPathWidth == 0)
            {
                throw new Exception("PlanarSlice.Resolve: must set embedded path width!");
            }
            foreach (var path in EmbeddedPaths)
            {
                Polygon2d thick_path = make_thickened_path(path, EmbeddedPathWidth);
                Solids = ClipperUtil.Difference(Solids, new GeneralPolygon2d(thick_path), MIN_AREA);
                Paths.Add(path);
            }

            // cleanup
            Solids = filter_solids(Solids);

            // subtract solids from clipped paths
            foreach (var path in ClippedPaths)
            {
                List <PolyLine2d> clipped = ClipperUtil.ClipAgainstPolygon(Solids, path);
                foreach (var cp in clipped)
                {
                    Paths.Add(cp);
                }
            }

            // combine support solids, while also subtracting print solids and thickened paths
            if (InputSupportSolids.Count > 0)
            {
                // make assembly of path solids
                // [TODO] do we need to boolean these?
                List <GeneralPolygon2d> path_solids = null;
                if (Paths.Count > 0)
                {
                    path_solids = new List <GeneralPolygon2d>();
                    foreach (var path in Paths)
                    {
                        path_solids.Add(new GeneralPolygon2d(make_thickened_path(path, EmbeddedPathWidth)));
                    }
                }

                foreach (var solid in InputSupportSolids)
                {
                    // convert this polygon into the solid we want to use
                    List <GeneralPolygon2d> resolved = make_solid(solid, true);

                    // now subtract print solids
                    resolved = ClipperUtil.PolygonBoolean(resolved, Solids, ClipperUtil.BooleanOp.Difference, MIN_AREA);

                    // now subtract paths
                    if (path_solids != null)
                    {
                        resolved = ClipperUtil.PolygonBoolean(resolved, path_solids, ClipperUtil.BooleanOp.Difference, MIN_AREA);
                    }

                    // now union in with accumulated support solids
                    if (SupportSolids.Count == 0)
                    {
                        SupportSolids.AddRange(resolved);
                    }
                    else
                    {
                        SupportSolids = ClipperUtil.PolygonBoolean(SupportSolids, resolved, ClipperUtil.BooleanOp.Union, MIN_AREA);
                    }
                }

                SupportSolids = filter_solids(SupportSolids);
            }

            // apply crop regions
            if (InputCropRegions.Count > 0)
            {
                // combine crop regions
                var CropRegions = make_solid(InputCropRegions[0], false);
                for (int k = 1; k < InputCropRegions.Count; ++k)
                {
                    CropRegions = combine_solids(CropRegions, make_solid(InputCropRegions[k], false));
                }

                Solids = ClipperUtil.Intersection(CropRegions, Solids, MIN_AREA);
                Solids = filter_solids(Solids);
                List <PolyLine2d> cropped_paths = new List <PolyLine2d>();
                foreach (var path in Paths)
                {
                    cropped_paths.AddRange(ClipperUtil.ClipAgainstPolygon(CropRegions, path, true));
                }
                // TODO: filter paths

                SupportSolids = ClipperUtil.Intersection(CropRegions, SupportSolids, MIN_AREA);
                SupportSolids = filter_solids(SupportSolids);
            }
        }