Ejemplo n.º 1
0
 public static void CreateLayerParts(SliceVolumeStorage storage, Slicer slicer, ConfigConstants.REPAIR_OVERLAPS unionAllType)
 {
     for (int layerIndex = 0; layerIndex < slicer.layers.Count; layerIndex++)
     {
         storage.layers.Add(new SliceLayer());
         storage.layers[layerIndex].printZ = slicer.layers[layerIndex].Z;
         LayerPart.CreateLayerWithParts(storage.layers[layerIndex], slicer.layers[layerIndex], unionAllType);
     }
 }
Ejemplo n.º 2
0
		public void SetOutputType(ConfigConstants.OUTPUT_TYPE outputType)
		{
			this.outputType = outputType;
			if (outputType == ConfigConstants.OUTPUT_TYPE.MACH3)
			{
				for (int n = 0; n < ConfigConstants.MAX_EXTRUDERS; n++)
				{
					extruderCharacter[n] = (char)('A' + n);
				}
			}
			else
			{
				for (int n = 0; n < ConfigConstants.MAX_EXTRUDERS; n++)
				{
					extruderCharacter[n] = 'E';
				}
			}
		}
Ejemplo n.º 3
0
        /*
        The layer-part creation step is the first step in creating actual useful data for 3D printing.
        It takes the result of the Slice step, which is an unordered list of polygons, and makes groups of polygons,
        each of these groups is called a "part", which sometimes are also known as "islands". These parts represent
        isolated areas in the 2D layer with possible holes.

        Creating "parts" is an important step, as all elements in a single part should be printed before going to another part.
        Every bit inside a single part can be printed without the nozzle leaving the boundery of this part.

        It's also the first step that stores the result in the "data storage" so all other steps can access it.
        */
        private static void CreateLayerWithParts(SliceLayer storageLayer, SlicerLayer layer, ConfigConstants.REPAIR_OVERLAPS unionAllType)
        {
            if ((unionAllType & ConfigConstants.REPAIR_OVERLAPS.REVERSE_ORIENTATION) == ConfigConstants.REPAIR_OVERLAPS.REVERSE_ORIENTATION)
            {
                for (int i = 0; i < layer.PolygonList.Count; i++)
                {
                    if (layer.PolygonList[i].Orientation())
                    {
                        layer.PolygonList[i].Reverse();
                    }
                }
            }

            List<Polygons> result;
            if ((unionAllType & ConfigConstants.REPAIR_OVERLAPS.UNION_ALL_TOGETHER) == ConfigConstants.REPAIR_OVERLAPS.UNION_ALL_TOGETHER)
            {
                result = layer.PolygonList.Offset(1000).CreateLayerOutlines(PolygonsHelper.LayerOpperation.UnionAll);
            }
            else
            {
                result = layer.PolygonList.CreateLayerOutlines(PolygonsHelper.LayerOpperation.EvenOdd);
            }

            for (int i = 0; i < result.Count; i++)
            {
                storageLayer.parts.Add(new SliceLayerPart());
                if ((unionAllType & ConfigConstants.REPAIR_OVERLAPS.UNION_ALL_TOGETHER) == ConfigConstants.REPAIR_OVERLAPS.UNION_ALL_TOGETHER)
                {
                    storageLayer.parts[i].TotalOutline.Add(result[i][0]);
                    storageLayer.parts[i].TotalOutline = storageLayer.parts[i].TotalOutline.Offset(-1000);
                }
                else
                {
                    storageLayer.parts[i].TotalOutline = result[i];
                }

                storageLayer.parts[i].BoundingBox.Calculate(storageLayer.parts[i].TotalOutline);
            }
        }
Ejemplo n.º 4
0
        public void MakePolygons(ConfigConstants.REPAIR_OUTLINES outlineRepairTypes)
        {
            if (false) // you can use this output segments for debugging
            {
                using (StreamWriter stream = File.AppendText("segments.txt"))
                {
                    stream.WriteLine(DumpSegmentListToString(SegmentList));
                }
            }

            CreateFastIndexLookup();

            for (int startingSegmentIndex = 0; startingSegmentIndex < SegmentList.Count; startingSegmentIndex++)
            {
                if (SegmentList[startingSegmentIndex].hasBeenAddedToPolygon)
                {
                    continue;
                }

                Polygon poly = new Polygon();
                // We start by adding the start, as we will add ends from now on.
                IntPoint polygonStartPosition = SegmentList[startingSegmentIndex].start;
                poly.Add(polygonStartPosition);

                int segmentIndexBeingAdded = startingSegmentIndex;
                bool canClose;

                while (true)
                {
                    canClose = false;
                    SegmentList[segmentIndexBeingAdded].hasBeenAddedToPolygon = true;
                    IntPoint addedSegmentEndPoint = SegmentList[segmentIndexBeingAdded].end;

                    poly.Add(addedSegmentEndPoint);
                    segmentIndexBeingAdded = GetTouchingSegmentIndex(addedSegmentEndPoint);
                    if (segmentIndexBeingAdded == -1)
                    {
                        break;
                    }
                    else
                    {
                        IntPoint foundSegmentStart = SegmentList[segmentIndexBeingAdded].start;
                        if (addedSegmentEndPoint == foundSegmentStart)
                        {
                            // if we have looped back around to where we started
                            if (addedSegmentEndPoint == polygonStartPosition)
                            {
                                canClose = true;
                            }
                        }
                    }
                }

                if (canClose)
                {
                    PolygonList.Add(poly);
                }
                else
                {
                    openPolygonList.Add(poly);
                }
            }

            // Link up all the missing ends, closing up the smallest gaps first. This is an inefficient implementation which can run in O(n*n*n) time.
            while (true)
            {
                long bestScore = 10000 * 10000;
                int bestA = -1;
                int bestB = -1;
                bool reversed = false;
                for (int polygonAIndex = 0; polygonAIndex < openPolygonList.Count; polygonAIndex++)
                {
                    if (openPolygonList[polygonAIndex].Count < 1)
                    {
                        continue;
                    }

                    for (int polygonBIndex = 0; polygonBIndex < openPolygonList.Count; polygonBIndex++)
                    {
                        if (openPolygonList[polygonBIndex].Count < 1)
                        {
                            continue;
                        }

                        IntPoint diff1 = openPolygonList[polygonAIndex][openPolygonList[polygonAIndex].Count - 1] - openPolygonList[polygonBIndex][0];
                        long distSquared1 = (diff1).LengthSquared();
                        if (distSquared1 < bestScore)
                        {
                            bestScore = distSquared1;
                            bestA = polygonAIndex;
                            bestB = polygonBIndex;
                            reversed = false;

                            if (bestScore == 0)
                            {
                                // found a perfect match stop looking
                                break;
                            }
                        }

                        if (polygonAIndex != polygonBIndex)
                        {
                            IntPoint diff2 = openPolygonList[polygonAIndex][openPolygonList[polygonAIndex].Count - 1] - openPolygonList[polygonBIndex][openPolygonList[polygonBIndex].Count - 1];
                            long distSquared2 = (diff2).LengthSquared();
                            if (distSquared2 < bestScore)
                            {
                                bestScore = distSquared2;
                                bestA = polygonAIndex;
                                bestB = polygonBIndex;
                                reversed = true;

                                if (bestScore == 0)
                                {
                                    // found a perfect match stop looking
                                    break;
                                }
                            }
                        }
                    }

                    if (bestScore == 0)
                    {
                        // found a perfect match stop looking
                        break;
                    }
                }

                if (bestScore >= 10000 * 10000)
                {
                    break;
                }

                if (bestA == bestB) // This loop connects to itself, close the polygon.
                {
                    PolygonList.Add(new Polygon(openPolygonList[bestA]));
                    openPolygonList[bestA].Clear(); // B is cleared as it is A
                }
                else
                {
                    if (reversed)
                    {
                        if (openPolygonList[bestA].PolygonLength() > openPolygonList[bestB].PolygonLength())
                        {
                            openPolygonList[bestA].AddRange(openPolygonList[bestB]);
                            openPolygonList[bestB].Clear();
                        }
                        else
                        {
                            openPolygonList[bestB].AddRange(openPolygonList[bestA]);
                            openPolygonList[bestA].Clear();
                        }
                    }
                    else
                    {
                        openPolygonList[bestA].AddRange(openPolygonList[bestB]);
                        openPolygonList[bestB].Clear();
                    }
                }
            }

            if ((outlineRepairTypes & ConfigConstants.REPAIR_OUTLINES.EXTENSIVE_STITCHING) == ConfigConstants.REPAIR_OUTLINES.EXTENSIVE_STITCHING)
            {
                //For extensive stitching find 2 open polygons that are touching 2 closed polygons.
                // Then find the sortest path over this polygon that can be used to connect the open polygons,
                // And generate a path over this shortest bit to link up the 2 open polygons.
                // (If these 2 open polygons are the same polygon, then the final result is a closed polyon)

                while (true)
                {
                    int bestA = -1;
                    int bestB = -1;
                    GapCloserResult bestResult = new GapCloserResult();
                    bestResult.len = long.MaxValue;
                    bestResult.polygonIndex = -1;
                    bestResult.pointIndexA = -1;
                    bestResult.pointIndexB = -1;

                    for (int i = 0; i < openPolygonList.Count; i++)
                    {
                        if (openPolygonList[i].Count < 1) continue;

                        {
                            GapCloserResult res = FindPolygonGapCloser(openPolygonList[i][0], openPolygonList[i][openPolygonList[i].Count - 1]);
                            if (res.len > 0 && res.len < bestResult.len)
                            {
                                bestA = i;
                                bestB = i;
                                bestResult = res;
                            }
                        }

                        for (int j = 0; j < openPolygonList.Count; j++)
                        {
                            if (openPolygonList[j].Count < 1 || i == j) continue;

                            GapCloserResult res = FindPolygonGapCloser(openPolygonList[i][0], openPolygonList[j][openPolygonList[j].Count - 1]);
                            if (res.len > 0 && res.len < bestResult.len)
                            {
                                bestA = i;
                                bestB = j;
                                bestResult = res;
                            }
                        }
                    }

                    if (bestResult.len < long.MaxValue)
                    {
                        if (bestA == bestB)
                        {
                            if (bestResult.pointIndexA == bestResult.pointIndexB)
                            {
                                PolygonList.Add(new Polygon(openPolygonList[bestA]));
                                openPolygonList[bestA].Clear();
                            }
                            else if (bestResult.AtoB)
                            {
                                Polygon poly = new Polygon();
                                PolygonList.Add(poly);
                                for (int j = bestResult.pointIndexA; j != bestResult.pointIndexB; j = (j + 1) % PolygonList[bestResult.polygonIndex].Count)
                                {
                                    poly.Add(PolygonList[bestResult.polygonIndex][j]);
                                }

                                poly.AddRange(openPolygonList[bestA]);
                                openPolygonList[bestA].Clear();
                            }
                            else
                            {
                                int n = PolygonList.Count;
                                PolygonList.Add(new Polygon(openPolygonList[bestA]));
                                for (int j = bestResult.pointIndexB; j != bestResult.pointIndexA; j = (j + 1) % PolygonList[bestResult.polygonIndex].Count)
                                {
                                    PolygonList[n].Add(PolygonList[bestResult.polygonIndex][j]);
                                }
                                openPolygonList[bestA].Clear();
                            }
                        }
                        else
                        {
                            if (bestResult.pointIndexA == bestResult.pointIndexB)
                            {
                                openPolygonList[bestB].AddRange(openPolygonList[bestA]);
                                openPolygonList[bestA].Clear();
                            }
                            else if (bestResult.AtoB)
                            {
                                Polygon poly = new Polygon();
                                for (int n = bestResult.pointIndexA; n != bestResult.pointIndexB; n = (n + 1) % PolygonList[bestResult.polygonIndex].Count)
                                {
                                    poly.Add(PolygonList[bestResult.polygonIndex][n]);
                                }

                                for (int n = poly.Count - 1; (int)(n) >= 0; n--)
                                {
                                    openPolygonList[bestB].Add(poly[n]);
                                }

                                for (int n = 0; n < openPolygonList[bestA].Count; n++)
                                {
                                    openPolygonList[bestB].Add(openPolygonList[bestA][n]);
                                }

                                openPolygonList[bestA].Clear();
                            }
                            else
                            {
                                for (int n = bestResult.pointIndexB; n != bestResult.pointIndexA; n = (n + 1) % PolygonList[bestResult.polygonIndex].Count)
                                {
                                    openPolygonList[bestB].Add(PolygonList[bestResult.polygonIndex][n]);
                                }

                                for (int n = openPolygonList[bestA].Count - 1; n >= 0; n--)
                                {
                                    openPolygonList[bestB].Add(openPolygonList[bestA][n]);
                                }

                                openPolygonList[bestA].Clear();
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if ((outlineRepairTypes & ConfigConstants.REPAIR_OUTLINES.KEEP_OPEN) == ConfigConstants.REPAIR_OUTLINES.KEEP_OPEN)
            {
                for (int n = 0; n < openPolygonList.Count; n++)
                {
                    if (openPolygonList[n].Count > 0)
                    {
                        PolygonList.Add(new Polygon(openPolygonList[n]));
                    }
                }
            }

            //Remove all the tiny polygons, or polygons that are not closed. As they do not contribute to the actual print.
            int minimumPerimeter = 1000;
            for (int polygonIndex = 0; polygonIndex < PolygonList.Count; polygonIndex++)
            {
                long perimeterLength = 0;

                for (int intPointIndex = 1; intPointIndex < PolygonList[polygonIndex].Count; intPointIndex++)
                {
                    perimeterLength += (PolygonList[polygonIndex][intPointIndex] - PolygonList[polygonIndex][intPointIndex - 1]).Length();
                    if (perimeterLength > minimumPerimeter)
                    {
                        break;
                    }
                }
                if (perimeterLength < minimumPerimeter)
                {
                    PolygonList.RemoveAt(polygonIndex);
                    polygonIndex--;
                }
            }

            //Finally optimize all the polygons. Every point removed saves time in the long run.
            double minimumDistanceToCreateNewPosition = 10;
            PolygonList = Clipper.CleanPolygons(PolygonList, minimumDistanceToCreateNewPosition);
        }