凸壳船库

我是C#的新手,并且很难计算凸包。 C#是否有某种数学库? 如果没有,那么我想我只需要实现自己的。

这是我使用Monotone Chain算法编写的2D凸包算法,也就是Andrew的算法。

 public static IListSource ComputeConvexHull(List points, bool sortInPlace = false) { if (!sortInPlace) points = new List(points); points.Sort((a, b) => aX == bX ? aYCompareTo(bY) : aXCompareTo(bX)); // Importantly, DList provides O(1) insertion at beginning and end DList hull = new DList(); int L = 0, U = 0; // size of lower and upper hulls // Builds a hull such that the output polygon starts at the leftmost point. for (int i = points.Count - 1; i >= 0 ; i--) { Point p = points[i], p1; // build lower hull (at end of output list) while (L >= 2 && (p1 = hull.Last).Sub(hull[hull.Count-2]).Cross(p.Sub(p1)) >= 0) { hull.RemoveAt(hull.Count-1); L--; } hull.PushLast(p); L++; // build upper hull (at beginning of output list) while (U >= 2 && (p1 = hull.First).Sub(hull[1]).Cross(p.Sub(p1)) <= 0) { hull.RemoveAt(0); U--; } if (U != 0) // when U=0, share the point added above hull.PushFirst(p); U++; Debug.Assert(U + L == hull.Count + 1); } hull.RemoveAt(hull.Count - 1); return hull; } 

它依赖于假设存在的一些东西,请参阅我的博客文章了解详细信息。

我将许多Convex Hull算法/实现与所提供的所有代码进行了比较。 一切都包含在CodeProject文章中。

算法比较:

  • 单调链
  • MiConvexHull(Delaunay三角剖分和Voronoi网格)
  • 格雷厄姆扫描
  • Ouellet(我的)

文章:

  • 2017-10-13 – 具有may算法/实现的测试平台: 快速和改进的2D Convex Hull算法及其在O(n log h)中的实现
  • 2014-05-20 – 解释我自己的算法: 一个凸壳算法及其在O(n log h)中的实现

下面是对Qwertie的答案中使用的相同Java源代码的C#的音译,但没有依赖于具有双字段的Point类之外的非标准类。

 class ConvexHull { public static double cross(Point O, Point A, Point B) { return (AX - OX) * (BY - OY) - (AY - OY) * (BX - OX); } public static List GetConvexHull(List points) { if (points == null) return null; if (points.Count() <= 1) return points; int n = points.Count(), k = 0; List H = new List(new Point[2 * n]); points.Sort((a, b) => aX == bX ? aYCompareTo(bY) : aXCompareTo(bX)); // Build lower hull for (int i = 0; i < n; ++i) { while (k >= 2 && cross(H[k - 2], H[k - 1], points[i]) <= 0) k--; H[k++] = points[i]; } // Build upper hull for (int i = n - 2, t = k + 1; i >= 0; i--) { while (k >= t && cross(H[k - 2], H[k - 1], points[i]) <= 0) k--; H[k++] = points[i]; } return H.Take(k - 1).ToList(); } }