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