//Expand each layer a bit and then keep the extra overlapping parts that overlap with other volumes. //This generates some overlap in dual extrusion, for better bonding in touching parts. public static void OverlapMultipleVolumesSlightly(List <SliceVolumeStorage> volumes, int overlap) { if (volumes.Count < 2 || overlap <= 0) { return; } for (int layerIndex = 0; layerIndex < volumes[0].layers.Count; layerIndex++) { Polygons fullLayer = new Polygons(); for (int volIdx = 0; volIdx < volumes.Count; volIdx++) { SliceLayer layer1 = volumes[volIdx].layers[layerIndex]; for (int p1 = 0; p1 < layer1.parts.Count; p1++) { fullLayer = fullLayer.CreateUnion(layer1.parts[p1].TotalOutline.Offset(20)); } } fullLayer = fullLayer.Offset(-20); for (int volumeIndex = 0; volumeIndex < volumes.Count; volumeIndex++) { SliceLayer layer1 = volumes[volumeIndex].layers[layerIndex]; for (int partIndex = 0; partIndex < layer1.parts.Count; partIndex++) { layer1.parts[partIndex].TotalOutline = fullLayer.CreateIntersection(layer1.parts[partIndex].TotalOutline.Offset(overlap / 2)); } } } }
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); }
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); }
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> CreateAirGappedBottomLayers(List <Polygons> inputPolys, List <Polygons> allPartOutlines) { int numLayers = inputPolys.Count; List <Polygons> airGappedBottoms = CreateEmptyPolygons(numLayers); for (int layerIndex = 1; layerIndex < numLayers; layerIndex++) { Polygons belowOutlines = allPartOutlines[layerIndex - 1]; Polygons curRequiredSupport = inputPolys[layerIndex]; Polygons airGapArea = belowOutlines.CreateIntersection(curRequiredSupport); airGappedBottoms[layerIndex] = airGapArea; } return(airGappedBottoms); }
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); }
//Expand each layer a bit and then keep the extra overlapping parts that overlap with other extruders. //This generates some overlap in dual extrusion, for better bonding in touching parts. public static void OverlapMultipleExtrudersSlightly(List <ExtruderLayers> extruders, int overlapUm) { if (extruders.Count < 2 || overlapUm <= 0) { return; } for (int layerIndex = 0; layerIndex < extruders[0].Layers.Count; layerIndex++) { Polygons fullLayer = new Polygons(); for (int extruderIndex = 0; extruderIndex < extruders.Count; extruderIndex++) { SliceLayer layer1 = extruders[extruderIndex].Layers[layerIndex]; fullLayer = fullLayer.CreateUnion(layer1.AllOutlines.Offset(20)); } fullLayer = fullLayer.Offset(-20); for (int extruderIndex = 0; extruderIndex < extruders.Count; extruderIndex++) { SliceLayer layer1 = extruders[extruderIndex].Layers[layerIndex]; layer1.AllOutlines = fullLayer.CreateIntersection(layer1.AllOutlines.Offset(overlapUm / 2)); } } }
private static Polygons AddAllOutlines(SliceLayer layerToAdd, SliceLayerPart partToUseAsBounds, Polygons polysToAddTo, ref bool makeInfillSolid, ConfigSettings config) { Polygons polysToIntersect = new Polygons(); for (int partIndex = 0; partIndex < layerToAdd.parts.Count; partIndex++) { var partToConsider = layerToAdd.parts[partIndex]; if (config.smallProtrusionProportion > 0) { // If the part under consideration intersects the part from the current layer and // the area of that intersection is less than smallProtrusionProportion % of the part under consideration solidify the infill var intersection = partToUseAsBounds.TotalOutline.CreateIntersection(partToConsider.TotalOutline); if (intersection.Count > 0) // They do intersect { if (intersection.TotalArea() < partToConsider.TotalOutline.TotalArea() * config.smallProtrusionProportion) { makeInfillSolid = true; return(polysToAddTo); } } } if (partToUseAsBounds.BoundingBox.Hit(partToConsider.BoundingBox)) { polysToIntersect = polysToIntersect.CreateUnion( layerToAdd.parts[partIndex].Insets[partToConsider.Insets.Count - 1]); polysToIntersect = Clipper.CleanPolygons(polysToIntersect, cleanDistance_um); } } polysToAddTo = polysToAddTo.CreateIntersection(polysToIntersect); return(polysToAddTo); }
public static bool BridgeAngle(Polygons outline, SliceLayer prevLayer, out double bridgeAngle, string debugName = "") { bridgeAngle = -1; Aabb boundaryBox = new Aabb(outline); //To detect if we have a bridge, first calculate the intersection of the current layer with the previous layer. // This gives us the islands that the layer rests on. Polygons islands = new Polygons(); foreach (SliceLayerPart prevLayerPart in prevLayer.parts) { if (!boundaryBox.Hit(prevLayerPart.BoundingBox)) { continue; } islands.AddRange(outline.CreateIntersection(prevLayerPart.TotalOutline)); } #if OUTPUT_DEBUG_DATA string outlineString = outline.WriteToString(); string partOutlineString = ""; foreach (SliceLayerPart prevLayerPart in prevLayer.parts) { foreach (Polygon prevPartOutline in prevLayerPart.outline) { partOutlineString += prevPartOutline.WriteToString(); } partOutlineString += "|"; } string islandsString = islands.WriteToString(); #endif if (islands.Count > 5 || islands.Count < 1) { return(false); } if (islands.Count == 1) { return(GetSingleIslandAngle(outline, islands[0], out bridgeAngle, debugName)); } // Find the 2 largest islands that we rest on. double biggestArea = 0; double nextBiggestArea = 0; int indexOfBiggest = -1; int indexOfNextBigest = -1; for (int islandIndex = 0; islandIndex < islands.Count; islandIndex++) { //Skip internal holes if (!islands[islandIndex].Orientation()) { continue; } double area = Math.Abs(islands[islandIndex].Area()); if (area > biggestArea) { if (biggestArea > nextBiggestArea) { nextBiggestArea = biggestArea; indexOfNextBigest = indexOfBiggest; } biggestArea = area; indexOfBiggest = islandIndex; } else if (area > nextBiggestArea) { nextBiggestArea = area; indexOfNextBigest = islandIndex; } } if (indexOfBiggest < 0 || indexOfNextBigest < 0) { return(false); } IntPoint center1 = islands[indexOfBiggest].CenterOfMass(); IntPoint center2 = islands[indexOfNextBigest].CenterOfMass(); bridgeAngle = Math.Atan2(center2.Y - center1.Y, center2.X - center1.X) / Math.PI * 180; Range0To360(ref bridgeAngle); #if OUTPUT_DEBUG_DATA islands.SaveToGCode("{0} - angle {1:0.}.gcode".FormatWith(debugName, bridgeAngle)); #endif return(true); }
public bool BridgeAngle(Polygons areaAboveToFill, out double bridgeAngle, string debugName = "") { SliceLayer layerToRestOn = this; bridgeAngle = -1; Aabb boundaryBox = new Aabb(areaAboveToFill); //To detect if we have a bridge, first calculate the intersection of the current layer with the previous layer. // This gives us the islands that the layer rests on. Polygons islandsToRestOn = new Polygons(); foreach (LayerIsland islandToRestOn in layerToRestOn.Islands) { if (!boundaryBox.Hit(islandToRestOn.BoundingBox)) { continue; } islandsToRestOn.AddRange(areaAboveToFill.CreateIntersection(islandToRestOn.IslandOutline)); } if (OUTPUT_DEBUG_DATA) { string outlineString = areaAboveToFill.WriteToString(); string islandOutlineString = ""; foreach (LayerIsland prevLayerIsland in layerToRestOn.Islands) { foreach (Polygon islandOutline in prevLayerIsland.IslandOutline) { islandOutlineString += islandOutline.WriteToString(); } islandOutlineString += "|"; } string islandsString = islandsToRestOn.WriteToString(); } Polygons islandConvexHuls = new Polygons(); foreach(Polygon poly in islandsToRestOn) { islandConvexHuls.Add(poly.CreateConvexHull()); } if (islandsToRestOn.Count > 5 || islandsToRestOn.Count < 1) { return false; } if (islandsToRestOn.Count == 1) { return GetSingleIslandAngle(areaAboveToFill, islandsToRestOn[0], out bridgeAngle, debugName); } // Find the 2 largest islands that we rest on. double biggestArea = 0; double nextBiggestArea = 0; int indexOfBiggest = -1; int indexOfNextBigest = -1; for (int islandIndex = 0; islandIndex < islandsToRestOn.Count; islandIndex++) { //Skip internal holes if (!islandsToRestOn[islandIndex].Orientation()) { continue; } double area = Math.Abs(islandConvexHuls[islandIndex].Area()); if (area > biggestArea) { if (biggestArea > nextBiggestArea) { nextBiggestArea = biggestArea; indexOfNextBigest = indexOfBiggest; } biggestArea = area; indexOfBiggest = islandIndex; } else if (area > nextBiggestArea) { nextBiggestArea = area; indexOfNextBigest = islandIndex; } } if (indexOfBiggest < 0 || indexOfNextBigest < 0) { return false; } Polygons big1 = new Polygons() { islandConvexHuls[indexOfBiggest] }; Polygons big2 = new Polygons() { islandConvexHuls[indexOfNextBigest] }; Polygons intersection = big1.CreateIntersection(big2); if(intersection.Count > 0) { return GetSingleIslandAngle(areaAboveToFill, islandsToRestOn[indexOfBiggest], out bridgeAngle, debugName); } IntPoint center1 = islandsToRestOn[indexOfBiggest].CenterOfMass(); IntPoint center2 = islandsToRestOn[indexOfNextBigest].CenterOfMass(); bridgeAngle = Math.Atan2(center2.Y - center1.Y, center2.X - center1.X) / Math.PI * 180; Range0To360(ref bridgeAngle); if (OUTPUT_DEBUG_DATA) { islandsToRestOn.SaveToGCode("{0} - angle {1:0.}.gcode".FormatWith(debugName, bridgeAngle)); } return true; }
public bool BridgeAngle(Polygons areaAboveToFill, out double bridgeAngle, string debugName = "") { SliceLayer layerToRestOn = this; bridgeAngle = -1; Aabb boundaryBox = new Aabb(areaAboveToFill); //To detect if we have a bridge, first calculate the intersection of the current layer with the previous layer. // This gives us the islands that the layer rests on. Polygons islandsToRestOn = new Polygons(); foreach (LayerIsland islandToRestOn in layerToRestOn.Islands) { if (!boundaryBox.Hit(islandToRestOn.BoundingBox)) { continue; } islandsToRestOn.AddRange(areaAboveToFill.CreateIntersection(islandToRestOn.IslandOutline)); } if (OUTPUT_DEBUG_DATA) { string outlineString = areaAboveToFill.WriteToString(); string islandOutlineString = ""; foreach (LayerIsland prevLayerIsland in layerToRestOn.Islands) { foreach (Polygon islandOutline in prevLayerIsland.IslandOutline) { islandOutlineString += islandOutline.WriteToString(); } islandOutlineString += "|"; } string islandsString = islandsToRestOn.WriteToString(); } if (islandsToRestOn.Count > 5 || islandsToRestOn.Count < 1) { return(false); } if (islandsToRestOn.Count == 1) { return(GetSingleIslandAngle(areaAboveToFill, islandsToRestOn[0], out bridgeAngle, debugName)); } // Find the 2 largest islands that we rest on. double biggestArea = 0; double nextBiggestArea = 0; int indexOfBiggest = -1; int indexOfNextBigest = -1; for (int islandIndex = 0; islandIndex < islandsToRestOn.Count; islandIndex++) { //Skip internal holes if (!islandsToRestOn[islandIndex].Orientation()) { continue; } double area = Math.Abs(islandsToRestOn[islandIndex].Area()); if (area > biggestArea) { if (biggestArea > nextBiggestArea) { nextBiggestArea = biggestArea; indexOfNextBigest = indexOfBiggest; } biggestArea = area; indexOfBiggest = islandIndex; } else if (area > nextBiggestArea) { nextBiggestArea = area; indexOfNextBigest = islandIndex; } } if (indexOfBiggest < 0 || indexOfNextBigest < 0) { return(false); } IntPoint center1 = islandsToRestOn[indexOfBiggest].CenterOfMass(); IntPoint center2 = islandsToRestOn[indexOfNextBigest].CenterOfMass(); bridgeAngle = Math.Atan2(center2.Y - center1.Y, center2.X - center1.X) / Math.PI * 180; Range0To360(ref bridgeAngle); if (OUTPUT_DEBUG_DATA) { islandsToRestOn.SaveToGCode("{0} - angle {1:0.}.gcode".FormatWith(debugName, bridgeAngle)); } return(true); }
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; }
//Expand each layer a bit and then keep the extra overlapping parts that overlap with other extruders. //This generates some overlap in dual extrusion, for better bonding in touching parts. public static void OverlapMultipleExtrudersSlightly(List<ExtruderLayers> extruders, int overlapUm) { if (extruders.Count < 2 || overlapUm <= 0) { return; } for (int layerIndex = 0; layerIndex < extruders[0].Layers.Count; layerIndex++) { Polygons fullLayer = new Polygons(); for (int extruderIndex = 0; extruderIndex < extruders.Count; extruderIndex++) { SliceLayer layer1 = extruders[extruderIndex].Layers[layerIndex]; fullLayer = fullLayer.CreateUnion(layer1.AllOutlines.Offset(20)); } fullLayer = fullLayer.Offset(-20); for (int extruderIndex = 0; extruderIndex < extruders.Count; extruderIndex++) { SliceLayer layer1 = extruders[extruderIndex].Layers[layerIndex]; layer1.AllOutlines = fullLayer.CreateIntersection(layer1.AllOutlines.Offset(overlapUm / 2)); } } }