/// <summary> /// Returns a sorted list of intersection points for a line segment with a (closed) polygon. /// </summary> /// <param name="v1">Start of line segment</param> /// <param name="v2">End of line segment</param> /// <param name="polygon">Polygon to be intersected</param> /// <returns>All intersection points sorted to their distance on the line segment</returns> public static List <IntersectionPoint> IntersectionLinePolygon(Vec2d v1, Vec2d v2, List <Vec2d> polygon) { List <IntersectionPoint> ips = new List <IntersectionPoint>(2); Vec2d ip; double fA, fB; // Intersect with all polygon edges for (int i = 0; i < polygon.Count; ++i) { Vec2d v3 = polygon[i]; Vec2d v4 = polygon[(i + 1) % polygon.Count]; if (MathUtilD.IntersectionLines(v1, v2, v3, v4, out fA, out fB, out ip)) { ips.Add(new IntersectionPoint(ip, fA)); } } // Sort the list ips.Sort(); return(ips); }
public static bool LineIntersectsPolygon(List <Vec2d> poly, Vec2d a, Vec2d b) { bool found = false; double fA, fB; Vec2d ip; if (poly.Count == 0) { return(found); } if (MathUtilD.IntersectionLines(a, b, poly[0], poly[poly.Count - 1], out fA, out fB, out ip)) { found = true; } for (int i = 0; !found && i < poly.Count - 1; i++) { if (MathUtilD.IntersectionLines(a, b, poly[i], poly[i + 1], out fA, out fB, out ip)) { found = true; } } return(found); }
/// <summary> /// Returns a list of sub-polygons resulting from a split of a (closed) polygon by a line. /// </summary> /// <param name="v1">Start of line</param> /// <param name="v2">End of line</param> /// <param name="polygon">Polygon to be split</param> /// <returns>All resulting polygons, or the original polygon if the line does not intersect the polygon</returns> public static List <SubPolygon> SplitPolygonByLine(Vec2d v1, Vec2d v2, SubPolygon polygon) { // TODO cleanup and rewrite this to perform no unneeded line intersections List <SubPolygon> result = new List <SubPolygon>(2); Vec2d ip; double fA, fB; // Intersect with all polygon edges List <Vec2d> points = new List <Vec2d>(); List <bool> onEdge = new List <bool>(); List <Vec2d> finalRun = new List <Vec2d>(); List <bool> finalRunOnEdge = new List <bool>(); for (int i = 0; i < polygon.Count; ++i) { Vec2d v3 = polygon[i]; // Run in progress if (points.Count > 0) { points.Add(v3); onEdge.Add(polygon.IsOnEdge(i)); } else { finalRun.Add(v3); finalRunOnEdge.Add(polygon.IsOnEdge(i)); } Vec2d v4 = polygon[(i + 1) % polygon.Count]; MathUtilD.IntersectionLines(v1, v2, v3, v4, out fA, out fB, out ip); // If intersection of line with polygon segment if (0.0 <= fB && fB <= 1.0) { if (points.Count == 0) { // Start of new run points.Add(ip); onEdge.Add(polygon.IsOnEdge(i)); if (fB > 0.0) { // ip != v3 finalRun.Add(ip); finalRunOnEdge.Add(false); } } else { // End of run if (fB < 1.0) { points.Add(ip); // Last edge from ip2 to ip1 is not on original polygon edge onEdge.Add(false); } List <Vec2d> r = new List <Vec2d>(points.Count); r.AddRange(points); if (!Polygon.IsClockWise(r)) { result.Add(new SubPolygon(r, onEdge.ToArray())); } else { finalRun.AddRange(r); finalRunOnEdge.AddRange(onEdge); } points.Clear(); onEdge.Clear(); // Next run points.Add(ip); onEdge.Add(polygon.IsOnEdge(i)); } } } if (points.Count > 0) { finalRun.InsertRange(0, points); finalRunOnEdge.InsertRange(0, onEdge); } if (finalRun.Count > 0 && !Polygon.IsClockWise(finalRun)) { result.Add(new SubPolygon(finalRun, finalRunOnEdge.ToArray())); } return(result); }