Ejemplo n.º 1
0
        private GapCloserResult FindPolygonGapCloser(IntPoint ip0, IntPoint ip1)
        {
            GapCloserResult    ret = new GapCloserResult();
            ClosePolygonResult c1  = FindPolygonPointClosestTo(ip0);
            ClosePolygonResult c2  = FindPolygonPointClosestTo(ip1);

            if (c1.polygonIdx < 0 || c1.polygonIdx != c2.polygonIdx)
            {
                ret.len = -1;
                return(ret);
            }
            ret.polygonIndex = c1.polygonIdx;
            ret.pointIndexA  = c1.pointIdx;
            ret.pointIndexB  = c2.pointIdx;
            ret.AtoB         = true;

            if (ret.pointIndexA == ret.pointIndexB)
            {
                //Connection points are on the same line segment.
                ret.len = (ip0 - ip1).Length();
            }
            else
            {
                //Find out if we have should go from A to B or the other way around.
                IntPoint p0   = PolygonList[ret.polygonIndex][ret.pointIndexA];
                long     lenA = (p0 - ip0).Length();
                for (int i = ret.pointIndexA; i != ret.pointIndexB; i = (i + 1) % PolygonList[ret.polygonIndex].Count)
                {
                    IntPoint p1 = PolygonList[ret.polygonIndex][i];
                    lenA += (p0 - p1).Length();
                    p0    = p1;
                }
                lenA += (p0 - ip1).Length();

                p0 = PolygonList[ret.polygonIndex][ret.pointIndexB];
                long lenB = (p0 - ip1).Length();
                for (int i = ret.pointIndexB; i != ret.pointIndexA; i = (i + 1) % PolygonList[ret.polygonIndex].Count)
                {
                    IntPoint p1 = PolygonList[ret.polygonIndex][i];
                    lenB += (p0 - p1).Length();
                    p0    = p1;
                }
                lenB += (p0 - ip0).Length();

                if (lenA < lenB)
                {
                    ret.AtoB = true;
                    ret.len  = lenA;
                }
                else
                {
                    ret.AtoB = false;
                    ret.len  = lenB;
                }
            }
            return(ret);
        }
Ejemplo n.º 2
0
        public void MakePolygons(OptimizedVolume optomizedMesh, ConfigConstants.REPAIR_OUTLINES outlineRepairTypes)
        {
            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;

                bool lastAddWasAStart = true;

                while (true)
                {
                    canClose = false;
                    segmentList[segmentIndexBeingAdded].hasBeenAddedToPolygon = true;
                    IntPoint addedSegmentEndPoint = segmentList[segmentIndexBeingAdded].end;
                    if (!lastAddWasAStart)
                    {
                        // the last added point was an end so add the start as the text end point
                        addedSegmentEndPoint = segmentList[segmentIndexBeingAdded].start;
                    }

                    poly.Add(addedSegmentEndPoint);
                    int           nextSegmentToCheckIndex = -1;
                    OptimizedFace face = optomizedMesh.facesTriangle[segmentList[segmentIndexBeingAdded].faceIndex];
                    for (int connectedFaceIndex = 0; connectedFaceIndex < 3; connectedFaceIndex++)
                    {
                        int testFaceIndex = face.touchingFaces[connectedFaceIndex];
                        if (testFaceIndex > -1)
                        {
                            // If the connected face has an edge that is in the segment list
                            if (faceTo2DSegmentIndex.ContainsKey(testFaceIndex))
                            {
                                int      touchingSegmentIndex = faceTo2DSegmentIndex[testFaceIndex];
                                IntPoint foundSegmentStart    = segmentList[touchingSegmentIndex].start;
                                if (addedSegmentEndPoint == foundSegmentStart)
                                {
                                    // if we have looped back around to where we started
                                    if (addedSegmentEndPoint == polygonStartPosition)
                                    {
                                        canClose = true;
                                    }

                                    // If this segment has already been added
                                    if (segmentList[touchingSegmentIndex].hasBeenAddedToPolygon)
                                    {
                                        continue;
                                    }

                                    nextSegmentToCheckIndex = touchingSegmentIndex;
                                    lastAddWasAStart        = true;
                                }
                                else // let's check if the other side of this segment can hook up (the normal is facing the wrong way)
                                {
                                    IntPoint foundSegmentEnd = segmentList[touchingSegmentIndex].end;
                                    if (addedSegmentEndPoint == foundSegmentEnd)
                                    {
                                        // if we have looped back around to where we started
                                        if (addedSegmentEndPoint == polygonStartPosition)
                                        {
                                            canClose = true;
                                        }

                                        // If this segment has already been added
                                        if (segmentList[touchingSegmentIndex].hasBeenAddedToPolygon)
                                        {
                                            continue;
                                        }

                                        nextSegmentToCheckIndex = touchingSegmentIndex;
                                        lastAddWasAStart        = false;
                                    }
                                }
                            }
                        }
                    }

                    if (nextSegmentToCheckIndex == -1)
                    {
                        break;
                    }

                    segmentIndexBeingAdded = nextSegmentToCheckIndex;
                }

                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)
                {
                    polygonList.Add(new Polygon(openPolygonList[bestA]));
                    openPolygonList[bestA].Clear();
                }
                else
                {
                    if (reversed)
                    {
                        if (openPolygonList[bestA].PolygonLength() > openPolygonList[bestB].PolygonLength())
                        {
                            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[bestB].AddRange(openPolygonList[bestA]);
                            openPolygonList[bestB].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 snapDistance = 1000;

            for (int polygonIndex = 0; polygonIndex < polygonList.Count; polygonIndex++)
            {
                int length = 0;

                for (int intPointIndex = 1; intPointIndex < polygonList[polygonIndex].Count; intPointIndex++)
                {
                    length += (polygonList[polygonIndex][intPointIndex] - polygonList[polygonIndex][intPointIndex - 1]).vSize();
                    if (length > snapDistance)
                    {
                        break;
                    }
                }
                if (length < snapDistance)
                {
                    polygonList.RemoveAt(polygonIndex);
                    polygonIndex--;
                }
            }

            //Finally optimize all the polygons. Every point removed saves time in the long run.
            double minimumDistanceToCreateNewPosition = 1.415;

            polygonList = Clipper.CleanPolygons(polygonList, minimumDistanceToCreateNewPosition);
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
		private GapCloserResult FindPolygonGapCloser(IntPoint ip0, IntPoint ip1)
		{
			GapCloserResult ret = new GapCloserResult();
			ClosePolygonResult c1 = FindPolygonPointClosestTo(ip0);
			ClosePolygonResult c2 = FindPolygonPointClosestTo(ip1);
			if (c1.polygonIdx < 0 || c1.polygonIdx != c2.polygonIdx)
			{
				ret.len = -1;
				return ret;
			}
			ret.polygonIndex = c1.polygonIdx;
			ret.pointIndexA = c1.pointIdx;
			ret.pointIndexB = c2.pointIdx;
			ret.AtoB = true;

			if (ret.pointIndexA == ret.pointIndexB)
			{
				//Connection points are on the same line segment.
				ret.len = (ip0 - ip1).Length();
			}
			else
			{
				//Find out if we have should go from A to B or the other way around.
				IntPoint p0 = PolygonList[ret.polygonIndex][ret.pointIndexA];
				long lenA = (p0 - ip0).Length();
				for (int i = ret.pointIndexA; i != ret.pointIndexB; i = (i + 1) % PolygonList[ret.polygonIndex].Count)
				{
					IntPoint p1 = PolygonList[ret.polygonIndex][i];
					lenA += (p0 - p1).Length();
					p0 = p1;
				}
				lenA += (p0 - ip1).Length();

				p0 = PolygonList[ret.polygonIndex][ret.pointIndexB];
				long lenB = (p0 - ip1).Length();
				for (int i = ret.pointIndexB; i != ret.pointIndexA; i = (i + 1) % PolygonList[ret.polygonIndex].Count)
				{
					IntPoint p1 = PolygonList[ret.polygonIndex][i];
					lenB += (p0 - p1).Length();
					p0 = p1;
				}
				lenB += (p0 - ip0).Length();

				if (lenA < lenB)
				{
					ret.AtoB = true;
					ret.len = lenA;
				}
				else
				{
					ret.AtoB = false;
					ret.len = lenB;
				}
			}
			return ret;
		}
Ejemplo n.º 5
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);
        }