public static Polygon MakeCloseSegmentsMergable(this Polygon polygonToSplit, Polygon pointsToSplitOn, long distanceNeedingAdd, bool pathIsClosed = true)
        {
            List <Segment> segments = Segment.ConvertToSegments(polygonToSplit, pathIsClosed);

            var touchingEnumerator = new PolygonEdgeIterator(pointsToSplitOn, distanceNeedingAdd);

            // for every segment
            for (int segmentIndex = segments.Count - 1; segmentIndex >= 0; segmentIndex--)
            {
                List <Segment> newSegments = segments[segmentIndex].GetSplitSegmentForVertecies(touchingEnumerator);
                if (newSegments?.Count > 0)
                {
                    // remove the old segment
                    segments.RemoveAt(segmentIndex);
                    // add the new ones
                    segments.InsertRange(segmentIndex, newSegments);
                }
            }

            var segmentedPolygon = new Polygon(segments.Count);

            foreach (var segment in segments)
            {
                segmentedPolygon.Add(segment.Start);
            }

            if (!pathIsClosed && segments.Count > 0)
            {
                // add the last point
                segmentedPolygon.Add(segments[segments.Count - 1].End);
            }

            return(segmentedPolygon);
        }
        public static Intersection FindIntersection(this Polygon polygon, IntPoint start, IntPoint end, QuadTree <int> edgeQuadTree = null)
        {
            Intersection bestIntersection = Intersection.None;

            IntPoint segmentDelta = end - start;
            var      edgeIterator = new PolygonEdgeIterator(polygon, 1, edgeQuadTree);

            foreach (var i in edgeIterator.GetTouching(new Quad(start, end)))
            {
                IntPoint edgeStart = polygon[i];

                // if we share a vertex we cannot be crossing the line
                IntPoint edgeEnd = polygon[(i + 1) % polygon.Count];
                if (start == edgeStart || start == edgeEnd || end == edgeStart || end == edgeEnd ||
                    start == polygon[i] || end == polygon[i])
                {
                    bestIntersection = Intersection.Colinear;
                }
                else
                {
                    var result = GetIntersection(start, end, edgeStart, edgeEnd);
                    if (result == Intersection.Intersect)
                    {
                        return(Intersection.Intersect);
                    }
                    else if (result == Intersection.Colinear)
                    {
                        bestIntersection = Intersection.Colinear;
                    }
                }
            }

            return(bestIntersection);
        }
Example #3
0
        public static IEnumerable <Tuple <int, IntPoint> > FindCrossingPoints(this Polygon polygon, IntPoint start, IntPoint end, QuadTree <int> edgeQuadTree = null)
        {
            IntPoint segmentDelta  = end - start;
            long     segmentLength = segmentDelta.Length();
            var      edgeIterator  = new PolygonEdgeIterator(polygon, 1, edgeQuadTree);

            foreach (var i in edgeIterator.GetTouching(new Quad(start, end)))
            {
                IntPoint edgeStart    = polygon[i];
                IntPoint edgeEnd      = polygon[(i + 1) % polygon.Count];
                IntPoint intersection = new IntPoint();

                if (OnSegment(edgeStart, start, edgeEnd))
                {
                    yield return(new Tuple <int, IntPoint>(i, start));
                }
                else if (OnSegment(edgeStart, end, edgeEnd))
                {
                    yield return(new Tuple <int, IntPoint>(i, end));
                }
                else if (DoIntersect(start, end, edgeStart, edgeEnd) &&
                         CalcIntersection(start, end, edgeStart, edgeEnd, out intersection))
                {
                    IntPoint pointRelStart = intersection - start;
                    yield return(new Tuple <int, IntPoint>(i, intersection));
                }
            }
        }
        public static bool TouchingEdge(this Polygon polygon, IntPoint testPosition, QuadTree <int> edgeQuadTree = null)
        {
            var edgeIterator = new PolygonEdgeIterator(polygon, 1, edgeQuadTree);

            foreach (var i in edgeIterator.GetTouching(new Quad(testPosition)))
            {
                IntPoint edgeStart = polygon[i];
                IntPoint edgeEnd   = polygon[(i + 1) % polygon.Count];
                if (OnSegment(edgeStart, testPosition, edgeEnd))
                {
                    return(true);
                }
            }

            return(false);
        }
        public static IEnumerable <(int pointIndex, IntPoint position)> FindCrossingPoints(this Polygon polygon, IntPoint start, IntPoint end, QuadTree <int> edgeQuadTree = null)
        {
            var edgeIterator = new PolygonEdgeIterator(polygon, 1, edgeQuadTree);

            foreach (var i in edgeIterator.GetTouching(new Quad(start, end)))
            {
                IntPoint edgeStart = polygon[i];
                IntPoint edgeEnd   = polygon[(i + 1) % polygon.Count];
                if (OnSegment(edgeStart, start, edgeEnd))
                {
                    yield return(i, start);
                }
                else if (OnSegment(edgeStart, end, edgeEnd))
                {
                    yield return(i, end);
                }
                else if (DoIntersect(start, end, edgeStart, edgeEnd) &&
                         CalcIntersection(start, end, edgeStart, edgeEnd, out IntPoint intersection))
                {
                    yield return(i, intersection);
                }
            }
        }
Example #6
0
        public List <Segment> GetSplitSegmentForVertecies(PolygonEdgeIterator touchingEnumerator)
        {
            IntPoint start2D = new IntPoint(Start)
            {
                Z = 0
            };
            IntPoint end2D = new IntPoint(End)
            {
                Z = 0
            };

            SortedList <long, IntPoint> requiredSplits2D = new SortedList <long, IntPoint>();

            // get some data we will need for the operations
            IntPoint direction             = (end2D - start2D);
            long     length                = direction.Length();
            long     lengthSquared         = length * length;
            IntPoint rightDirection        = direction.GetPerpendicularRightXY();
            long     maxDistanceNormalized = touchingEnumerator.OverlapAmount * length;

            // for every vertex
            foreach (int touchingPoint in touchingEnumerator.GetTouching(new Quad(this.Left, this.Bottom, this.Right, this.Top)))
            //for (int splintIndex = 0; splintIndex < splitPoints.Count; splintIndex++)
            {
                IntPoint vertex = new IntPoint(touchingEnumerator.SourcePoints[touchingPoint])
                {
                    Z = 0
                } -start2D;
                // if the vertex is close enough to the segment
                long dotProduct = rightDirection.Dot(vertex);
                if (Math.Abs(dotProduct) < maxDistanceNormalized)
                {
                    long dotProduct2 = direction.Dot(vertex);
                    if (dotProduct2 > 0 && dotProduct2 < lengthSquared)
                    {
                        long distance = dotProduct2 / length;
                        // don't add if there is already a point at this position
                        if (!requiredSplits2D.ContainsKey(distance))
                        {
                            // we are close enough to the line split it
                            requiredSplits2D.Add(distance, start2D + direction * distance / length);
                        }
                    }
                }
            }

            if (requiredSplits2D.Count > 0)
            {
                // add in the start and end
                if (!requiredSplits2D.ContainsKey(0))
                {
                    requiredSplits2D.Add(0, start2D);
                }
                if (!requiredSplits2D.ContainsKey(length))
                {
                    requiredSplits2D.Add(length, end2D);
                }
                // convert to a segment list
                List <Segment> newSegments = Segment.ConvertPathToSegments(requiredSplits2D.Values, Start.Z, false);
                // return them;
                return(newSegments);
            }

            return(null);
        }