public static List <Point> ConvexHullGrahams(List <Point> points)
        {
            if (points.Count == 1)
            {
                return(points);
            }

            List <Point> outPoints = new List <Point>();

            var(minPoint, idx) = HelperMethods.GetMinPoint(points, 'y');
            var minVec = new Vector2D(new Point(minPoint.X + 1234, minPoint.Y));

            points.Sort((a, b) =>
            {
                if (HelperMethods.CheckTurn(new Line(minPoint, a), b) == Enums.TurnType.Colinear)
                {
                    return(Point.GetSqrDistance(a, minPoint).CompareTo(Point.GetSqrDistance(b, minPoint)));
                }

                return(minVec.AngleTo(new Vector2D(minPoint.VectorTo(a))).Degrees
                       .CompareTo(minVec.AngleTo(new Vector2D(minPoint.VectorTo(b))).Degrees));
            });

            for (int i = 1; i < points.Count - 1; ++i)
            {
                if (HelperMethods.CheckTurn(new Line(points[0], points[i]), points[i + 1]) == Enums.TurnType.Colinear)
                {
                    points.RemoveAt(i--);
                }
            }
            if (points.Count <= 3)
            {
                outPoints.AddRange(points); return(outPoints);
            }

            Stack <Point> st = new Stack <Point>();

            st.PushRange(points.GetRange(0, 3));

            for (int i = 3; i < points.Count; ++i)
            {
                while (HelperMethods.CheckTurn(new Line(st.GetSecondTop(), st.Peek()), points[i])
                       != Enums.TurnType.Left)
                {
                    st.Pop();
                }
                st.Push(points[i]);
            }
            outPoints.AddRange(st);
            outPoints.Reverse();
            return(outPoints);
        }
        public static List <Point> SortPoints(List <Point> points)
        {
            var(minPoint, idx) = HelperMethods.GetMinPoint(points, 'y');
            var minVec = new Vector2D(new Point(minPoint.X + 1234, minPoint.Y));

            points.Sort((a, b) =>
            {
                if (HelperMethods.CheckTurn(new Line(minPoint, a), b) == Enums.TurnType.Colinear)
                {
                    return(Point.GetSqrDistance(a, minPoint).CompareTo(Point.GetSqrDistance(b, minPoint)));
                }

                return(minVec.AngleTo(new Vector2D(minPoint.VectorTo(a))).Degrees
                       .CompareTo(minVec.AngleTo(new Vector2D(minPoint.VectorTo(b))).Degrees));
            });
            return(points);
        }
        public static bool IsSupportLine(Line l, List <Point> points)
        {
            int idx = 0;

            Enums.TurnType prevSide = Enums.TurnType.Left;//dummy value
            bool           inside   = true;

            foreach (Point p in points)
            {
                if (p.Equals(l.Start) || p.Equals(l.End))
                {
                    continue;
                }

                var curSide = HelperMethods.CheckTurn(l, p);

                if (curSide == Enums.TurnType.Colinear)
                {
                    var dst1 = Point.GetSqrDistance(l.Start, l.End);
                    var dst2 = Point.GetSqrDistance(l.Start, p);
                    if (dst1 < dst2)
                    {
                        inside = false;
                        break;
                    }
                }
                if (idx != 0)
                {
                    if (curSide != prevSide)
                    {
                        inside = false;
                        break;
                    }
                }
                prevSide = curSide;
                idx++;
            }
            return(inside);
        }