//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));
                    }
                }
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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));
                }
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
		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;
		}
Beispiel #11
0
        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));
				}
			}
		}