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