Example #1
0
 public bool Hit(Aabb other)
 {
     if (max.X < other.min.X) return false;
     if (min.X > other.max.X) return false;
     if (max.Y < other.min.Y) return false;
     if (min.Y > other.max.Y) return false;
     return true;
 }
Example #2
0
		public static void GenerateLinePaths(Polygons polygonToInfill, ref Polygons infillLinesToPrint, int lineSpacing, int infillExtendIntoPerimeter_um, double rotation, long rotationOffset = 0)
		{
			if (polygonToInfill.Count > 0)
			{
				Polygons outlines = polygonToInfill.Offset(infillExtendIntoPerimeter_um);
				if (outlines.Count > 0)
				{
					PointMatrix matrix = new PointMatrix(-(rotation + 90)); // we are rotating the part so we rotate by the negative so the lines go the way we expect

					outlines.ApplyMatrix(matrix);

					Aabb boundary = new Aabb(outlines);

					boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing - rotationOffset;
					int xLineCount = (int)((boundary.max.X - boundary.min.X + (lineSpacing - 1)) / lineSpacing);
					Polygons unclipedPatern = new Polygons();

					long firstX = boundary.min.X / lineSpacing * lineSpacing;
					for (int lineIndex = 0; lineIndex < xLineCount; lineIndex++)
					{
						Polygon line = new Polygon();
						line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.min.Y));
						line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.max.Y));
						unclipedPatern.Add(line);
					}

					PolyTree ret = new PolyTree();
					Clipper clipper = new Clipper();
					clipper.AddPaths(unclipedPatern, PolyType.ptSubject, false);
					clipper.AddPaths(outlines, PolyType.ptClip, true);
					clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);

					Polygons newSegments = Clipper.OpenPathsFromPolyTree(ret);
					PointMatrix inversematrix = new PointMatrix((rotation + 90));
					newSegments.ApplyMatrix(inversematrix);

					infillLinesToPrint.AddRange(newSegments);
				}
			}
		}
Example #3
0
		public static void GenerateHexLinePaths(Polygons in_outline, ref Polygons result, int lineSpacing, int infillExtendIntoPerimeter_um, double rotationDegrees, int layerIndex)
		{
			int extraRotationAngle = 0;
			if (in_outline.Count > 0)
			{
				Polygons outlines = in_outline.Offset(infillExtendIntoPerimeter_um);
				if (outlines.Count > 0)
				{
					int perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);
					PointMatrix matrix = new PointMatrix(-(rotationDegrees + extraRotationAngle)); // we are rotating the part so we rotate by the negative so the lines go the way we expect

					outlines.ApplyMatrix(matrix);

					Aabb boundary = new Aabb(outlines);

					boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing;
					boundary.min.Y = ((boundary.min.Y / perIncrementOffset) - 2) * perIncrementOffset;
					boundary.max.X += lineSpacing;
					boundary.max.Y += perIncrementOffset;
					Polygons unclipedPatern = new Polygons();

					foreach (IntPoint startPoint in StartPositionIterator(boundary, lineSpacing, layerIndex))
					{
						Polygon attachedLine = new Polygon();
						foreach (IntPoint center in IncrementPositionIterator(startPoint, boundary, lineSpacing, layerIndex))
						{
							// what we are adding are the little plusses that define the points
							//        | top
							//        |
							//        /\ center
							//   left/  \ right
							//
							IntPoint left = center + new IntPoint(-lineSpacing / 2, -perIncrementOffset / 3);
							IntPoint right = center + new IntPoint(lineSpacing / 2, -perIncrementOffset / 3);
							IntPoint top = center + new IntPoint(0, perIncrementOffset * 2 / 3);

							switch (layerIndex % 3)
							{
								case 0: // left to right
									attachedLine.Add(left); attachedLine.Add(center);
									attachedLine.Add(center); attachedLine.Add(right);
									unclipedPatern.Add(new Polygon() { top, center });
									break;

								case 1: // left to top
									attachedLine.Add(left); attachedLine.Add(center);
									attachedLine.Add(center); attachedLine.Add(top);
									unclipedPatern.Add(new Polygon() { center, right });
									break;

								case 2: // top to right
									attachedLine.Add(top); attachedLine.Add(center);
									attachedLine.Add(center); attachedLine.Add(right);
									unclipedPatern.Add(new Polygon() { left, center });
									break;
							}
						}
						if (attachedLine.Count > 0)
						{
							unclipedPatern.Add(attachedLine);
						}
					}

					PolyTree ret = new PolyTree();
					Clipper clipper = new Clipper();
					clipper.AddPaths(unclipedPatern, PolyType.ptSubject, false);
					clipper.AddPaths(outlines, PolyType.ptClip, true);
					clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);

					Polygons newSegments = Clipper.OpenPathsFromPolyTree(ret);
					PointMatrix inversematrix = new PointMatrix((rotationDegrees + extraRotationAngle));
					newSegments.ApplyMatrix(inversematrix);

					result.AddRange(newSegments);
				}
			}
		}
Example #4
0
		private static IEnumerable<IntPoint> IncrementPositionIterator(IntPoint startPoint, Aabb boundary, int lineSpacing, int layerIndex)
		{
			IntPoint positionAdd = new IntPoint(lineSpacing, 0);
			int perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);
			switch (layerIndex % 3)
			{
				case 0: // left to right
					positionAdd = new IntPoint(lineSpacing, 0);
					break;

				case 1: // left to top
					positionAdd = new IntPoint(lineSpacing / 2, perIncrementOffset);
					break;

				case 2: // top to right
					positionAdd = new IntPoint(lineSpacing / 2, -perIncrementOffset);
					break;
			}
			IntPoint nextPoint = startPoint;
			do
			{
				yield return nextPoint;
				nextPoint += positionAdd;
			} while (nextPoint.X > boundary.min.X
				&& nextPoint.X < boundary.max.X
				&& nextPoint.Y > boundary.min.Y
				&& nextPoint.Y < boundary.max.Y);
		}
Example #5
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;
		}
Example #6
0
        private static IEnumerable <IntPoint> StartPositionIterator(Aabb boundary, int lineSpacing, int layerIndex)
        {
            int perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);
            int yLineCount         = (int)((boundary.max.Y - boundary.min.Y + perIncrementOffset) / perIncrementOffset) + 1;

            switch (layerIndex % 3)
            {
            case 0:                     // left to right
                for (int yIndex = 0; yIndex < yLineCount; yIndex++)
                {
                    long yPosition     = boundary.min.Y + yIndex * perIncrementOffset;
                    bool removeXOffset = ((yPosition / perIncrementOffset) % 2) == 0;
                    long xOffsetForY   = lineSpacing / 2;
                    if (removeXOffset)                             // if we are at every other y
                    {
                        xOffsetForY = 0;
                    }
                    long firstX = boundary.min.X + xOffsetForY;

                    yield return(new IntPoint(firstX, yPosition));
                }
                break;

            case 1:                     // left to top
            {
                IntPoint nextPoint = new IntPoint();
                for (int yIndex = yLineCount; yIndex >= 0; yIndex--)
                {
                    long yPosition         = boundary.min.Y + yIndex * perIncrementOffset;
                    bool createLineSegment = ((yPosition / perIncrementOffset) % 2) == 0;
                    if (createLineSegment)
                    {
                        nextPoint = new IntPoint(boundary.min.X, yPosition);
                        yield return(nextPoint);
                    }
                }

                IntPoint positionAdd = new IntPoint(lineSpacing, 0);
                nextPoint += positionAdd;
                while (nextPoint.X > boundary.min.X &&
                       nextPoint.X < boundary.max.X)
                {
                    yield return(nextPoint);

                    nextPoint += positionAdd;
                }
            }
            break;

            case 2:                     // top to right
            {
                IntPoint nextPoint = new IntPoint();
                for (int yIndex = 0; yIndex < yLineCount; yIndex++)
                {
                    long yPosition         = boundary.min.Y + yIndex * perIncrementOffset;
                    bool createLineSegment = ((yPosition / perIncrementOffset) % 2) == 0;
                    if (createLineSegment)
                    {
                        nextPoint = new IntPoint(boundary.min.X, yPosition);
                        yield return(nextPoint);
                    }
                }

                IntPoint positionAdd = new IntPoint(lineSpacing, 0);
                nextPoint += positionAdd;
                while (nextPoint.X > boundary.min.X &&
                       nextPoint.X < boundary.max.X)
                {
                    yield return(nextPoint);

                    nextPoint += positionAdd;
                }
            }
            break;
            }
        }
Example #7
0
        private static IEnumerable <IntPoint> IncrementPositionIterator(IntPoint startPoint, Aabb boundary, int lineSpacing, int layerIndex)
        {
            IntPoint positionAdd        = new IntPoint(lineSpacing, 0);
            int      perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);

            switch (layerIndex % 3)
            {
            case 0:                     // left to right
                positionAdd = new IntPoint(lineSpacing, 0);
                break;

            case 1:                     // left to top
                positionAdd = new IntPoint(lineSpacing / 2, perIncrementOffset);
                break;

            case 2:                     // top to right
                positionAdd = new IntPoint(lineSpacing / 2, -perIncrementOffset);
                break;
            }
            IntPoint nextPoint = startPoint;

            do
            {
                yield return(nextPoint);

                nextPoint += positionAdd;
            } while (nextPoint.X > boundary.min.X &&
                     nextPoint.X < boundary.max.X &&
                     nextPoint.Y > boundary.min.Y &&
                     nextPoint.Y < boundary.max.Y);
        }
Example #8
0
        public bool BridgeAngle(Polygons areaGoingOnTop, long perimeterExpandDistance, out double bridgeAngle, Polygons bridgeAreas, string debugName = "")
        {
            SliceLayer layerToRestOn = this;

            bridgeAngle = -1;
            var boundaryBox = new Aabb(areaGoingOnTop);

            boundaryBox.Expand(perimeterExpandDistance);
            // 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.

            var islandsToRestOn = new Polygons();

            foreach (LayerIsland islandToRestOn in layerToRestOn.Islands)
            {
                if (!boundaryBox.Hit(islandToRestOn.BoundingBox))
                {
                    continue;
                }

                islandsToRestOn.AddRange(areaGoingOnTop.CreateIntersection(islandToRestOn.IslandOutline));
            }

            if (bridgeAreas != null)
            {
                bridgeAreas.AddRange(areaGoingOnTop.CreateDifference(layerToRestOn.AllOutlines));
            }

            if (outputDebugData)
            {
                WriteDebugData(areaGoingOnTop, layerToRestOn, islandsToRestOn);
            }

            if (islandsToRestOn.Count > 5 || islandsToRestOn.Count < 1)
            {
                return(false);
            }

            if (islandsToRestOn.Count == 1)
            {
                return(GetSingleIslandAngle(areaGoingOnTop, 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 (outputDebugData)
            {
                islandsToRestOn.SaveToGCode("{0} - angle {1:0.}.gcode".FormatWith(debugName, bridgeAngle));
            }

            return(true);
        }
Example #9
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);
        }
Example #10
0
		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;
		}
Example #11
0
		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;
		}
Example #12
0
        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))
                {
                    if (islands[islandIndex].InsetToolPaths.Count > 0)
                    {
                        polygonsToSubtractFrom = polygonsToSubtractFrom.CreateDifference(islands[islandIndex].InsetToolPaths[islands[islandIndex].InsetToolPaths.Count - 1]);
                        polygonsToSubtractFrom = Clipper.CleanPolygons(polygonsToSubtractFrom, cleanDistance_um);
                    }
                }
            }

            return(polygonsToSubtractFrom);
        }
Example #13
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);
        }
Example #14
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);
        }
Example #15
0
		private static IEnumerable<IntPoint> StartPositionIterator(Aabb boundary, int lineSpacing, int layerIndex)
		{
			int perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);
			int yLineCount = (int)((boundary.max.Y - boundary.min.Y + perIncrementOffset) / perIncrementOffset) + 1;

			switch (layerIndex % 3)
			{
				case 0: // left to right
					for (int yIndex = 0; yIndex < yLineCount; yIndex++)
					{
						long yPosition = boundary.min.Y + yIndex * perIncrementOffset;
						bool removeXOffset = ((yPosition / perIncrementOffset) % 2) == 0;
						long xOffsetForY = lineSpacing / 2;
						if (removeXOffset) // if we are at every other y
						{
							xOffsetForY = 0;
						}
						long firstX = boundary.min.X + xOffsetForY;

						yield return new IntPoint(firstX, yPosition);
					}
					break;

				case 1: // left to top
					{
						IntPoint nextPoint = new IntPoint();
						for (int yIndex = yLineCount; yIndex >= 0; yIndex--)
						{
							long yPosition = boundary.min.Y + yIndex * perIncrementOffset;
							bool createLineSegment = ((yPosition / perIncrementOffset) % 2) == 0;
							if (createLineSegment)
							{
								nextPoint = new IntPoint(boundary.min.X, yPosition);
								yield return nextPoint;
							}
						}

						IntPoint positionAdd = new IntPoint(lineSpacing, 0);
						nextPoint += positionAdd;
						while (nextPoint.X > boundary.min.X
							&& nextPoint.X < boundary.max.X)
						{
							yield return nextPoint;
							nextPoint += positionAdd;
						}
					}
					break;

				case 2: // top to right
					{
						IntPoint nextPoint = new IntPoint();
						for (int yIndex = 0; yIndex < yLineCount; yIndex++)
						{
							long yPosition = boundary.min.Y + yIndex * perIncrementOffset;
							bool createLineSegment = ((yPosition / perIncrementOffset) % 2) == 0;
							if (createLineSegment)
							{
								nextPoint = new IntPoint(boundary.min.X, yPosition);
								yield return nextPoint;
							}
						}

						IntPoint positionAdd = new IntPoint(lineSpacing, 0);
						nextPoint += positionAdd;
						while (nextPoint.X > boundary.min.X
							&& nextPoint.X < boundary.max.X)
						{
							yield return nextPoint;
							nextPoint += positionAdd;
						}
					}
					break;
			}
		}
Example #16
0
        public static void GenerateHexLinePaths(Polygons in_outline, Polygons result, int lineSpacing, long infillExtendIntoPerimeter_um, double rotationDegrees, int layerIndex)
        {
            int extraRotationAngle = 0;

            if (in_outline.Count > 0)
            {
                Polygons outlines = in_outline.Offset(infillExtendIntoPerimeter_um);
                if (outlines.Count > 0)
                {
                    int         perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);
                    PointMatrix matrix             = new PointMatrix(-(rotationDegrees + extraRotationAngle));         // we are rotating the part so we rotate by the negative so the lines go the way we expect

                    outlines.ApplyMatrix(matrix);

                    Aabb boundary = new Aabb(outlines);

                    boundary.min.X  = ((boundary.min.X / lineSpacing) - 1) * lineSpacing;
                    boundary.min.Y  = ((boundary.min.Y / perIncrementOffset) - 2) * perIncrementOffset;
                    boundary.max.X += lineSpacing;
                    boundary.max.Y += perIncrementOffset;
                    Polygons unclippedPattern = new Polygons();

                    foreach (IntPoint startPoint in StartPositionIterator(boundary, lineSpacing, layerIndex))
                    {
                        Polygon attachedLine = new Polygon();
                        foreach (IntPoint center in IncrementPositionIterator(startPoint, boundary, lineSpacing, layerIndex))
                        {
                            // what we are adding are the little pluses that define the points
                            //        | top
                            //        |
                            //        /\ center
                            //   left/  \ right
                            //
                            IntPoint left  = center + new IntPoint(-lineSpacing / 2, -perIncrementOffset / 3);
                            IntPoint right = center + new IntPoint(lineSpacing / 2, -perIncrementOffset / 3);
                            IntPoint top   = center + new IntPoint(0, perIncrementOffset * 2 / 3);

                            switch (layerIndex % 3)
                            {
                            case 0:                                     // left to right
                                attachedLine.Add(left); attachedLine.Add(center);
                                attachedLine.Add(center); attachedLine.Add(right);
                                unclippedPattern.Add(new Polygon()
                                {
                                    top, center
                                });
                                break;

                            case 1:                                     // left to top
                                attachedLine.Add(left); attachedLine.Add(center);
                                attachedLine.Add(center); attachedLine.Add(top);
                                unclippedPattern.Add(new Polygon()
                                {
                                    center, right
                                });
                                break;

                            case 2:                                     // top to right
                                attachedLine.Add(top); attachedLine.Add(center);
                                attachedLine.Add(center); attachedLine.Add(right);
                                unclippedPattern.Add(new Polygon()
                                {
                                    left, center
                                });
                                break;
                            }
                        }
                        if (attachedLine.Count > 0)
                        {
                            unclippedPattern.Add(attachedLine);
                        }
                    }

                    PolyTree ret     = new PolyTree();
                    Clipper  clipper = new Clipper();
                    clipper.AddPaths(unclippedPattern, PolyType.ptSubject, false);
                    clipper.AddPaths(outlines, PolyType.ptClip, true);
                    clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);

                    Polygons    newSegments   = Clipper.OpenPathsFromPolyTree(ret);
                    PointMatrix inversematrix = new PointMatrix((rotationDegrees + extraRotationAngle));
                    newSegments.ApplyMatrix(inversematrix);

                    result.AddRange(newSegments);
                }
            }
        }
Example #17
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;
        }