Beispiel #1
0
        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;
                    }
                }
            }
        }
        public void CalculateInfillData(ConfigSettings config,
                                        int extruderIndex,
                                        int layerIndex,
                                        LayerIsland part,
                                        Polygons bottomFillLines,
                                        Polygons sparseFillPolygons   = null,
                                        Polygons solidFillPolygons    = null,
                                        Polygons firstTopFillPolygons = null,
                                        Polygons topFillPolygons      = null,
                                        Polygons bridgePolygons       = null,
                                        Polygons bridgeAreas          = null)
        {
            double alternatingInfillAngle = config.InfillStartingAngle;

            if ((layerIndex % 2) == 0)
            {
                alternatingInfillAngle += 90;
            }

            // generate infill for the bottom layer including bridging
            foreach (Polygons bottomFillIsland in part.BottomPaths.ProcessIntoSeparateIslands())
            {
                if (layerIndex > 0)
                {
                    if (this.Support != null)
                    {
                        double infillAngle = config.SupportInterfaceLayers > 0 ? config.InfillStartingAngle : config.InfillStartingAngle + 90;
                        Infill.GenerateLinePaths(bottomFillIsland, bottomFillLines, config.ExtrusionWidth_um, config.InfillExtendIntoPerimeter_um, infillAngle);
                    }
                    else
                    {
                        SliceLayer previousLayer = this.Extruders[extruderIndex].Layers[layerIndex - 1];

                        if (bridgePolygons != null &&
                            previousLayer.BridgeAngle(bottomFillIsland, config.GetNumberOfPerimeters() * config.ExtrusionWidth_um, out double bridgeAngle, bridgeAreas))
                        {
                            // TODO: Make this code handle very complex pathing between different sizes or layouts of support under the island to fill.
                            Infill.GenerateLinePaths(bottomFillIsland, bridgePolygons, config.ExtrusionWidth_um, config.InfillExtendIntoPerimeter_um, bridgeAngle);
                        }
                        else                         // we still need to extrude at bridging speed
                        {
                            Infill.GenerateLinePaths(bottomFillIsland, bottomFillLines, config.ExtrusionWidth_um, config.InfillExtendIntoPerimeter_um, alternatingInfillAngle, 0, config.BridgeSpeed);
                        }
                    }
                }
        public void DumpLayerparts(string filename)
        {
            var streamToWriteTo = new StreamWriter(filename);

            streamToWriteTo.Write("<!DOCTYPE html><html><body>");

            for (int extruderIndex = 0; extruderIndex < this.Extruders.Count; extruderIndex++)
            {
                for (int layerNr = 0; layerNr < this.Extruders[extruderIndex].Layers.Count; layerNr++)
                {
                    streamToWriteTo.Write("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"width: 500px; height:500px\">\n");
                    SliceLayer layer = this.Extruders[extruderIndex].Layers[layerNr];
                    for (int i = 0; i < layer.Islands.Count; i++)
                    {
                        LayerIsland part = layer.Islands[i];
                        for (int j = 0; j < part.IslandOutline.Count; j++)
                        {
                            streamToWriteTo.Write("<polygon points=\"");

                            for (int k = 0; k < part.IslandOutline[j].Count; k++)
                            {
                                streamToWriteTo.Write("{0},{1} ".FormatWith((float)(part.IslandOutline[j][k].X - modelMin.X) / modelSize.X * 500, (float)(part.IslandOutline[j][k].Y - modelMin.Y) / modelSize.Y * 500));
                            }

                            if (j == 0)
                            {
                                streamToWriteTo.Write("\" style=\"fill:gray; stroke:black;stroke-width:1\" />\n");
                            }
                            else
                            {
                                streamToWriteTo.Write("\" style=\"fill:red; stroke:black;stroke-width:1\" />\n");
                            }
                        }
                    }

                    streamToWriteTo.Write("</svg>\n");
                }
            }

            streamToWriteTo.Write("</body></html>");
            streamToWriteTo.Close();
        }
Beispiel #4
0
        public void GenerateTopAndBottoms(ConfigSettings config, int layerIndex, long extrusionWidth_um, long outerPerimeterWidth_um, int downLayerCount, int upLayerCount, long infillExtendIntoPerimeter_um)
        {
            var clippingOffset = infillExtendIntoPerimeter_um * 2;

            ExtruderLayers extruder = this;
            SliceLayer     layer    = extruder.Layers[layerIndex];

            Agg.Parallel.For(0, layer.Islands.Count, (islandIndex) =>
                             // for (int islandIndex = 0; islandIndex < layer.Islands.Count; islandIndex++)
            {
                LayerIsland island = layer.Islands[islandIndex];
                if (island.InsetToolPaths.Count == 0)
                {
                    return;
                }

                // this is the entire extrusion width to make sure we are outside of the extrusion line
                Polygons lastInset         = island.InsetToolPaths[island.InsetToolPaths.Count - 1];
                Polygons infillRegionPath  = lastInset.Offset(-extrusionWidth_um);
                Polygons sparseInfillPaths = new Polygons(infillRegionPath);

                // calculate the bottom outlines
                if (downLayerCount > 0)
                {
                    Polygons bottomOutlines = new Polygons(infillRegionPath);

                    if (layerIndex - 1 >= 0)
                    {
                        var previousLayer = extruder.Layers[layerIndex - 1];

                        bottomOutlines = RemoveIslandsFromPolygons(previousLayer.Islands, island.BoundingBox, bottomOutlines);
                        bottomOutlines.RemoveSmallAreas(extrusionWidth_um);
                    }

                    sparseInfillPaths = sparseInfillPaths.CreateDifference(bottomOutlines);
                    sparseInfillPaths = Clipper.CleanPolygons(sparseInfillPaths, cleanDistance_um);

                    island.BottomPaths = bottomOutlines;
                }

                // calculate the top outlines
                if (upLayerCount > 0)
                {
                    Polygons topOutlines = new Polygons(infillRegionPath);
                    topOutlines          = topOutlines.CreateDifference(island.BottomPaths.Offset(clippingOffset));
                    topOutlines          = Clipper.CleanPolygons(topOutlines, cleanDistance_um);

                    if (layerIndex + 1 < extruder.Layers.Count)
                    {
                        // Remove the top layer that is above this one to get only the data that is a top layer on this layer.
                        topOutlines = RemoveIslandsFromPolygons(extruder.Layers[layerIndex + 1].Islands, island.BoundingBox, topOutlines);
                    }

                    topOutlines.RemoveSmallAreas(extrusionWidth_um);

                    sparseInfillPaths = sparseInfillPaths.CreateDifference(topOutlines.Offset(clippingOffset));
                    sparseInfillPaths = Clipper.CleanPolygons(sparseInfillPaths, cleanDistance_um);

                    island.TopPaths = topOutlines;
                }

                if (upLayerCount <= 0 && downLayerCount <= 0)
                {
                    // Assign infill directly if no top/bottom solid layers
                    island.SparseInfillPaths = sparseInfillPaths;
                }
                else
                {
                    // calculate the solid infill outlines
                    Polygons solidInfillPaths = new Polygons(infillRegionPath);

                    // remove all the top layers
                    solidInfillPaths = solidInfillPaths.CreateDifference(island.BottomPaths.Offset(clippingOffset));
                    solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);

                    // remove all the bottom layers
                    solidInfillPaths = solidInfillPaths.CreateDifference(island.TopPaths.Offset(clippingOffset));
                    solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);

                    int upEnd = layerIndex + upLayerCount + 1;
                    if (upEnd <= extruder.Layers.Count && layerIndex - downLayerCount >= 0)
                    {
                        // find all the regions that have more top and bottom layers than should be solid (will remain sparse)
                        Polygons regionsThatWillBeSparse = new Polygons(infillRegionPath);

                        int upStart = layerIndex + 2;

                        Agg.Parallel.For(upStart, upEnd, (layerToTest) =>
                                         // for (int layerToTest = upStart; layerToTest < upEnd; layerToTest++)
                        {
                            regionsThatWillBeSparse = IntersectWithPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, regionsThatWillBeSparse);
                            regionsThatWillBeSparse = Clipper.CleanPolygons(regionsThatWillBeSparse, cleanDistance_um);
                        });

                        // find all the solid infill bottom layers
                        int downStart = Math.Max(0, layerIndex - 1);
                        int downEnd   = Math.Max(0, layerIndex - downLayerCount);

                        Agg.Parallel.For(downStart, downEnd, (layerToTest) =>
                                         // for (int layerToTest = downStart; layerToTest >= downEnd; layerToTest--)
                        {
                            regionsThatWillBeSparse = IntersectWithPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, regionsThatWillBeSparse);
                            regionsThatWillBeSparse = Clipper.CleanPolygons(regionsThatWillBeSparse, cleanDistance_um);
                        });

                        solidInfillPaths = solidInfillPaths.CreateDifference(regionsThatWillBeSparse);
                        solidInfillPaths.RemoveSmallAreas(extrusionWidth_um);
                        solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);
                    }

                    // remove the solid infill from the sparse infill
                    sparseInfillPaths = sparseInfillPaths.CreateDifference(solidInfillPaths.Offset(clippingOffset));
                    sparseInfillPaths.RemoveSmallAreas(extrusionWidth_um);
                    sparseInfillPaths        = Clipper.CleanPolygons(sparseInfillPaths, cleanDistance_um);
                    island.SparseInfillPaths = sparseInfillPaths;

                    if (config == null ||                   // this is to make our tests test the bridgeOverInfill
                        config.BridgeOverInfill)
                    {
                        // now figure out what part of the solid infill is actually first top layers and switch it to that
                        // we can only have a first top y layer at the bottom of the top layers
                        if (layerIndex == extruder.Layers.Count - upLayerCount)
                        {
                            // all of it is first top layers
                            island.FirstTopPaths = solidInfillPaths;
                            solidInfillPaths     = new Polygons();
                        }
                        else if (layerIndex > 0 &&
                                 layerIndex < extruder.Layers.Count - upLayerCount)
                        {
                            // Intersect the current solid layer with the previous spars layer
                            // that will be all of the new solid layers that are currently on sparse layer

                            var firstTopPaths = new Polygons(solidInfillPaths);
                            firstTopPaths     = IntersectWithSparsePolygons(extruder.Layers[layerIndex - 1].Islands, island.BoundingBox, firstTopPaths);
                            firstTopPaths.RemoveSmallAreas(extrusionWidth_um);
                            firstTopPaths = Clipper.CleanPolygons(firstTopPaths, cleanDistance_um);

                            if (firstTopPaths.Count > 0)
                            {
                                solidInfillPaths = solidInfillPaths.CreateDifference(firstTopPaths.Offset(clippingOffset));
                                solidInfillPaths.RemoveSmallAreas(extrusionWidth_um);
                                solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);

                                island.FirstTopPaths = firstTopPaths;
                            }
                        }
                    }

                    island.SolidInfillPaths = solidInfillPaths;
                }
            });
        }
        public void GenerateTopAndBottoms(int layerIndex, int extrusionWidth_um, int outerPerimeterWidth_um, int downLayerCount, int upLayerCount)
        {
            ExtruderLayers extruder = this;
            SliceLayer     layer    = extruder.Layers[layerIndex];

            for (int islandIndex = 0; islandIndex < layer.Islands.Count; islandIndex++)
            {
                LayerIsland island = layer.Islands[islandIndex];
                // this is the entire extrusion width to make sure we are outside of the extrusion line
                Polygons lastInset       = island.InsetToolPaths[island.InsetToolPaths.Count - 1];
                Polygons insetWithOffset = lastInset.Offset(-extrusionWidth_um);
                Polygons infillOutlines  = new Polygons(insetWithOffset);

                // calculate the bottom outlines
                if (downLayerCount > 0)
                {
                    Polygons bottomOutlines = new Polygons(insetWithOffset);

                    if (layerIndex - 1 >= 0)
                    {
                        bottomOutlines = RemoveIslandsFromPolygons(extruder.Layers[layerIndex - 1].Islands, island.BoundingBox, bottomOutlines);
                        bottomOutlines.RemoveSmallAreas(extrusionWidth_um);
                    }

                    infillOutlines = infillOutlines.CreateDifference(bottomOutlines);
                    infillOutlines = Clipper.CleanPolygons(infillOutlines, cleanDistance_um);

                    island.SolidBottomToolPaths = bottomOutlines;
                }

                // calculate the top outlines
                if (upLayerCount > 0)
                {
                    Polygons topOutlines = new Polygons(insetWithOffset);
                    topOutlines = topOutlines.CreateDifference(island.SolidBottomToolPaths);
                    topOutlines = Clipper.CleanPolygons(topOutlines, cleanDistance_um);

                    for (int insetIndex = 0; insetIndex < island.InsetToolPaths.Count - 1; insetIndex++)
                    {
                        // Add thin wall filling by taking the area between the insets.
                        Polygons largerInset  = island.InsetToolPaths[insetIndex].Offset(-extrusionWidth_um / 2);
                        Polygons smallerInset = island.InsetToolPaths[insetIndex + 1].Offset(extrusionWidth_um / 2);

                        Polygons thinWalls = largerInset.CreateDifference(smallerInset).Offset(-extrusionWidth_um / 4);
                        if (thinWalls.Count > 0)
                        {
                            topOutlines.AddAll(thinWalls);
                        }
                    }

                    if (layerIndex + 1 < extruder.Layers.Count)
                    {
                        // Remove the top layer that is above this one to get only the data that is a top layer on this layer.
                        topOutlines = RemoveIslandsFromPolygons(extruder.Layers[layerIndex + 1].Islands, island.BoundingBox, topOutlines);
                    }

                    topOutlines.RemoveSmallAreas(extrusionWidth_um);

                    infillOutlines = infillOutlines.CreateDifference(topOutlines);
                    infillOutlines = Clipper.CleanPolygons(infillOutlines, cleanDistance_um);

                    island.SolidTopToolPaths = topOutlines;
                }

                // calculate the solid infill outlines
                if (upLayerCount > 1 || downLayerCount > 1)
                {
                    Polygons solidInfillOutlines = new Polygons(insetWithOffset);
                    solidInfillOutlines = solidInfillOutlines.CreateDifference(island.SolidBottomToolPaths);
                    solidInfillOutlines = Clipper.CleanPolygons(solidInfillOutlines, cleanDistance_um);
                    solidInfillOutlines = solidInfillOutlines.CreateDifference(island.SolidTopToolPaths);

                    solidInfillOutlines = Clipper.CleanPolygons(solidInfillOutlines, cleanDistance_um);

                    int upEnd = layerIndex + upLayerCount + 1;
                    if (upEnd <= extruder.Layers.Count && layerIndex - downLayerCount >= 0)
                    {
                        Polygons totalPartsToRemove = new Polygons(insetWithOffset);

                        int upStart = layerIndex + 2;

                        for (int layerToTest = upStart; layerToTest < upEnd; layerToTest++)
                        {
                            totalPartsToRemove = AddIslandsToPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, totalPartsToRemove);
                            totalPartsToRemove = Clipper.CleanPolygons(totalPartsToRemove, cleanDistance_um);
                        }

                        int downStart = layerIndex - 1;
                        int downEnd   = layerIndex - downLayerCount;

                        for (int layerToTest = downStart; layerToTest >= downEnd; layerToTest--)
                        {
                            totalPartsToRemove = AddIslandsToPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, totalPartsToRemove);
                            totalPartsToRemove = Clipper.CleanPolygons(totalPartsToRemove, cleanDistance_um);
                        }

                        solidInfillOutlines = solidInfillOutlines.CreateDifference(totalPartsToRemove);
                        solidInfillOutlines.RemoveSmallAreas(extrusionWidth_um);

                        solidInfillOutlines = Clipper.CleanPolygons(solidInfillOutlines, cleanDistance_um);
                    }

                    island.SolidInfillToolPaths = solidInfillOutlines;
                    infillOutlines = infillOutlines.CreateDifference(solidInfillOutlines);
                }

                infillOutlines.RemoveSmallAreas(extrusionWidth_um);
                infillOutlines         = Clipper.CleanPolygons(infillOutlines, cleanDistance_um);
                island.InfillToolPaths = infillOutlines;
            }
        }
Beispiel #6
0
		private void CalculateInfillData(LayerDataStorage slicingData, int extruderIndex, int layerIndex, LayerIsland part, ref Polygons bottomFillPolygons, ref Polygons fillPolygons, ref Polygons topFillPolygons, ref Polygons bridgePolygons)
		{
			// generate infill the bottom layer including bridging
			foreach (Polygons outline in part.SolidBottomToolPaths.ProcessIntoSeparatIslands())
			{
				if (layerIndex > 0)
				{
					double bridgeAngle = 0;
					SliceLayer previousLayer = slicingData.Extruders[extruderIndex].Layers[layerIndex - 1];
                    if (!config.generateSupport &&
						previousLayer.BridgeAngle(outline, out bridgeAngle))
					{
						Infill.GenerateLinePaths(outline, ref bridgePolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, bridgeAngle);
					}
					else
					{
						Infill.GenerateLinePaths(outline, ref bottomFillPolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle);
					}
				}
				else
				{
					Infill.GenerateLinePaths(outline, ref bottomFillPolygons, config.firstLayerExtrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle);
				}
			}

			// generate infill for the top layer
			foreach (Polygons outline in part.SolidTopToolPaths.ProcessIntoSeparatIslands())
			{
				Infill.GenerateLinePaths(outline, ref topFillPolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle);
			}

			// generate infill intermediate layers
			foreach (Polygons outline in part.SolidInfillToolPaths.ProcessIntoSeparatIslands())
			{
				if (true) // use the old infill method
				{
					Infill.GenerateLinePaths(outline, ref fillPolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle + 90 * (layerIndex % 2));
				}
				else // use the new concentric infill (not tested enough yet) have to handle some bad cases better
				{
					double oldInfillPercent = config.infillPercent;
					config.infillPercent = 100;
					Infill.GenerateConcentricInfill(config, outline, ref fillPolygons);
					config.infillPercent = oldInfillPercent;
				}
			}

			double fillAngle = config.infillStartingAngle;

			// generate the sparse infill for this part on this layer
			if (config.infillPercent > 0)
			{
				switch (config.infillType)
				{
					case ConfigConstants.INFILL_TYPE.LINES:
						if ((layerIndex & 1) == 1)
						{
							fillAngle += 90;
						}
						Infill.GenerateLineInfill(config, part.InfillToolPaths, ref fillPolygons, fillAngle);
						break;

					case ConfigConstants.INFILL_TYPE.GRID:
						Infill.GenerateGridInfill(config, part.InfillToolPaths, ref fillPolygons, fillAngle);
						break;

					case ConfigConstants.INFILL_TYPE.TRIANGLES:
						Infill.GenerateTriangleInfill(config, part.InfillToolPaths, ref fillPolygons, fillAngle);
						break;

					case ConfigConstants.INFILL_TYPE.HEXAGON:
						Infill.GenerateHexagonInfill(config, part.InfillToolPaths, ref fillPolygons, fillAngle, layerIndex);
						break;

					case ConfigConstants.INFILL_TYPE.CONCENTRIC:
						Infill.GenerateConcentricInfill(config, part.InfillToolPaths, ref fillPolygons);
						break;

					default:
						throw new NotImplementedException();
				}
			}
		}
Beispiel #7
0
        public void GenerateInsets(ConfigSettings config, 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
                    if (config.MergeOverlappingLines)
                    {
                        // be aggressive about maintaining small polygons
                        currentInset = Clipper.CleanPolygons(currentInset);
                    }
                    else
                    {
                        // clean the polygon to make it have less jaggies
                        currentInset = Clipper.CleanPolygons(currentInset, minimumDistanceToCreateNewPosition);
                    }

                    // check that we have actual paths
                    if (currentInset.Count > 0)
                    {
                        var run = true;
                        // if we are centering the seam put a point exactly in back
                        if (run && (config.SeamPlacement == SEAM_PLACEMENT.ALWAYS_CENTERED_IN_BACK ||
                                    config.SeamPlacement == SEAM_PLACEMENT.CENTERED_IN_BACK))
                        {
                            foreach (var polygon in currentInset)
                            {
                                var count = polygon.Count;
                                if (count > 2)
                                {
                                    // if we are going to center the seam in the back make sure there is a vertex to center on that is exactly in back
                                    var centeredIndex = polygon.GetCenteredInBackIndex(out IntPoint center);
                                    var start         = -1;
                                    var end           = -1;

                                    if (polygon[centeredIndex].X <= center.X)
                                    {
                                        // start should always be left of center
                                        start = centeredIndex;
                                        // is the next point right of center
                                        end = (centeredIndex + 1) % count;
                                        if (polygon[end].X < center.X)
                                        {
                                            // no it is left of center
                                            // is the previous point right of center
                                            end = (centeredIndex + count - 1) % count;
                                            if (polygon[end].X < center.X)
                                            {
                                                // it is still left of center (so no crossing)
                                                continue;                                                 // skip placing a seam at this point
                                            }
                                        }
                                    }
                                    else if (polygon[centeredIndex].X >= center.X)
                                    {
                                        // we are to the right of center so this is the end
                                        end = centeredIndex;
                                        // set start to the left of center
                                        start = (centeredIndex + 1) % count;
                                        if (polygon[start].X > center.X)
                                        {
                                            // start is also right of center it need to be left
                                            start = (centeredIndex + count - 1) % count;
                                            if (polygon[start].X > center.X)
                                            {
                                                // it is still right of center skip this point
                                                continue;
                                            }
                                        }
                                    }

                                    // find the y intercept
                                    var delta = polygon[end] - polygon[start];
                                    if (delta.X != 0)
                                    {
                                        var insert = Math.Max(start, end);
                                        if (insert == count - 1 && (start == 0 || end == 0))
                                        {
                                            insert = count;
                                        }
                                        var ratio = (center.X - polygon[start].X) / (double)delta.X;
                                        polygon.Insert(insert, new IntPoint(center.X, polygon[start].Y + (polygon[end].Y - polygon[start].Y) * ratio));
                                    }
                                }
                            }
                        }

                        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;
                    }
                }
            }
        }