【问题标题】:How to compute Convex Hull in C#如何在 C# 中计算凸包
【发布时间】:2013-01-18 05:39:18
【问题描述】:

如何从点集合开始计算凸包?

我正在寻找 C# 中凸包算法的实现

【问题讨论】:

  • c# convex hull - codeproject.com/Articles/29275/Convex-Hull 在谷歌中的第一次点击。你做过研究吗?
  • 是的,我已经看到了。我的问题是 C# 是否有一个现有的内置库......
  • 可能可以重新打开,因为有代码(相同算法)的答案,以及对库/博客的引用。编辑删除“给我图书馆”部分。

标签: c# convex-hull


【解决方案1】:

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

算法比较:

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

文章:

【讨论】:

  • @ephraim,非常感谢您向我报告。我目前正在看那个案子!
  • @ephraim,您在哪里遇到了错误,在哪篇文章中?我不能用我最新文章中的代码重现它?你有关于我如何自己看到这个错误的提示吗? 1 000 000 次测试,4 分(偶尔会导致象限 1 分),所有 Ouellet 算法且没有错误/异常?
  • @ephraim,发现错误!非常感谢!这只是在第一篇文章中。带有更正的文章应该很快就会发布(将在 15 分钟内完成,并在 CodeProject 批准后发布 ~ 可能在今天)
  • 谢谢!真的很棒的图书馆(删除了错误报告.. - 尤其是在修复它之后......+它非常小)
  • 不客气。但我真的很感激知道这个错误。非常感谢你!如果有,请随时报告更多信息。
【解决方案2】:

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

class ConvexHull
{
    public static double cross(Point O, Point A, Point B)
    {
        return (A.X - O.X) * (B.Y - O.Y) - (A.Y - O.Y) * (B.X - O.X);
    }

    public static List<Point> GetConvexHull(List<Point> points)
    {
        if (points == null)
            return null;

        if (points.Count() <= 1)
            return points;

        int n = points.Count(), k = 0;
        List<Point> H = new List<Point>(new Point[2 * n]);

        points.Sort((a, b) =>
             a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X));

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

【讨论】:

    【解决方案3】:

    MIConvexHull - https://designengrlab.github.io/MIConvexHull/ - 是 C# 中的高性能凸包实现,也支持更高维的凸包。 LGPL 许可证。

    【讨论】:

      【解决方案4】:

      这是我使用Monotone Chain 算法(又名安德鲁算法)编写的二维凸包算法。

      public static IListSource<Point> ComputeConvexHull(List<Point> points, bool sortInPlace = false)
      {
          if (!sortInPlace)
              points = new List<Point>(points);
          points.Sort((a, b) => 
              a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X));
      
          // Importantly, DList provides O(1) insertion at beginning and end
          DList<Point> hull = new DList<Point>();
          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;
      }
      

      它依赖于一些假定存在的东西,有关详细信息,请参阅我的blog post

      【讨论】:

        猜你喜欢
        • 2016-06-10
        • 1970-01-01
        • 2020-02-16
        • 2015-06-06
        • 2017-04-21
        • 2017-06-15
        • 2019-02-28
        • 1970-01-01
        • 2015-05-24
        相关资源
        最近更新 更多