首页 文章

凸壳库[关闭]

提问于
浏览
7

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

4 回答

  • 2

    这是我使用Monotone Chain算法编写的二维凸包算法,a.k.a . 安德鲁的算法 .

    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 .

  • 3

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

  • 2

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

    算法比较:

    • 单调链

    • MiConvexHull(Delaunay三角剖分和Voronoi网格)

    • 格雷厄姆扫描

    • Ouellet(我的)

    文章:

  • 9

    下面是对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();
        }
    }
    

相关问题