public static Polygon2 Convexhull(IEnumerable <Vector2> vertices) { var pts = vertices.ToArray(); if (!pts.Any()) { return(new Polygon2()); } // Sort points lexicographically by increasing (x, y) int n = pts.Length; Polysort.Quicksort(pts); var left = pts[0]; var right = pts[n - 1]; // Partition into lower hull and upper hull var lower = new CircularDoublyLinkedList <Vector2>(left); var upper = new CircularDoublyLinkedList <Vector2>(left); for (int i = 0; i < n; i++) { double det = Vector2.Area2(left, right, pts[i]); if (det > 0) { upper = upper.Append(new CircularDoublyLinkedList <Vector2>(pts[i])); } else if (det < 0) { lower = lower.Prepend(new CircularDoublyLinkedList <Vector2>(pts[i])); } } lower = lower.Prepend(new CircularDoublyLinkedList <Vector2>(right)); upper = upper.Append(new CircularDoublyLinkedList <Vector2>(right)).Next; // Eliminate points not on the hull Eliminate(lower); Eliminate(upper); // Eliminate duplicate endpoints if (lower.Prev.Value.Equals(upper.Value)) { lower.Prev.Delete(); } if (upper.Prev.Value.Equals(lower.Value)) { upper.Prev.Delete(); } // Join the lower and upper hull var res = new Vector2[lower.Size() + upper.Size()]; lower.CopyInto(res, 0); upper.CopyInto(res, lower.Size()); return(new Polygon2(res)); }