Вычислить выпуклую оболочку

Как вычислить выпуклую оболочку, начиная с набора точек?


person Owen    schedule 03.02.2013    source источник


Ответы (4)


MIConvexHullhttps://designengrlab.github.io/MIConvexHull/ — — это высокопроизводительная реализация выпуклой оболочки на C#, поддерживающая также многомерные выпуклые оболочки. Лицензия LGPL.

person Govert    schedule 03.02.2013

Ниже приведена транслитерация на С# того же источника Java, который использовался в ответе Qwertie, но без зависимости от нестандартных классов, кроме класса 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();
    }
}
person jwezorek    schedule 22.09.2017

Вот двухмерный алгоритм выпуклой оболочки, который я написал с использованием алгоритма монотонной цепочки. он же Алгоритм Эндрю.

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;
}

Он основан на некоторых вещах, которые предполагаются существующими, см. мой запись в блоге для получения подробной информации.

person Qwertie    schedule 14.05.2014

Я сравнил многие алгоритмы/реализации Convex Hull со всем предоставленным кодом. Все включено в CodeProject. статья.

Алгоритм сравнения:

  • Монотонная цепочка
  • MiConvexHull (триангуляции Делоне и сетки Вороного)
  • сканирование Грэма
  • Чан
  • Уэлле (мой)

Статьи:

person Eric Ouellet    schedule 27.10.2017
comment
@ephraim, большое спасибо, что сообщили мне об этом. Я сейчас смотрю на это дело! - person Eric Ouellet; 11.12.2017
comment
@ephraim, Где у тебя ошибка, в какой статье? Я не могу воспроизвести это с помощью кода из моей последней статьи? У вас есть подсказка о том, как я могу увидеть ошибку самостоятельно? 1 000 000 тестов с 4 баллами (которые должны время от времени давать 1 балл по квадранту) со всеми аглоритмами Уэлле и без ошибок/исключений? - person Eric Ouellet; 11.12.2017
comment
@ephraim, ошибка найдена! Спасибо большое! Это было только в первой статье. статья с исправлением должна быть доступна очень скоро (будет в разработке через 15 минут и будет доступна после утверждения CodeProject ~ вероятно, сегодня) - person Eric Ouellet; 11.12.2017
comment
Спасибо! Действительно отличная библиотека (Удален отчет об ошибке... - особенно после исправления...+ это было очень незначительно) - person ephraim; 11.12.2017
comment
Пожалуйста. Но я действительно ценил, чтобы знать ошибку. Спасибо большое! Не стесняйтесь сообщать больше, если таковые имеются. - person Eric Ouellet; 11.12.2017