private static List <Polygons> CreateInterfaceLayers(List <Polygons> inputPolys, int numInterfaceLayers) { int numLayers = inputPolys.Count; List <Polygons> allInterfaceLayers = CreateEmptyPolygons(numLayers); if (numInterfaceLayers > 0) { for (int layerIndex = 0; layerIndex < numLayers; layerIndex++) { Polygons requiredInterfacePolys = inputPolys[layerIndex].DeepCopy(); if (layerIndex < numLayers - 1) { Polygons intersectionsAbove = inputPolys[layerIndex + 1].DeepCopy(); for (int aboveIndex = layerIndex + 2; aboveIndex < Math.Min(layerIndex + numInterfaceLayers + 1, numLayers); aboveIndex++) { intersectionsAbove = intersectionsAbove.CreateIntersection(inputPolys[aboveIndex]); intersectionsAbove = Clipper.CleanPolygons(intersectionsAbove, cleanDistance_um); } requiredInterfacePolys = requiredInterfacePolys.CreateDifference(intersectionsAbove); requiredInterfacePolys = Clipper.CleanPolygons(requiredInterfacePolys, cleanDistance_um); } allInterfaceLayers[layerIndex] = requiredInterfacePolys; } } return(allInterfaceLayers); }
public void GenerateMarchingSquaresAndLines(Action <double, string> progressReporter, ImageBuffer image, IThresholdFunction thresholdFunction) { if (image != null) { // Regenerate outline var marchingSquaresData = new MarchingSquaresByte( image, thresholdFunction.ZeroColor, thresholdFunction.Threshold, 0); progressReporter?.Invoke(0, "Creating Outline"); marchingSquaresData.CreateLineSegments(); progressReporter?.Invoke(.1, null); int pixelsToIntPointsScale = 1000; var lineLoops = marchingSquaresData.CreateLineLoops(pixelsToIntPointsScale); progressReporter?.Invoke(.15, null); var min = new IntPoint(-10, -10); var max = new IntPoint(10 + image.Width * pixelsToIntPointsScale, 10 + image.Height * pixelsToIntPointsScale); var boundingPoly = new Polygon(); boundingPoly.Add(min); boundingPoly.Add(new IntPoint(min.X, max.Y)); boundingPoly.Add(max); boundingPoly.Add(new IntPoint(max.X, min.Y)); // now clip the polygons to get the inside and outside polys var clipper = new Clipper(); clipper.AddPaths(lineLoops, PolyType.ptSubject, true); clipper.AddPath(boundingPoly, PolyType.ptClip, true); var polygonShape = new Polygons(); progressReporter?.Invoke(.3, null); clipper.Execute(ClipType.ctIntersection, polygonShape); progressReporter?.Invoke(.55, null); polygonShape = Clipper.CleanPolygons(polygonShape, 100); progressReporter?.Invoke(.75, null); VertexStorage rawVectorShape = polygonShape.PolygonToPathStorage(); var aabb = this.VisibleMeshes().FirstOrDefault().GetAxisAlignedBoundingBox(); var xScale = aabb.XSize / image.Width; var affine = Affine.NewScaling(1.0 / pixelsToIntPointsScale * xScale); affine *= Affine.NewTranslation(-aabb.XSize / 2, -aabb.YSize / 2); rawVectorShape.transform(affine); this.VertexSource = rawVectorShape; progressReporter?.Invoke(1, null); } }
/// <summary> /// Clean up a proposed corridor shape (primarily removing holes, which are invalid in a floorplan) /// </summary> /// <param name="clipper"></param> /// <param name="outline"></param> /// <param name="corridor"></param> /// <param name="width"></param> /// <returns></returns> public static List <List <IntPoint> > CleanCorridorPolygon(Clipper clipper, List <IntPoint> outline, IEnumerable <Vector2> corridor, float width) { //Clean up after the previous run, just in case clipper.Clear(); //Clip this spanning tree to the footprint of the floorplan (to create a polytree) var result = new List <List <IntPoint> >(); clipper.AddPath(outline, PolyType.ptClip, true); clipper.AddPath(corridor.Select(ToPoint).ToList(), PolyType.ptSubject, true); clipper.Execute(ClipType.ctIntersection, result); //Clean up after self, to be polite clipper.Clear(); //Keep simplifying, and removing holes until nothing happens do { //merge together vertices which are very close result = Clipper.CleanPolygons(result, width / 8); //Remove holes from the result var holes = result.RemoveAll(r => !Clipper.Orientation(r)); //Once we have one single polygon, or removing holes did nothing we've finished! if (result.Count == 1 || holes == 0) { return(result); } } while (result.Count > 0); //This shouldn't ever happen unless we simplify away to nothing return(result); }
private Polygons FixWinding(Polygons polygonsToPathAround) { polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround); Polygon boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToPathAround); bounds.minX -= 10; bounds.maxY += 10; bounds.maxX += 10; bounds.minY -= 10; boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY)); boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY)); Clipper clipper = new Clipper(); clipper.AddPaths(polygonsToPathAround, PolyType.ptSubject, true); clipper.AddPath(boundsPolygon, PolyType.ptClip, true); PolyTree intersectionResult = new PolyTree(); clipper.Execute(ClipType.ctIntersection, intersectionResult); Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult); return(outputPolygons); }
private static List <Polygons> AccumulateDownPolygons(ConfigSettings config, List <Polygons> inputPolys, List <Polygons> allPartOutlines) { int numLayers = inputPolys.Count; long nozzleSize = config.ExtrusionWidth_um; List <Polygons> allDownOutlines = CreateEmptyPolygons(numLayers); for (int layerIndex = numLayers - 2; layerIndex >= 0; layerIndex--) { Polygons aboveRequiredSupport = inputPolys[layerIndex + 1]; // get all the polygons above us Polygons accumulatedAbove = allDownOutlines[layerIndex + 1].CreateUnion(aboveRequiredSupport); // add in the support on this level Polygons curRequiredSupport = inputPolys[layerIndex]; Polygons totalSupportThisLayer = accumulatedAbove.CreateUnion(curRequiredSupport); // remove the solid polygons on this level Polygons remainingAbove = totalSupportThisLayer.CreateDifference(allPartOutlines[layerIndex]); allDownOutlines[layerIndex] = Clipper.CleanPolygons(remainingAbove, cleanDistance_um); } return(allDownOutlines); }
public static void generateInsets(SliceLayerPart part, int offset, int insetCount) { part.combBoundery = part.outline.Offset(-offset); if (insetCount == 0) { // if we have no insets defined still create one part.insets.Add(part.outline); } else // generate the insets { for (int i = 0; i < insetCount; i++) { part.insets.Add(new Polygons()); part.insets[i] = part.outline.Offset(-offset * i - offset / 2); if (i == 0) { // Add thin wall filling by taking the area between the insets. //Polygons thinWalls = part.insets[0].Offset(-offset / 4).CreateDifference(part.insets[0].Offset); //upskin.AddAll(thinWalls); //downskin.AddAll(thinWalls); } long minimumDistanceToCreateNewPosition = 10; part.insets[i] = Clipper.CleanPolygons(part.insets[i], minimumDistanceToCreateNewPosition); if (part.insets[i].Count < 1) { part.insets.RemoveAt(part.insets.Count - 1); break; } } } }
private static List <Polygons> RemoveSelfSupportedSections(List <Polygons> inputPolys, long supportWidth_um) { int numLayers = inputPolys.Count; List <Polygons> allRequiredSupportOutlines = CreateEmptyPolygons(numLayers); // calculate all the non-supported areas for (int layerIndex = numLayers - 1; layerIndex > 0; layerIndex--) { if (inputPolys[layerIndex - 1].Count > 0) { if (inputPolys[layerIndex].Count > 0) { Polygons expandedLayerBellow = inputPolys[layerIndex - 1].Offset(supportWidth_um); allRequiredSupportOutlines[layerIndex] = inputPolys[layerIndex].CreateDifference(expandedLayerBellow); allRequiredSupportOutlines[layerIndex] = Clipper.CleanPolygons(allRequiredSupportOutlines[layerIndex], cleanDistance_um); } } else { allRequiredSupportOutlines[layerIndex] = inputPolys[layerIndex].DeepCopy(); } } return(allRequiredSupportOutlines); }
private void InsetPath() { var path = this.Children.OfType <IPathObject>().FirstOrDefault(); if (path == null) { // clear our existing data VertexSource = new VertexStorage(); return; } var aPolys = path.VertexSource.CreatePolygons(); var offseter = new ClipperOffset(); offseter.AddPaths(aPolys, InflatePathObject3D.GetJoinType(OuterStyle), EndType.etClosedPolygon); var outerLoops = new List <List <IntPoint> >(); offseter.Execute(ref outerLoops, OutlineWidth * Ratio * 1000); Clipper.CleanPolygons(outerLoops); offseter.AddPaths(aPolys, InflatePathObject3D.GetJoinType(InnerStyle), EndType.etClosedPolygon); var innerLoops = new List <List <IntPoint> >(); offseter.Execute(ref innerLoops, -OutlineWidth * (1 - Ratio) * 1000); Clipper.CleanPolygons(innerLoops); var allLoops = outerLoops; allLoops.AddRange(innerLoops); VertexSource = allLoops.CreateVertexStorage(); (VertexSource as VertexStorage).Add(0, 0, ShapePath.FlagsAndCommand.Stop); }
public static Polygons GetCorrectedWinding(this Polygons polygonsToFix) { polygonsToFix = Clipper.CleanPolygons(polygonsToFix); var boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToFix); bounds.minX -= 10; bounds.minY -= 10; bounds.maxY += 10; bounds.maxX += 10; boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY)); boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY)); var clipper = new Clipper(); clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true); clipper.AddPath(boundsPolygon, PolyType.ptClip, true); var intersectionResult = new PolyTree(); clipper.Execute(ClipType.ctIntersection, intersectionResult); Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult); return(outputPolygons); }
public static void GenerateInsets(SliceLayerPart part, int offset, int insetCount) { part.AvoidCrossingBoundery = part.TotalOutline.Offset(-offset); if (insetCount == 0) { // if we have no insets defined still create one part.Insets.Add(part.TotalOutline); } else // generate the insets { for (int i = 0; i < insetCount; i++) { part.Insets.Add(new Polygons()); part.Insets[i] = part.TotalOutline.Offset(-offset * i - offset / 2); double minimumDistanceToCreateNewPosition = 10; part.Insets[i] = Clipper.CleanPolygons(part.Insets[i], minimumDistanceToCreateNewPosition); if (part.Insets[i].Count < 1) { part.Insets.RemoveAt(part.Insets.Count - 1); break; } } } }
private Polygons FixWinding(Polygons polygonsToPathAround) { polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround); Polygon boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToPathAround); bounds.left -= 10; bounds.bottom += 10; bounds.right += 10; bounds.top -= 10; boundsPolygon.Add(new IntPoint(bounds.left, bounds.top)); boundsPolygon.Add(new IntPoint(bounds.right, bounds.top)); boundsPolygon.Add(new IntPoint(bounds.right, bounds.bottom)); boundsPolygon.Add(new IntPoint(bounds.left, bounds.bottom)); Clipper clipper = new Clipper(); clipper.AddPaths(polygonsToPathAround, PolyType.ptSubject, true); clipper.AddPath(boundsPolygon, PolyType.ptClip, true); PolyTree intersectionResult = new PolyTree(); clipper.Execute(ClipType.ctIntersection, intersectionResult); Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult); Clipper.ReversePaths(outputPolygons); return(outputPolygons); }
public static Polygons GetCorrectedWinding(this Polygons polygonsToFix) { polygonsToFix = Clipper.CleanPolygons(polygonsToFix); Polygon boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToFix); bounds.left -= 10; bounds.bottom += 10; bounds.right += 10; bounds.top -= 10; boundsPolygon.Add(new IntPoint(bounds.left, bounds.top)); boundsPolygon.Add(new IntPoint(bounds.right, bounds.top)); boundsPolygon.Add(new IntPoint(bounds.right, bounds.bottom)); boundsPolygon.Add(new IntPoint(bounds.left, bounds.bottom)); Clipper clipper = new Clipper(); clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true); clipper.AddPath(boundsPolygon, PolyType.ptClip, true); PolyTree intersectionResult = new PolyTree(); clipper.Execute(ClipType.ctIntersection, intersectionResult); Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult); return(outputPolygons); }
public void QueueAirGappedBottomLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig) { // normal support Polygons currentAirGappedBottoms = airGappedBottomOutlines[layerIndex]; currentAirGappedBottoms = currentAirGappedBottoms.Offset(-config.ExtrusionWidth_um / 2); List <Polygons> supportIslands = currentAirGappedBottoms.ProcessIntoSeparatIslands(); foreach (Polygons islandOutline in supportIslands) { Polygons islandInfillLines = new Polygons(); // render a grid of support if (config.GenerateSupportPerimeter) { Polygons outlines = Clipper.CleanPolygons(islandOutline, config.ExtrusionWidth_um / 4); gcodeLayer.QueuePolygonsByOptimizer(outlines, supportNormalConfig); } Polygons infillOutline = islandOutline.Offset(-config.ExtrusionWidth_um / 2); switch (config.SupportType) { case ConfigConstants.SUPPORT_TYPE.GRID: Infill.GenerateGridInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um); break; case ConfigConstants.SUPPORT_TYPE.LINES: Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um); break; } gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, supportNormalConfig); } }
public bool QueueNormalSupportLayer(ConfigSettings config, GCodePlanner gcodeLayer, int layerIndex, GCodePathConfig supportNormalConfig) { // normal support Polygons currentSupportOutlines = supportOutlines[layerIndex]; currentSupportOutlines = currentSupportOutlines.Offset(-supportNormalConfig.lineWidth_um / 2); List <Polygons> supportIslands = currentSupportOutlines.ProcessIntoSeparatIslands(); bool outputPaths = false; foreach (Polygons islandOutline in supportIslands) { // force a retract if changing islands if (config.RetractWhenChangingIslands) { gcodeLayer.ForceRetract(); } Polygons islandInfillLines = new Polygons(); // render a grid of support if (config.GenerateSupportPerimeter || layerIndex == 0) { Polygons outlines = Clipper.CleanPolygons(islandOutline, config.ExtrusionWidth_um / 4); if (gcodeLayer.QueuePolygonsByOptimizer(outlines, supportNormalConfig)) { outputPaths = true; } } Polygons infillOutline = islandOutline.Offset(-supportNormalConfig.lineWidth_um / 2); if (layerIndex == 0) { // on the first layer print this as solid Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.ExtrusionWidth_um); } else { switch (config.SupportType) { case ConfigConstants.SUPPORT_TYPE.GRID: Infill.GenerateGridInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um); break; case ConfigConstants.SUPPORT_TYPE.LINES: Infill.GenerateLineInfill(config, infillOutline, islandInfillLines, config.SupportInfillStartingAngle, config.SupportLineSpacing_um); break; } } if (gcodeLayer.QueuePolygonsByOptimizer(islandInfillLines, supportNormalConfig)) { outputPaths |= true; } } return(outputPaths); }
public void GenerateInsets(long extrusionWidth_um, long outerExtrusionWidth_um, int insetCount, bool avoidCrossingPerimeters) { LayerIsland part = this; part.BoundingBox.Calculate(part.IslandOutline); if (avoidCrossingPerimeters) { part.PathFinder = new PathFinder(part.IslandOutline, extrusionWidth_um * 3 / 2, useInsideCache: avoidCrossingPerimeters, name: "inset island"); } if (insetCount == 0) { // if we have no insets defined still create one part.InsetToolPaths.Add(part.IslandOutline); } else // generate the insets { long currentOffset = 0; // Inset 0 will use the outerExtrusionWidth_um, everyone else will use extrusionWidth_um long offsetBy = outerExtrusionWidth_um / 2; for (int i = 0; i < insetCount; i++) { // Increment by half the offset amount currentOffset += offsetBy; Polygons currentInset = part.IslandOutline.Offset(-currentOffset); // make sure our polygon data is reasonable currentInset = Clipper.CleanPolygons(currentInset, minimumDistanceToCreateNewPosition); // check that we have actual paths if (currentInset.Count > 0) { part.InsetToolPaths.Add(currentInset); // Increment by the second half currentOffset += offsetBy; } else { // we are done making insets as we have no area left break; } if (i == 0) { // Reset offset amount to half the standard extrusion width offsetBy = extrusionWidth_um / 2; } } } }
private static List <Polygons> CreateInsetPartOutlines(List <Polygons> inputPolys, long insetAmount_um) { int numLayers = inputPolys.Count; List <Polygons> allInsetOutlines = CreateEmptyPolygons(numLayers); // calculate all the non-supported areas for (int layerIndex = 0; layerIndex < numLayers; layerIndex++) { allInsetOutlines[layerIndex] = Clipper.CleanPolygons(inputPolys[layerIndex].Offset(-insetAmount_um), cleanDistance_um); } return(allInsetOutlines); }
private static Polygons RemoveIslandsFromPolygons(List <LayerIsland> islands, Aabb boundsToConsider, Polygons polygonsToSubtractFrom) { for (int islandIndex = 0; islandIndex < islands.Count; islandIndex++) { if (boundsToConsider.Hit(islands[islandIndex].BoundingBox)) { polygonsToSubtractFrom = polygonsToSubtractFrom.CreateDifference(islands[islandIndex].InsetToolPaths[islands[islandIndex].InsetToolPaths.Count - 1]); polygonsToSubtractFrom = Clipper.CleanPolygons(polygonsToSubtractFrom, cleanDistance_um); } } return(polygonsToSubtractFrom); }
private static Polygons RemoveAdditionalOutlinesForPart(SliceLayer layerToSubtract, SliceLayerPart partToUseAsBounds, Polygons polygonsToSubtractFrom) { for (int partIndex = 0; partIndex < layerToSubtract.parts.Count; partIndex++) { if (partToUseAsBounds.BoundingBox.Hit(layerToSubtract.parts[partIndex].BoundingBox)) { polygonsToSubtractFrom = polygonsToSubtractFrom.CreateDifference(layerToSubtract.parts[partIndex].Insets[layerToSubtract.parts[partIndex].Insets.Count - 1]); polygonsToSubtractFrom = Clipper.CleanPolygons(polygonsToSubtractFrom, cleanDistance_um); } } return(polygonsToSubtractFrom); }
public void Offset(float offset) { Paths polygons = Clipper.ClosedPathsFromPolyTree(polyTree); ClipperOffset co = new ClipperOffset(); co.ArcTolerance = scale * .0001f; co.AddPaths(polygons, JoinType.jtRound, EndType.etClosedPolygon); polyTree = new PolyTree(); Paths offsetPaths = new Paths(); co.Execute(ref offsetPaths, scale * offset); offsetPaths = Clipper.CleanPolygons(offsetPaths, scale * .0001f); polyTree = PolygonsToPolyTree(offsetPaths); }
private static List <Polygons> ExpandToEasyGrabDistance(List <Polygons> inputPolys, long grabDistance_um) { int numLayers = inputPolys.Count; List <Polygons> easyGrabDistanceOutlines = CreateEmptyPolygons(numLayers); for (int layerIndex = numLayers - 1; layerIndex >= 0; layerIndex--) { Polygons curLayerPolys = inputPolys[layerIndex]; easyGrabDistanceOutlines[layerIndex] = Clipper.CleanPolygons(curLayerPolys.Offset(grabDistance_um), cleanDistance_um); } return(easyGrabDistanceOutlines); }
private static List <Polygons> FindAllPotentialSupportOutlines(List <Polygons> inputPolys, long supportWidth_um) { int numLayers = inputPolys.Count; List <Polygons> allPotentialSupportOutlines = CreateEmptyPolygons(numLayers); // calculate all the non-supported areas for (int layerIndex = numLayers - 2; layerIndex >= 0; layerIndex--) { Polygons aboveLayerPolys = inputPolys[layerIndex + 1]; Polygons curLayerPolys = inputPolys[layerIndex].Offset(supportWidth_um); Polygons areasNeedingSupport = aboveLayerPolys.CreateDifference(curLayerPolys); allPotentialSupportOutlines[layerIndex] = Clipper.CleanPolygons(areasNeedingSupport, cleanDistance_um); } return(allPotentialSupportOutlines); }
private static List <Polygons> CalculateDifferencePerLayer(List <Polygons> inputPolys, List <Polygons> outlinesToRemove) { int numLayers = inputPolys.Count; List <Polygons> diferenceLayers = CreateEmptyPolygons(numLayers); for (int layerIndex = numLayers - 2; layerIndex >= 0; layerIndex--) { Polygons curRequiredSupport = inputPolys[layerIndex]; Polygons totalSupportThisLayer = curRequiredSupport.CreateDifference(outlinesToRemove[layerIndex]); diferenceLayers[layerIndex] = Clipper.CleanPolygons(totalSupportThisLayer, cleanDistance_um); } return(diferenceLayers); }
private static Polygons AddIslandsToPolygons(List <LayerIsland> islands, Aabb boundsToConsider, Polygons polysToAddTo) { Polygons polysToIntersect = new Polygons(); for (int islandIndex = 0; islandIndex < islands.Count; islandIndex++) { if (boundsToConsider.Hit(islands[islandIndex].BoundingBox)) { polysToIntersect = polysToIntersect.CreateUnion(islands[islandIndex].InsetToolPaths[islands[islandIndex].InsetToolPaths.Count - 1]); polysToIntersect = Clipper.CleanPolygons(polysToIntersect, cleanDistance_um); } } polysToAddTo = polysToAddTo.CreateIntersection(polysToIntersect); return(polysToAddTo); }
public static VertexStorage Offset(this IVertexSource a, double distance) { List<List<IntPoint>> aPolys = a.CreatePolygons(); ClipperOffset offseter = new ClipperOffset(); offseter.AddPaths(aPolys, JoinType.jtMiter, EndType.etClosedPolygon); var solution = new List<List<IntPoint>>(); offseter.Execute(ref solution, distance * 1000); Clipper.CleanPolygons(solution); VertexStorage output = solution.CreateVertexStorage(); output.Add(0, 0, ShapePath.FlagsAndCommand.Stop); return output; }
private static List <Polygons> ClipToXyDistance(List <Polygons> inputPolys, List <Polygons> allPartOutlines, ConfigSettings config) { int numLayers = inputPolys.Count; List <Polygons> clippedToXyOutlines = CreateEmptyPolygons(numLayers); for (int layerIndex = numLayers - 2; layerIndex >= 0; layerIndex--) { Polygons curRequiredSupport = inputPolys[layerIndex]; Polygons expandedlayerPolys = allPartOutlines[layerIndex].Offset(config.SupportXYDistance_um); Polygons totalSupportThisLayer = curRequiredSupport.CreateDifference(expandedlayerPolys); clippedToXyOutlines[layerIndex] = Clipper.CleanPolygons(totalSupportThisLayer, cleanDistance_um); } return(clippedToXyOutlines); }
private static Polygons AddAllOutlines(SliceLayer layerToAdd, SliceLayerPart partToUseAsBounds, Polygons polysToAddTo) { Polygons polysToIntersect = new Polygons(); for (int partIndex = 0; partIndex < layerToAdd.parts.Count; partIndex++) { if (partToUseAsBounds.BoundingBox.Hit(layerToAdd.parts[partIndex].BoundingBox)) { polysToIntersect = polysToIntersect.CreateUnion(layerToAdd.parts[partIndex].Insets[layerToAdd.parts[partIndex].Insets.Count - 1]); polysToIntersect = Clipper.CleanPolygons(polysToIntersect, cleanDistance_um); } } polysToAddTo = polysToAddTo.CreateIntersection(polysToIntersect); return(polysToAddTo); }
private static List <Polygons> RemoveSupportFromInternalSpaces(List <Polygons> inputPolys, List <Polygons> allPartOutlines) { int numLayers = inputPolys.Count; Polygons accumulatedLayers = new Polygons(); for (int layerIndex = 0; layerIndex < numLayers; layerIndex++) { accumulatedLayers = accumulatedLayers.CreateUnion(allPartOutlines[layerIndex]); accumulatedLayers = Clipper.CleanPolygons(accumulatedLayers, cleanDistance_um); inputPolys[layerIndex] = inputPolys[layerIndex].CreateDifference(accumulatedLayers); inputPolys[layerIndex] = Clipper.CleanPolygons(inputPolys[layerIndex], cleanDistance_um); } return(inputPolys); }
public static void GenerateInsets(SliceLayerPart part, int offset_um, int outerPerimeterOffset_um, int insetCount) { double minimumDistanceToCreateNewPosition = 10; int currentOffset = 0; int offsetBy = outerPerimeterOffset_um / 2; part.AvoidCrossingBoundery = part.TotalOutline.Offset(-offset_um); if (insetCount == 0) { // if we have no insets defined still create one part.Insets.Add(part.TotalOutline); } else // generate the insets { for (int i = 0; i < insetCount; i++) { currentOffset += offsetBy; Polygons currentInset = part.TotalOutline.Offset(-currentOffset); // make sure our polygon data is reasonable currentInset = Clipper.CleanPolygons(currentInset, minimumDistanceToCreateNewPosition); // check that we have actuall paths if (currentInset.Count > 0) { part.Insets.Add(currentInset); currentOffset += (offsetBy + offset_um / 2); offsetBy = offset_um / 2; } else { // we are done making insets as we have no arrea left break; } currentOffset += offsetBy; if (i == 0) { offsetBy = offset_um / 2; } } } }
private static Polygons IntersectWithSparsePolygons(List <LayerIsland> islands, Aabb boundsToConsider, Polygons polysToIntersect) { Polygons polysFromIslands = new Polygons(); for (int islandIndex = 0; islandIndex < islands.Count; islandIndex++) { if (boundsToConsider.Hit(islands[islandIndex].BoundingBox)) { if (islands[islandIndex].InsetToolPaths.Count > 0) { polysFromIslands = polysFromIslands.CreateUnion(islands[islandIndex].SparseInfillPaths); polysFromIslands = Clipper.CleanPolygons(polysFromIslands, cleanDistance_um); } } } polysToIntersect = polysToIntersect.CreateIntersection(polysFromIslands); return(polysToIntersect); }
private static List <Polygons> PushUpTops(List <Polygons> inputPolys, ConfigSettings config) { int numLayers = inputPolys.Count; return(inputPolys); int layersFor2Mm = 2000 / config.LayerThickness_um; List <Polygons> pushedUpPolys = CreateEmptyPolygons(numLayers); for (int layerIndex = numLayers - 1; layerIndex >= 0; layerIndex--) { for (int layerToAddToIndex = Math.Min(layerIndex + layersFor2Mm, numLayers - 1); layerToAddToIndex >= 0; layerToAddToIndex--) { } Polygons curLayerPolys = inputPolys[layerIndex]; pushedUpPolys[layerIndex] = Clipper.CleanPolygons(curLayerPolys.Offset(config.ExtrusionWidth_um + config.SupportXYDistance_um), cleanDistance_um); } return(pushedUpPolys); }