예제 #1
0
        public void Accept <TGene>(EvolutionResult <TGene, T> result)
            where TGene : IGene <TGene>
        {
            Accept(result.GetDurations());

            Killed.Accept(result.GetKillCount());
            Invalids.Accept(result.GetInvalidCount());
            Altered.Accept(result.GetAlterCount());

            foreach (var pt in result.GetPopulation())
            {
                Accept(pt, result.GetGeneration());
            }
        }
        /// <summary>
        /// Create the list of polygon segments (not closed) that represent the parts of the source polygons that are close (almost touching).
        /// </summary>
        /// <param name="polygons"></param>
        /// <param name="overlapMergeAmount">If edges under consideration, are this distance or less appart (but greater than minimumRequiredWidth) they will generate edges</param>
        /// <param name="minimumRequiredWidth">If the distance between edges is less this they will not be generated. This lets us avoid considering very very thin lines.</param>
        /// <param name="onlyMergeLines">The output segments that are calculated</param>
        /// <param name="pathIsClosed">Is the source path closed (does not contain the last edge but assumes it).</param>
        /// <returns></returns>
        public static bool FindThinLines(this Polygons polygons, long overlapMergeAmount, long minimumRequiredWidth, out Polygons onlyMergeLines, bool pathIsClosed = true)
        {
            bool pathHasMergeLines = false;

            polygons = MakeCloseSegmentsMergable(polygons, overlapMergeAmount, pathIsClosed);

            // make a copy that has every point duplicated (so that we have them as segments).
            List <Segment> polySegments = Segment.ConvertToSegments(polygons);

            Altered[] markedAltered = new Altered[polySegments.Count];

            var touchingEnumerator = new CloseSegmentsIterator(polySegments, overlapMergeAmount);
            int segmentCount       = polySegments.Count;

            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                foreach (int checkSegmentIndex in touchingEnumerator.GetTouching(firstSegmentIndex, segmentCount))
                {
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                        if (endDelta < overlapMergeAmount)
                        {
                            // move the first segments points to the average of the merge positions
                            long startEndWidth = Math.Abs((polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length());
                            long endStartWidth = Math.Abs((polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length());
                            long width         = Math.Min(startEndWidth, endStartWidth);

                            if (width > minimumRequiredWidth)
                            {
                                // We need to check if the new start position is on the inside of the curve. We can only add thin lines on the insides of our exisiting curves.
                                IntPoint newStartPosition  = (polySegments[firstSegmentIndex].Start + polySegments[checkSegmentIndex].End) / 2;                                // the start;
                                IntPoint newStartDirection = newStartPosition - polySegments[firstSegmentIndex].Start;
                                IntPoint normalLeft        = (polySegments[firstSegmentIndex].End - polySegments[firstSegmentIndex].Start).GetPerpendicularLeft();
                                long     dotProduct        = normalLeft.Dot(newStartDirection);
                                if (dotProduct > 0)
                                {
                                    pathHasMergeLines = true;

                                    polySegments[firstSegmentIndex].Start       = newStartPosition;
                                    polySegments[firstSegmentIndex].Start.Width = width;
                                    polySegments[firstSegmentIndex].End         = (polySegments[firstSegmentIndex].End + polySegments[checkSegmentIndex].Start) / 2;                             // the end
                                    polySegments[firstSegmentIndex].End.Width   = width;

                                    markedAltered[firstSegmentIndex] = Altered.merged;
                                    // mark this segment for removal
                                    markedAltered[checkSegmentIndex] = Altered.remove;
                                    // We only expect to find one match for each segment, so move on to the next segment
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                // remove every segment that has not been merged
                if (markedAltered[segmentIndex] != Altered.merged)
                {
                    polySegments.RemoveAt(segmentIndex);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            onlyMergeLines = new Polygons();
            Polygon currentPolygon = new Polygon();

            onlyMergeLines.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex++)
            {
                // add the start point
                currentPolygon.Add(polySegments[segmentIndex].Start);

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 1 &&
                    polySegments[segmentIndex].End != polySegments[segmentIndex + 1].Start)
                {
                    // add the end point
                    currentPolygon.Add(polySegments[segmentIndex].End);

                    // create a new polygon
                    currentPolygon = new Polygon();
                    onlyMergeLines.Add(currentPolygon);
                }
            }

            // add the end point
            if (polySegments.Count > 0)
            {
                currentPolygon.Add(polySegments[polySegments.Count - 1].End);
            }

            //long cleanDistance = overlapMergeAmount / 40;
            //Clipper.CleanPolygons(onlyMergeLines, cleanDistance);

            return(pathHasMergeLines);
        }
예제 #3
0
        public bool RemovePerimeterOverlaps(List <Point3> perimeter, long overlapMergeAmount_um, out List <PathAndWidth> separatedPolygons, bool pathIsClosed = true)
        {
            bool pathWasOptomized = false;

            perimeter = MakeCloseSegmentsMergable(perimeter, overlapMergeAmount_um);

            // make a copy that has every point duplicated (so that we have them as segments).
            List <Segment> polySegments = Segment.ConvertPathToSegments(perimeter, pathIsClosed);

            Altered[] markedAltered = new Altered[polySegments.Count];

            int segmentCount = polySegments.Count;

            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                for (int checkSegmentIndex = firstSegmentIndex + 1; checkSegmentIndex < segmentCount; checkSegmentIndex++)
                {
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            pathWasOptomized = true;
                            // move the first segments points to the average of the merge positions
                            long startEndWidth = Math.Abs((polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length());
                            long endStartWidth = Math.Abs((polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length());
                            polySegments[firstSegmentIndex].Width = Math.Min(startEndWidth, endStartWidth);
                            polySegments[firstSegmentIndex].Start = (polySegments[firstSegmentIndex].Start + polySegments[checkSegmentIndex].End) / 2;                           // the start
                            polySegments[firstSegmentIndex].End   = (polySegments[firstSegmentIndex].End + polySegments[checkSegmentIndex].Start) / 2;                           // the end

                            markedAltered[firstSegmentIndex] = Altered.merged;
                            // mark this segment for removal
                            markedAltered[checkSegmentIndex] = Altered.remove;
                            // We only expect to find one match for each segment, so move on to the next segment
                            break;
                        }
                    }
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                if (markedAltered[segmentIndex] == Altered.remove)
                {
                    polySegments.RemoveAt(segmentIndex);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            separatedPolygons = new List <PathAndWidth>();
            PathAndWidth currentPolygon = new PathAndWidth();

            separatedPolygons.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex++)
            {
                // add the start point
                currentPolygon.Path.Add(polySegments[segmentIndex].Start);
                currentPolygon.ExtrusionWidthUm = polySegments[segmentIndex].Width + overlapMergeAmount_um;

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 1 &&
                    (polySegments[segmentIndex].End != polySegments[segmentIndex + 1].Start ||
                     polySegments[segmentIndex].Width != polySegments[segmentIndex + 1].Width))
                {
                    // add the end point
                    currentPolygon.Path.Add(polySegments[segmentIndex].End);

                    // create a new polygon
                    currentPolygon = new PathAndWidth();
                    separatedPolygons.Add(currentPolygon);
                }
            }

            // add the end point
            currentPolygon.Path.Add(polySegments[polySegments.Count - 1].End);

            return(pathWasOptomized);
        }
예제 #4
0
        public static bool MergePerimeterOverlaps(this Polygons perimetersIn, long overlapMergeAmount_um, out Polygons separatedPolygons, bool pathIsClosed = true)
        {
            // if the path is wound CW
            separatedPolygons = new Polygons();

            long cleanDistance_um = overlapMergeAmount_um / 40;

            var perimeters = Clipper.CleanPolygons(perimetersIn, cleanDistance_um);

            if (perimeters.Count == 0)
            {
                return(false);
            }

            bool pathWasOptimized = false;

            // Set all the paths to have the width we are starting width (as we will be changing some of them)
            foreach (var perimeter in perimeters)
            {
                for (int i = 0; i < perimeter.Count; i++)
                {
                    perimeter[i] = new IntPoint(perimeter[i])
                    {
                        Width = overlapMergeAmount_um
                    };
                }
            }

            perimeters = perimeters.MakeCloseSegmentsMergable(overlapMergeAmount_um * 3 / 4, pathIsClosed);

            // make a copy that has every point duplicated (so that we have them as segments).
            List <Segment> polySegments = Segment.ConvertToSegments(perimeters, pathIsClosed);

            var markedAltered = new Altered[polySegments.Count];

            var minimumLengthToCreateSquared = overlapMergeAmount_um;

            minimumLengthToCreateSquared *= minimumLengthToCreateSquared;

            var touchingEnumerator = new CloseSegmentsIterator(polySegments, overlapMergeAmount_um);
            int segmentCount       = polySegments.Count;

            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                foreach (int checkSegmentIndex in touchingEnumerator.GetTouching(firstSegmentIndex, segmentCount))
                {
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            // only consider the merge if the directions of the lines are towards each other
                            var firstSegmentDirection = polySegments[firstSegmentIndex].End - polySegments[firstSegmentIndex].Start;
                            var checkSegmentDirection = polySegments[checkSegmentIndex].End - polySegments[checkSegmentIndex].Start;
                            if (firstSegmentDirection.Dot(checkSegmentDirection) > 0)
                            {
                                continue;
                            }

                            // get the line width
                            long startEndWidth = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                            long endStartWidth = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                            long width         = Math.Min(startEndWidth, endStartWidth) + overlapMergeAmount_um;

                            // check if we extrude enough to consider doing this merge
                            var segmentStart = (polySegments[firstSegmentIndex].Start + polySegments[checkSegmentIndex].End) / 2;
                            var segmentEnd   = (polySegments[firstSegmentIndex].End + polySegments[checkSegmentIndex].Start) / 2;

                            if ((segmentStart - segmentEnd).LengthSquared() < minimumLengthToCreateSquared)
                            {
                                continue;
                            }

                            pathWasOptimized = true;
                            // move the first segments points to the average of the merge positions
                            polySegments[firstSegmentIndex].Start       = segmentStart;
                            polySegments[firstSegmentIndex].Start.Width = width;
                            polySegments[firstSegmentIndex].End         = segmentEnd;
                            polySegments[firstSegmentIndex].End.Width   = width;

                            markedAltered[firstSegmentIndex] = Altered.Merged;
                            // mark this segment for removal
                            markedAltered[checkSegmentIndex] = Altered.Remove;
                            // We only expect to find one match for each segment, so move on to the next segment
                            break;
                        }
                    }
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                if (markedAltered[segmentIndex] == Altered.Remove)
                {
                    polySegments.RemoveAt(segmentIndex);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            var currentPolygon = new Polygon();

            separatedPolygons.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex++)
            {
                // add the start point
                currentPolygon.Add(polySegments[segmentIndex].Start);

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 1 &&
                    polySegments[segmentIndex].End != polySegments[segmentIndex + 1].Start)
                {
                    // add the end point
                    currentPolygon.Add(polySegments[segmentIndex].End);

                    // create a new polygon
                    currentPolygon = new Polygon();
                    separatedPolygons.Add(currentPolygon);
                }
            }

            if (polySegments.Count > 0)
            {
                // add the end point
                currentPolygon.Add(polySegments[polySegments.Count - 1].End);
            }

            if (pathWasOptimized &&
                Math.Abs(perimeters.PolygonLength() - separatedPolygons.PolygonLength(false)) < overlapMergeAmount_um * 2)
            {
                return(false);
            }

            return(pathWasOptimized);
        }
예제 #5
0
        public bool RemovePerimeterOverlaps(List<Point3> perimeter, long overlapMergeAmount_um, out List<PathAndWidth> separatedPolygons, bool pathIsClosed = true)
        {
            bool pathWasOptomized = false;

            perimeter = MakeCloseSegmentsMergable(perimeter, overlapMergeAmount_um);

            // make a copy that has every point duplicated (so that we have them as segments).
            List <Segment> polySegments = Segment.ConvertPathToSegments(perimeter, pathIsClosed);

            Altered[] markedAltered = new Altered[polySegments.Count];

            int segmentCount = polySegments.Count;
            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                for (int checkSegmentIndex = firstSegmentIndex + 1; checkSegmentIndex < segmentCount; checkSegmentIndex++)
                {
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            pathWasOptomized = true;
                            // move the first segments points to the average of the merge positions
                            long startEndWidth = Math.Abs((polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length());
                            long endStartWidth = Math.Abs((polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length());
                            polySegments[firstSegmentIndex].Width = Math.Min(startEndWidth, endStartWidth);
                            polySegments[firstSegmentIndex].Start = (polySegments[firstSegmentIndex].Start + polySegments[checkSegmentIndex].End) / 2; // the start
                            polySegments[firstSegmentIndex].End = (polySegments[firstSegmentIndex].End + polySegments[checkSegmentIndex].Start) / 2; // the end

                            markedAltered[firstSegmentIndex] = Altered.merged;
                            // mark this segment for removal
                            markedAltered[checkSegmentIndex] = Altered.remove;
                            // We only expect to find one match for each segment, so move on to the next segment
                            break;
                        }
                    }
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                if (markedAltered[segmentIndex] == Altered.remove)
                {
                    polySegments.RemoveAt(segmentIndex);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            separatedPolygons = new List<PathAndWidth>();
            PathAndWidth currentPolygon = new PathAndWidth();
            separatedPolygons.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex++)
            {
                // add the start point
                currentPolygon.Path.Add(polySegments[segmentIndex].Start);
                currentPolygon.ExtrusionWidthUm = polySegments[segmentIndex].Width + overlapMergeAmount_um;

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 1
                    && (polySegments[segmentIndex].End != polySegments[segmentIndex + 1].Start
                    || polySegments[segmentIndex].Width != polySegments[segmentIndex + 1].Width))
                {
                    // add the end point
                    currentPolygon.Path.Add(polySegments[segmentIndex].End);

                    // create a new polygon
                    currentPolygon = new PathAndWidth();
                    separatedPolygons.Add(currentPolygon);
                }
            }

            // add the end point
            currentPolygon.Path.Add(polySegments[polySegments.Count - 1].End);

            return pathWasOptomized;
        }
예제 #6
0
        public static bool MergePerimeterOverlaps(Polygon perimeter, long overlapMergeAmount_um, out Polygons separatedPolygons, bool pathIsClosed = true)
        {
            separatedPolygons = new Polygons();

            long cleanDistance_um = overlapMergeAmount_um / 40;

            Polygons cleanedPolygs = Clipper.CleanPolygons(new Polygons()
            {
                perimeter
            }, cleanDistance_um);

            perimeter = cleanedPolygs[0];

            if (perimeter.Count == 0)
            {
                return(false);
            }
            bool pathWasOptomized = false;

            for (int i = 0; i < perimeter.Count; i++)
            {
                perimeter[i] = new IntPoint(perimeter[i])
                {
                    Width = overlapMergeAmount_um
                };
            }

            perimeter = MakeCloseSegmentsMergable(perimeter, overlapMergeAmount_um, pathIsClosed);

            // make a copy that has every point duplicated (so that we have them as segments).
            List <Segment> polySegments = Segment.ConvertToSegments(perimeter, pathIsClosed);

            Altered[] markedAltered = new Altered[polySegments.Count];

            int segmentCount = polySegments.Count;

            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                //polySegments[firstSegmentIndex].Start.Width = overlapMergeAmount_um;
                //polySegments[firstSegmentIndex].End.Width = overlapMergeAmount_um;

                for (int checkSegmentIndex = firstSegmentIndex + 1; checkSegmentIndex < segmentCount; checkSegmentIndex++)
                {
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            // only considre the merge if the directions of the lines are towards eachother
                            var firstSegmentDirection = polySegments[firstSegmentIndex].End - polySegments[firstSegmentIndex].Start;
                            var checkSegmentDirection = polySegments[checkSegmentIndex].End - polySegments[checkSegmentIndex].Start;
                            if (firstSegmentDirection.Dot(checkSegmentDirection) > 0)
                            {
                                continue;
                            }
                            pathWasOptomized = true;
                            // move the first segments points to the average of the merge positions
                            long startEndWidth = Math.Abs((polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length());
                            long endStartWidth = Math.Abs((polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length());
                            long width         = Math.Min(startEndWidth, endStartWidth) + overlapMergeAmount_um;
                            polySegments[firstSegmentIndex].Start       = (polySegments[firstSegmentIndex].Start + polySegments[checkSegmentIndex].End) / 2;                     // the start
                            polySegments[firstSegmentIndex].Start.Width = width;
                            polySegments[firstSegmentIndex].End         = (polySegments[firstSegmentIndex].End + polySegments[checkSegmentIndex].Start) / 2;                     // the end
                            polySegments[firstSegmentIndex].End.Width   = width;

                            markedAltered[firstSegmentIndex] = Altered.merged;
                            // mark this segment for removal
                            markedAltered[checkSegmentIndex] = Altered.remove;
                            // We only expect to find one match for each segment, so move on to the next segment
                            break;
                        }
                    }
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                if (markedAltered[segmentIndex] == Altered.remove)
                {
                    polySegments.RemoveAt(segmentIndex);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            Polygon currentPolygon = new Polygon();

            separatedPolygons.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex++)
            {
                // add the start point
                currentPolygon.Add(polySegments[segmentIndex].Start);

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 1 &&
                    polySegments[segmentIndex].End != polySegments[segmentIndex + 1].Start)
                {
                    // add the end point
                    currentPolygon.Add(polySegments[segmentIndex].End);

                    // create a new polygon
                    currentPolygon = new Polygon();
                    separatedPolygons.Add(currentPolygon);
                }
            }

            // add the end point
            currentPolygon.Add(polySegments[polySegments.Count - 1].End);

            return(pathWasOptomized);
        }
예제 #7
0
        public Polygons GetPathsWithOverlapsRemoved(Polygon perimeter, int overlapMergeAmount_um)
        {
            // make a copy that has every point duplicatiod (so that we have them as segments).
            Polygon polySegments = new Polygon(perimeter.Count * 2);
            for (int i = 0; i < perimeter.Count - 1; i++)
            {
                IntPoint point = perimeter[i];
                IntPoint nextPoint = perimeter[i + 1];

                polySegments.Add(point);
                polySegments.Add(nextPoint);
            }

            Altered[] markedAltered = new Altered[polySegments.Count/2];

            int segmentCount = polySegments.Count / 2;
            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                int firstPointIndex = firstSegmentIndex * 2;
                for (int checkSegmentIndex = firstSegmentIndex + 1; checkSegmentIndex < segmentCount; checkSegmentIndex++)
                {
                    int checkPointIndex = checkSegmentIndex * 2;
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstPointIndex] - polySegments[checkPointIndex + 1]).Length();
                    // if the segmets are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstPointIndex + 1] - polySegments[checkPointIndex]).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            // move the first segments points to the average of the merge positions
                            polySegments[firstPointIndex] = (polySegments[firstPointIndex] + polySegments[checkPointIndex + 1]) / 2; // the start
                            polySegments[firstPointIndex + 1] = (polySegments[firstPointIndex + 1] + polySegments[checkPointIndex]) / 2; // the end

                            markedAltered[firstSegmentIndex] = Altered.merged;
                            // mark this segment for removal
                            markedAltered[checkSegmentIndex] = Altered.remove;
                            // We only expect to find one match for each segment, so move on to the next segment
                            break;
                        }
                    }
                }
            }

            // Check for perimeter edeges that need to be removed that are the u turns of sectons that go back on themselves.
            //  __________
            // |__________|	->  |--------|  the 2 vertical sections should be removed
            for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++)
            {
                int prevSegmentIndex = (int)((uint)(segmentIndex - 1) % (uint)segmentCount);
                int nextSegmentIndex = (segmentIndex + 1) % segmentCount;
                if ((markedAltered[nextSegmentIndex] == Altered.merged && markedAltered[prevSegmentIndex] == Altered.remove)
                    || (markedAltered[nextSegmentIndex] == Altered.remove && markedAltered[prevSegmentIndex] == Altered.merged))
                {
                    markedAltered[segmentIndex] = Altered.remove;
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                int pointIndex = segmentIndex * 2;
                if (markedAltered[segmentIndex] == Altered.remove)
                {
                    polySegments.RemoveRange(pointIndex, 2);
                }
            }

            // go through the polySegmets and create a new polygon for every connected set of segmets
            Polygons separatedPolygons = new Polygons();
            Polygon currentPolygon = new Polygon();
            separatedPolygons.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex += 2)
            {
                // add the start point
                currentPolygon.Add(polySegments[segmentIndex]);

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 2
                    && polySegments[segmentIndex + 1] != polySegments[segmentIndex + 2])
                {
                    // add the end point
                    currentPolygon.Add(polySegments[segmentIndex + 1]);

                    // create a new polygon
                    currentPolygon = new Polygon();
                    separatedPolygons.Add(currentPolygon);
                }
            }

            // add the end point
            currentPolygon.Add(polySegments[polySegments.Count - 1]);

            return separatedPolygons;
        }
예제 #8
0
        public List <List <Point3> > GetPathsWithOverlapsRemoved(List <Point3> perimeter, int overlapMergeAmount_um)
        {
            // make a copy that has every point duplicated (so that we have them as segments).
            List <Point3> polySegments = new List <Point3>(perimeter.Count * 2);

            for (int i = 0; i < perimeter.Count - 1; i++)
            {
                Point3 point     = perimeter[i];
                Point3 nextPoint = perimeter[i + 1];

                polySegments.Add(point);
                polySegments.Add(nextPoint);
            }

            Altered[] markedAltered = new Altered[polySegments.Count / 2];

            int segmentCount = polySegments.Count / 2;

            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                int firstPointIndex = firstSegmentIndex * 2;
                for (int checkSegmentIndex = firstSegmentIndex + 1; checkSegmentIndex < segmentCount; checkSegmentIndex++)
                {
                    int checkPointIndex = checkSegmentIndex * 2;
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstPointIndex] - polySegments[checkPointIndex + 1]).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstPointIndex + 1] - polySegments[checkPointIndex]).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            // move the first segments points to the average of the merge positions
                            polySegments[firstPointIndex]     = (polySegments[firstPointIndex] + polySegments[checkPointIndex + 1]) / 2;                         // the start
                            polySegments[firstPointIndex + 1] = (polySegments[firstPointIndex + 1] + polySegments[checkPointIndex]) / 2;                         // the end

                            markedAltered[firstSegmentIndex] = Altered.merged;
                            // mark this segment for removal
                            markedAltered[checkSegmentIndex] = Altered.remove;
                            // We only expect to find one match for each segment, so move on to the next segment
                            break;
                        }
                    }
                }
            }

            // Check for perimeter edges that need to be removed that are the u turns of sections that go back on themselves.
            //  __________
            // |__________|	->  |--------|  the 2 vertical sections should be removed
            for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++)
            {
                int prevSegmentIndex = (int)((uint)(segmentIndex - 1) % (uint)segmentCount);
                int nextSegmentIndex = (segmentIndex + 1) % segmentCount;
                if ((markedAltered[nextSegmentIndex] == Altered.merged && markedAltered[prevSegmentIndex] == Altered.remove) ||
                    (markedAltered[nextSegmentIndex] == Altered.remove && markedAltered[prevSegmentIndex] == Altered.merged))
                {
                    markedAltered[segmentIndex] = Altered.remove;
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                int pointIndex = segmentIndex * 2;
                if (markedAltered[segmentIndex] == Altered.remove)
                {
                    polySegments.RemoveRange(pointIndex, 2);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            List <List <Point3> > separatedPolygons = new List <List <Point3> >();
            List <Point3>         currentPolygon    = new List <Point3>();

            separatedPolygons.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex += 2)
            {
                // add the start point
                currentPolygon.Add(polySegments[segmentIndex]);

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 2 &&
                    polySegments[segmentIndex + 1] != polySegments[segmentIndex + 2])
                {
                    // add the end point
                    currentPolygon.Add(polySegments[segmentIndex + 1]);

                    // create a new polygon
                    currentPolygon = new List <Point3>();
                    separatedPolygons.Add(currentPolygon);
                }
            }

            // add the end point
            currentPolygon.Add(polySegments[polySegments.Count - 1]);

            return(separatedPolygons);
        }