/// <summary> /// Convert the input polygons to a set of paths. /// If FilterSelfOverlaps=true, then the paths will be clipped against /// themselves, in an attempt to avoid over-printing. /// </summary> public virtual FillCurveSet2d ShellPolysToPaths(List <GeneralPolygon2d> shell_polys, int nShell) { FillCurveSet2d paths = new FillCurveSet2d(); FillTypeFlags flags = FillTypeFlags.PerimeterShell; if (nShell == 0 && ShellType == ShellTypes.ExternalPerimeters) { flags = FillTypeFlags.OutermostShell; } else if (ShellType == ShellTypes.InternalShell) { flags = FillTypeFlags.InteriorShell; } else if (ShellType == ShellTypes.BridgeShell) { flags = FillTypeFlags.BridgeSupport; } if (FilterSelfOverlaps == false) { foreach (GeneralPolygon2d shell in shell_polys) { paths.Append(shell, flags); } return(paths); } int outer_shell_edgegroup = 100; foreach (GeneralPolygon2d shell in shell_polys) { PathOverlapRepair repair = new PathOverlapRepair(); repair.OverlapRadius = SelfOverlapTolerance; repair.Add(shell, outer_shell_edgegroup); // Ideally want to presreve outermost shell of external perimeters. // However in many cases internal holes are 'too close' to outer border. // So we will still apply to those, but use edge filter to preserve outermost loop. // [TODO] could we be smarter about this somehow? if (PreserveOuterShells && nShell == 0 && ShellType == ShellTypes.ExternalPerimeters) { repair.PreserveEdgeFilterF = (eid) => { return(repair.Graph.GetEdgeGroup(eid) == outer_shell_edgegroup); } } ; repair.Compute(); DGraph2Util.Curves c = DGraph2Util.ExtractCurves(repair.GetResultGraph()); foreach (var polygon in c.Loops) { paths.Append(polygon, flags); } foreach (var polyline in c.Paths) { if (polyline.ArcLength < DiscardTinyPerimterLengthMM) { continue; } if (polyline.Bounds.MaxDim < DiscardTinyPerimterLengthMM) { continue; } paths.Append(new FillPolyline2d(polyline) { TypeFlags = flags }); } } return(paths); }
/// <summary> /// Convert the input polygons to a set of paths. /// If FilterSelfOverlaps=true, then the paths will be clipped against /// themselves, in an attempt to avoid over-printing. /// </summary> public virtual FillCurveSet2d ShellPolysToPaths(List <GeneralPolygon2d> shell_polys, int nShell) { FillCurveSet2d paths = new FillCurveSet2d(); IFillType currentFillType = nShell == 0 ? firstShellFillType ?? fillType : fillType; if (FilterSelfOverlaps == false) { foreach (var shell in shell_polys) { paths.Append(new FillLoop <FillSegment>(shell.Outer.Vertices) { FillType = currentFillType, PerimeterOrder = nShell }); foreach (var hole in shell.Holes) { paths.Append(new FillLoop <FillSegment>(hole.Vertices) { FillType = currentFillType, PerimeterOrder = nShell, IsHoleShell = true });; } } return(paths); } int outer_shell_edgegroup = 100; foreach (GeneralPolygon2d shell in shell_polys) { PathOverlapRepair repair = new PathOverlapRepair(); repair.OverlapRadius = SelfOverlapTolerance; repair.Add(shell, outer_shell_edgegroup); // Ideally want to presreve outermost shell of external perimeters. // However in many cases internal holes are 'too close' to outer border. // So we will still apply to those, but use edge filter to preserve outermost loop. // [TODO] could we be smarter about this somehow? if (PreserveOuterShells && nShell == 0) { repair.PreserveEdgeFilterF = (eid) => { return(repair.Graph.GetEdgeGroup(eid) == outer_shell_edgegroup); } } ; repair.Compute(); DGraph2Util.Curves c = DGraph2Util.ExtractCurves(repair.GetResultGraph()); #region Borrow nesting calculations from PlanarSlice to enforce winding direction PlanarComplex complex = new PlanarComplex(); foreach (Polygon2d poly in c.Loops) { complex.Add(poly); } PlanarComplex.FindSolidsOptions options = PlanarComplex.FindSolidsOptions.Default; options.WantCurveSolids = false; options.SimplifyDeviationTolerance = 0.001; options.TrustOrientations = false; options.AllowOverlappingHoles = false; PlanarComplex.SolidRegionInfo solids = complex.FindSolidRegions(options); foreach (var polygon in solids.Polygons) { polygon.EnforceCounterClockwise(); paths.Append(new FillLoop <FillSegment>(polygon.Outer.Vertices) { FillType = currentFillType, PerimeterOrder = nShell }); foreach (var hole in polygon.Holes) { paths.Append(new FillLoop <FillSegment>(hole.Vertices) { FillType = currentFillType, PerimeterOrder = nShell, IsHoleShell = true, }); } } #endregion Borrow nesting calculations from PlanarSlice to enforce winding direction foreach (var polyline in c.Paths) { if (polyline.ArcLength < DiscardTinyPerimeterLengthMM) { continue; } if (polyline.Bounds.MaxDim < DiscardTinyPerimeterLengthMM) { continue; } paths.Append(new FillCurve <FillSegment>(polyline) { FillType = currentFillType, PerimeterOrder = nShell }); } } return(paths); }