/// <summary> /// Implementation of Convex Hull using the Monotone Chain Convex Hull Algorithm. /// The algorithm was chosen for implementation due to its simplicity. Chan's /// Convex Hull algorithm is a tad more efficient when the output point set /// is smaller than the input set. /// /// based on http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain /// </summary> /// <param name="input"></param> /// <returns> /// The convex hull of the points in counterclockwise order (starting from the /// rightmost point) /// </returns> public static Point2D[] ConvexHull(Point2D[] input) { // sort input by x, then y Array.Sort( input, new LambdaComparer<Point2D>( (a, b) => { if (a.X < b.X) return -1; if (a.X > b.X) return 1; return a.Y.CompareTo(b.Y); } ) ); // Initialize upper and lower hull lists var h = new Point2D[2 * input.Length]; int k = 0; // build lower hull for (int i = 0; i < input.Length; i++) { while (k >= 2 && Cross(h[k - 2], h[k - 1], input[i]) <= 0) k--; h[k++] = input[i]; } // build upper hull for (int i = input.Length - 2, t = k + 1; i >= 0; i--) { while (k >= t && Cross(h[k - 2], h[k - 1], input[i]) <= 0) k--; h[k++] = input[i]; } return h.TakeWhile(x => x != null).ToArray(); }